diff --git a/.gitmodules b/.gitmodules index 48ec365..0f3dfa8 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -212,10 +212,6 @@ [submodule "third_party/devtools-frontend/src"] path = third_party/devtools-frontend/src url = https://chromium.googlesource.com/devtools/devtools-frontend -[submodule "third_party/devtools-frontend-internal"] - path = third_party/devtools-frontend-internal - url = https://chrome-internal.googlesource.com/devtools/devtools-internal - gclient-condition = checkout_src_internal [submodule "third_party/dom_distiller_js/dist"] path = third_party/dom_distiller_js/dist url = https://chromium.googlesource.com/chromium/dom-distiller/dist
diff --git a/DEPS b/DEPS index 5fd862a..ba6fdd5 100644 --- a/DEPS +++ b/DEPS
@@ -280,11 +280,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '16e728a177b3902b1e9e311bf4af3acd769730e7', + 'skia_revision': '9e2547efbe95f4a535bb7871256a7286e67a5a0e', # 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': 'bdff9e1d4b2c4b1a0c29c60f4c412f269750aff6', + 'v8_revision': 'f99b675360f4753b9474c0594114447e8ca2c2f0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -292,7 +292,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '7e54d43d6905f978ccf90680dd22a48b0ede8d8b', + 'swiftshader_revision': 'c0fe4d40475b709a42d78315d3929d41d44838c8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -300,7 +300,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': '830e786772558fa9b80aa7e7118aaa5b2a042344', + 'boringssl_revision': 'aefa5d24da34ef77ac797bdbe684734e5bd870f4', # 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. @@ -348,15 +348,15 @@ # 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': '2cbeabb6a85ec0ec5ad214ca4fc9a403a4ed3139', + 'catapult_revision': 'bfa1c497260c357345844a06eeb70bd69ac46245', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': '0dc34c7c88996e0dbd967e45d0c1359dfc595939', + 'chromium_variations_revision': '1ec85168f5e4e8290cfef0ba9a7baf2c898919c3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '692b047779e4e658d748581bfadebbd1552ea335', + 'crossbench_revision': 'd64333a2353b602e2623119369c0b120c505bd22', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -372,7 +372,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': '3c514332542cdc7893afbc30de905e21753d9852', + 'devtools_frontend_revision': 'e5f236b0250de3bc4cbfa43540e4bd0785a70eb1', # 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. @@ -396,7 +396,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': '00934c211879c15a9ca6b5a031949c587837f1af', + 'dawn_revision': 'b8306de17c9a5775819a8526802fe85a860f5216', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -424,7 +424,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': '3196438660ca478f85e8a3d209b166adcd845c4a', + 'libavif_revision': '260879ce2383da96de411d440ed6adf9ea98bfe6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling crabbyavif # and whatever else without interference from each other. @@ -468,7 +468,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. - 'libcxxabi_revision': 'd82e9c4d06c1ec29dc3421e738aecb7514cc4bfc', + 'libcxxabi_revision': 'a6362b2727ba0eea15d024bfac7e1dc8e79db009', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -496,11 +496,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling llvm-libc # and whatever else without interference from each other. - 'llvm_libc_revision': '5f1326b036bfd81c2831089915545189d154426c', + 'llvm_libc_revision': '5dda25750dd119c2bff8e279dd1c0f13fbd422e5', # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '643441dc2f2da5fe3e09c7559249b558f224a2dc', + 'libcxx_revision': '2d9b9a9eea77b09fe4bc7a41b33140fa7298d39f', # GN CIPD package version. 'gn_version': 'git_revision:468c6128db7fabe32a29d4753460ef53594406fc', @@ -707,7 +707,7 @@ 'packages': [ { 'package': 'chrome_internal/third_party/google3/data_sharing_sdk', - 'version': '2qQtp9Dzcd1eRxNMupBH_fbnMd3LZ5_tCd9lngJn5OgC', + 'version': 'aUh0lm0ZUvAROWVybt5kOpv5TCTMhpH4TgAGe83AQ-EC', }, ], 'condition': 'checkout_src_internal and non_git_source', @@ -1304,7 +1304,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '2f52e8c05d050394684c53b038ac105abf95f4d0', + 'b5d98568bc15a6db04d96b75da6adede917e67e4', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1463,7 +1463,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'ZDDwOQoXoGUcFWpDnhnRo0pbZS_dI4bWIOUNi6cDEy4C', + 'version': '99Dez97fnBwo2SopS7EvvLqkdRwWIXXuJBHUTamWqskC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1605,7 +1605,7 @@ }, { 'package': 'chromium/third_party/android_sdk/public/cmdline-tools', - 'version': 'B4p95sDPpm34K8Cf4JcfTM-iYSglWko9qjWgbT9dxWQC', + 'version': 'OCGHZKTdjXjIELVI6FMAgcDkfnd_1ybB0_MtljPtz-8C', }, ], 'condition': 'checkout_android and non_git_source', @@ -1783,7 +1783,7 @@ Var('chromium_git') + '/external/github.com/google/cpu_features.git' + '@' + '936b9ab5515dead115606559502e3864958f7f6e', 'src/third_party/cpuinfo/src': - Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + 'cebb0933058d7f181c979afd50601dc311e1bf8c', + Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + 'ca156f7bc9109c552973414a63d310f76ef0cbf8', 'src/third_party/crc32c/src': Var('chromium_git') + '/external/github.com/google/crc32c.git' + '@' + 'd3d60ac6e0f16780bcfcc825385e1d338801a558', @@ -1804,16 +1804,11 @@ 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), - 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '4b0016e116288e419beb13a521994b584acc435e', - 'condition': 'checkout_src_internal', - }, - 'src/third_party/dom_distiller_js/dist': Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d', 'src/third_party/eigen3/src': - Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '5610a13b7767a94e063342277e0b9de4de13be57', + Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '77a073aaa821300fc129ef24b3b052be2e670a3e', 'src/third_party/emoji-metadata/src': { 'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06', @@ -2171,7 +2166,7 @@ Var('chromium_git') + '/webm/libwebp.git' + '@' + '845d5476a866141ba35ac133f856fa62f0b7445f', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '307b951229cc2eb756af09ea111f7be6ff065d4f', + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '192b8c2238cae1c26774962eb5b61ba90cd45210', 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -2243,7 +2238,7 @@ }, 'src/third_party/neon_2_sse/src': - Var('chromium_git') + '/external/github.com/intel/ARM_NEON_2_x86_SSE.git' + '@' + 'a15b489e1222b2087007546b4912e21293ea86ff', + Var('chromium_git') + '/external/github.com/intel/ARM_NEON_2_x86_SSE.git' + '@' + 'eb8b80b28f956275e291ea04a7beb5ed8289e872', 'src/third_party/netty-tcnative/src': { 'url': Var('chromium_git') + '/external/netty-tcnative.git' + '@' + '035726f76293d142ec3c4464be0703605feb4d02', @@ -2526,7 +2521,7 @@ }, 'src/third_party/ruy/src': - Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '9889171210b81138fd15fb57dd06e98fe6d37b3c', + Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '95484c3e02206f73309c08ee5ee23d2304ca092b', 'src/third_party/skia': Var('skia_git') + '/skia.git' + '@' + Var('skia_revision'), @@ -2609,7 +2604,7 @@ Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f', 'src/third_party/tflite/src': - Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '54d2d15dabe13df91cd97d5290f31b776660ca79', + Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '73e1e9f4d021a1819a3e2a28889b75de1174bdbe', 'src/third_party/turbine/cipd': { 'packages': [ @@ -2668,13 +2663,13 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '450cceb587613ac1469c5a131fac15935c99e0e7', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '64eb522c87efb458b46d84048c3bb4c3c063a21c', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '726f4dd24eac0296f4ae39f11ad28d42635b5e55', 'src/third_party/webpagereplay': Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '3a1f2e6a694464636d5e779157fc80d691981463', + Var('webrtc_git') + '/src.git' + '@' + 'e754fcfee51354cf4e0f54cbe7051eb235264514', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -2705,14 +2700,14 @@ }, 'src/third_party/xnnpack/src': - Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '98f1c8e5c5411bd435d994881440c3c6fc58d109', + Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '7440eee88f66c4b81d4e7d31f6ae07af66e059ea', 'src/third_party/libei/cipd': { 'packages': [ { 'package': 'chromium/third_party/libei/linux-amd64', - 'version': 'PQz4zG5Q3SXoAaCYq3RK99W3wg_v0NoOu1OzTSvA_oIC', + 'version': '7V4n9OUxAo8k8zayCwZ47Bc5Mqr7Br1NXrxeMKXYBNQC', }, ], @@ -4480,7 +4475,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '603eaf71b0c1cccaa12b473013d621fffa56d087', + '8804f341dfbd03ceec57471c98bcaba90b64eaf9', 'condition': 'checkout_ios and checkout_src_internal', }, @@ -5565,7 +5560,6 @@ # Dawn manages DEPS for its copy of the WebGPU CTS as well as GLFW for which # it has build files. 'src/third_party/dawn', - 'src/third_party/devtools-frontend-internal', 'src/third_party/instrumented_libs', 'src/third_party/openscreen/src', 'src/third_party/devtools-frontend/src',
diff --git a/WATCHLISTS b/WATCHLISTS index 50cec2b..63ee370a 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1043,12 +1043,12 @@ 'desktop_in_product_help': { 'filepath': 'components/feature_engagement/|'\ 'components/user_education/|'\ - 'chrome/browser/resources/internals/user_education/|'\ + 'chrome/browser/resources/user_education_internals/|'\ 'chrome/browser/resources/whats_new/|'\ 'chrome/browser/user_education/|'\ 'chrome/browser/ui/user_education/|'\ 'chrome/browser/ui/views/user_education/|'\ - 'chrome/browser/ui/webui/internals/user_education/|'\ + 'chrome/browser/ui/webui/user_education_internals/|'\ 'chrome/browser/ui/webui/whats_new/', }, 'device_bluetooth': {
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index f89e172..1c880a8 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -562,11 +562,6 @@ + " text in the currently focused element to Android. These rectangles " + "are sent for <input> and <textarea> elements."), Flag.baseFeature( - BlinkFeatures.STYLUS_POINTER_ADJUSTMENT, - "When enabled, a hover icon is shown over editable HTML elements when" - + " using a stylus and the rectangle to trigger stylus writing on" - + " editable elements is expanded."), - Flag.baseFeature( BlinkFeatures.STYLUS_RICH_GESTURES, "When enabled, stylus input can be used to draw rich gestures which " + "affect text in editable web content."),
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedLoaderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedLoaderTest.java index 863653b..3647eee1 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedLoaderTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedLoaderTest.java
@@ -7,6 +7,7 @@ import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.EITHER_PROCESS; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -31,6 +32,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.HistogramWatcher; import java.io.File; @@ -388,6 +390,9 @@ @Test @MediumTest @CommandLineFlags.Add(AwSwitches.FINCH_SEED_EXPIRATION_AGE + "=0") + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/351017155") public void testFinchSeedExpirationAgeFlag() throws Exception { try { // Create a new seed file with a recent timestamp.
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index 83a0c62..2987640 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -97,6 +97,7 @@ #include "ui/accessibility/aura/aura_window_properties.h" #include "ui/aura/window.h" #include "ui/base/cursor/cursor_size.h" +#include "ui/base/ime/ash/ime_keyboard.h" #include "ui/base/l10n/l10n_util.h" #include "ui/display/screen.h" #include "ui/display/tablet_state.h" @@ -1253,6 +1254,14 @@ registry->RegisterBooleanPref( prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled, false); registry->RegisterBooleanPref(prefs::kAccessibilityFaceGazeEnabled, false); + registry->RegisterBooleanPref(prefs::kAccessibilityFaceGazeEnabledSentinel, + false); + registry->RegisterBooleanPref( + prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog, true); + registry->RegisterBooleanPref( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, true); + registry->RegisterBooleanPref( + prefs::kAccessibilityFaceGazeActionsEnabledSentinel, true); registry->RegisterBooleanPref(prefs::kAccessibilityDisableTrackpadEnabled, false); registry->RegisterIntegerPref(prefs::kAccessibilityDisableTrackpadMode, @@ -2575,6 +2584,8 @@ // Features will be initialized from current prefs later. } + // TODO(crbug.com/383754550): Consider updating calls from + // base::Unretained(this) to GetWeakPtr(). pref_change_registrar_->Add( prefs::kAccessibilityAutoclickDelayMs, base::BindRepeating( @@ -2767,6 +2778,25 @@ if (::features::IsAccessibilityFaceGazeEnabled()) { UpdateFaceGazeFromPrefs(); + pref_change_registrar_->Add( + prefs::kAccessibilityFaceGazeEnabledSentinel, + base::BindRepeating(&AccessibilityController::OnFaceGazeSentinelChanged, + base::Unretained(this), + prefs::kAccessibilityFaceGazeEnabledSentinel, + prefs::kAccessibilityFaceGazeEnabled)); + pref_change_registrar_->Add( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + base::BindRepeating( + &AccessibilityController::OnFaceGazeSentinelChanged, + base::Unretained(this), + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + prefs::kAccessibilityFaceGazeCursorControlEnabled)); + pref_change_registrar_->Add( + prefs::kAccessibilityFaceGazeActionsEnabledSentinel, + base::BindRepeating(&AccessibilityController::OnFaceGazeSentinelChanged, + base::Unretained(this), + prefs::kAccessibilityFaceGazeActionsEnabledSentinel, + prefs::kAccessibilityFaceGazeActionsEnabled)); } if (::features::IsAccessibilityFlashScreenFeatureEnabled()) { UpdateFlashNotificationsFromPrefs(); @@ -2854,7 +2884,11 @@ } void AccessibilityController::UpdateSlowKeysDelayFromPref() { - // TODO(b/375218308): Hook up slow keys setter, similar to bounce keys above. + DCHECK(active_user_prefs_); + base::TimeDelta delay = base::Milliseconds( + active_user_prefs_->GetInteger(prefs::kAccessibilitySlowKeysDelayMs)); + input_method::InputMethodManager::Get()->GetImeKeyboard()->SetSlowKeysDelay( + delay); } void AccessibilityController::UpdateMouseKeysAccelerationFromPref() { @@ -3001,6 +3035,43 @@ if (!::features::IsAccessibilityFaceGazeEnabled()) { return; } + + const bool enabled = + active_user_prefs_->GetBoolean(prefs::kAccessibilityFaceGazeEnabled); + const bool sentinel_enabled = active_user_prefs_->GetBoolean( + prefs::kAccessibilityFaceGazeEnabledSentinel); + // Sentinel and behavior pref are not in sync. + if (enabled != sentinel_enabled) { + if (enabled) { + active_user_prefs_->SetBoolean( + prefs::kAccessibilityFaceGazeEnabledSentinel, true); + } else { + // Set sentinel pref to false without showing the dialog. + active_user_prefs_->SetBoolean( + prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog, false); + active_user_prefs_->SetBoolean( + prefs::kAccessibilityFaceGazeEnabledSentinel, false); + } + } + + const bool cursor_control_enabled = active_user_prefs_->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabled); + const bool cursor_control_sentinel_enabled = active_user_prefs_->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel); + if (cursor_control_enabled != cursor_control_sentinel_enabled) { + active_user_prefs_->SetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + cursor_control_enabled); + } + + const bool actions_enabled = active_user_prefs_->GetBoolean( + prefs::kAccessibilityFaceGazeActionsEnabled); + const bool actions_sentinel_enabled = active_user_prefs_->GetBoolean( + prefs::kAccessibilityFaceGazeActionsEnabledSentinel); + if (actions_enabled != actions_sentinel_enabled) { + active_user_prefs_->SetBoolean( + prefs::kAccessibilityFaceGazeActionsEnabledSentinel, actions_enabled); + } } void AccessibilityController::UpdateFlashNotificationsFromPrefs() { @@ -3623,6 +3694,28 @@ return confirmation_dialog_.get()->GetWidget()->GetWindowBoundsInScreen(); } +void AccessibilityController::ShowFeatureDisableDialog( + int window_title_text_id, + base::OnceClosure on_accept_callback, + base::OnceClosure on_cancel_callback) { + if (disable_dialog_) { + // If a dialog is already being shown we do not show a new one. + // Instead, run the on_close_callback on the new dialog to indicate + // it was closed without the user taking any action. + // This is consistent with AcceleratorController. + std::move(on_cancel_callback).Run(); + return; + } + + auto* dialog = new AccessibilityFeatureDisableDialog( + window_title_text_id, std::move(on_accept_callback), + std::move(on_cancel_callback)); + disable_dialog_ = dialog->GetWeakPtr(); + if (show_disable_dialog_callback_for_testing_) { + show_disable_dialog_callback_for_testing_.Run(); + } +} + void AccessibilityController::PreviewFlashNotification() const { flash_screen_controller_->PreviewFlash(); } @@ -3811,8 +3904,10 @@ } break; case FeatureType::kSlowKeys: - if (filter_keys_event_rewriter_) { - // TODO(b/375218308): Hook up slow keys enablement. + if (::features::IsAccessibilitySlowKeysEnabled()) { + input_method::InputMethodManager::Get() + ->GetImeKeyboard() + ->SetSlowKeysEnabled(enabled); } break; case FeatureType::kStickyKeys: @@ -3933,6 +4028,11 @@ show_confirmation_dialog_callback_for_testing_ = std::move(callback); } +void AccessibilityController::AddFeatureDisableDialogCallbackForTesting( + base::RepeatingCallback<void()> callback) { + show_disable_dialog_callback_for_testing_ = std::move(callback); +} + bool AccessibilityController::VerifyFeaturesDataForTesting() { return VerifyFeaturesData(); } @@ -3976,6 +4076,62 @@ std::ignore = host->GetEventSink()->OnEventFromSource(&wheel); } +void AccessibilityController::OnFaceGazeSentinelChanged( + const std::string& sentinel_pref, + const std::string& behavior_pref) { + DCHECK(active_user_prefs_); + if (active_user_prefs_->GetBoolean(sentinel_pref)) { + active_user_prefs_->SetBoolean(behavior_pref, true); + return; + } + + // Set to FaceGaze disable confirmation text by default to ensure a valid + // value. + int window_title_text_id = IDS_ASH_FACEGAZE_DISABLE_CONFIRMATION_TEXT; + if (sentinel_pref == prefs::kAccessibilityFaceGazeEnabledSentinel) { + const bool show_dialog = active_user_prefs_->GetBoolean( + prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog); + if (!show_dialog) { + face_gaze().SetEnabled(false); + // Reset show dialog pref to default after pref is handled. + active_user_prefs_->SetBoolean( + prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog, true); + return; + } + } else if (sentinel_pref == + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel) { + window_title_text_id = + IDS_ASH_FACEGAZE_CURSOR_CONTROL_DISABLE_CONFIRMATION_TEXT; + } else if (sentinel_pref == + prefs::kAccessibilityFaceGazeActionsEnabledSentinel) { + window_title_text_id = IDS_ASH_FACEGAZE_ACTIONS_DISABLE_CONFIRMATION_TEXT; + } + + ShowFeatureDisableDialog( + window_title_text_id, + BindOnce(&AccessibilityController::OnFaceGazeDisableDialogClosed, + GetWeakPtr(), sentinel_pref, behavior_pref, + /*dialog_accepted=*/true), + BindOnce(&AccessibilityController::OnFaceGazeDisableDialogClosed, + GetWeakPtr(), sentinel_pref, behavior_pref, + /*dialog_accepted=*/false)); +} + +void AccessibilityController::OnFaceGazeDisableDialogClosed( + const std::string& sentinel_pref, + const std::string& behavior_pref, + bool dialog_accepted) { + if (dialog_accepted) { + // After confirmation, set behavior pref to false to turn off the feature. + active_user_prefs_->SetBoolean(behavior_pref, false); + } else { + // Ensure sentinel pref is in sync with behavior pref if dialog is + // cancelled. + active_user_prefs_->SetBoolean(sentinel_pref, true); + } + disable_dialog_.reset(); +} + void AccessibilityController::UpdateFaceGazeBubble(const std::u16string& text, bool is_warning) { if (!facegaze_bubble_controller_ ||
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h index 505d6a79..10792e2 100644 --- a/ash/accessibility/accessibility_controller.h +++ b/ash/accessibility/accessibility_controller.h
@@ -55,6 +55,7 @@ class AccessibilityConfirmationDialog; class AccessibilityControllerClient; class AccessibilityEventRewriter; +class AccessibilityFeatureDisableDialog; class AccessibilityHighlightController; class AccessibilityObserver; enum class AccessibilityPanelState; @@ -644,6 +645,12 @@ std::optional<int> timeout_seconds = std::nullopt); gfx::Rect GetConfirmationDialogBoundsInScreen(); + // Shows a dialog to disable a feature with the given text, and calls the + // relevant callback when the dialog is accepted or cancelled. + void ShowFeatureDisableDialog(int window_title_text_id, + base::OnceClosure on_accept_callback, + base::OnceClosure on_cancel_callback); + void PreviewFlashNotification() const; // SessionObserver: @@ -679,6 +686,9 @@ AccessibilityConfirmationDialog* GetConfirmationDialogForTest() { return confirmation_dialog_.get(); } + AccessibilityFeatureDisableDialog* GetFeatureDisableDialogForTest() { + return disable_dialog_.get(); + } bool enable_chromevox_volume_slide_gesture() { return enable_chromevox_volume_slide_gesture_; @@ -718,6 +728,9 @@ void AddShowConfirmationDialogCallbackForTesting( base::RepeatingCallback<void()> callback); + void AddFeatureDisableDialogCallbackForTesting( + base::RepeatingCallback<void()> callback); + bool VerifyFeaturesDataForTesting(); SelectToSpeakEventHandler* GetSelectToSpeakEventHandlerForTesting() const { @@ -813,6 +826,12 @@ void OnDisableTouchpadDialogDismissed(); void ExternalDeviceConnected(); + void OnFaceGazeSentinelChanged(const std::string& sentinel_pref, + const std::string& behavior_pref); + void OnFaceGazeDisableDialogClosed(const std::string& sentinel_pref, + const std::string& behavior_pref, + bool dialog_accepted); + void RecordSelectToSpeakSpeechDuration(SelectToSpeakState old_state, SelectToSpeakState new_state); @@ -912,6 +931,11 @@ base::RepeatingCallback<void()> show_confirmation_dialog_callback_for_testing_; + // The current AccessibilityFeatureDisableDialog, if one exists. + base::WeakPtr<AccessibilityFeatureDisableDialog> disable_dialog_; + + base::RepeatingCallback<void()> show_disable_dialog_callback_for_testing_; + base::Time select_to_speak_speech_start_time_; base::ScopedObservation<InputDeviceSettingsController,
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc index 72d75e9..4689a33 100644 --- a/ash/accessibility/accessibility_controller_unittest.cc +++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -342,6 +342,14 @@ prefs()->FindPreference(prefs::kAccessibilityFaceGazePrecisionClick)); EXPECT_TRUE(prefs()->FindPreference( prefs::kAccessibilityFaceGazePrecisionClickSpeedFactor)); + EXPECT_TRUE( + prefs()->FindPreference(prefs::kAccessibilityFaceGazeEnabledSentinel)); + EXPECT_TRUE(prefs()->FindPreference( + prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog)); + EXPECT_TRUE(prefs()->FindPreference( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel)); + EXPECT_TRUE(prefs()->FindPreference( + prefs::kAccessibilityFaceGazeActionsEnabledSentinel)); EXPECT_TRUE(prefs()->FindPreference(prefs::kAccessibilityCaretBlinkInterval)); EXPECT_TRUE( prefs()->FindPreference(prefs::kAccessibilityFlashNotificationsEnabled));
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 50e7b48..135f762a 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -113,6 +113,8 @@ // The app id for the settings app used for testing quick app access. constexpr char kOsSettingsAppId[] = "odknhmnlageboeamepcngndbggdpaobj"; +bool g_sunfish_nudge_disabled_for_test = false; + // Update layer animation settings for launcher scale and opacity animation that // runs on overview mode change. void UpdateOverviewSettings(base::TimeDelta duration, @@ -2082,8 +2084,17 @@ return model_provider_->quick_app_access_model()->SetQuickApp(app_id); } +// static +void AppListControllerImpl::SetSunfishNudgeDisabledForTest(bool is_disabled) { + g_sunfish_nudge_disabled_for_test = is_disabled; +} + void AppListControllerImpl::MaybeShowSunfishLauncherNudge( views::View* launcher_button) { + if (g_sunfish_nudge_disabled_for_test) { + return; + } + if (!IsSunfishAllowedAndEnabled()) { return; }
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index c0096aa0..58bc90b1 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -99,6 +99,10 @@ static void RegisterProfilePrefs(PrefRegistrySimple* registry); + // Set the value of global variable `g_sunfish_nudge_disabled_for_test` to + // disable showing the nudge. + static void SetSunfishNudgeDisabledForTest(bool is_disabled); + AppListPresenterImpl* fullscreen_presenter() { return fullscreen_presenter_.get(); }
diff --git a/ash/app_list/test/app_list_test_helper.cc b/ash/app_list/test/app_list_test_helper.cc index afd054e..fb950c65 100644 --- a/ash/app_list/test/app_list_test_helper.cc +++ b/ash/app_list/test/app_list_test_helper.cc
@@ -65,6 +65,7 @@ // Disable app list nudge as default. DisableAppListNudge(true); AppListNudgeController::SetPrivacyNoticeAcceptedForTest(true); + AppListControllerImpl::SetSunfishNudgeDisabledForTest(true); } AppListTestHelper::~AppListTestHelper() {
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 78c9bb4..54d01626 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1512,6 +1512,17 @@ You can also use the keyboard shortcut. First, highlight text, then press <ph name="modifier">$1<ex>launcher</ex></ph> + s. </message> + <!-- FaceGaze dialog strings --> + <message name="IDS_ASH_FACEGAZE_DISABLE_CONFIRMATION_TEXT" desc="The text for the modal dialog shown when the user disables FaceGaze, to confirm they meant to disable the feature."> + Are you sure you want to turn off face control? + </message> + <message name="IDS_ASH_FACEGAZE_CURSOR_CONTROL_DISABLE_CONFIRMATION_TEXT" desc="The text for the modal dialog shown when the user disables cursor control in FaceGaze, to confirm they meant to disable the feature." translateable="false"> + Are you sure you want to turn off mouse cursor control? + </message> + <message name="IDS_ASH_FACEGAZE_ACTIONS_DISABLE_CONFIRMATION_TEXT" desc="The text for the modal dialog shown when the user disables performing actions using facial gestures in FaceGaze, to confirm they meant to disable the feature." translateable="false"> + Are you sure you want to turn off facial gestures? + </message> + <!-- Accessibility nudges --> <message name="IDS_ASH_ACCESSIBILITY_NUDGE_DICTATION_NO_FOCUSED_TEXT_FIELD" desc="Displayed in a nudge when Dictation is stopped automatically because there is no focused text field."> Go to a text field to use Dictation @@ -8201,17 +8212,11 @@ <message name="IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT" desc="Text shown in the body of the dialog as part of the System UI Welcome Tour."> Take a quick tour to learn how to get around your <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph>. Get up and running in 5 steps. </message> - <message name="IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2" desc="Text shown in the body of the dialog as part of the System UI Welcome Tour V2."> - Take a quick tour to learn how to get around your <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> - </message> <message name="IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT" desc="Text shown as the Welcome Tour dialog title."> Hi there. <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> is a little different. </message> - <message name="IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2" desc="Text shown as the Welcome Tour V2 dialog title."> - 6 tips to get started on <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> - </message> <message name="IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT" desc="Text shown in the body of a help bubble anchored to the Explore app as part of the System UI Welcome Tour."> - Those were the basics! Continue in Explore, our built-in app for tips and help. You’ll find tips for getting started, recommended apps, special offers, and the newest <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> features. + Those were the basics! Continue in Explore, our built-in app for tips and help. You’ll find tips for getting started, special offers, and the newest <ph name="PRODUCT_NAME">$1<ex>Chromebook</ex></ph> features. </message> <message name="IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_ACCNAME" desc="The accessible name of a help bubble anchored to the Files app as part of the System UI Welcome Tour."> Tour step <ph name="STEP">$1<ex>1</ex></ph> of <ph name="TOTAL_STEPS">$2<ex>5</ex></ph>. You can find the Files app in Launcher. Manage your local files and your Google Drive files, all in the Files app.
diff --git a/ash/ash_strings_grd/IDS_ASH_FACEGAZE_DISABLE_CONFIRMATION_TEXT.png.sha1 b/ash/ash_strings_grd/IDS_ASH_FACEGAZE_DISABLE_CONFIRMATION_TEXT.png.sha1 new file mode 100644 index 0000000..d114f7b --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_FACEGAZE_DISABLE_CONFIRMATION_TEXT.png.sha1
@@ -0,0 +1 @@ +2ef8fbb30486b5eb3b1bee216347beaa3de2040c \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2.png.sha1 b/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2.png.sha1 deleted file mode 100644 index 7ae09e85..0000000 --- a/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -51a3652b0cb8ef770f15462f0519ea031f18d413 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2.png.sha1 b/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2.png.sha1 deleted file mode 100644 index 7ae09e85..0000000 --- a/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -51a3652b0cb8ef770f15462f0519ea031f18d413 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT.png.sha1 b/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT.png.sha1 index 0c52ec4..63e9db8 100644 --- a/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT.png.sha1
@@ -1 +1 @@ -3e66510f6e69fdb7d266853f790053f92bb45bf3 \ No newline at end of file +436236cc943f42618bc1d415957f6c71a4918893 \ No newline at end of file
diff --git a/ash/capture_mode/sunfish_unittest.cc b/ash/capture_mode/sunfish_unittest.cc index a790fe6..ad8cf174 100644 --- a/ash/capture_mode/sunfish_unittest.cc +++ b/ash/capture_mode/sunfish_unittest.cc
@@ -1687,6 +1687,7 @@ // Tests that the sunfish launcher nudge appears and closes properly in // clamshell mode. TEST_F(SunfishTest, ClamshellLauncherNudge) { + AppListControllerImpl::SetSunfishNudgeDisabledForTest(false); // Advance clock so we aren't at zero time. task_environment()->AdvanceClock(base::Hours(25)); @@ -1716,6 +1717,7 @@ // Tests that the sunfish launcher nudge appears and closes properly in // tablet mode. TEST_F(SunfishTest, TabletLauncherNudge) { + AppListControllerImpl::SetSunfishNudgeDisabledForTest(false); // Advance clock so we aren't at zero time. task_environment()->AdvanceClock(base::Hours(25)); @@ -1746,6 +1748,7 @@ // Tests that the sunfish nudge only appears three times at most, with at least // 24 hours between showings. TEST_F(SunfishTest, LauncherNudgeLimits) { + AppListControllerImpl::SetSunfishNudgeDisabledForTest(false); // Advance clock so we aren't at zero time. task_environment()->AdvanceClock(base::Hours(25));
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index ce081a46..7d79e629 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1875,7 +1875,7 @@ // Settings Calendar. BASE_FEATURE(kMultiCalendarSupport, "MultiCalendarSupport", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables multi-zone rgb keyboard customization. BASE_FEATURE(kMultiZoneRgbKeyboard, @@ -3115,10 +3115,10 @@ "WelcomeTourHoldbackArm", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables the Welcome Tour V2 that has different strings and steps than V1. +// Enables the Welcome Tour V3 that has different strings and steps than V1. // Enabling this flag has no effect unless `kWelcomeTour` is also enabled. -BASE_FEATURE(kWelcomeTourV2, - "WelcomeTourV2", +BASE_FEATURE(kWelcomeTourV3, + "WelcomeTourV3", base::FEATURE_DISABLED_BY_DEFAULT); // Controls whether to enable MAC Address Randomization on WiFi connection. @@ -3247,6 +3247,10 @@ "DeferConciergeStartup", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kEnableDozeModePowerScheduler, + "EnableDozeModePowerScheduler", + base::FEATURE_ENABLED_BY_DEFAULT); + //////////////////////////////////////////////////////////////////////////////// bool AreDesksTemplatesEnabled() { @@ -3476,6 +3480,10 @@ return base::FeatureList::IsEnabled(kDeskTemplateSync); } +bool IsDozeModePowerSchedulerEnabled() { + return base::FeatureList::IsEnabled(kEnableDozeModePowerScheduler); +} + bool IsDisplayPerformanceModeEnabled() { return base::FeatureList::IsEnabled(kDisplayPerformanceMode); } @@ -4669,8 +4677,8 @@ base::FeatureList::IsEnabled(kWelcomeTourHoldbackArm); } -bool IsWelcomeTourV2Enabled() { - return IsWelcomeTourEnabled() && base::FeatureList::IsEnabled(kWelcomeTourV2); +bool IsWelcomeTourV3Enabled() { + return IsWelcomeTourEnabled() && base::FeatureList::IsEnabled(kWelcomeTourV3); } bool IsWifiConcurrencyEnabled() {
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index e9c95f32..bc292bad 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -220,6 +220,8 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableBrightnessControlInSettings); COMPONENT_EXPORT(ASH_CONSTANTS) +BASE_DECLARE_FEATURE(kEnableDozeModePowerScheduler); +COMPONENT_EXPORT(ASH_CONSTANTS) COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableExternalKeyboardsInDiagnostics); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kEnableFilesAppCopyImage); @@ -991,7 +993,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kWelcomeTourHoldbackArm); COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kWelcomeTourV2); +BASE_DECLARE_FEATURE(kWelcomeTourV3); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kWifiConnectMacAddressRandomization); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kWifiConcurrency); @@ -1077,6 +1079,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPeripheralCustomizationEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPeripheralsLoggingEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsDisplayAlignmentAssistanceEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsDozeModePowerSchedulerEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsDriveFsMirroringEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) int GetDriveFsBulkPinningQueueSize(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsEapGtcWifiAuthenticationEnabled(); @@ -1410,7 +1413,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourForceUserEligibilityEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourHoldbackEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourV2Enabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWelcomeTourV3Enabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWifiConcurrencyEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWifiDirectEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsWifiSyncAndroidEnabled();
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h index df654ccb..28393d3 100644 --- a/ash/constants/ash_pref_names.h +++ b/ash/constants/ash_pref_names.h
@@ -912,6 +912,49 @@ // should be dampened by during a precision click. inline constexpr char kAccessibilityFaceGazePrecisionClickSpeedFactor[] = "settings.a11y.face_gaze.precision_click_speed_factor"; +// A boolean pref which indicates when a request has been made to change the +// FaceGaze enabled state. This pref acts a sentinel for the requested state. +// The feature uses this pref to determine whether FaceGaze should be 1) enabled +// 2) disabled, or 3) a dialog needs to be shown to confirm whether the user +// wants to disable the feature. Using a separate sentinel pref to store the +// requested state here ensures the kAccessibilityFaceGazeEnabled pref always +// accurately reflects the feature state, specifically in the case where the +// sentinel pref is set to false and the behavior pref must remain true until +// the confirmation dialog is accepted or cancelled. This is to ensure the user +// can interact with the dialog with FaceGaze as expected. In all other +// scenarios, the behavior pref and sentinel pref are kept in sync. +inline constexpr char kAccessibilityFaceGazeEnabledSentinel[] = + "settings.a11y.face_gaze.enabled_sentinel"; +// A boolean pref which indicates whether the confirmation dialog should be +// shown when kAccessibilityFaceGazeEnabledSentinel is set to false. +inline constexpr char kAccessibilityFaceGazeEnabledSentinelShowDialog[] = + "settings.a11y.face_gaze.enabled_sentinel_show_dialog"; +// A boolean pref which indicates the requested enabled state for FaceGaze +// cursor control. This pref acts as a sentinel for the requested cursor control +// state. The feature uses this pref to determine whether cursor control should +// be 1) enabled or 2) a dialog needs to be shown to confirm whether the user +// wants to disable the feature. Using a separate sentinel pref to store the +// requested state here ensures the kAccessibilityFaceGazeCursorControlEnabled +// pref always accurately reflects the feature state, specifically in the case +// where the sentinel pref is set to false and the behavior pref must remain +// true until the confirmation dialog is accepted or cancelled. This is to +// ensure the user can interact with the dialog with FaceGaze as expected. In +// all other scenarios, the behavior pref and sentinel pref are kept in sync. +inline constexpr char kAccessibilityFaceGazeCursorControlEnabledSentinel[] = + "settings.a11y.face_gaze.cursor_control_enabled_sentinel"; +// A boolean pref which indicates the requested enabled state for FaceGaze +// actions. This pref acts as a sentinel for the requested actions +// state. The feature uses this pref to determine whether actions should +// be 1) enabled or 2) a dialog needs to be shown to confirm whether the user +// wants to disable the feature. Using a separate sentinel pref to store the +// requested state here ensures the kAccessibilityFaceGazeActionsEnabled pref +// always accurately reflects the feature state, specifically in the case where +// the sentinel pref is set to false and the behavior pref must remain true +// until the confirmation dialog is accepted or cancelled. This is to ensure the +// user can interact with the dialog with FaceGaze as expected. In all other +// scenarios, the behavior pref and sentinel pref are kept in sync. +inline constexpr char kAccessibilityFaceGazeActionsEnabledSentinel[] = + "settings.a11y.face_gaze.actions_enabled_sentinel"; // A boolean pref which determines whether the accessibility menu shows // regardless of the state of a11y features.
diff --git a/ash/shelf/back_button.cc b/ash/shelf/back_button.cc index c749ed7..63f05832 100644 --- a/ash/shelf/back_button.cc +++ b/ash/shelf/back_button.cc
@@ -14,6 +14,7 @@ #include "ash/wm/window_util.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/l10n/l10n_util.h" @@ -34,9 +35,14 @@ BackButton::~BackButton() {} void BackButton::HandleLocaleChange() { + ax_name_change_subscription_ = + GetViewAccessibility().AddStringAttributeChangedCallback( + ax::mojom::StringAttribute::kName, + base::BindRepeating(&BackButton::OnAXNameChanged, + base::Unretained(this))); + GetViewAccessibility().SetName( l10n_util::GetStringUTF16(IDS_ASH_SHELF_BACK_BUTTON_TITLE)); - TooltipTextChanged(); } void BackButton::PaintButtonContents(gfx::Canvas* canvas) { @@ -50,10 +56,6 @@ GetCenterPoint().y() - img.height() / 2); } -std::u16string BackButton::GetTooltipText(const gfx::Point& p) const { - return GetViewAccessibility().GetCachedName(); -} - void BackButton::OnShelfButtonAboutToRequestFocusFromTabTraversal( ShelfButton* button, bool reverse) { @@ -90,6 +92,11 @@ SchedulePaint(); } +void BackButton::OnAXNameChanged(ax::mojom::StringAttribute attribute, + const std::optional<std::string>& name) { + SetCachedTooltipText(GetViewAccessibility().GetCachedName()); +} + BEGIN_METADATA(BackButton) END_METADATA
diff --git a/ash/shelf/back_button.h b/ash/shelf/back_button.h index ea8f54b..4d05774 100644 --- a/ash/shelf/back_button.h +++ b/ash/shelf/back_button.h
@@ -10,6 +10,7 @@ #include "ash/ash_export.h" #include "ash/shelf/shelf_button_delegate.h" #include "ash/shelf/shelf_control_button.h" +#include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/base/metadata/metadata_header_macros.h" namespace ash { @@ -37,7 +38,6 @@ // views::Button: void PaintButtonContents(gfx::Canvas* canvas) override; - std::u16string GetTooltipText(const gfx::Point& p) const override; // views::View: void OnThemeChanged() override; @@ -49,6 +49,12 @@ void ButtonPressed(views::Button* sender, const ui::Event& event, views::InkDrop* ink_drop) override; + + private: + void OnAXNameChanged(ax::mojom::StringAttribute attribute, + const std::optional<std::string>& name); + + base::CallbackListSubscription ax_name_change_subscription_; }; } // namespace ash
diff --git a/ash/system/audio/mic_gain_slider_view.cc b/ash/system/audio/mic_gain_slider_view.cc index aab7e99..23a03b89 100644 --- a/ash/system/audio/mic_gain_slider_view.cc +++ b/ash/system/audio/mic_gain_slider_view.cc
@@ -92,8 +92,14 @@ void MicGainSliderView::Update(bool by_user) { auto* audio_handler = CrasAudioHandler::Get(); + if (!audio_handler) { + return; + } uint64_t active_device_id = audio_handler->GetPrimaryActiveInputNode(); auto* active_device = audio_handler->GetDeviceFromId(active_device_id); + if (!active_device) { + return; + } // For device that has dual internal mics, a new device will be created to // show only one slider for both the internal mics, and the new device has a @@ -151,6 +157,9 @@ // For active internal mic stub, `show_internal_stub` indicates whether it's // showing and `device_id_` doesn't match with `active_device_id`. const bool is_active = show_internal_stub || active_device_id == device_id_; + if (!slider()) { + return; + } auto* qs_slider = static_cast<QuickSettingsSlider*>(slider()); const Style slider_style = qs_slider->slider_style(); // The default style is for the slider in the toast, and the radio style is @@ -166,6 +175,9 @@ is_active ? (is_muted ? Style::kRadioActiveMuted : Style::kRadioActive) : Style::kRadioInactive); } + if (!slider_button()) { + return; + } slider_button()->SetVectorIcon(is_muted ? kMutedMicrophoneIcon : kImeMenuMicrophoneIcon); slider_button()->SetIconColor(
diff --git a/ash/system/notification_center/notification_center_tray.cc b/ash/system/notification_center/notification_center_tray.cc index cb926c49..ee6fc5f 100644 --- a/ash/system/notification_center/notification_center_tray.cc +++ b/ash/system/notification_center/notification_center_tray.cc
@@ -14,16 +14,18 @@ #include "ash/shelf/shelf.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/notification_center/notification_center_bubble.h" -#include "ash/system/notification_center/views/notification_center_view.h" #include "ash/system/notification_center/notification_metrics_recorder.h" +#include "ash/system/notification_center/views/notification_center_view.h" #include "ash/system/privacy/privacy_indicators_tray_item_view.h" #include "ash/system/tray/tray_background_view.h" #include "ash/system/tray/tray_bubble_view.h" #include "ash/system/tray/tray_container.h" +#include "ash/system/unified/notification_counter_view.h" #include "chromeos/constants/chromeos_features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/display/screen.h" +#include "ui/views/accessibility/view_accessibility.h" namespace ash { @@ -51,6 +53,8 @@ /*main_axis_margin=*/kUnifiedTrayContentPadding - ShelfConfig::Get()->status_area_hit_region_padding(), 0); + + UpdateAccessibleName(); } NotificationCenterTray::~NotificationCenterTray() { @@ -84,6 +88,14 @@ UpdateVisibility(); } +void NotificationCenterTray::AddTooltipChangedCallbackToNotificationIcon( + NotificationIconTrayItemView* tray_item) { + notification_icon_image_tooltip_changed_subscriptions_.push_back( + tray_item->image_view()->AddTooltipTextChangedCallback( + base::BindRepeating(&NotificationCenterTray::UpdateAccessibleName, + base::Unretained(this)))); +} + void NotificationCenterTray::OnSystemTrayVisibilityChanged( bool system_tray_visible) { system_tray_visible_ = system_tray_visible; @@ -136,6 +148,9 @@ observer.OnAllTrayItemsAdded(); } + // Now that the NotificationTrayItem objects are created, add callbacks. + AddCallbacksForAccessibility(); + // Update this tray's visibility as well as the visibility of all of its tray // items according to the current state of notifications. UpdateVisibility(); @@ -147,11 +162,6 @@ return l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_ACCESSIBLE_NAME); } -std::u16string NotificationCenterTray::GetAccessibleNameForTray() { - return notification_icons_controller_->GetAccessibleNameString().value_or( - l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_ACCESSIBLE_NAME)); -} - void NotificationCenterTray::HandleLocaleChange() {} void NotificationCenterTray::HideBubbleWithView( @@ -249,6 +259,34 @@ } } +void NotificationCenterTray::UpdateAccessibleName() { + std::u16string name = + notification_icons_controller_->GetAccessibleNameString().value_or( + l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_ACCESSIBLE_NAME)); + GetViewAccessibility().SetName(name); +} + +void NotificationCenterTray::AddCallbacksForAccessibility() { + notification_counter_image_tooltip_changed_subscription_ = + notification_icons_controller_->notification_counter_view() + ->image_view() + ->AddTooltipTextChangedCallback( + base::BindRepeating(&NotificationCenterTray::UpdateAccessibleName, + base::Unretained(this))); + + quiet_mode_visibility_changed_subscription_ = + notification_icons_controller_->quiet_mode_view() + ->AddVisibleChangedCallback( + base::BindRepeating(&NotificationCenterTray::UpdateAccessibleName, + base::Unretained(this))); + + notification_counter_visibility_changed_subscription_ = + notification_icons_controller_->notification_counter_view() + ->AddVisibleChangedCallback( + base::BindRepeating(&NotificationCenterTray::UpdateAccessibleName, + base::Unretained(this))); +} + BEGIN_METADATA(NotificationCenterTray) END_METADATA
diff --git a/ash/system/notification_center/notification_center_tray.h b/ash/system/notification_center/notification_center_tray.h index a084add..351fe47 100644 --- a/ash/system/notification_center/notification_center_tray.h +++ b/ash/system/notification_center/notification_center_tray.h
@@ -70,10 +70,12 @@ // otherwise. void UpdateVisibility(); + // Update the accessible name of the tray in the ViewAccessibility cache. + void UpdateAccessibleName(); + // TrayBackgroundView: void Initialize() override; std::u16string GetAccessibleNameForBubble() override; - std::u16string GetAccessibleNameForTray() override; void HandleLocaleChange() override; void HideBubbleWithView(const TrayBubbleView* bubble_view) override; void HideBubble(const TrayBubbleView* bubble_view) override; @@ -89,6 +91,11 @@ // ash::TrayItemView::Observer: void OnTrayItemVisibilityAboutToChange(bool target_visibility) override; + // Add a TooltipTextChanged callback on the ImageView associated with the + // tray_item. This impacts the tray's accessible name. + void AddTooltipChangedCallbackToNotificationIcon( + NotificationIconTrayItemView* tray_item); + PrivacyIndicatorsTrayItemView* privacy_indicators_view() { return privacy_indicators_view_; } @@ -112,6 +119,10 @@ friend class NotificationCounterViewTest; friend class NotificationIconsControllerTest; + // Registers callbacks for child View properties that impact the tray's + // accessible properties. + void AddCallbacksForAccessibility(); + // Manages notification grouping. const std::unique_ptr<NotificationGroupingController> notification_grouping_controller_; @@ -138,6 +149,17 @@ bool system_tray_visible_ = true; base::ObserverList<Observer> observers_; + + base::CallbackListSubscription + notification_counter_image_tooltip_changed_subscription_; + + base::CallbackListSubscription quiet_mode_visibility_changed_subscription_; + + base::CallbackListSubscription + notification_counter_visibility_changed_subscription_; + + std::vector<base::CallbackListSubscription> + notification_icon_image_tooltip_changed_subscriptions_; }; } // namespace ash
diff --git a/ash/system/unified/notification_icons_controller.cc b/ash/system/unified/notification_icons_controller.cc index 9258c894..c1463c0 100644 --- a/ash/system/unified/notification_icons_controller.cc +++ b/ash/system/unified/notification_icons_controller.cc
@@ -208,9 +208,11 @@ void NotificationIconsController::AddNotificationTrayItems( TrayContainer* tray_container) { for (int i = 0; i < kMaxNotificationIconsShown; ++i) { - tray_items_.push_back(tray_container->AddChildView( + NotificationIconTrayItemView* tray_item = tray_container->AddChildView( std::make_unique<NotificationIconTrayItemView>(shelf_, - /*controller=*/this))); + /*controller=*/this)); + tray_items_.push_back(tray_item); + notification_center_tray_->AddTooltipChangedCallbackToNotificationIcon(tray_item); } notification_counter_view_ = tray_container->AddChildView( @@ -236,8 +238,13 @@ return quiet_mode_view_->GetAccessibleNameString(); } - if (!TrayItemHasNotification()) + if (!notification_counter_view_) { + return std::nullopt; + } + + if (!TrayItemHasNotification()) { return notification_counter_view_->GetAccessibleNameString(); + } std::vector<std::u16string> status; status.push_back(l10n_util::GetPluralStringFUTF16( @@ -274,6 +281,7 @@ } first_unused_item_index_ = std::distance(tray_items_.rbegin(), tray_it); + notification_center_tray_->UpdateAccessibleName(); for (; tray_it != tray_items_.rend(); ++tray_it) { // Note: It is important to set the visibility before resetting so that the
diff --git a/ash/system/unified/notification_icons_controller_unittest.cc b/ash/system/unified/notification_icons_controller_unittest.cc index 1da854c..a84a58c 100644 --- a/ash/system/unified/notification_icons_controller_unittest.cc +++ b/ash/system/unified/notification_icons_controller_unittest.cc
@@ -12,12 +12,15 @@ #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/vm_camera_mic_constants.h" #include "ash/shelf/shelf.h" +#include "ash/strings/grit/ash_strings.h" #include "ash/system/notification_center/notification_center_tray.h" #include "ash/system/tray/tray_item_view.h" #include "ash/system/unified/notification_counter_view.h" #include "ash/test/ash_test_base.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notification.h" +#include "ui/views/accessibility/view_accessibility.h" namespace ash { @@ -317,4 +320,154 @@ GetNotificationIconsController()->tray_items().back()->GetVisible()); } +// This is a large test that captures the nominal cases that can impact the name +// of the NotificationCenterTray. This test lives in +// NotificationIconsControllerTest and not NotificationCenterTrayTest because +// most of the logic to calculate the tray's accessible name lives in +// |NotificationIconsController::GetAccessibleNameString|. This test looks at +// each part of that function and tests the logic. +TEST_F(NotificationIconsControllerTest, NotificationCenterTrayAccessibleName) { + NotificationCenterTray* tray = + GetPrimaryShelf()->GetStatusAreaWidget()->notification_center_tray(); + NotificationIconsController* controller = GetNotificationIconsController(); + + // In quiet mode, the tray's accessible name should be the same as the + // QuietModeView's tooltip text. + UpdateDisplay("800x700"); + message_center::MessageCenter::Get()->SetQuietMode(true); + EXPECT_TRUE(controller->quiet_mode_view()->GetVisible()); + { + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ( + node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_QUIET_MODE_TOOLTIP)); + } + + // Keep quiet_mode_view object, but set it invisible. Since there are no + // notifications and the NotificationCounterView is not visible, the + // accessible name should be set to the NotificationCenterTray's default + // string option. + message_center::MessageCenter::Get()->SetQuietMode(false); + EXPECT_FALSE(controller->quiet_mode_view()->GetVisible()); + EXPECT_FALSE(controller->notification_counter_view()->GetVisible()); + EXPECT_FALSE(controller->TrayItemHasNotification()); + { + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ( + node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + l10n_util::GetStringUTF16(IDS_ASH_MESSAGE_CENTER_ACCESSIBLE_NAME)); + } + + // Ensure that the accessible name is correctly set when there is a + // notification but the NotificationCounterView is not visible because there + // are fewer than 3 notifications. + AddNotification(true /* is_pinned */, false /* is_critical_warning */); + EXPECT_TRUE(controller->TrayItemHasNotification()); + EXPECT_TRUE(controller->TrayNotificationIconsCount() == 1); + // The status object will hold all the status information that will be + // concatenated into the accessible name. This series of logic is following + // and testing the logic in + // NotificationIconsController::GetAccessibleNameString(). + std::vector<std::u16string> status; + status.push_back(l10n_util::GetPluralStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_IMPORTANT_COUNT_ACCESSIBLE_NAME, + controller->TrayNotificationIconsCount())); + for (NotificationIconTrayItemView* tray_item : controller->tray_items()) { + status.push_back(tray_item->GetAccessibleNameString()); + } + // This is an empty string because NotificationCounterView is not visible. + status.push_back(std::u16string()); + { + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ(node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_ICONS_ACCESSIBLE_NAME, + status, nullptr)); + } + + // Add more notifications, which will make the NotificationCounterView + // visible, to test that the accessible name will be set correctly. + AddNotification(true /* is_pinned */, false /* is_critical_warning */); + AddNotification(true /* is_pinned */, false /* is_critical_warning */); + AddNotification(true /* is_pinned */, false /* is_critical_warning */); + controller->notification_counter_view()->Update(); + // Follow the logic in NotificationIconsController::GetAccessibleNameString(). + { + status = std::vector<std::u16string>(); + status.push_back(l10n_util::GetPluralStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_IMPORTANT_COUNT_ACCESSIBLE_NAME, + controller->TrayNotificationIconsCount())); + for (NotificationIconTrayItemView* tray_item : controller->tray_items()) { + status.push_back(tray_item->GetAccessibleNameString()); + } + status.push_back(l10n_util::GetPluralStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_HIDDEN_COUNT_TOOLTIP, 2)); + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ(node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_ICONS_ACCESSIBLE_NAME, + status, nullptr)); + } + + // Update the tray item tooltip texts for test purposes. + for (NotificationIconTrayItemView* tray_item : controller->tray_items()) { + tray_item->image_view()->SetTooltipText(u"test"); + } + + // Follow the logic in NotificationIconsController::GetAccessibleNameString(). + { + status = std::vector<std::u16string>(); + status.push_back(l10n_util::GetPluralStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_IMPORTANT_COUNT_ACCESSIBLE_NAME, + controller->TrayNotificationIconsCount())); + for (NotificationIconTrayItemView* tray_item : controller->tray_items()) { + status.push_back(tray_item->GetAccessibleNameString()); + } + status.push_back(l10n_util::GetPluralStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_HIDDEN_COUNT_TOOLTIP, 2)); + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ(node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_NOTIFICATIONS_ICONS_ACCESSIBLE_NAME, + status, nullptr)); + } + + message_center::MessageCenter::Get()->RemoveAllNotifications( + /*by_user=*/false, message_center::MessageCenter::RemoveType::ALL); + EXPECT_FALSE(controller->TrayItemHasNotification()); + + // Force visibility of the notification_counter_view() for the purposes of the + // next test. + controller->notification_counter_view()->SetVisible(true); + EXPECT_TRUE(controller->notification_counter_view()->GetVisible()); + + // If there are no notifications but the NotificationCounterView is visible, + // the accessible name should be the same as the NotificationCounterView's + // image tooltip text. + { + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ(node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + controller->notification_counter_view() + ->image_view() + ->GetCachedTooltipText()); + } + + // If the NotificationCounterView's image tooltip text is updated, the tray + // accessible name should match. + controller->notification_counter_view()->image_view()->SetTooltipText( + u"Test"); + { + ui::AXNodeData node_data; + tray->GetViewAccessibility().GetAccessibleNodeData(&node_data); + EXPECT_EQ(node_data.GetString16Attribute(ax::mojom::StringAttribute::kName), + u"Test"); + } +} + } // namespace ash
diff --git a/ash/user_education/welcome_tour/welcome_tour_controller.cc b/ash/user_education/welcome_tour/welcome_tour_controller.cc index 0a08aabf..08426c85 100644 --- a/ash/user_education/welcome_tour/welcome_tour_controller.cc +++ b/ash/user_education/welcome_tour/welcome_tour_controller.cc
@@ -66,9 +66,8 @@ // The singleton instance owned by the `UserEducationController`. WelcomeTourController* g_instance = nullptr; -// Strings. -constexpr char16_t kTotalStepsV1[] = u"5"; -constexpr char16_t kTotalStepsV2[] = u"6"; +// Strings. V3 adds a Files app step, but removes the status area step. +constexpr char16_t kTotalSteps[] = u"5"; // Helpers --------------------------------------------------------------------- @@ -184,11 +183,29 @@ GetMatchingViewInPrimaryRootWindow(kShelfViewElementId)); } +// There are some difference between V1 and V3. Here are the steps in summary. +// V1: +// 0. Optin dialog +// 1. Shelf +// 2. Status area +// 3. Home button +// 4. Search box +// 5. Settings app +// 6. Explore app +// 7. Explore app window +// +// V3: +// 0. Optin dialog +// 1. Shelf +// 2. Home button +// 3. Search box +// 4. Files app +// 5. Settings app +// 6. Explore app +// 7. Explore app window user_education::TutorialDescription WelcomeTourController::GetTutorialDescription() const { const std::u16string product_name = ui::GetChromeOSDeviceName(); - const std::u16string total_steps = - features::IsWelcomeTourV2Enabled() ? kTotalStepsV2 : kTotalStepsV1; int current_step = 1; user_education::TutorialDescription tutorial_description; @@ -219,59 +236,70 @@ /*accessible_name=*/ l10n_util::GetStringFUTF8( IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps), + base::NumberToString16(current_step++), kTotalSteps), /*body_text=*/ l10n_util::GetStringUTF8( IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT))) - .AddCustomNextButton(DefaultNextButtonCallback().Then( - base::BindRepeating(&WelcomeTourController::SetCurrentStep, - weak_ptr_factory_.GetMutableWeakPtr(), - welcome_tour_metrics::Step::kStatusArea)))); + .AddCustomNextButton( + DefaultNextButtonCallback().Then(base::BindRepeating( + &WelcomeTourController::SetCurrentStep, + weak_ptr_factory_.GetMutableWeakPtr(), + features::IsWelcomeTourV3Enabled() + ? welcome_tour_metrics::Step::kHomeButton + : welcome_tour_metrics::Step::kStatusArea)))); - // Wait for "Next" button click before proceeding to the next bubble step. - // NOTE: This event step also ensures that the next bubble step will show on - // the primary display by naming the primary root window's status area. - tutorial_description.steps.emplace_back( - user_education::TutorialDescription::EventStep( - user_education::kHelpBubbleNextButtonClickedEvent, - kShelfViewElementId) - .NameElements(NameMatchingElementInPrimaryRootWindowCallback( - kUnifiedSystemTrayElementId, kUnifiedSystemTrayElementName)) - .InSameContext()); + if (!features::IsWelcomeTourV3Enabled()) { + // Wait for "Next" button click before proceeding to the next bubble step. + // NOTE: This event step also ensures that the next bubble step will show on + // the primary display by naming the primary root window's status area. + tutorial_description.steps.emplace_back( + user_education::TutorialDescription::EventStep( + user_education::kHelpBubbleNextButtonClickedEvent, + kShelfViewElementId) + .NameElements(NameMatchingElementInPrimaryRootWindowCallback( + kUnifiedSystemTrayElementId, kUnifiedSystemTrayElementName)) + .InSameContext()); - // Step 2: Status area. - tutorial_description.steps.emplace_back( - user_education::TutorialDescription::BubbleStep( - kUnifiedSystemTrayElementName) - .SetBubbleArrow(user_education::HelpBubbleArrow::kBottomRight) - .SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT) - .SetExtendedProperties(CreateHelpBubbleExtendedProperties( - HelpBubbleId::kWelcomeTourStatusArea, - /*accessible_name=*/ - l10n_util::GetStringFUTF8( - IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps), - /*body_text=*/ - l10n_util::GetStringUTF8( - IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT))) - .AddCustomNextButton(DefaultNextButtonCallback().Then( - base::BindRepeating(&WelcomeTourController::SetCurrentStep, - weak_ptr_factory_.GetMutableWeakPtr(), - welcome_tour_metrics::Step::kHomeButton))) - .InAnyContext()); + // Step 2 in V1: Status area. + tutorial_description.steps.emplace_back( + user_education::TutorialDescription::BubbleStep( + kUnifiedSystemTrayElementName) + .SetBubbleArrow(user_education::HelpBubbleArrow::kBottomRight) + .SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT) + .SetExtendedProperties(CreateHelpBubbleExtendedProperties( + HelpBubbleId::kWelcomeTourStatusArea, + /*accessible_name=*/ + l10n_util::GetStringFUTF8( + IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME, + base::NumberToString16(current_step++), kTotalSteps), + /*body_text=*/ + l10n_util::GetStringUTF8( + IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT))) + .AddCustomNextButton(DefaultNextButtonCallback().Then( + base::BindRepeating(&WelcomeTourController::SetCurrentStep, + weak_ptr_factory_.GetMutableWeakPtr(), + welcome_tour_metrics::Step::kHomeButton))) + .InAnyContext()); + } // Wait for "Next" button click before proceeding to the next bubble step. // NOTE: This event step also ensures that the next bubble step will show on // the primary display by naming the primary root window's home button. + std::variant<ui::ElementIdentifier, std::string> current_element; + if (features::IsWelcomeTourV3Enabled()) { + current_element = kShelfViewElementId; + } else { + current_element = kUnifiedSystemTrayElementName; + } + tutorial_description.steps.emplace_back( user_education::TutorialDescription::EventStep( - user_education::kHelpBubbleNextButtonClickedEvent, - kUnifiedSystemTrayElementName) + user_education::kHelpBubbleNextButtonClickedEvent, current_element) .NameElements(NameMatchingElementInPrimaryRootWindowCallback( kHomeButtonElementId, kHomeButtonElementName)) .InSameContext()); - // Step 3: Home button. + // Step 3 in V1 and step 2 in V3: Home button. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kHomeButtonElementName) .SetBubbleArrow(user_education::HelpBubbleArrow::kBottomLeft) @@ -281,7 +309,7 @@ /*accessible_name=*/ l10n_util::GetStringFUTF8( IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps, + base::NumberToString16(current_step++), kTotalSteps, product_name), /*body_text=*/ l10n_util::GetStringFUTF8( @@ -303,7 +331,7 @@ welcome_tour_metrics::Step::kSearch))) .InAnyContext()); - // Step 4: Search box. + // Step 4 in V1 and step 3 in V3: Search box. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kSearchBoxViewElementId) .SetBubbleArrow(user_education::HelpBubbleArrow::kTopCenter) @@ -313,7 +341,7 @@ /*accessible_name=*/ l10n_util::GetStringFUTF8( IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps, + base::NumberToString16(current_step++), kTotalSteps, product_name), /*body_text=*/ l10n_util::GetStringFUTF8( @@ -323,7 +351,7 @@ DefaultNextButtonCallback().Then(base::BindRepeating( &WelcomeTourController::SetCurrentStep, weak_ptr_factory_.GetMutableWeakPtr(), - features::IsWelcomeTourV2Enabled() + features::IsWelcomeTourV3Enabled() ? welcome_tour_metrics::Step::kFilesApp : welcome_tour_metrics::Step::kSettingsApp))) .InAnyContext()); @@ -335,8 +363,8 @@ kSearchBoxViewElementId) .InSameContext()); - if (features::IsWelcomeTourV2Enabled()) { - // Step 5 in V2: Files app. + if (features::IsWelcomeTourV3Enabled()) { + // Step 4 in V3: Files app. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kFilesAppElementId) .SetBubbleArrow(user_education::HelpBubbleArrow::kBottomLeft) @@ -346,7 +374,7 @@ /*accessible_name=*/ l10n_util::GetStringFUTF8( IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps), + base::NumberToString16(current_step++), kTotalSteps), /*body_text=*/ l10n_util::GetStringUTF8( IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_BODY_TEXT))) @@ -364,7 +392,7 @@ .InSameContext()); } - // Step 5 in V1 and step 6 in V2: Settings app. + // Step 5: Settings app. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kSettingsAppElementId) .SetBubbleArrow(user_education::HelpBubbleArrow::kBottomLeft) @@ -374,7 +402,7 @@ /*accessible_name=*/ l10n_util::GetStringFUTF8( IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps, + base::NumberToString16(current_step++), kTotalSteps, product_name), /*body_text=*/ l10n_util::GetStringFUTF8( @@ -393,7 +421,7 @@ kSettingsAppElementId) .InSameContext()); - // Step 6 in V1 and step 7 in V2: Explore app. + // Step 6: Explore app. // NOTE: The accessible name is the same as the body text. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kExploreAppElementId) @@ -406,7 +434,7 @@ product_name))) .InSameContext()); - // Step 7 in V1 and step 8 in V2: Explore app window. + // Step 7: Explore app window. // Implemented in `WelcomeTourController::OnWelcomeTourEnded()`. return tutorial_description;
diff --git a/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc b/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc index fb2dc82..c2f85a4 100644 --- a/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc +++ b/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc
@@ -102,8 +102,7 @@ using ElementSpecifier = TutorialDescription::ElementSpecifier; // Strings. -constexpr char16_t kTotalStepsV1[] = u"5"; -constexpr char16_t kTotalStepsV2[] = u"6"; +constexpr char16_t kTotalSteps[] = u"5"; // Actions --------------------------------------------------------------------- @@ -570,31 +569,31 @@ EXPECT_TRUE(ended_future.Wait()); } -// WelcomeTourControllerV2Test ------------------------------------------------- +// WelcomeTourControllerV3Test ------------------------------------------------- // Base class for tests of the `WelcomeTourController` which are concerned with -// the behavior of WelcomeTourV2 experiment arms, parameterized by whether the -// Welcome Tour V2 feature is enabled. -class WelcomeTourControllerV2Test +// the behavior of WelcomeTourV3 experiment arms, parameterized by whether the +// Welcome Tour V3 feature is enabled. +class WelcomeTourControllerV3Test : public WelcomeTourControllerTest, public ::testing::WithParamInterface<std::tuple< - /*is_welcome_tour_v2_enabled=*/bool, + /*is_welcome_tour_v3_enabled=*/bool, /*is_welcome_tour_counterfactually_enabled=*/bool>> { public: - WelcomeTourControllerV2Test() { + WelcomeTourControllerV3Test() { // Only one of those features can be enabled at a time. scoped_feature_list_.InitWithFeatureStates( - {{features::kWelcomeTourV2, - IsWelcomeTourV2Enabled() && !IsWelcomeTourCounterfactuallyEnabled()}, + {{features::kWelcomeTourV3, + IsWelcomeTourV3Enabled() && !IsWelcomeTourCounterfactuallyEnabled()}, {features::kWelcomeTourCounterfactualArm, IsWelcomeTourCounterfactuallyEnabled()}, {features::kWelcomeTourHoldbackArm, false}}); } protected: - // Returns whether the WelcomeTourV2 feature is enabled given test + // Returns whether the WelcomeTourV3 feature is enabled given test // parameterization. - bool IsWelcomeTourV2Enabled() const { return std::get<0>(GetParam()); } + bool IsWelcomeTourV3Enabled() const { return std::get<0>(GetParam()); } // Returns whether the WelcomeTour feature is counterfactually enabled given // test parameterization. @@ -608,19 +607,17 @@ INSTANTIATE_TEST_SUITE_P( All, - WelcomeTourControllerV2Test, + WelcomeTourControllerV3Test, testing::Combine( - /*is_welcome_tour_v2_enabled=*/testing::Bool(), + /*is_welcome_tour_v3_enabled=*/testing::Bool(), /*is_welcome_tour_counterfactually_enabled=*/testing::Bool())); // Verifies that `GetTutorialDescription()` returns expected values. -TEST_P(WelcomeTourControllerV2Test, GetTutorialDescription) { +TEST_P(WelcomeTourControllerV3Test, GetTutorialDescription) { auto* welcome_tour_controller = WelcomeTourController::Get(); ASSERT_TRUE(welcome_tour_controller); const std::u16string product_name = ui::GetChromeOSDeviceName(); - const std::u16string total_steps = - features::IsWelcomeTourV2Enabled() ? kTotalStepsV2 : kTotalStepsV1; int current_step = 1; using ::testing::Matcher; @@ -634,63 +631,73 @@ ElementSpecifier(kShelfViewElementId), ContextMode::kInitial, HelpBubbleId::kWelcomeTourShelf, StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps), + base::NumberToString16(current_step++), kTotalSteps), IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, StringUTF8Eq(IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT), HelpBubbleArrow::kBottomCenter, /*has_next_button=*/true), EventStep(ElementSpecifier(kShelfViewElementId), ContextMode::kFromPreviousStep, - /*has_name_elements_callback=*/true), - BubbleStep( - ElementSpecifier(kUnifiedSystemTrayElementName), ContextMode::kAny, - HelpBubbleId::kWelcomeTourStatusArea, - StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps), - IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, - StringUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT), - HelpBubbleArrow::kBottomRight, - /*has_next_button=*/true), - EventStep(ElementSpecifier(kUnifiedSystemTrayElementName), - ContextMode::kFromPreviousStep, - /*has_name_elements_callback=*/true), - BubbleStep( - ElementSpecifier(kHomeButtonElementName), ContextMode::kAny, - HelpBubbleId::kWelcomeTourHomeButton, - StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps, - product_name), - IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, - StringFUTF8Eq( - (chromeos::GetDeviceType() == chromeos::DeviceType::kChromebook) - ? IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_CHROMEBOOK - : IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_OTHER_DEVICE_TYPES, - product_name), - HelpBubbleArrow::kBottomLeft, - /*has_next_button=*/true), - BubbleStep(ElementSpecifier(kSearchBoxViewElementId), ContextMode::kAny, - HelpBubbleId::kWelcomeTourSearchBox, - StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), - total_steps, product_name), - IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, - StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_BODY_TEXT, - product_name), - HelpBubbleArrow::kTopCenter, - /*has_next_button=*/true), - EventStep(ElementSpecifier(kSearchBoxViewElementId), - ContextMode::kFromPreviousStep, - /*has_name_elements_callback=*/false)}; + /*has_name_elements_callback=*/true)}; - if (features::IsWelcomeTourV2Enabled()) { + if (!features::IsWelcomeTourV3Enabled()) { + // No status area step for V3. expected_steps.insert( expected_steps.end(), - {// Files app step for V2. + {BubbleStep( + ElementSpecifier(kUnifiedSystemTrayElementName), ContextMode::kAny, + HelpBubbleId::kWelcomeTourStatusArea, + StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_ACCNAME, + base::NumberToString16(current_step++), kTotalSteps), + IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, + StringUTF8Eq(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT), + HelpBubbleArrow::kBottomRight, + /*has_next_button=*/true), + EventStep(ElementSpecifier(kUnifiedSystemTrayElementName), + ContextMode::kFromPreviousStep, + /*has_name_elements_callback=*/true)}); + } + + expected_steps.insert( + expected_steps.end(), + {BubbleStep( + ElementSpecifier(kHomeButtonElementName), ContextMode::kAny, + HelpBubbleId::kWelcomeTourHomeButton, + StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_ACCNAME, + base::NumberToString16(current_step++), kTotalSteps, + product_name), + IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, + StringFUTF8Eq( + (chromeos::GetDeviceType() == chromeos::DeviceType::kChromebook) + ? IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_CHROMEBOOK + : IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT_OTHER_DEVICE_TYPES, + product_name), + HelpBubbleArrow::kBottomLeft, + /*has_next_button=*/true), + BubbleStep( + ElementSpecifier(kSearchBoxViewElementId), ContextMode::kAny, + HelpBubbleId::kWelcomeTourSearchBox, + StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_ACCNAME, + base::NumberToString16(current_step++), kTotalSteps, + product_name), + IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, + StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_BODY_TEXT, + product_name), + HelpBubbleArrow::kTopCenter, + /*has_next_button=*/true), + EventStep(ElementSpecifier(kSearchBoxViewElementId), + ContextMode::kFromPreviousStep, + /*has_name_elements_callback=*/false)}); + + if (features::IsWelcomeTourV3Enabled()) { + expected_steps.insert( + expected_steps.end(), + {// Files app step for V3. BubbleStep( ElementSpecifier(kFilesAppElementId), ContextMode::kFromPreviousStep, HelpBubbleId::kWelcomeTourFilesApp, StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps), + base::NumberToString16(current_step++), kTotalSteps), IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, StringUTF8Eq(IDS_ASH_WELCOME_TOUR_FILES_APP_BUBBLE_BODY_TEXT), HelpBubbleArrow::kBottomLeft, @@ -707,7 +714,7 @@ ContextMode::kFromPreviousStep, HelpBubbleId::kWelcomeTourSettingsApp, StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_ACCNAME, - base::NumberToString16(current_step++), total_steps, + base::NumberToString16(current_step++), kTotalSteps, product_name), IDS_ASH_WELCOME_TOUR_OVERRIDDEN_BUBBLE_BODY_TEXT, StringFUTF8Eq(IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_BODY_TEXT, @@ -878,7 +885,7 @@ if (const auto& is_holdback = IsHoldback()) { scoped_feature_list_.InitWithFeatureStates( {{features::kWelcomeTourHoldbackArm, is_holdback.value()}, - {features::kWelcomeTourV2, false}, + {features::kWelcomeTourV3, false}, {features::kWelcomeTourCounterfactualArm, false}}); } }
diff --git a/ash/user_education/welcome_tour/welcome_tour_dialog.cc b/ash/user_education/welcome_tour/welcome_tour_dialog.cc index b71ce01..fba42d5 100644 --- a/ash/user_education/welcome_tour/welcome_tour_dialog.cc +++ b/ash/user_education/welcome_tour/welcome_tour_dialog.cc
@@ -71,7 +71,6 @@ g_instance = this; const std::u16string product_name = ui::GetChromeOSDeviceName(); - bool is_welcome_tour_v2_enabled = features::IsWelcomeTourV2Enabled(); views::Builder<SystemDialogDelegateView>(this) .SetAcceptButtonText(l10n_util::GetStringUTF16( @@ -82,16 +81,11 @@ .SetCancelCallback(std::move(cancel_callback)) .SetCloseCallback(std::move(close_callback)) .SetDescription(l10n_util::GetStringFUTF16( - is_welcome_tour_v2_enabled - ? IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2 - : IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT, - product_name)) + IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT, product_name)) .SetModalType(ui::mojom::ModalType::kSystem) .SetProperty(views::kElementIdentifierKey, kWelcomeTourDialogElementId) .SetTitleText(l10n_util::GetStringFUTF16( - is_welcome_tour_v2_enabled ? IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2 - : IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT, - product_name)) + IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT, product_name)) .SetTopContentView(views::Builder<views::ImageView>() .SetImage(ui::ResourceBundle::GetSharedInstance() .GetThemedLottieImageNamed(
diff --git a/ash/user_education/welcome_tour/welcome_tour_metrics.cc b/ash/user_education/welcome_tour/welcome_tour_metrics.cc index 9b8e395..cbc1fa8 100644 --- a/ash/user_education/welcome_tour/welcome_tour_metrics.cc +++ b/ash/user_education/welcome_tour/welcome_tour_metrics.cc
@@ -45,22 +45,22 @@ // NOTE: Checking feature flag state activates experimental arms. const bool is_holdback_enabled = features::IsWelcomeTourHoldbackEnabled(); const bool is_v1_enabled = features::IsWelcomeTourCounterfactuallyEnabled(); - const bool is_v2_enabled = features::IsWelcomeTourV2Enabled(); + const bool is_v3_enabled = features::IsWelcomeTourV3Enabled(); bool changed_experimental_arm = false; const auto experimental_arm = first_experimental_arm.value(); switch (experimental_arm) { case welcome_tour_metrics::ExperimentalArm::kHoldback: changed_experimental_arm = - !is_holdback_enabled && (is_v1_enabled || is_v2_enabled); + !is_holdback_enabled && (is_v1_enabled || is_v3_enabled); break; case welcome_tour_metrics::ExperimentalArm::kV1: changed_experimental_arm = - !is_v1_enabled && (is_holdback_enabled || is_v2_enabled); + !is_v1_enabled && (is_holdback_enabled || is_v3_enabled); break; - case welcome_tour_metrics::ExperimentalArm::kV2: + case welcome_tour_metrics::ExperimentalArm::kV3: changed_experimental_arm = - !is_v2_enabled && (is_holdback_enabled || is_v1_enabled); + !is_v3_enabled && (is_holdback_enabled || is_v1_enabled); break; } @@ -78,16 +78,16 @@ std::optional<ExperimentalArm> experimental_arm; if (features::IsWelcomeTourCounterfactuallyEnabled()) { CHECK(!features::IsWelcomeTourHoldbackEnabled()); - CHECK(!features::IsWelcomeTourV2Enabled()); + CHECK(!features::IsWelcomeTourV3Enabled()); experimental_arm = ExperimentalArm::kV1; } else if (features::IsWelcomeTourHoldbackEnabled()) { CHECK(!features::IsWelcomeTourCounterfactuallyEnabled()); - CHECK(!features::IsWelcomeTourV2Enabled()); + CHECK(!features::IsWelcomeTourV3Enabled()); experimental_arm = ExperimentalArm::kHoldback; - } else if (features::IsWelcomeTourV2Enabled()) { + } else if (features::IsWelcomeTourV3Enabled()) { CHECK(!features::IsWelcomeTourCounterfactuallyEnabled()); CHECK(!features::IsWelcomeTourHoldbackEnabled()); - experimental_arm = ExperimentalArm::kV2; + experimental_arm = ExperimentalArm::kV3; } if (!experimental_arm) {
diff --git a/ash/user_education/welcome_tour/welcome_tour_metrics.h b/ash/user_education/welcome_tour/welcome_tour_metrics.h index c8dfef3..5a7d816 100644 --- a/ash/user_education/welcome_tour/welcome_tour_metrics.h +++ b/ash/user_education/welcome_tour/welcome_tour_metrics.h
@@ -52,8 +52,9 @@ kMinValue = 0, kHoldback = kMinValue, kV1 = 1, - kV2 = 2, - kMaxValue = kV2, + // kV2 = 2, Deprecated. + kV3 = 3, + kMaxValue = kV3, }; static constexpr auto kAllExperimentalArmsSet = @@ -62,7 +63,7 @@ ExperimentalArm::kMaxValue>({ ExperimentalArm::kHoldback, ExperimentalArm::kV1, - ExperimentalArm::kV2, + ExperimentalArm::kV3, }); // Enumeration of interactions users may engage in after the Welcome Tour. These
diff --git a/ash/user_education/welcome_tour/welcome_tour_metrics_unittest.cc b/ash/user_education/welcome_tour/welcome_tour_metrics_unittest.cc index 45136afc..c484e946 100644 --- a/ash/user_education/welcome_tour/welcome_tour_metrics_unittest.cc +++ b/ash/user_education/welcome_tour/welcome_tour_metrics_unittest.cc
@@ -59,7 +59,7 @@ scoped_feature_list.InitWithFeatureStates( {{features::kWelcomeTourCounterfactualArm, IsV1Enabled()}, {features::kWelcomeTourHoldbackArm, IsHoldbackEnabled()}, - {features::kWelcomeTourV2, IsV2Enabled()}, + {features::kWelcomeTourV3, IsV3Enabled()}, {features::kWelcomeTourForceUserEligibility, true}}); } @@ -77,7 +77,7 @@ bool IsPrefValueV1() const { return GetPrefValue() == ExperimentalArm::kV1; } - bool IsPrefValueV2() const { return GetPrefValue() == ExperimentalArm::kV2; } + bool IsPrefValueV3() const { return GetPrefValue() == ExperimentalArm::kV3; } bool IsHoldbackEnabled() const { return GetEnabledArm() == ExperimentalArm::kHoldback; @@ -85,7 +85,7 @@ bool IsV1Enabled() const { return GetEnabledArm() == ExperimentalArm::kV1; } - bool IsV2Enabled() const { return GetEnabledArm() == ExperimentalArm::kV2; } + bool IsV3Enabled() const { return GetEnabledArm() == ExperimentalArm::kV3; } private: base::test::ScopedFeatureList scoped_feature_list; @@ -99,12 +99,12 @@ ::testing::Values(std::nullopt, std::make_optional(ExperimentalArm::kHoldback), std::make_optional(ExperimentalArm::kV1), - std::make_optional(ExperimentalArm::kV2)), + std::make_optional(ExperimentalArm::kV3)), /*enabled_arm=*/ ::testing::Values(std::nullopt, std::make_optional(ExperimentalArm::kHoldback), std::make_optional(ExperimentalArm::kV1), - std::make_optional(ExperimentalArm::kV2)))); + std::make_optional(ExperimentalArm::kV3)))); // Tests ----------------------------------------------------------------------- @@ -161,7 +161,7 @@ scoped_feature_list.InitWithFeatureStates( {{features::kWelcomeTourCounterfactualArm, IsV1Enabled()}, {features::kWelcomeTourHoldbackArm, IsHoldbackEnabled()}, - {features::kWelcomeTourV2, IsV2Enabled()}, + {features::kWelcomeTourV3, IsV3Enabled()}, {features::kWelcomeTourForceUserEligibility, true}}); } @@ -173,7 +173,7 @@ bool IsV1Enabled() const { return GetEnabledArm() == ExperimentalArm::kV1; } - bool IsV2Enabled() const { return GetEnabledArm() == ExperimentalArm::kV2; } + bool IsV3Enabled() const { return GetEnabledArm() == ExperimentalArm::kV3; } private: base::test::ScopedFeatureList scoped_feature_list; @@ -186,7 +186,7 @@ ::testing::Values(std::nullopt, std::make_optional(ExperimentalArm::kHoldback), std::make_optional(ExperimentalArm::kV1), - std::make_optional(ExperimentalArm::kV2))); + std::make_optional(ExperimentalArm::kV3))); // Tests ----------------------------------------------------------------------- @@ -225,7 +225,7 @@ // Only one of those features can be enabled at a time. scoped_feature_list.InitWithFeatureStates( {{features::kWelcomeTourHoldbackArm, IsHoldback()}, - {features::kWelcomeTourV2, false}, + {features::kWelcomeTourV3, false}, {features::kWelcomeTourCounterfactualArm, false}}); } @@ -377,7 +377,7 @@ switch (arm) { case ExperimentalArm::kHoldback: case ExperimentalArm::kV1: - case ExperimentalArm::kV2: + case ExperimentalArm::kV3: should_exist_in_all_set = true; }
diff --git a/ash/user_education/welcome_tour/welcome_tour_prefs.cc b/ash/user_education/welcome_tour/welcome_tour_prefs.cc index 8495a890b..3d18a56 100644 --- a/ash/user_education/welcome_tour/welcome_tour_prefs.cc +++ b/ash/user_education/welcome_tour/welcome_tour_prefs.cc
@@ -29,6 +29,8 @@ // static constexpr char kReasonForFirstTourPrevention[] = // "ash.welcome_tour.prevented.first_reason"; +// We will reuse the `v2` prefs for `v3` since there is no conflict. +// TODO: crbug.com/353568276 - Clean up the prefs after full launch. static constexpr char kFirstExperimentalArm[] = "ash.welcome_tour.v2.experimental_arm.first"; static constexpr char kTimeOfFirstInteractionPrefPrefix[] =
diff --git a/ash/user_education/welcome_tour/welcome_tour_prefs_unittest.cc b/ash/user_education/welcome_tour/welcome_tour_prefs_unittest.cc index 7b9415b1..cf2d2aad 100644 --- a/ash/user_education/welcome_tour/welcome_tour_prefs_unittest.cc +++ b/ash/user_education/welcome_tour/welcome_tour_prefs_unittest.cc
@@ -104,7 +104,7 @@ // For any call beyond the first, the function should return false and the // marked first experimental arm should not change. - EXPECT_FALSE(MarkFirstExperimentalArm(pref_service(), ExperimentalArm::kV2)); + EXPECT_FALSE(MarkFirstExperimentalArm(pref_service(), ExperimentalArm::kV3)); EXPECT_EQ(GetFirstExperimentalArm(pref_service()), ExperimentalArm::kHoldback); }
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.html b/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.html index 42f8d1aa..17207bd3 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.html +++ b/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.html
@@ -6,12 +6,9 @@ margin-inline-start: calc(var(--personalization-app-grid-item-spacing) / 2); } - #heading { - margin-bottom: 18px; - } - - #heading:has(#tabContainer) { - margin-bottom: 0px; + #headingMargin { + /* The margin should only appear when the tab buttons are not visible. */ + height: 18px; } #tabContainer cr-button { @@ -26,7 +23,7 @@ } /* This pseudo-element is the line above the selected tab. */ - #tabContainer cr-button[aria-pressed='true']::before { + #tabContainer cr-button[aria-selected='true']::before { background-color: var(--cros-sys-primary); border-radius: 0 0 4px 4px; /* content has a zero-width space so the line is visible. */ @@ -37,11 +34,11 @@ width: 80%; } - #tabContainer cr-button[aria-pressed='false'] { + #tabContainer cr-button[aria-selected='false'] { color: var(--cros-text-color-secondary); } - #tabContainer cr-button[aria-pressed='false']:hover { + #tabContainer cr-button[aria-selected='false']:hover { background-color: var(--cros-sys-hover_on_subtle); } @@ -82,44 +79,58 @@ } </style> <div id="heading"> - <template is="dom-if" if="[[isTabContainerEnabled_(seaPenQuery_, thumbnailResponseStatusCode_)]]" restamp> - <div id="tabContainer"> - <cr-button id="resultsTab" - aria-pressed="[[isResultsTabSelected_(freeformTab_)]]" - on-click="onTabSelected_"> - <div class="text">[[i18n('seaPenFreeformResultsLabel')]]</div> - </cr-button> - <cr-button id="samplePromptsTab" - aria-pressed="[[isSamplePromptsTabSelected_(freeformTab_)]]" - on-click="onTabSelected_"> - <div class="text">[[i18n('seaPenFreeformSamplePromptsLabel')]]</div> - </cr-button> - </div> - </template> + <iron-a11y-keys id="tabKeys" keys="left right" on-keys-pressed="onTabKeysPressed_"> + </iron-a11y-keys> + <div + id="tabContainer" + hidden="[[isTabContainerHidden_(seaPenQuery_, thumbnailResponseStatusCode_)]]" + role="tablist"> + <cr-button id="resultsTab" + aria-selected="[[isResultsTabSelected_(freeformTab_)]]" + class="tab" + on-click="onTabSelected_" + role="tab" + tabindex$="[[getResultsTabIndex_(freeformTab_)]]"> + <div class="text">[[i18n('seaPenFreeformResultsLabel')]]</div> + </cr-button> + <cr-button id="samplePromptsTab" + aria-selected="[[isSamplePromptsTabSelected_(freeformTab_)]]" + class="tab" + on-click="onTabSelected_" + role="tab" + tabindex$="[[getSamplePromptsTabIndex_(freeformTab_)]]"> + <div class="text">[[i18n('seaPenFreeformSamplePromptsLabel')]]</div> + </cr-button> + </div> + <div id="headingMargin" + hidden="[[!isTabContainerHidden_(seaPenQuery_, thumbnailResponseStatusCode_)]]"> + </div> <template is="dom-if" if="[[!isSamplePromptsTabSelected_(freeformTab_)]]"> <h2 id="seaPenImagesHeading" class="wallpaper-collections-heading"> [[i18n('seaPenFreeformPoweredByGoogle')]] </h2> </template> </div> -<div id="samplePromptHeading"> - <template is="dom-if" if="[[isSamplePromptsTabSelected_(freeformTab_)]]"> - <div id="promptingGuide" - inner-h-t-m-l="[[i18nAdvanced('seaPenFreeformPromptingGuide')]]"> - </div> - <cr-button - id="shuffle" - on-click="onShuffleClicked_"> - <iron-icon icon="personalization-shared:refresh" slot="prefix-icon"> - </iron-icon> - <p>[[i18n('seaPenFreeformShuffle')]]</p> - </cr-button> - </template> -</div> <template is="dom-if" if="[[isSamplePromptsTabSelected_(freeformTab_)]]" restamp> - <sea-pen-samples samples="[[samples]]"></sea-pen-samples> - <sea-pen-recent-wallpapers></sea-pen-recent-wallpapers> + <div id="samplePromptsContainer" role="tabpanel"> + <div id="samplePromptHeading"> + <div id="promptingGuide" + inner-h-t-m-l="[[i18nAdvanced('seaPenFreeformPromptingGuide')]]"> + </div> + <cr-button + id="shuffle" + on-click="onShuffleClicked_"> + <iron-icon icon="personalization-shared:refresh" slot="prefix-icon"> + </iron-icon> + <p>[[i18n('seaPenFreeformShuffle')]]</p> + </cr-button> + </div> + <sea-pen-samples samples="[[samples]]"></sea-pen-samples> + <sea-pen-recent-wallpapers></sea-pen-recent-wallpapers> + </div> </template> <template is="dom-if" if="[[isResultsTabSelected_(freeformTab_)]]" restamp> - <sea-pen-images template-id="Query"></sea-pen-images> + <div id="seaPenImagesContainer" role="tabpanel"> + <sea-pen-images template-id="Query"></sea-pen-images> + </div> </template>
diff --git a/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.ts b/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.ts index 644bd839..bfc7d68 100644 --- a/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.ts +++ b/ash/webui/common/resources/sea_pen/sea_pen_freeform_element.ts
@@ -12,6 +12,7 @@ import 'chrome://resources/ash/common/personalization/wallpaper.css.js'; import {assertNotReached} from 'chrome://resources/js/assert.js'; +import {IronA11yKeysElement} from 'chrome://resources/polymer/v3_0/iron-a11y-keys/iron-a11y-keys.js'; import {FreeformTab, SeaPenSamplePrompt} from './constants.js'; import {MantaStatusCode, SeaPenQuery} from './sea_pen.mojom-webui.js'; @@ -21,6 +22,15 @@ import {SEA_PEN_SAMPLES} from './sea_pen_untranslated_constants.js'; import {isArrayEqual, shuffle} from './sea_pen_utils.js'; +export interface SeaPenFreeformElement { + $: { + samplePromptsTab: HTMLElement, + resultsTab: HTMLElement, + tabContainer: HTMLElement, + tabKeys: IronA11yKeysElement, + } +} + export class SeaPenFreeformElement extends WithSeaPenStore { static get is() { return 'sea-pen-freeform'; @@ -67,6 +77,7 @@ state => state.thumbnailResponseStatusCode); this.updateFromStore(); this.shuffleSamplePrompts_(); + this.$.tabKeys.target = this.$.tabContainer; } /** Invoked on tab selected. */ @@ -85,6 +96,22 @@ logSeaPenFreeformTabClicked(this.freeformTab_); } + /** Handle keyboard navigation. */ + private onTabKeysPressed_(e: CustomEvent) { + const focusedElement = this.shadowRoot!.activeElement; + // Remove focus state of focused tab. + focusedElement?.removeAttribute('tabindex'); + + const nextTab = this.getOtherTab_(focusedElement) + if (nextTab) { + // Add focus state for next tab. + nextTab.setAttribute('tabindex', '0'); + nextTab.focus(); + } + + e.detail.keyboardEvent.preventDefault(); + } + private onSeaPenQueryChanged_(query: SeaPenQuery|null) { // Update selected tab to Results tab once a freeform query search starts. // Otherwise, stay in Sample Prompts tab. @@ -99,10 +126,10 @@ } } - private isTabContainerEnabled_( + private isTabContainerHidden_( query: SeaPenQuery, thumbnailResponseStatusCode: MantaStatusCode|null): boolean { - return !!query?.textQuery || !!thumbnailResponseStatusCode; + return !query?.textQuery && !thumbnailResponseStatusCode; } private isSamplePromptsTabSelected_(tab: FreeformTab): boolean { @@ -113,6 +140,24 @@ return tab === FreeformTab.RESULTS; } + private getSamplePromptsTabIndex_(tab: FreeformTab): string { + return this.isSamplePromptsTabSelected_(tab) ? '0' : '-1' + } + + private getResultsTabIndex_(tab: FreeformTab): string { + return this.isResultsTabSelected_(tab) ? '0' : '-1' + } + + private getOtherTab_(element: Element|null): HTMLElement|null { + if (element === this.$.resultsTab) { + return this.$.samplePromptsTab; + } + if (element === this.$.samplePromptsTab) { + return this.$.resultsTab; + } + return null; + } + private onShuffleClicked_(): void { logSamplePromptShuffleClicked(); this.shuffleSamplePrompts_();
diff --git a/ash/webui/scanner_feedback_ui/BUILD.gn b/ash/webui/scanner_feedback_ui/BUILD.gn new file mode 100644 index 0000000..d487db2 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/BUILD.gn
@@ -0,0 +1,27 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chromeos/ui_mode.gni") + +assert(is_chromeos_ash, "Scanner is ash-chrome only") + +static_library("scanner_feedback_ui") { + sources = [ + "scanner_feedback_untrusted_ui.cc", + "scanner_feedback_untrusted_ui.h", + "url_constants.h", + ] + + deps = [ + "//ash/constants", + "//ash/webui/common:trusted_types_util", + "//ash/webui/scanner_feedback_ui/resources", + "//content/public/browser", + ] + + public_deps = [ + "//ash/webui/common:chrome_os_webui_config", + "//ui/webui", + ] +}
diff --git a/ash/webui/scanner_feedback_ui/OWNERS b/ash/webui/scanner_feedback_ui/OWNERS new file mode 100644 index 0000000..56e138c9 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/OWNERS
@@ -0,0 +1 @@ +file://ash/scanner/OWNERS
diff --git a/ash/webui/scanner_feedback_ui/resources/.gitignore b/ash/webui/scanner_feedback_ui/resources/.gitignore new file mode 100644 index 0000000..62cc30ab --- /dev/null +++ b/ash/webui/scanner_feedback_ui/resources/.gitignore
@@ -0,0 +1,2 @@ +# Generated by various developer tools. +/tsconfig.json
diff --git a/ash/webui/scanner_feedback_ui/resources/BUILD.gn b/ash/webui/scanner_feedback_ui/resources/BUILD.gn new file mode 100644 index 0000000..b6b8a92 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/resources/BUILD.gn
@@ -0,0 +1,30 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chromeos/ui_mode.gni") +import("//ui/webui/resources/tools/build_webui.gni") + +assert(is_chromeos_ash) + +build_webui("build") { + grd_prefix = "ash_scanner_feedback_ui" + + static_files = [ + "index.html", + "index.css", + ] + + web_component_files = [ "app.ts" ] + + ts_deps = [ + "//third_party/cros-components:cros_components_ts", + "//third_party/polymer/v3_0:library", + ] + + ts_composite = true + + webui_context_type = "untrusted" + + grit_output_dir = "$root_gen_dir/ash/webui" +}
diff --git a/ash/webui/scanner_feedback_ui/resources/app.html b/ash/webui/scanner_feedback_ui/resources/app.html new file mode 100644 index 0000000..eac703c --- /dev/null +++ b/ash/webui/scanner_feedback_ui/resources/app.html
@@ -0,0 +1,4 @@ +<mako-orca-feedback + string-source="[[stringSource]]" + open-url="[[openUrl]]" + ></mako-orca-feedback>
diff --git a/ash/webui/scanner_feedback_ui/resources/app.ts b/ash/webui/scanner_feedback_ui/resources/app.ts new file mode 100644 index 0000000..2ed05465 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/resources/app.ts
@@ -0,0 +1,69 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '//resources/cros_components/orca_feedback/orca-feedback.js'; + +import type {OrcaFeedback} from '//resources/cros_components/orca_feedback/orca-feedback.js'; +import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './app.html.js'; + +// `StringSource` is not exported from orca-feedback.js, so get a reference to +// it via `OrcaFeedback`. +type StringSource = NonNullable<OrcaFeedback['stringSource']>; + +const STRING_SOURCE: StringSource = { + getAriaLabelForLink(linkText: string): string { + return `ARIA LABEL FOR ${linkText}`; + }, + MSG_FEEDBACK_TITLE: 'FEEDBACK TITLE', + MSG_FEEDBACK_SUBTITLE: 'FEEDBACK SUBTITLE', + MSG_FEEDBACK_QUESTION: 'FEEDBACK QUESTION', + MSG_FEEDBACK_QUESTION_PLACEHOLDER: 'FEEDBACK QUESTION PLACEHOLDER', + MSG_OFFENSIVE_OR_UNSAFE: 'OFFENSIVE OR UNSAFE', + MSG_FACTUALLY_INCORRECT: 'FACTUALLY INCORRECT', + MSG_LEGAL_ISSUE: 'LEGAL ISSUE', + getFeedbackDisclaimer( + linkPolicyBegin: string, linkPolicyEnd: string, + linkTermsOfServiceBegin: string, linkTermsOfServiceEnd: string): string { + return `FEEDBACK DISCLAIMER ${linkPolicyBegin}POLICY${linkPolicyEnd} ${ + linkTermsOfServiceBegin}TERMS OF SERVICE${linkTermsOfServiceEnd}`; + }, + MSG_PRIVACY_POLICY: 'PRIVACY POLICY', + MSG_TERMS_OF_SERVICE: 'TERMS OF SERVICE', + MSG_CANCEL: 'CANCEL', + MSG_SEND: 'SEND' +}; + +export class ScannerFeedbackAppElement extends PolymerElement { + static get is() { + return 'scanner-feedback-app' as const; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + // Private properties: + stringSource: Object, + openUrl: Object, + }; + } + + private readonly stringSource = STRING_SOURCE; + private readonly openUrl = (url: string) => { + window.open(url, '_blank'); + // TODO: b/382562555 - Close the dialog after opening the URL. + }; +} + +declare global { + interface HTMLElementTagNameMap { + [ScannerFeedbackAppElement.is]: ScannerFeedbackAppElement; + } +} + +customElements.define(ScannerFeedbackAppElement.is, ScannerFeedbackAppElement);
diff --git a/ash/webui/scanner_feedback_ui/resources/index.css b/ash/webui/scanner_feedback_ui/resources/index.css new file mode 100644 index 0000000..62d3185 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/resources/index.css
@@ -0,0 +1,7 @@ +/* Copyright 2024 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +body { + margin: 0; +}
diff --git a/ash/webui/scanner_feedback_ui/resources/index.html b/ash/webui/scanner_feedback_ui/resources/index.html new file mode 100644 index 0000000..552b9a2 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/resources/index.html
@@ -0,0 +1,12 @@ +<!-- +Copyright 2024 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<!DOCTYPE HTML> +<html> + <meta charset="utf-8"> + <link rel="stylesheet" href="index.css"> + <scanner-feedback-app></scanner-feedback-app> + <script type="module" src="app.js"></script> +</html>
diff --git a/ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.cc b/ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.cc new file mode 100644 index 0000000..3635ee3 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.cc
@@ -0,0 +1,70 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.h" + +#include <string> + +#include "ash/constants/ash_features.h" +#include "ash/webui/common/chrome_os_webui_config.h" +#include "ash/webui/common/trusted_types_util.h" +#include "ash/webui/grit/ash_scanner_feedback_ui_resources.h" +#include "ash/webui/grit/ash_scanner_feedback_ui_resources_map.h" +#include "ash/webui/scanner_feedback_ui/url_constants.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/common/url_constants.h" +#include "ui/webui/untrusted_web_ui_controller.h" + +namespace ash { + +ScannerFeedbackUntrustedUIConfig::ScannerFeedbackUntrustedUIConfig() + : ChromeOSWebUIConfig(content::kChromeUIUntrustedScheme, + kScannerFeedbackUntrustedHost) {} + +ScannerFeedbackUntrustedUIConfig::~ScannerFeedbackUntrustedUIConfig() = default; + +bool ScannerFeedbackUntrustedUIConfig::IsWebUIEnabled( + content::BrowserContext* browser_context) { + return features::IsScannerEnabled(); +} + +ScannerFeedbackUntrustedUI::ScannerFeedbackUntrustedUI(content::WebUI* web_ui) + : ui::UntrustedWebUIController(web_ui) { + // `content::WebUIDataSource`s are stored on the browser context. If an + // existing `content::WebUIDataSource` exists in the browser context for the + // given source name, calling `CreateAndAdd` will destroy the previous one. + // + // This destruction is unnecessary, as our `content::WebUIDataSource` is + // deterministic per browser context. However, there is no way of determining + // whether a browser context already has a data source for a given source + // name, as that would require calling + // + // content::URLDataManagerBackend::GetForBrowserContext(browser_context) + // ->data_sources() + // .contains(source_name) + // + // which uses `URLDataManagerBackend` in //content/browser - not available to + // Ash. + // + // Note that `content::URLDataSource::ShouldReplaceExistingSource` has a TODO + // comment that all callers should be converted to _not_ replace existing data + // sources, so this may change in the future. + content::WebUIDataSource* untrusted_source = + content::WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + std::string(kScannerFeedbackUntrustedUrl)); + + untrusted_source->AddResourcePaths(kAshScannerFeedbackUiResources); + // We intentionally do not use `SetDefaultResource` here as we do not want to + // serve index.html for non-HTML paths. + untrusted_source->AddResourcePath("", IDR_ASH_SCANNER_FEEDBACK_UI_INDEX_HTML); + + ash::EnableTrustedTypesCSP(untrusted_source); +} + +ScannerFeedbackUntrustedUI::~ScannerFeedbackUntrustedUI() = default; + +} // namespace ash
diff --git a/ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.h b/ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.h new file mode 100644 index 0000000..0a842c9 --- /dev/null +++ b/ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.h
@@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_SCANNER_FEEDBACK_UI_SCANNER_FEEDBACK_UNTRUSTED_UI_H_ +#define ASH_WEBUI_SCANNER_FEEDBACK_UI_SCANNER_FEEDBACK_UNTRUSTED_UI_H_ + +#include "ash/webui/common/chrome_os_webui_config.h" +#include "ui/webui/untrusted_web_ui_controller.h" + +namespace content { +class BrowserContext; +} + +namespace ash { + +class ScannerFeedbackUntrustedUI; + +class ScannerFeedbackUntrustedUIConfig + : public ChromeOSWebUIConfig<ScannerFeedbackUntrustedUI> { + public: + ScannerFeedbackUntrustedUIConfig(); + ~ScannerFeedbackUntrustedUIConfig() override; + + // ChromeOSWebUIConfig: + bool IsWebUIEnabled(content::BrowserContext* browser_context) override; +}; + +class ScannerFeedbackUntrustedUI : public ui::UntrustedWebUIController { + public: + explicit ScannerFeedbackUntrustedUI(content::WebUI* web_ui); + + ScannerFeedbackUntrustedUI(const ScannerFeedbackUntrustedUI&) = delete; + ScannerFeedbackUntrustedUI& operator=(const ScannerFeedbackUntrustedUI&) = + delete; + + ~ScannerFeedbackUntrustedUI() override; +}; + +} // namespace ash + +#endif // ASH_WEBUI_SCANNER_FEEDBACK_UI_SCANNER_FEEDBACK_UNTRUSTED_UI_H_
diff --git a/ash/webui/scanner_feedback_ui/url_constants.h b/ash/webui/scanner_feedback_ui/url_constants.h new file mode 100644 index 0000000..87a9c4e --- /dev/null +++ b/ash/webui/scanner_feedback_ui/url_constants.h
@@ -0,0 +1,19 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_SCANNER_FEEDBACK_UI_URL_CONSTANTS_H_ +#define ASH_WEBUI_SCANNER_FEEDBACK_UI_URL_CONSTANTS_H_ + +#include <string_view> + +namespace ash { + +inline constexpr std::string_view kScannerFeedbackUntrustedUrl = + "chrome-untrusted://scanner-feedback/"; +inline constexpr std::string_view kScannerFeedbackUntrustedHost = + "scanner-feedback"; + +} // namespace ash + +#endif // ASH_WEBUI_SCANNER_FEEDBACK_UI_URL_CONSTANTS_H_
diff --git a/ash/wm/coral/coral_controller_unittest.cc b/ash/wm/coral/coral_controller_unittest.cc index bc6fc78..b495617 100644 --- a/ash/wm/coral/coral_controller_unittest.cc +++ b/ash/wm/coral/coral_controller_unittest.cc
@@ -246,6 +246,16 @@ 0u); } +// Tests that there is no crash when removing a coral chip by user. +TEST_F(CoralControllerTest, NoCrashOnRemovingChipByUser) { + Shell::Get()->overview_controller()->StartOverview( + OverviewStartAction::kTests); + + // Remove the first coral chip and there should be no crash. + CoralChipButton* coral_chip = GetFirstCoralButton(); + BirchBarController::Get()->OnItemHiddenByUser(coral_chip->GetItem()); +} + class CoralSavedGroupTest : public CoralControllerTest { public: desks_storage::DeskModel* desk_model() {
diff --git a/ash/wm/overview/birch/birch_bar_controller.cc b/ash/wm/overview/birch/birch_bar_controller.cc index 407ecbd..aeaf672 100644 --- a/ash/wm/overview/birch/birch_bar_controller.cc +++ b/ash/wm/overview/birch/birch_bar_controller.cc
@@ -185,14 +185,23 @@ return; } + auto iter = base::ranges::find_if(items_, base::MatchesUniquePtr(item)); + if (iter == items_.end()) { + return; + } + RemoveItemChips(item); + // Move the removing item out of the `items_` such that item-removed observers + // could know the item is being removed to avoid duplicated removing. + auto removing_item = std::move(*iter); + items_.erase(iter); + // Erase the item from model and controller. Shell::Get()->birch_model()->RemoveItem(item); if (item->GetType() == BirchItemType::kLostMedia) { OnLostMediaItemRemoved(); } - std::erase_if(items_, base::MatchesUniquePtr(item)); } void BirchBarController::SetShowBirchSuggestions(bool show) {
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index 3e137836..94387d69 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -228,15 +228,11 @@ } void OverviewItem::UpdateRoundedCorners() { - // TODO(sammiequon): Clean up this function. - - // Do not show the rounded corners and the shadow if overview is shutting - // down or we're currently in entering overview animation. Also don't update - // or animate the window's frame header clip under these conditions. If the - // feature ContinuousOverviewScrollAnimation is enabled, always show rounded - // corners for minimized windows, and show rounded corners for non-minimized - // windows after the continuous scroll has ended. OverviewController* overview_controller = OverviewController::Get(); + + // If the feature ContinuousOverviewScrollAnimation is enabled, always show + // rounded corners for minimized windows, and show rounded corners for + // non-minimized windows after the continuous scroll has ended. bool show_rounded_corners_for_start_animation = false; if (features::IsContinuousOverviewScrollAnimationEnabled() && !display::Screen::GetScreen()->InTabletMode()) { @@ -248,6 +244,9 @@ !overview_controller->IsInStartAnimation(); } + // Do not show the rounded corners and the shadow if overview is shutting + // down or we're currently in entering overview animation. Also don't update + // or animate the window's frame header clip under these conditions. const bool is_shutting_down = !overview_controller || !overview_controller->InOverviewSession(); const bool should_show_rounded_corners =
diff --git a/ash/wm/scoped_window_tucker.cc b/ash/wm/scoped_window_tucker.cc index 225cc15..5dadb68 100644 --- a/ash/wm/scoped_window_tucker.cc +++ b/ash/wm/scoped_window_tucker.cc
@@ -182,8 +182,6 @@ tuck_handle->SetBounds(delegate_->GetTuckHandleBounds(left_, final_bounds)); views::AnimationBuilder() - // TODO(sammiequon|sophiewen): Should we handle the case where the - // animation gets aborted? .OnEnded(std::move(callback)) .SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET)
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc index 44f6b79..9e47070f 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_state.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -158,7 +158,6 @@ state_type_on_attach_ = snap || state->IsFloated() ? current_state_type_ : state->GetWindowTypeOnMaximizable(); - // TODO(oshima|sammiequon): consider SplitView scenario. WindowState::ScopedBoundsChangeAnimation bounds_animation( window, entering_tablet_mode && !ShouldAnimateWindowForTransition(window) ? WindowState::BoundsChangeAnimationType::kAnimateZero
diff --git a/ash/wm/window_restore/informed_restore_controller.cc b/ash/wm/window_restore/informed_restore_controller.cc index ee51033..07dfec6 100644 --- a/ash/wm/window_restore/informed_restore_controller.cc +++ b/ash/wm/window_restore/informed_restore_controller.cc
@@ -71,8 +71,6 @@ const gfx::Size image_size = image.size(); const bool is_image_landscape = image_size.width() > image_size.height(); - // TODO(minch|sammiequon): The informed restore dialog will only be shown - // inside the primary display for now. Change the logic here if it changes. const display::Display display_with_dialog = display::Screen::GetScreen()->GetPrimaryDisplay(); const bool is_display_landscape = chromeos::IsLandscapeOrientation(
diff --git a/base/android/java/src/org/chromium/base/ActivityLifecycleCallbacksAdapter.java b/base/android/java/src/org/chromium/base/ActivityLifecycleCallbacksAdapter.java index 4abcc95..a60bcac 100644 --- a/base/android/java/src/org/chromium/base/ActivityLifecycleCallbacksAdapter.java +++ b/base/android/java/src/org/chromium/base/ActivityLifecycleCallbacksAdapter.java
@@ -8,13 +8,17 @@ import android.app.Application; import android.os.Bundle; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** An ActivityLifecycleCallbacks that routes all methods to a single onStateChanged(). */ +@NullMarked public abstract class ActivityLifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks { public abstract void onStateChanged(Activity activity, @ActivityState int newState); @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + public void onActivityCreated(Activity activity, @Nullable Bundle savedInstanceState) { onStateChanged(activity, ActivityState.CREATED); }
diff --git a/base/android/java/src/org/chromium/base/ActivityState.java b/base/android/java/src/org/chromium/base/ActivityState.java index 08adc88cb..09c754d 100644 --- a/base/android/java/src/org/chromium/base/ActivityState.java +++ b/base/android/java/src/org/chromium/base/ActivityState.java
@@ -6,10 +6,13 @@ import androidx.annotation.IntDef; +import org.chromium.build.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** A set of states that represent the last state change of an Activity. */ +@NullMarked @Retention(RetentionPolicy.SOURCE) @IntDef({ ActivityState.CREATED,
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java index 814467f..8b25cc7 100644 --- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java +++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -25,7 +25,8 @@ import android.view.Display; import android.view.View; -import androidx.annotation.NonNull; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -40,6 +41,7 @@ * Do not inline because we use many new APIs, and if they are inlined, they could cause dex * validation errors on low Android versions. */ +@NullMarked public class ApiCompatibilityUtils { private static final String TAG = "ApiCompatUtil"; @@ -58,7 +60,7 @@ * AppCompatResources} to parse drawable to prevent fail on {@link VectorDrawable}. * (http://crbug.com/792129) */ - public static Drawable getDrawable(Resources res, int id) throws NotFoundException { + public static @Nullable Drawable getDrawable(Resources res, int id) throws NotFoundException { return getDrawableForDensity(res, id, 0); } @@ -66,7 +68,7 @@ * @see android.content.res.Resources#getDrawableForDensity(int id, int density). */ @SuppressWarnings("deprecation") - public static Drawable getDrawableForDensity(Resources res, int id, int density) { + public static @Nullable Drawable getDrawableForDensity(Resources res, int id, int density) { StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { // For Android Oreo+, Resources.getDrawable(id, null) delegates to @@ -114,7 +116,6 @@ * @return A list of display ids. Empty if there is none or version is less than Q, or * windowAndroid does not contain an activity. */ - @NonNull public static List<Integer> getTargetableDisplayIds(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { List<Integer> displayList = new ArrayList<>(); @@ -146,8 +147,7 @@ * * @param options {@ActivityOptions} to set the required mode to. */ - public static void setActivityOptionsBackgroundActivityStartMode( - @NonNull ActivityOptions options) { + public static void setActivityOptionsBackgroundActivityStartMode(ActivityOptions options) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) return; options.setPendingIntentBackgroundActivityStartMode( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED); @@ -160,7 +160,7 @@ * @param options {@ActivityOptions} to set the required mode to. */ public static void setCreatorActivityOptionsBackgroundActivityStartMode( - @NonNull ActivityOptions options) { + ActivityOptions options) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) return; options.setPendingIntentCreatorBackgroundActivityStartMode( ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
diff --git a/base/android/java/src/org/chromium/base/ApkAssets.java b/base/android/java/src/org/chromium/base/ApkAssets.java index 87a40b63..d923b7f 100644 --- a/base/android/java/src/org/chromium/base/ApkAssets.java +++ b/base/android/java/src/org/chromium/base/ApkAssets.java
@@ -13,6 +13,8 @@ import org.jni_zero.JNINamespace; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.io.IOException; import java.util.Arrays; @@ -22,13 +24,14 @@ * defined as tuple (file descriptor, offset, size) enabling direct mapping without deflation. This * can be used even within the renderer process, since it just dup's the apk's fd. */ +@NullMarked @JNINamespace("base::android") public class ApkAssets { private static final String TAG = "ApkAssets"; // This isn't thread safe, but that's ok because it's only used for debugging. // Note reference operations are atomic so there is no security issue. - private static String sLastError; + private static @Nullable String sLastError; @CalledByNative public static long[] open(String apkSubpath, String splitName) { @@ -58,7 +61,7 @@ // For that reason, we only suppress the message when the exception message doesn't look // informative (Android framework passes the filename as the message on actual file not // found, and the empty string also wouldn't give any useful information for debugging). - if (!e.getMessage().equals("") && !e.getMessage().equals(apkSubpath)) { + if (!TextUtils.isEmpty(e.getMessage()) && !e.getMessage().equals(apkSubpath)) { Log.e(TAG, sLastError); } return new long[] {-1, -1, -1}; @@ -91,7 +94,7 @@ } @CalledByNative - private static String takeLastErrorString() { + private static @Nullable String takeLastErrorString() { String rv = sLastError; sLastError = null; return rv;
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java index e4bc6db0..76d7078f 100644 --- a/base/android/java/src/org/chromium/base/ApplicationStatus.java +++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -4,6 +4,8 @@ package org.chromium.base; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.annotation.SuppressLint; import android.app.Activity; import android.app.Application; @@ -12,13 +14,15 @@ import androidx.annotation.AnyThread; import androidx.annotation.MainThread; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; @@ -40,6 +44,7 @@ * WebView/WebLayer, and should be moved out of base and into //chrome. It should not be relied upon * for //components. */ +@NullMarked @JNINamespace("base::android") public class ApplicationStatus { private static final String TOOLBAR_CALLBACK_WRAPPER_CLASS = @@ -92,28 +97,28 @@ /** Last activity that was shown (or null if none or it was destroyed). */ @SuppressLint("StaticFieldLeak") - private static Activity sActivity; + private static @Nullable Activity sActivity; /** A lazily initialized listener that forwards application state changes to native. */ - private static ApplicationStateListener sNativeApplicationStateListener; + private static @Nullable ApplicationStateListener sNativeApplicationStateListener; /** A list of observers to be notified when any {@link Activity} has a state change. */ - private static ObserverList<ActivityStateListener> sGeneralActivityStateListeners; + private static @Nullable ObserverList<ActivityStateListener> sGeneralActivityStateListeners; /** * A list of observers to be notified when the visibility state of this {@link Application} * changes. See {@link #getStateForApplication()}. */ - private static ObserverList<ApplicationStateListener> sApplicationStateListeners; + private static @Nullable ObserverList<ApplicationStateListener> sApplicationStateListeners; /** * A list of observers to be notified when the window focus changes. * See {@link #registerWindowFocusChangedListener}. */ - private static ObserverList<WindowFocusChangedListener> sWindowFocusListeners; + private static @Nullable ObserverList<WindowFocusChangedListener> sWindowFocusListeners; /** A list of observers to be notified when the visibility of any task changes. */ - private static ObserverList<TaskVisibilityListener> sTaskVisibilityListeners; + private static @Nullable ObserverList<TaskVisibilityListener> sTaskVisibilityListeners; /** Interface to be implemented by listeners. */ public interface ApplicationStateListener { @@ -247,7 +252,8 @@ } @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + public @Nullable Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { if (method.getName().equals("onWindowFocusChanged") && args.length == 1 && args[0] instanceof Boolean) { @@ -348,7 +354,7 @@ * checking the declared fields of the given callback using reflection. */ @VisibleForTesting - static boolean reachesWindowCallback(@Nullable Window.Callback callback) { + static boolean reachesWindowCallback(Window.@Nullable Callback callback) { if (callback == null) return false; if (callback.getClass().getName().equals(TOOLBAR_CALLBACK_WRAPPER_CLASS)) { // We're actually not going to get called, see AndroidX report here: @@ -390,8 +396,6 @@ * @param newState New state value. */ private static void onStateChange(Activity activity, @ActivityState int newState) { - assert activity != null; - if (sActivity == null || newState == ActivityState.CREATED || newState == ActivityState.RESUMED @@ -409,7 +413,7 @@ sActivityInfo.put(activity, new ActivityInfo()); } - info = sActivityInfo.get(activity); + info = assumeNonNull(sActivityInfo.get(activity)); info.setStatus(newState); // Remove before calling listeners so that isEveryActivityDestroyed() returns false when @@ -467,7 +471,7 @@ * out of all the activities tracked here, it has most recently gained window focus. */ @MainThread - public static Activity getLastTrackedFocusedActivity() { + public static @Nullable Activity getLastTrackedFocusedActivity() { return sActivity; }
diff --git a/base/android/java/src/org/chromium/base/BaseFeatureMap.java b/base/android/java/src/org/chromium/base/BaseFeatureMap.java index 22c2bb5..989cc17 100644 --- a/base/android/java/src/org/chromium/base/BaseFeatureMap.java +++ b/base/android/java/src/org/chromium/base/BaseFeatureMap.java
@@ -7,6 +7,9 @@ import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + +@NullMarked @JNINamespace("base::android") public class BaseFeatureMap extends FeatureMap { private static final BaseFeatureMap sInstance = new BaseFeatureMap();
diff --git a/base/android/java/src/org/chromium/base/BinderCallsListener.java b/base/android/java/src/org/chromium/base/BinderCallsListener.java index 18c03fb7..0723975 100644 --- a/base/android/java/src/org/chromium/base/BinderCallsListener.java +++ b/base/android/java/src/org/chromium/base/BinderCallsListener.java
@@ -8,10 +8,12 @@ import android.os.IBinder; import android.os.RemoteException; -import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -26,15 +28,16 @@ * covers all Binder calls made through BinderProxy, which covers Chromium code, as well as * third-party and framework code. */ +@NullMarked public class BinderCallsListener { private static final String TAG = "BinderCallsListener"; private static final String PROXY_TRANSACT_LISTENER_CLASS_NAME = "android.os.Binder$ProxyTransactListener"; - private static BinderCallsListener sInstance; + private static @Nullable BinderCallsListener sInstance; - private Object mImplementation; - private InterfaceInvocationHandler mInvocationHandler; + private @Nullable Object mImplementation; + private @Nullable InterfaceInvocationHandler mInvocationHandler; private boolean mInstalled; @UiThread @@ -80,7 +83,7 @@ return installListener(mImplementation); } - private boolean installListener(Object listener) { + private boolean installListener(@Nullable Object listener) { if (mInstalled) return false; try { @@ -119,11 +122,11 @@ } private static class InterfaceInvocationHandler implements InvocationHandler { - private String mCurrentInterfaceDescriptor; - private BiConsumer<String, String> mObserver; + private @Nullable String mCurrentInterfaceDescriptor; + private @Nullable BiConsumer<String, String> mObserver; @Override - public Object invoke(Object proxy, Method method, Object[] args) { + public @Nullable Object invoke(Object proxy, Method method, Object[] args) { if (!ThreadUtils.runningOnUiThread()) return null; switch (method.getName()) { case "onTransactStarted":
diff --git a/base/android/java/src/org/chromium/base/BuildInfo.java b/base/android/java/src/org/chromium/base/BuildInfo.java index 2240537..fa012461 100644 --- a/base/android/java/src/org/chromium/base/BuildInfo.java +++ b/base/android/java/src/org/chromium/base/BuildInfo.java
@@ -6,6 +6,8 @@ import static android.content.Context.UI_MODE_SERVICE; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.app.UiModeManager; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -25,6 +27,9 @@ import org.chromium.build.BuildConfig; import org.chromium.build.NativeLibraries; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.NullUnmarked; +import org.chromium.build.annotations.Nullable; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -35,19 +40,20 @@ * BuildInfo is a utility class providing easy access to {@link PackageInfo} information. This is * primarily of use for accessing package information from native code. */ +@NullMarked public class BuildInfo { private static final String TAG = "BuildInfo"; private static final int MAX_FINGERPRINT_LENGTH = 128; - private static PackageInfo sBrowserPackageInfo; - private static ApplicationInfo sBrowserApplicationInfo; + private static @Nullable PackageInfo sBrowserPackageInfo; + private static @Nullable ApplicationInfo sBrowserApplicationInfo; private static boolean sInitialized; /** * The package name of the host app which has loaded WebView, retrieved from the application * context. In the context of the SDK Runtime, the package name of the app that owns this - * particular instance of the SDK Runtime will also be included. - * e.g. com.google.android.sdksandbox:com:com.example.myappwithads + * particular instance of the SDK Runtime will also be included. e.g. + * com.google.android.sdksandbox:com:com.example.myappwithads */ public final String hostPackageName; @@ -114,7 +120,7 @@ * an empty string if we were unable to retrieve it. */ @GuardedBy("mCertLock") - private String mHostSigningCertSha256; + private @Nullable String mHostSigningCertSha256; /** The versionCode of Play Services. Can be overridden in tests. */ private String mGmsVersionCode; @@ -183,7 +189,7 @@ }; } - private static String nullToEmpty(CharSequence seq) { + private static String nullToEmpty(@Nullable CharSequence seq) { return seq == null ? "" : seq.toString(); } @@ -224,7 +230,7 @@ /** * @return ApplicationInfo for Chrome/WebView (as opposed to host app). */ - public ApplicationInfo getBrowserApplicationInfo() { + public @Nullable ApplicationInfo getBrowserApplicationInfo() { return sBrowserApplicationInfo; } @@ -242,6 +248,7 @@ return mGmsVersionCode; } + @NullUnmarked // https://github.com/uber/NullAway/issues/98 private BuildInfo() { sInitialized = true; Context appContext = ContextUtils.getApplicationContext(); @@ -265,9 +272,10 @@ providedPackageVersionName = commandLine.getSwitchValue(BaseSwitches.PACKAGE_VERSION_NAME); - if (commandLine.hasSwitch(BaseSwitches.HOST_VERSION_CODE)) { - providedHostVersionCode = - Long.parseLong(commandLine.getSwitchValue(BaseSwitches.HOST_VERSION_CODE)); + String flagValue = commandLine.getSwitchValue(BaseSwitches.HOST_VERSION_CODE); + + if (flagValue != null) { + providedHostVersionCode = Long.parseLong(flagValue); } } @@ -307,7 +315,7 @@ final int hostId = Process.myUid() - 10000; final String[] packageNames = pm.getPackagesForUid(hostId); - if (packageNames.length > 0) { + if (packageNames != null && packageNames.length > 0) { // We could end up with more than one package name if the app used a // sharedUserId but these are deprecated so this is a safe bet to rely on the // first package name. @@ -316,9 +324,10 @@ } } - PackageInfo pi = PackageUtils.getPackageInfo(appInstalledPackageName, 0); + PackageInfo pi = assumeNonNull(PackageUtils.getPackageInfo(appInstalledPackageName, 0)); + ApplicationInfo appInfo = pi.applicationInfo; hostPackageName = sdkQualifiedName; - hostPackageLabel = nullToEmpty(pm.getApplicationLabel(pi.applicationInfo)); + hostPackageLabel = nullToEmpty(pm.getApplicationLabel(appInfo)); hostVersionCode = packageVersionCode(pi); if (sBrowserPackageInfo != null) { @@ -473,6 +482,7 @@ return target >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE; } + @NullUnmarked public String getHostSigningCertSha256() { // We currently only make use of this certificate for calls from the storage access API // within WebView. So we rather lazy load this value to avoid impacting app startup. @@ -513,7 +523,7 @@ return PackageManager.GET_SIGNATURES; } - private Signature[] getPackageSignatures(PackageInfo pi) { + private Signature @Nullable [] getPackageSignatures(PackageInfo pi) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (pi.signingInfo == null) { return null;
diff --git a/base/android/java/src/org/chromium/base/BundleUtils.java b/base/android/java/src/org/chromium/base/BundleUtils.java index f040b4c..8a01da5d 100644 --- a/base/android/java/src/org/chromium/base/BundleUtils.java +++ b/base/android/java/src/org/chromium/base/BundleUtils.java
@@ -4,6 +4,8 @@ package org.chromium.base; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; @@ -16,7 +18,6 @@ import android.util.ArrayMap; import android.view.LayoutInflater; -import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import dalvik.system.BaseDexClassLoader; @@ -25,6 +26,9 @@ import org.jni_zero.CalledByNative; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.NullUnmarked; +import org.chromium.build.annotations.Nullable; import java.lang.reflect.Field; import java.util.ArrayList; @@ -33,6 +37,7 @@ import java.util.Map; /** Utils for working with android app bundles. */ +@NullMarked public class BundleUtils { private static final String TAG = "BundleUtils"; private static final String LOADED_SPLITS_KEY = "split_compat_loaded_splits"; @@ -43,13 +48,13 @@ private static final Map<String, ClassLoader> sInflationClassLoaders = Collections.synchronizedMap(new ArrayMap<>()); - private static SplitCompatClassLoader sSplitCompatClassLoaderInstance; + private static @Nullable SplitCompatClassLoader sSplitCompatClassLoaderInstance; // List of splits that were loaded during the last run of chrome when // restoring from recents. - private static ArrayList<String> sSplitsToRestore; + private static @Nullable ArrayList<String> sSplitsToRestore; - private static Boolean sIsBundle; + private static @Nullable Boolean sIsBundle; public static void resetForTesting() { sCachedClassLoaders.clear(); @@ -78,15 +83,16 @@ ResettersForTesting.register(() -> sIsBundle = oldVal); } + @NullUnmarked @RequiresApi(api = Build.VERSION_CODES.O) - private static String getSplitApkPath(String splitName) { + private static @Nullable String getSplitApkPath(String splitName) { ApplicationInfo appInfo = ContextUtils.getApplicationContext().getApplicationInfo(); String[] splitNames = appInfo.splitNames; if (splitNames == null) { return null; } int idx = Arrays.binarySearch(splitNames, splitName); - return idx < 0 ? null : appInfo.splitSourceDirs[idx]; + return idx < 0 ? null : assumeNonNull(appInfo.splitSourceDirs)[idx]; } /** @@ -183,8 +189,7 @@ /* Returns absolute path to a native library in a feature module. */ @CalledByNative - @Nullable - public static String getNativeLibraryPath(String libraryName, String splitName) { + public static @Nullable String getNativeLibraryPath(String libraryName, String splitName) { try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { // Due to b/171269960 isolated split class loaders have an empty library path, so check // the base module class loader first which loaded BundleUtils. If the library is not @@ -338,6 +343,7 @@ private static class SplitCompatClassLoader extends ClassLoader { private static final String TAG = "SplitCompatClassLoader"; + @NullUnmarked public SplitCompatClassLoader() { // The chrome split classloader if the chrome split exists, otherwise // the base module class loader. @@ -345,7 +351,8 @@ Log.i(TAG, "Splits: %s", sSplitsToRestore); } - private Class<?> checkSplitsClassLoaders(String className) throws ClassNotFoundException { + private @Nullable Class<?> checkSplitsClassLoaders(String className) + throws ClassNotFoundException { for (ClassLoader cl : sInflationClassLoaders.values()) { try { return cl.loadClass(className); @@ -387,7 +394,7 @@ private void restoreSplitsClassLoaders() { // Load splits that were stored in the SavedInstanceState Bundle. - for (String splitName : sSplitsToRestore) { + for (String splitName : assumeNonNull(sSplitsToRestore)) { if (!sInflationClassLoaders.containsKey(splitName)) { registerSplitClassLoaderForInflation(splitName); } @@ -396,8 +403,7 @@ } } - @Nullable - private static String getSplitApkLibraryPath(String libraryName, String splitName) { + private static @Nullable String getSplitApkLibraryPath(String libraryName, String splitName) { // If isolated splits aren't supported, the library should have already been found. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { return null;
diff --git a/base/android/java/src/org/chromium/base/Callback.java b/base/android/java/src/org/chromium/base/Callback.java index 8764426..4d56928d 100644 --- a/base/android/java/src/org/chromium/base/Callback.java +++ b/base/android/java/src/org/chromium/base/Callback.java
@@ -4,10 +4,11 @@ package org.chromium.base; -import androidx.annotation.Nullable; - import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.util.Optional; /** @@ -15,8 +16,9 @@ * * @param <T> The type of the computation's result. */ +@NullMarked @FunctionalInterface -public interface Callback<T> { +public interface Callback<T extends @Nullable Object> { /** Invoked with the result of a computation. */ void onResult(T result); @@ -41,7 +43,7 @@ * @param callback The {@link Callback} to run. * @param object The payload to provide to the callback (may be null). */ - static <T> void runNullSafe(@Nullable Callback<T> callback, @Nullable T object) { + static <T extends @Nullable Object> void runNullSafe(@Nullable Callback<T> callback, T object) { if (callback != null) callback.onResult(object); }
diff --git a/base/android/java/src/org/chromium/base/CallbackController.java b/base/android/java/src/org/chromium/base/CallbackController.java index 8e8e07a..99a82080 100644 --- a/base/android/java/src/org/chromium/base/CallbackController.java +++ b/base/android/java/src/org/chromium/base/CallbackController.java
@@ -4,12 +4,13 @@ package org.chromium.base; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; +import org.chromium.build.annotations.EnsuresNonNull; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; +import org.chromium.build.annotations.RequiresNonNull; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Objects; import javax.annotation.concurrent.GuardedBy; @@ -79,6 +80,7 @@ * mCallbackController = new CallbackController(); // Allows to start handing out new callbacks. * }</pre> */ +@NullMarked @SuppressWarnings({"NoSynchronizedThisCheck", "NoSynchronizedMethodCheck"}) public final class CallbackController { /** Interface for cancelable objects tracked by this class. */ @@ -90,9 +92,9 @@ /** Class wrapping a {@link Callback} interface with a {@link Cancelable} interface. */ private class CancelableCallback<T> implements Cancelable, Callback<T> { @GuardedBy("CallbackController.this") - private Callback<T> mCallback; + private @Nullable Callback<T> mCallback; - private CancelableCallback(@NonNull Callback<T> callback) { + private CancelableCallback(Callback<T> callback) { mCallback = callback; } @@ -115,9 +117,9 @@ /** Class wrapping {@link Runnable} interface with a {@link Cancelable} interface. */ private class CancelableRunnable implements Cancelable, Runnable { @GuardedBy("CallbackController.this") - private Runnable mRunnable; + private @Nullable Runnable mRunnable; - private CancelableRunnable(@NonNull Runnable runnable) { + private CancelableRunnable(Runnable runnable) { mRunnable = runnable; } @@ -138,9 +140,8 @@ } /** A list of cancelables created and cancelable by this object. */ - @Nullable @GuardedBy("this") - private ArrayList<WeakReference<Cancelable>> mCancelables = new ArrayList<>(); + private @Nullable ArrayList<WeakReference<Cancelable>> mCancelables = new ArrayList<>(); /** * Wraps a provided {@link Callback} with a cancelable object that is tracked by this {@link @@ -152,7 +153,7 @@ * @param callback A callback that will be made cancelable. * @return A cancelable instance of the callback. */ - public synchronized <T> Callback<T> makeCancelable(@NonNull Callback<T> callback) { + public synchronized <T> Callback<T> makeCancelable(Callback<T> callback) { checkNotCanceled(); CancelableCallback<T> cancelable = new CancelableCallback<>(callback); addInternal(cancelable); @@ -168,7 +169,7 @@ * @param runnable A runnable that will be made cancelable. * @return A cancelable instance of the runnable. */ - public synchronized Runnable makeCancelable(@NonNull Runnable runnable) { + public synchronized Runnable makeCancelable(Runnable runnable) { checkNotCanceled(); CancelableRunnable cancelable = new CancelableRunnable(runnable); addInternal(cancelable); @@ -176,6 +177,7 @@ } @GuardedBy("this") + @RequiresNonNull("mCancelables") private void addInternal(Cancelable cancelable) { var cancelables = mCancelables; cancelables.add(new WeakReference<>(cancelable)); @@ -202,8 +204,8 @@ /** If the cancelation already happened, throws an {@link IllegalStateException}. */ @GuardedBy("this") + @EnsuresNonNull("mCancelables") private void checkNotCanceled() { - // Use NullPointerException because it optimizes well. - Objects.requireNonNull(mCancelables); + assert mCancelables != null; } }
diff --git a/base/android/java/src/org/chromium/base/CallbackUtils.java b/base/android/java/src/org/chromium/base/CallbackUtils.java index 891dae7a..fa6ab5d 100644 --- a/base/android/java/src/org/chromium/base/CallbackUtils.java +++ b/base/android/java/src/org/chromium/base/CallbackUtils.java
@@ -4,7 +4,10 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + /** Utilities for interacting with {@link Callback}s. */ +@NullMarked public class CallbackUtils { /** * @see #emptyCallback() to avoid unchecked generic checks.
diff --git a/base/android/java/src/org/chromium/base/CollectionUtil.java b/base/android/java/src/org/chromium/base/CollectionUtil.java index 01423d95..7b9769b5 100644 --- a/base/android/java/src/org/chromium/base/CollectionUtil.java +++ b/base/android/java/src/org/chromium/base/CollectionUtil.java
@@ -4,7 +4,7 @@ package org.chromium.base; -import androidx.annotation.NonNull; +import org.chromium.build.annotations.NullMarked; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -13,10 +13,11 @@ import java.util.List; /** Helpers for working with collections that do not already exist in JDK / Guava. */ +@NullMarked public final class CollectionUtil { private CollectionUtil() {} - public static int[] integerCollectionToIntArray(@NonNull Collection<Integer> collection) { + public static int[] integerCollectionToIntArray(Collection<Integer> collection) { int[] array = new int[collection.size()]; int index = 0; for (int num : collection) {
diff --git a/base/android/java/src/org/chromium/base/CommandLine.java b/base/android/java/src/org/chromium/base/CommandLine.java index 86bdccd1..1431589 100644 --- a/base/android/java/src/org/chromium/base/CommandLine.java +++ b/base/android/java/src/org/chromium/base/CommandLine.java
@@ -6,12 +6,14 @@ import android.text.TextUtils; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -26,12 +28,13 @@ * Instead, they're "simulated" by reading a file at a specific location early during startup. * Applications each define their own files, e.g., ContentShellApplication.COMMAND_LINE_FILE. */ +@NullMarked public abstract class CommandLine { // Public abstract interface, implemented in derived classes. // All these methods reflect their native-side counterparts. /** - * Returns true if this command line contains the given switch. - * (Switch names ARE case-sensitive). + * Returns true if this command line contains the given switch. (Switch names ARE + * case-sensitive). */ public abstract boolean hasSwitch(String switchString); @@ -100,7 +103,8 @@ return sCommandLine.get() instanceof NativeCommandLine; } - private static final AtomicReference<CommandLine> sCommandLine = new AtomicReference<>(); + private static final AtomicReference<@Nullable CommandLine> sCommandLine = + new AtomicReference<>(); /** * @return true if the command line has already been initialized. @@ -122,7 +126,7 @@ * * @param args command line flags in 'argv' format: args[0] is the program name. */ - public static void init(@Nullable String[] args) { + public static void init(String @Nullable [] args) { assert !(sCommandLine.get() instanceof NativeCommandLine); sCommandLine.set(new JavaCommandLine(args)); } @@ -232,7 +236,7 @@ * @param fileName the file to read in. * @return Array of chars read from the file, or null if the file cannot be read. */ - private static char[] readFileAsUtf8(String fileName) { + private static char @Nullable [] readFileAsUtf8(String fileName) { File f = new File(fileName); try (FileReader reader = new FileReader(f)) { char[] buffer = new char[(int) f.length()]; @@ -254,7 +258,7 @@ // The arguments begin at index 1, since index 0 contains the executable name. private int mArgsBegin = 1; - JavaCommandLine(@Nullable String[] args) { + JavaCommandLine(String @Nullable [] args) { if (args == null || args.length == 0 || args[0] == null) { mArgs.add(""); } else {
diff --git a/base/android/java/src/org/chromium/base/CommandLineInitUtil.java b/base/android/java/src/org/chromium/base/CommandLineInitUtil.java index 7ead455..73fe0a6 100644 --- a/base/android/java/src/org/chromium/base/CommandLineInitUtil.java +++ b/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
@@ -7,13 +7,14 @@ import android.content.Context; import android.provider.Settings; -import androidx.annotation.Nullable; - import org.chromium.base.supplier.Supplier; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.io.File; /** Provides implementation of command line initialization for Android. */ +@NullMarked public final class CommandLineInitUtil { /** * The location of the command line file needs to be in a protected @@ -33,7 +34,7 @@ private static final String COMMAND_LINE_FILE_PATH_DEBUG_APP = "/data/local/tmp"; /** The name of the command line file to pull arguments from. */ - private static String sFilenameOverrideForTesting; + private static @Nullable String sFilenameOverrideForTesting; private CommandLineInitUtil() {} @@ -78,7 +79,7 @@ return context.getPackageName().equals(getDebugApp(context)) || BuildInfo.isDebugAndroid(); } - private static String getDebugApp(Context context) { + private static @Nullable String getDebugApp(Context context) { boolean adbEnabled = Settings.Global.getInt(context.getContentResolver(), Settings.Global.ADB_ENABLED, 0) == 1;
diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java index 5b33964..38c86ea 100644 --- a/base/android/java/src/org/chromium/base/ContextUtils.java +++ b/base/android/java/src/org/chromium/base/ContextUtils.java
@@ -17,23 +17,24 @@ import android.os.Process; import android.preference.PreferenceManager; -import androidx.annotation.Nullable; - import org.jni_zero.JNINamespace; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** This class provides Android application context related utility methods. */ @JNINamespace("base::android") +@NullMarked public class ContextUtils { private static final String TAG = "ContextUtils"; - private static Context sApplicationContext; + private static @Nullable Context sApplicationContext; /** * Flag for {@link Context#registerReceiver}: The receiver can receive broadcasts from other * Apps. Has the same behavior as marking a statically registered receiver with "exported=true". * - * TODO(mthiesse): Move to ApiHelperForT when we build against T SDK. + * <p>TODO(mthiesse): Move to ApiHelperForT when we build against T SDK. */ public static final int RECEIVER_EXPORTED = 0x2; @@ -48,16 +49,18 @@ /** * Get the Android application context. * - * Under normal circumstances there is only one application context in a process, so it's safe - * to treat this as a global. In WebView it's possible for more than one app using WebView to be - * running in a single process, but this mechanism is rarely used and this is not the only + * <p>Under normal circumstances there is only one application context in a process, so it's + * safe to treat this as a global. In WebView it's possible for more than one app using WebView + * to be running in a single process, but this mechanism is rarely used and this is not the only * problem in that scenario, so we don't currently forbid using it as a global. * - * Do not downcast the context returned by this method to Application (or any subclass). It may - * not be an Application object; it may be wrapped in a ContextWrapper. The only assumption you - * may make is that it is a Context whose lifetime is the same as the lifetime of the process. + * <p>Do not downcast the context returned by this method to Application (or any subclass). It + * may not be an Application object; it may be wrapped in a ContextWrapper. The only assumption + * you may make is that it is a Context whose lifetime is the same as the lifetime of the + * process. */ public static Context getApplicationContext() { + assert sApplicationContext != null; return sApplicationContext; } @@ -88,7 +91,7 @@ // This may need to create the prefs directory if we've never used shared prefs before, so // allow disk writes. This is rare but can happen if code used early in startup reads prefs. try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { - return PreferenceManager.getDefaultSharedPreferences(sApplicationContext); + return PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); } } @@ -216,14 +219,17 @@ * <p> * You can unregister receivers using the normal {@link Context#unregisterReceiver} method. */ - public static Intent registerProtectedBroadcastReceiver( - Context context, BroadcastReceiver receiver, IntentFilter filter) { + public static @Nullable Intent registerProtectedBroadcastReceiver( + Context context, @Nullable BroadcastReceiver receiver, IntentFilter filter) { return registerBroadcastReceiver( context, receiver, filter, /* permission= */ null, /* scheduler= */ null, 0); } - public static Intent registerProtectedBroadcastReceiver( - Context context, BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) { + public static @Nullable Intent registerProtectedBroadcastReceiver( + Context context, + @Nullable BroadcastReceiver receiver, + IntentFilter filter, + Handler scheduler) { return registerBroadcastReceiver( context, receiver, filter, /* permission= */ null, scheduler, 0); } @@ -240,8 +246,11 @@ * <p> * You can unregister receivers using the normal {@link Context#unregisterReceiver} method. */ - public static Intent registerExportedBroadcastReceiver( - Context context, BroadcastReceiver receiver, IntentFilter filter, String permission) { + public static @Nullable Intent registerExportedBroadcastReceiver( + Context context, + @Nullable BroadcastReceiver receiver, + IntentFilter filter, + String permission) { return registerBroadcastReceiver( context, receiver, filter, permission, /* scheduler= */ null, RECEIVER_EXPORTED); } @@ -278,8 +287,8 @@ * <p> * You can unregister receivers using the normal {@link Context#unregisterReceiver} method. */ - public static Intent registerNonExportedBroadcastReceiver( - Context context, BroadcastReceiver receiver, IntentFilter filter) { + public static @Nullable Intent registerNonExportedBroadcastReceiver( + Context context, @Nullable BroadcastReceiver receiver, IntentFilter filter) { return registerBroadcastReceiver( context, receiver, @@ -289,8 +298,11 @@ RECEIVER_NOT_EXPORTED); } - public static Intent registerNonExportedBroadcastReceiver( - Context context, BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) { + public static @Nullable Intent registerNonExportedBroadcastReceiver( + Context context, + @Nullable BroadcastReceiver receiver, + IntentFilter filter, + Handler scheduler) { return registerBroadcastReceiver( context, receiver, @@ -300,12 +312,12 @@ RECEIVER_NOT_EXPORTED); } - private static Intent registerBroadcastReceiver( + private static @Nullable Intent registerBroadcastReceiver( Context context, - BroadcastReceiver receiver, + @Nullable BroadcastReceiver receiver, IntentFilter filter, - String permission, - Handler scheduler, + @Nullable String permission, + @Nullable Handler scheduler, int flags) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return context.registerReceiver(receiver, filter, permission, scheduler, flags);
diff --git a/base/android/java/src/org/chromium/base/CpuFeatures.java b/base/android/java/src/org/chromium/base/CpuFeatures.java index b2d9fe13..dd918ab 100644 --- a/base/android/java/src/org/chromium/base/CpuFeatures.java +++ b/base/android/java/src/org/chromium/base/CpuFeatures.java
@@ -7,6 +7,8 @@ import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + // The only purpose of this class is to allow sending CPU properties // from the browser process to sandboxed renderer processes. This is // needed because sandboxed processes cannot, on ARM, query the kernel @@ -20,6 +22,7 @@ // library. The exact CPU features bits are never used in Java so // there is no point in duplicating their definitions here. // +@NullMarked @JNINamespace("base::android") public abstract class CpuFeatures { /** Return the number of CPU Cores on the device. */
diff --git a/base/android/java/src/org/chromium/base/DiscardableReferencePool.java b/base/android/java/src/org/chromium/base/DiscardableReferencePool.java index 6a84e43..e69288cb 100644 --- a/base/android/java/src/org/chromium/base/DiscardableReferencePool.java +++ b/base/android/java/src/org/chromium/base/DiscardableReferencePool.java
@@ -4,7 +4,8 @@ package org.chromium.base; -import androidx.annotation.Nullable; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.Collections; import java.util.Set; @@ -23,6 +24,7 @@ * <p>This class and its references are not thread-safe and should not be used simultaneously by * multiple threads. */ +@NullMarked public class DiscardableReferencePool { /** * The underlying data storage. The wildcard type parameter allows using a single pool for @@ -40,7 +42,7 @@ * @param <T> The type of the object. */ public static class DiscardableReference<T> { - @Nullable private T mPayload; + private @Nullable T mPayload; private DiscardableReference(T payload) { assert payload != null; @@ -50,8 +52,7 @@ /** * @return The referent, or null if the pool has been drained. */ - @Nullable - public T get() { + public @Nullable T get() { return mPayload; }
diff --git a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java index d7510ac..a474827 100644 --- a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java +++ b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
@@ -14,6 +14,9 @@ import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullUnmarked; +import org.chromium.build.annotations.Nullable; + import java.io.File; import java.util.ArrayList; import java.util.List; @@ -37,6 +40,7 @@ * final String| class member. Otherwise NoDynamicStringsInTraceEventCheck error will be thrown. */ @JNINamespace("base::android") +@NullUnmarked // Cannot accurately model due to enable() / disable() public class EarlyTraceEvent { /** Single trace event. */ @VisibleForTesting @@ -135,11 +139,11 @@ // Not final because in many configurations these objects are not used. @GuardedBy("sLock") @VisibleForTesting - static List<Event> sEvents; + static @Nullable List<Event> sEvents; @GuardedBy("sLock") @VisibleForTesting - static List<AsyncEvent> sAsyncEvents; + static @Nullable List<AsyncEvent> sAsyncEvents; @GuardedBy("sLock") @VisibleForTesting
diff --git a/base/android/java/src/org/chromium/base/EventLog.java b/base/android/java/src/org/chromium/base/EventLog.java index 6f09010f..979ade90 100644 --- a/base/android/java/src/org/chromium/base/EventLog.java +++ b/base/android/java/src/org/chromium/base/EventLog.java
@@ -7,7 +7,10 @@ import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; +import org.chromium.build.annotations.NullMarked; + /** A simple interface to Android's EventLog to be used by native code. */ +@NullMarked @JNINamespace("base::android") public class EventLog {
diff --git a/base/android/java/src/org/chromium/base/FeatureList.java b/base/android/java/src/org/chromium/base/FeatureList.java index 1958639..844b91c 100644 --- a/base/android/java/src/org/chromium/base/FeatureList.java +++ b/base/android/java/src/org/chromium/base/FeatureList.java
@@ -6,19 +6,20 @@ import android.util.ArrayMap; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; import org.chromium.base.library_loader.LibraryLoader; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.HashMap; import java.util.Map; /** Provides shared capabilities for feature flag support. */ +@NullMarked @JNINamespace("base::android") public class FeatureList { /** Test value overrides for tests without native. */ @@ -61,16 +62,19 @@ addFieldTrialParamOverride(param.getFeatureName(), param.getName(), testValue); } + @Nullable Boolean getFeatureFlagOverride(String featureName) { return mFeatureFlags.get(featureName); } + @Nullable String getFieldTrialParamOverride(String featureName, String paramName) { Map<String, String> featureParams = mFieldTrialParams.get(featureName); if (featureParams == null) return null; return featureParams.get(paramName); } + @Nullable Map<String, String> getAllFieldTrialParamOverridesForFeature(String featureName) { return mFieldTrialParams.get(featureName); } @@ -234,7 +238,7 @@ * @param testValuesToMerge the TestValues to merge into existing ones * @param replace if true, replaces existing values (e.g. from @EnableFeatures annotations) */ - public static void mergeTestValues(@NonNull TestValues testValuesToMerge, boolean replace) { + public static void mergeTestValues(TestValues testValuesToMerge, boolean replace) { TestValues newTestValues = new TestValues(); if (sTestFeatures != null) { newTestValues.merge(sTestFeatures, /* replace= */ true); @@ -274,7 +278,7 @@ * @return The test value set for the feature, or null if no test value has been set. * @throws IllegalArgumentException if no test value was set and default values aren't allowed. */ - public static Boolean getTestValueForFeatureStrict(String featureName) { + public static @Nullable Boolean getTestValueForFeatureStrict(String featureName) { Boolean testValue = getTestValueForFeature(featureName); if (testValue == null && sDisableNativeForTesting) { throw new IllegalArgumentException( @@ -293,7 +297,7 @@ * @param featureName The name of the feature to query. * @return The test value set for the feature, or null if no test value has been set. */ - public static Boolean getTestValueForFeature(String featureName) { + public static @Nullable Boolean getTestValueForFeature(String featureName) { // TODO(crbug.com/40264751)): Copy into a local reference to avoid race conditions // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow // this mitigation to be removed. @@ -314,7 +318,8 @@ * @param paramName The name of the field trial parameter to query. * @return The test value set for the parameter, or null if no test value has been set. */ - public static String getTestValueForFieldTrialParam(String featureName, String paramName) { + public static @Nullable String getTestValueForFieldTrialParam( + String featureName, String paramName) { // TODO(crbug.com/40264751)): Copy into a local reference to avoid race conditions // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow // this mitigation to be removed. @@ -332,7 +337,7 @@ * @return The test values set for the parameter, or null if no test values have been set (if * test values were set for other features, an empty Map will be returned, not null). */ - public static Map<String, String> getTestValuesForAllFieldTrialParamsForFeature( + public static @Nullable Map<String, String> getTestValuesForAllFieldTrialParamsForFeature( String featureName) { // TODO(crbug.com/40264751)): Copy into a local reference to avoid race conditions // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow
diff --git a/base/android/java/src/org/chromium/base/FeatureMap.java b/base/android/java/src/org/chromium/base/FeatureMap.java index 115012e..dd87b86 100644 --- a/base/android/java/src/org/chromium/base/FeatureMap.java +++ b/base/android/java/src/org/chromium/base/FeatureMap.java
@@ -8,6 +8,8 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -23,6 +25,7 @@ * to get the pointer to the base::android::FeatureMap. The derived class will provide Java code * access to the list of base::Features passed to the base::android::FeatureMap. */ +@NullMarked @JNINamespace("base::android") public abstract class FeatureMap { private long mNativeMapPtr;
diff --git a/base/android/java/src/org/chromium/base/FeatureParam.java b/base/android/java/src/org/chromium/base/FeatureParam.java index b4fc105..e748399 100644 --- a/base/android/java/src/org/chromium/base/FeatureParam.java +++ b/base/android/java/src/org/chromium/base/FeatureParam.java
@@ -6,11 +6,10 @@ import android.util.Pair; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.build.BuildConfig; import org.chromium.build.annotations.CheckDiscard; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.HashMap; import java.util.Map; @@ -22,6 +21,7 @@ * * @param <T> The boxed type of data behind held. */ +@NullMarked @NotThreadSafe public abstract class FeatureParam<T> { @CheckDiscard("Only needed to reset tests. Production code shouldn't use.") @@ -33,13 +33,10 @@ protected final T mDefaultValue; // Null means this is not cached, and the feature map should be read from. - @Nullable protected T mInMemoryCachedValue; + protected @Nullable T mInMemoryCachedValue; public FeatureParam( - @NonNull FeatureMap featureMap, - @NonNull String featureName, - @NonNull String paramName, - @NonNull T defaultValue) { + FeatureMap featureMap, String featureName, String paramName, T defaultValue) { assert defaultValue != null; mFeatureMap = featureMap; mFeatureName = featureName;
diff --git a/base/android/java/src/org/chromium/base/Features.java b/base/android/java/src/org/chromium/base/Features.java index a54d52bf..c4315e0 100644 --- a/base/android/java/src/org/chromium/base/Features.java +++ b/base/android/java/src/org/chromium/base/Features.java
@@ -8,12 +8,15 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** * A class that serves as a bridge to native code to check the status of feature switches. * * <p>Each subclass represents a set of related features. Each instance of such a class correlates * to a single C++ Feature. */ +@NullMarked @JNINamespace("base::android") public abstract class Features { private final String mName;
diff --git a/base/android/java/src/org/chromium/base/FieldTrialList.java b/base/android/java/src/org/chromium/base/FieldTrialList.java index 5e2b0a6..ef5a09b 100644 --- a/base/android/java/src/org/chromium/base/FieldTrialList.java +++ b/base/android/java/src/org/chromium/base/FieldTrialList.java
@@ -7,7 +7,10 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** Helper to get field trial information. */ +@NullMarked public class FieldTrialList { private FieldTrialList() {}
diff --git a/base/android/java/src/org/chromium/base/FileProviderUtils.java b/base/android/java/src/org/chromium/base/FileProviderUtils.java index ac3b783..ecbd84a 100644 --- a/base/android/java/src/org/chromium/base/FileProviderUtils.java +++ b/base/android/java/src/org/chromium/base/FileProviderUtils.java
@@ -6,12 +6,16 @@ import android.net.Uri; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.io.File; /** This class provides methods to access content URI schemes. */ +@NullMarked public abstract class FileProviderUtils { private static final String TAG = "FileProviderUtils"; - private static FileProviderUtil sFileProviderUtil; + private static @Nullable FileProviderUtil sFileProviderUtil; // Guards access to sFileProviderUtil. private static final Object sLock = new Object(); @@ -47,7 +51,7 @@ * @throws IllegalArgumentException when the given File is outside the paths supported by the * provider. */ - public static Uri getContentUriFromFile(File file) { + public static @Nullable Uri getContentUriFromFile(File file) { synchronized (sLock) { if (sFileProviderUtil != null) { return sFileProviderUtil.getContentUriFromFile(file);
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java index f47922d..8aea5c3 100644 --- a/base/android/java/src/org/chromium/base/FileUtils.java +++ b/base/android/java/src/org/chromium/base/FileUtils.java
@@ -10,13 +10,13 @@ import android.net.Uri; import android.os.ParcelFileDescriptor; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.jni_zero.JNINamespace; import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; @@ -28,6 +28,7 @@ import java.util.function.Function; /** Helper methods for dealing with Files. */ +@NullMarked @JNINamespace("base::android") public class FileUtils { private static final String TAG = "FileUtils"; @@ -122,7 +123,6 @@ } /** Reads inputStream into a byte array. */ - @NonNull public static byte[] readStream(InputStream inputStream) throws IOException { ByteArrayOutputStream data = new ByteArrayOutputStream(); FileUtils.copyStream(inputStream, data); @@ -166,8 +166,7 @@ } /** Queries and decodes bitmap from content provider. */ - @Nullable - public static Bitmap queryBitmapFromContentProvider(Context context, Uri uri) { + public static @Nullable Bitmap queryBitmapFromContentProvider(Context context, Uri uri) { try (ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(uri, "r")) { if (parcelFileDescriptor == null) {
diff --git a/base/android/java/src/org/chromium/base/Flag.java b/base/android/java/src/org/chromium/base/Flag.java index 4a1a4dd3..f4560e65 100644 --- a/base/android/java/src/org/chromium/base/Flag.java +++ b/base/android/java/src/org/chromium/base/Flag.java
@@ -5,6 +5,7 @@ package org.chromium.base; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; import java.util.HashMap; @@ -21,6 +22,7 @@ * * <p>This class and its subclasses are not thread safe. */ +@NullMarked @NotThreadSafe public abstract class Flag { // Used to reset all flags between tests.
diff --git a/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java b/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java index 1c3b0b0e..f600755 100644 --- a/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java +++ b/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java
@@ -10,10 +10,13 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** * This class provides an interface to the native class for writing important data files without * risking data loss. */ +@NullMarked @JNINamespace("base::android") public class ImportantFileWriterAndroid {
diff --git a/base/android/java/src/org/chromium/base/InputHintChecker.java b/base/android/java/src/org/chromium/base/InputHintChecker.java index 3c789b58..7f3a3947 100644 --- a/base/android/java/src/org/chromium/base/InputHintChecker.java +++ b/base/android/java/src/org/chromium/base/InputHintChecker.java
@@ -8,12 +8,14 @@ import android.os.Build.VERSION_CODES; import android.view.View; -import androidx.annotation.Nullable; - import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** This class allows native code to discover the root view of the current Window. */ +@NullMarked @JNINamespace("base::android") public class InputHintChecker { @@ -97,7 +99,7 @@ @NativeMethods public interface Natives { - void setView(Object view); + void setView(@Nullable Object view); void onCompositorViewHolderTouchEvent();
diff --git a/base/android/java/src/org/chromium/base/IntStringCallback.java b/base/android/java/src/org/chromium/base/IntStringCallback.java index 2022d94..49c2d23 100644 --- a/base/android/java/src/org/chromium/base/IntStringCallback.java +++ b/base/android/java/src/org/chromium/base/IntStringCallback.java
@@ -6,6 +6,8 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; + /** * A simple 2-argument callback with an int and a String as arguments. * @@ -17,6 +19,7 @@ * 2-argument callback also adds a few code lines but it is clear and the compiler does the type * checking. */ +@NullMarked public interface IntStringCallback { /** * Invoked with the result of a computation.
diff --git a/base/android/java/src/org/chromium/base/IntentUtils.java b/base/android/java/src/org/chromium/base/IntentUtils.java index 3cadec1..a306e01 100644 --- a/base/android/java/src/org/chromium/base/IntentUtils.java +++ b/base/android/java/src/org/chromium/base/IntentUtils.java
@@ -19,12 +19,14 @@ import android.os.TransactionTooLargeException; import android.text.TextUtils; -import androidx.annotation.Nullable; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.io.Serializable; import java.util.ArrayList; /** Utilities dealing with extracting information from intents and creating common intents. */ +@NullMarked public class IntentUtils { private static final String TAG = "IntentUtils"; @@ -35,7 +37,7 @@ public static final String TRUSTED_APPLICATION_CODE_EXTRA = "trusted_application_code_extra"; /** Fake ComponentName used in constructing TRUSTED_APPLICATION_CODE_EXTRA. */ - private static ComponentName sFakeComponentName; + private static @Nullable ComponentName sFakeComponentName; private static final Object COMPONENT_NAME_LOCK = new Object(); @@ -107,7 +109,7 @@ } /** Just like {@link Intent#getIntArrayExtra(String)} but doesn't throw exceptions. */ - public static int[] safeGetIntArrayExtra(Intent intent, String name) { + public static int @Nullable [] safeGetIntArrayExtra(Intent intent, String name) { try { return intent.getIntArrayExtra(name); } catch (Throwable t) { @@ -118,7 +120,7 @@ } /** Just like {@link Bundle#getIntArray(String)} but doesn't throw exceptions. */ - public static int[] safeGetIntArray(Bundle bundle, String name) { + public static int @Nullable [] safeGetIntArray(Bundle bundle, String name) { try { return bundle.getIntArray(name); } catch (Throwable t) { @@ -129,7 +131,7 @@ } /** Just like {@link Bundle#getFloatArray(String)} but doesn't throw exceptions. */ - public static float[] safeGetFloatArray(Bundle bundle, String name) { + public static float @Nullable [] safeGetFloatArray(Bundle bundle, String name) { try { return bundle.getFloatArray(name); } catch (Throwable t) { @@ -162,7 +164,7 @@ } /** Just like {@link Intent#getStringExtra(String)} but doesn't throw exceptions. */ - public static String safeGetStringExtra(Intent intent, String name) { + public static @Nullable String safeGetStringExtra(Intent intent, String name) { try { return intent.getStringExtra(name); } catch (Throwable t) { @@ -173,7 +175,7 @@ } /** Just like {@link Bundle#getString(String)} but doesn't throw exceptions. */ - public static String safeGetString(Bundle bundle, String name) { + public static @Nullable String safeGetString(Bundle bundle, String name) { try { return bundle.getString(name); } catch (Throwable t) { @@ -184,7 +186,7 @@ } /** Just like {@link Intent#getBundleExtra(String)} but doesn't throw exceptions. */ - public static Bundle safeGetBundleExtra(Intent intent, String name) { + public static @Nullable Bundle safeGetBundleExtra(Intent intent, String name) { try { return intent.getBundleExtra(name); } catch (Throwable t) { @@ -195,7 +197,7 @@ } /** Just like {@link Bundle#getBundle(String)} but doesn't throw exceptions. */ - public static Bundle safeGetBundle(Bundle bundle, String name) { + public static @Nullable Bundle safeGetBundle(Bundle bundle, String name) { try { return bundle.getBundle(name); } catch (Throwable t) { @@ -206,7 +208,7 @@ } /** Just like {@link Bundle#getParcelable(String)} but doesn't throw exceptions. */ - public static <T extends Parcelable> T safeGetParcelable(Bundle bundle, String name) { + public static <T extends Parcelable> @Nullable T safeGetParcelable(Bundle bundle, String name) { try { return bundle.getParcelable(name); } catch (Throwable t) { @@ -217,7 +219,8 @@ } /** Just like {@link Intent#getParcelableExtra(String)} but doesn't throw exceptions. */ - public static <T extends Parcelable> T safeGetParcelableExtra(Intent intent, String name) { + public static <T extends Parcelable> @Nullable T safeGetParcelableExtra( + Intent intent, String name) { try { return intent.getParcelableExtra(name); } catch (Throwable t) { @@ -230,7 +233,7 @@ /** * Just link {@link Intent#getParcelableArrayListExtra(String)} but doesn't throw exceptions. */ - public static <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra( + public static <T extends Parcelable> @Nullable ArrayList<T> getParcelableArrayListExtra( Intent intent, String name) { try { return intent.getParcelableArrayListExtra(name); @@ -242,7 +245,7 @@ } /** Just link {@link Bundle#getParcelableArrayList(String)} but doesn't throw exceptions. */ - public static <T extends Parcelable> ArrayList<T> safeGetParcelableArrayList( + public static <T extends Parcelable> @Nullable ArrayList<T> safeGetParcelableArrayList( Bundle bundle, String name) { try { return bundle.getParcelableArrayList(name); @@ -254,7 +257,7 @@ } /** Just like {@link Intent#getParcelableArrayExtra(String)} but doesn't throw exceptions. */ - public static Parcelable[] safeGetParcelableArrayExtra(Intent intent, String name) { + public static Parcelable @Nullable [] safeGetParcelableArrayExtra(Intent intent, String name) { try { return intent.getParcelableArrayExtra(name); } catch (Throwable t) { @@ -264,7 +267,8 @@ } /** Just like {@link Intent#getStringArrayListExtra(String)} but doesn't throw exceptions. */ - public static ArrayList<String> safeGetStringArrayListExtra(Intent intent, String name) { + public static @Nullable ArrayList<String> safeGetStringArrayListExtra( + Intent intent, String name) { try { return intent.getStringArrayListExtra(name); } catch (Throwable t) { @@ -275,7 +279,7 @@ } /** Just like {@link Intent#getByteArrayExtra(String)} but doesn't throw exceptions. */ - public static byte[] safeGetByteArrayExtra(Intent intent, String name) { + public static byte @Nullable [] safeGetByteArrayExtra(Intent intent, String name) { try { return intent.getByteArrayExtra(name); } catch (Throwable t) { @@ -287,7 +291,8 @@ /** Just like {@link Intent#getSerializableExtra(String)} but doesn't throw exceptions. */ @SuppressWarnings("unchecked") - public static <T extends Serializable> T safeGetSerializableExtra(Intent intent, String name) { + public static <T extends Serializable> @Nullable T safeGetSerializableExtra( + Intent intent, String name) { try { return (T) intent.getSerializableExtra(name); } catch (ClassCastException ex) { @@ -307,7 +312,7 @@ * @param name a key string * @return an IBinder value, or null */ - public static IBinder safeGetBinder(Bundle bundle, String name) { + public static @Nullable IBinder safeGetBinder(@Nullable Bundle bundle, String name) { if (bundle == null) return null; try { return bundle.getBinder(name); @@ -324,7 +329,7 @@ * Creates a temporary copy of the extra Bundle, which is required as * Intent#getBinderExtra() doesn't exist, but Bundle.getBinder() does. */ - public static IBinder safeGetBinderExtra(Intent intent, String name) { + public static @Nullable IBinder safeGetBinderExtra(Intent intent, String name) { if (!intent.hasExtra(name)) return null; Bundle extras = intent.getExtras(); return safeGetBinder(extras, name); @@ -416,7 +421,7 @@ * make it safe to use. * @return A safe to use version of this intent. */ - public static Intent sanitizeIntent(final Intent incomingIntent) { + public static @Nullable Intent sanitizeIntent(final Intent incomingIntent) { // On Android T+, items are only deserialized when the items themselves are queried, so the // code below is a no-op. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) return incomingIntent; @@ -469,11 +474,11 @@ */ public static boolean intentTargetsSelf(Context context, Intent intent) { boolean hasPackage = !TextUtils.isEmpty(intent.getPackage()); - boolean matchesPackage = hasPackage && context.getPackageName().equals(intent.getPackage()); - boolean hasComponent = intent.getComponent() != null; + String appPackage = context.getPackageName(); + boolean matchesPackage = hasPackage && appPackage.equals(intent.getPackage()); + ComponentName componentName = intent.getComponent(); boolean matchesComponent = - hasComponent - && context.getPackageName().equals(intent.getComponent().getPackageName()); + componentName != null && appPackage.equals(componentName.getPackageName()); // Component takes precedence over PackageName when routing Intents if both are set, but to // be on the safe side, ensure that if we have both package and component set, that they @@ -488,8 +493,8 @@ return true; } if (matchesPackage) { - assert !hasComponent; - return !hasComponent; + assert componentName == null; + return true; } return false; }
diff --git a/base/android/java/src/org/chromium/base/JNIUtils.java b/base/android/java/src/org/chromium/base/JNIUtils.java index db0b936..495e23b 100644 --- a/base/android/java/src/org/chromium/base/JNIUtils.java +++ b/base/android/java/src/org/chromium/base/JNIUtils.java
@@ -6,10 +6,14 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** This class provides JNI-related methods to the native library. */ +@NullMarked public class JNIUtils { private static final String TAG = "JNIUtils"; - private static ClassLoader sJniClassLoader; + private static @Nullable ClassLoader sJniClassLoader; /** * Returns a ClassLoader which can load Java classes from the specified split.
diff --git a/base/android/java/src/org/chromium/base/JavaExceptionReporter.java b/base/android/java/src/org/chromium/base/JavaExceptionReporter.java index ad636d6..0de0138 100644 --- a/base/android/java/src/org/chromium/base/JavaExceptionReporter.java +++ b/base/android/java/src/org/chromium/base/JavaExceptionReporter.java
@@ -13,6 +13,9 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * This UncaughtExceptionHandler will create a breakpad minidump when there is an uncaught * exception. @@ -20,6 +23,7 @@ * <p>The exception's stack trace will be added to the minidump's data. This allows java-only * crashes to be reported in the same way as other native crashes. */ +@NullMarked @JNINamespace("base::android") public class JavaExceptionReporter implements Thread.UncaughtExceptionHandler { private final Thread.UncaughtExceptionHandler mParent; @@ -102,7 +106,7 @@ @NativeMethods interface Natives { - void reportJavaException(boolean crashAfterReport, Throwable e); + void reportJavaException(boolean crashAfterReport, @Nullable Throwable e); void reportJavaStackTrace(@JniType("std::string") String stackTrace); }
diff --git a/base/android/java/src/org/chromium/base/JavaHandlerThread.java b/base/android/java/src/org/chromium/base/JavaHandlerThread.java index 377eebdd..80dc90b 100644 --- a/base/android/java/src/org/chromium/base/JavaHandlerThread.java +++ b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
@@ -13,14 +13,18 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.lang.Thread.UncaughtExceptionHandler; /** Thread in Java with an Android Handler. This class is not thread safe. */ +@NullMarked @JNINamespace("base::android") public class JavaHandlerThread { private final HandlerThread mThread; - private Throwable mUnhandledException; + private @Nullable Throwable mUnhandledException; /** * Construct a java-only instance. Can be connected with native side later. @@ -111,7 +115,7 @@ } @CalledByNative - private Throwable getUncaughtExceptionIfAny() { + private @Nullable Throwable getUncaughtExceptionIfAny() { return mUnhandledException; }
diff --git a/base/android/java/src/org/chromium/base/JniAndroid.java b/base/android/java/src/org/chromium/base/JniAndroid.java index 9cd89c1..1dfb963 100644 --- a/base/android/java/src/org/chromium/base/JniAndroid.java +++ b/base/android/java/src/org/chromium/base/JniAndroid.java
@@ -6,7 +6,11 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** Provides Java-side code to back `jni_android` native logic. */ +@NullMarked public final class JniAndroid { private JniAndroid() {} @@ -21,7 +25,7 @@ * effort not to throw; instead, any failures will be surfaced through the returned string. */ @CalledByNative - private static String sanitizedStacktraceForUnhandledException(Throwable throwable) { + private static @Nullable String sanitizedStacktraceForUnhandledException(Throwable throwable) { if (sSimulateOomInSanitizedStacktraceForTesting) { return null; } @@ -75,7 +79,8 @@ * OutOfMemoryError exception, in which case that exception is returned. */ @CalledByNative - private static Throwable handleException(Throwable throwable, String nativeStackTrace) { + private static @Nullable Throwable handleException( + Throwable throwable, String nativeStackTrace) { try { // Try to make sure the exception details at least make their way to the log even if the // rest of this method goes horribly wrong.
diff --git a/base/android/java/src/org/chromium/base/LifetimeAssert.java b/base/android/java/src/org/chromium/base/LifetimeAssert.java index ae5a60b..724285b 100644 --- a/base/android/java/src/org/chromium/base/LifetimeAssert.java +++ b/base/android/java/src/org/chromium/base/LifetimeAssert.java
@@ -9,6 +9,8 @@ import org.chromium.base.task.PostTask; import org.chromium.build.BuildConfig; import org.chromium.build.annotations.CheckDiscard; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; @@ -32,10 +34,11 @@ * } * </pre> */ +@NullMarked @CheckDiscard("Lifetime assertions aren't used when DCHECK is off.") public class LifetimeAssert { interface TestHook { - void onCleaned(WrappedReference ref, String msg); + void onCleaned(WrappedReference ref, @Nullable String msg); } /** Thrown for failed assertions. */ @@ -53,7 +56,7 @@ } // Used only for unit test. - static TestHook sTestHook; + static @Nullable TestHook sTestHook; @VisibleForTesting final WrappedReference mWrapper; @@ -126,7 +129,7 @@ mTarget = target; } - public static LifetimeAssert create(Object target) { + public static @Nullable LifetimeAssert create(Object target) { if (!BuildConfig.ENABLE_ASSERTS) { return null; } @@ -134,7 +137,7 @@ new WrappedReference(target, new CreationException(), false), target); } - public static LifetimeAssert create(Object target, boolean safeToGc) { + public static @Nullable LifetimeAssert create(Object target, boolean safeToGc) { if (!BuildConfig.ENABLE_ASSERTS) { return null; } @@ -142,8 +145,9 @@ new WrappedReference(target, new CreationException(), safeToGc), target); } - public static void setSafeToGc(LifetimeAssert asserter, boolean value) { + public static void setSafeToGc(@Nullable LifetimeAssert asserter, boolean value) { if (BuildConfig.ENABLE_ASSERTS) { + assert asserter != null; // This guaratees that the target object is reachable until after mSafeToGc value // is updated here. See comment on Reference.reachabilityFence and review comments // on https://chromium-review.googlesource.com/c/chromium/src/+/1887151 for a
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java index 10999cb..c356c15 100644 --- a/base/android/java/src/org/chromium/base/LocaleUtils.java +++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -15,10 +15,14 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.util.ArrayList; import java.util.Locale; /** This class provides the locale related methods. */ +@NullMarked public class LocaleUtils { /** Guards this class from being instantiated. */ private LocaleUtils() {} @@ -195,7 +199,7 @@ * @return The default country code set during install. */ @CalledByNative - public static String getDefaultCountryCode() { + public static @Nullable String getDefaultCountryCode() { CommandLine commandLine = CommandLine.getInstance(); return commandLine.hasSwitch(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL) ? commandLine.getSwitchValue(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL)
diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java index fff5eaa..da4b5e1 100644 --- a/base/android/java/src/org/chromium/base/Log.java +++ b/base/android/java/src/org/chromium/base/Log.java
@@ -4,11 +4,10 @@ package org.chromium.base; -import androidx.annotation.Nullable; - import org.chromium.build.BuildConfig; import org.chromium.build.annotations.AlwaysInline; import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.Locale; @@ -161,33 +160,42 @@ } @AlwaysInline - public static void i(String tag, String messageTemplate, Object param1) { + public static void i(String tag, String messageTemplate, @Nullable Object param1) { tag = normalizeTag(tag); android.util.Log.i(tag, String.format(Locale.US, messageTemplate, param1)); } @AlwaysInline - public static void i(String tag, String messageTemplate, Object param1, Throwable t) { + public static void i(String tag, String messageTemplate, @Nullable Object param1, Throwable t) { tag = normalizeTag(tag); android.util.Log.i(tag, String.format(Locale.US, messageTemplate, param1), t); } @AlwaysInline - public static void i(String tag, String messageTemplate, Object param1, Object param2) { + public static void i( + String tag, String messageTemplate, @Nullable Object param1, @Nullable Object param2) { tag = normalizeTag(tag); android.util.Log.i(tag, String.format(Locale.US, messageTemplate, param1, param2)); } @AlwaysInline public static void i( - String tag, String messageTemplate, Object param1, Object param2, Throwable t) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + Throwable t) { tag = normalizeTag(tag); android.util.Log.i(tag, String.format(Locale.US, messageTemplate, param1, param2), t); } @AlwaysInline public static void i( - String tag, String messageTemplate, Object param1, Object param2, Object param3) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3) { tag = normalizeTag(tag); android.util.Log.i(tag, String.format(Locale.US, messageTemplate, param1, param2, param3)); } @@ -196,9 +204,9 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, Throwable t) { tag = normalizeTag(tag); android.util.Log.i( @@ -209,10 +217,10 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4) { tag = normalizeTag(tag); android.util.Log.i( tag, String.format(Locale.US, messageTemplate, param1, param2, param3, param4)); @@ -222,10 +230,10 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, Throwable t) { tag = normalizeTag(tag); android.util.Log.i( @@ -236,11 +244,11 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5) { tag = normalizeTag(tag); android.util.Log.i( tag, @@ -251,11 +259,11 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, Throwable t) { tag = normalizeTag(tag); android.util.Log.i( @@ -268,12 +276,12 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6) { tag = normalizeTag(tag); android.util.Log.i( tag, @@ -292,12 +300,12 @@ public static void i( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6, Throwable t) { tag = normalizeTag(tag); android.util.Log.i( @@ -344,33 +352,42 @@ } @AlwaysInline - public static void w(String tag, String messageTemplate, Object param1) { + public static void w(String tag, String messageTemplate, @Nullable Object param1) { tag = normalizeTag(tag); android.util.Log.w(tag, String.format(Locale.US, messageTemplate, param1)); } @AlwaysInline - public static void w(String tag, String messageTemplate, Object param1, Throwable t) { + public static void w(String tag, String messageTemplate, @Nullable Object param1, Throwable t) { tag = normalizeTag(tag); android.util.Log.w(tag, String.format(Locale.US, messageTemplate, param1), t); } @AlwaysInline - public static void w(String tag, String messageTemplate, Object param1, Object param2) { + public static void w( + String tag, String messageTemplate, @Nullable Object param1, @Nullable Object param2) { tag = normalizeTag(tag); android.util.Log.w(tag, String.format(Locale.US, messageTemplate, param1, param2)); } @AlwaysInline public static void w( - String tag, String messageTemplate, Object param1, Object param2, Throwable t) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + Throwable t) { tag = normalizeTag(tag); android.util.Log.w(tag, String.format(Locale.US, messageTemplate, param1, param2), t); } @AlwaysInline public static void w( - String tag, String messageTemplate, Object param1, Object param2, Object param3) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3) { tag = normalizeTag(tag); android.util.Log.w(tag, String.format(Locale.US, messageTemplate, param1, param2, param3)); } @@ -379,9 +396,9 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, Throwable t) { tag = normalizeTag(tag); android.util.Log.w( @@ -392,10 +409,10 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4) { tag = normalizeTag(tag); android.util.Log.w( tag, String.format(Locale.US, messageTemplate, param1, param2, param3, param4)); @@ -405,10 +422,10 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, Throwable t) { tag = normalizeTag(tag); android.util.Log.w( @@ -419,11 +436,11 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5) { tag = normalizeTag(tag); android.util.Log.w( tag, @@ -434,11 +451,11 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, Throwable t) { tag = normalizeTag(tag); android.util.Log.w( @@ -451,12 +468,12 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6) { tag = normalizeTag(tag); android.util.Log.w( tag, @@ -475,12 +492,12 @@ public static void w( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6, Throwable t) { tag = normalizeTag(tag); android.util.Log.w( @@ -526,33 +543,42 @@ } @AlwaysInline - public static void e(String tag, String messageTemplate, Object param1) { + public static void e(String tag, String messageTemplate, @Nullable Object param1) { tag = normalizeTag(tag); android.util.Log.e(tag, String.format(Locale.US, messageTemplate, param1)); } @AlwaysInline - public static void e(String tag, String messageTemplate, Object param1, Throwable t) { + public static void e(String tag, String messageTemplate, @Nullable Object param1, Throwable t) { tag = normalizeTag(tag); android.util.Log.e(tag, String.format(Locale.US, messageTemplate, param1), t); } @AlwaysInline - public static void e(String tag, String messageTemplate, Object param1, Object param2) { + public static void e( + String tag, String messageTemplate, @Nullable Object param1, @Nullable Object param2) { tag = normalizeTag(tag); android.util.Log.e(tag, String.format(Locale.US, messageTemplate, param1, param2)); } @AlwaysInline public static void e( - String tag, String messageTemplate, Object param1, Object param2, Throwable t) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + Throwable t) { tag = normalizeTag(tag); android.util.Log.e(tag, String.format(Locale.US, messageTemplate, param1, param2), t); } @AlwaysInline public static void e( - String tag, String messageTemplate, Object param1, Object param2, Object param3) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3) { tag = normalizeTag(tag); android.util.Log.e(tag, String.format(Locale.US, messageTemplate, param1, param2, param3)); } @@ -561,9 +587,9 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, Throwable t) { tag = normalizeTag(tag); android.util.Log.e( @@ -574,10 +600,10 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4) { tag = normalizeTag(tag); android.util.Log.e( tag, String.format(Locale.US, messageTemplate, param1, param2, param3, param4)); @@ -587,10 +613,10 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, Throwable t) { tag = normalizeTag(tag); android.util.Log.e( @@ -601,11 +627,11 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5) { tag = normalizeTag(tag); android.util.Log.e( tag, @@ -616,11 +642,11 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, Throwable t) { tag = normalizeTag(tag); android.util.Log.e( @@ -633,12 +659,12 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6) { tag = normalizeTag(tag); android.util.Log.e( tag, @@ -657,12 +683,12 @@ public static void e( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6, Throwable t) { tag = normalizeTag(tag); android.util.Log.e( @@ -713,33 +739,43 @@ } @AlwaysInline - public static void wtf(String tag, String messageTemplate, Object param1) { + public static void wtf(String tag, String messageTemplate, @Nullable Object param1) { tag = normalizeTag(tag); android.util.Log.wtf(tag, String.format(Locale.US, messageTemplate, param1)); } @AlwaysInline - public static void wtf(String tag, String messageTemplate, Object param1, Throwable t) { + public static void wtf( + String tag, String messageTemplate, @Nullable Object param1, Throwable t) { tag = normalizeTag(tag); android.util.Log.wtf(tag, String.format(Locale.US, messageTemplate, param1), t); } @AlwaysInline - public static void wtf(String tag, String messageTemplate, Object param1, Object param2) { + public static void wtf( + String tag, String messageTemplate, @Nullable Object param1, @Nullable Object param2) { tag = normalizeTag(tag); android.util.Log.wtf(tag, String.format(Locale.US, messageTemplate, param1, param2)); } @AlwaysInline public static void wtf( - String tag, String messageTemplate, Object param1, Object param2, Throwable t) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + Throwable t) { tag = normalizeTag(tag); android.util.Log.wtf(tag, String.format(Locale.US, messageTemplate, param1, param2), t); } @AlwaysInline public static void wtf( - String tag, String messageTemplate, Object param1, Object param2, Object param3) { + String tag, + String messageTemplate, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3) { tag = normalizeTag(tag); android.util.Log.wtf( tag, String.format(Locale.US, messageTemplate, param1, param2, param3)); @@ -749,9 +785,9 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, Throwable t) { tag = normalizeTag(tag); android.util.Log.wtf( @@ -762,10 +798,10 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4) { tag = normalizeTag(tag); android.util.Log.wtf( tag, String.format(Locale.US, messageTemplate, param1, param2, param3, param4)); @@ -775,10 +811,10 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, Throwable t) { tag = normalizeTag(tag); android.util.Log.wtf( @@ -789,11 +825,11 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5) { tag = normalizeTag(tag); android.util.Log.wtf( tag, @@ -804,11 +840,11 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, Throwable t) { tag = normalizeTag(tag); android.util.Log.wtf( @@ -821,12 +857,12 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6) { + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6) { tag = normalizeTag(tag); android.util.Log.wtf( tag, @@ -845,12 +881,12 @@ public static void wtf( String tag, String messageTemplate, - Object param1, - Object param2, - Object param3, - Object param4, - Object param5, - Object param6, + @Nullable Object param1, + @Nullable Object param2, + @Nullable Object param3, + @Nullable Object param4, + @Nullable Object param5, + @Nullable Object param6, Throwable t) { tag = normalizeTag(tag); android.util.Log.wtf(
diff --git a/base/android/java/src/org/chromium/base/MathUtils.java b/base/android/java/src/org/chromium/base/MathUtils.java index 5d30785..80803d0 100644 --- a/base/android/java/src/org/chromium/base/MathUtils.java +++ b/base/android/java/src/org/chromium/base/MathUtils.java
@@ -4,7 +4,10 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + /** Contains various math utilities used throughout Chrome Mobile. */ +@NullMarked public class MathUtils { /** A minimum difference to use when comparing floats for equality. */ public static final float EPSILON = 0.001f;
diff --git a/base/android/java/src/org/chromium/base/MemoryPressureListener.java b/base/android/java/src/org/chromium/base/MemoryPressureListener.java index 576dfb7..63a63cc 100644 --- a/base/android/java/src/org/chromium/base/MemoryPressureListener.java +++ b/base/android/java/src/org/chromium/base/MemoryPressureListener.java
@@ -4,6 +4,8 @@ package org.chromium.base; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.app.Activity; import android.content.ComponentCallbacks2; import android.os.Handler; @@ -15,6 +17,8 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.memory.MemoryPressureCallback; import org.chromium.base.memory.SelfFreezeCallback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * This class is Java equivalent of base::MemoryPressureListener: it distributes signals to @@ -30,6 +34,7 @@ * main thread for Chrome, but can be some other thread for WebView), except for the self freeze * calls, which are done on the launcher thread. */ +@NullMarked public class MemoryPressureListener { /** * Sending an intent with this action to Chrome will cause it to issue a call to onLowMemory @@ -57,10 +62,10 @@ private static final String ACTION_TRIM_MEMORY_MODERATE = "org.chromium.base.ACTION_TRIM_MEMORY_MODERATE"; - private static ObserverList<MemoryPressureCallback> sCallbacks; + private static @Nullable ObserverList<MemoryPressureCallback> sCallbacks; // This is used only on the Launcher thread. - private static ObserverList<SelfFreezeCallback> sSelfFreezeCallbacks; - private static volatile Handler sSelfFreezeHandler; + private static @Nullable ObserverList<SelfFreezeCallback> sSelfFreezeCallbacks; + private static volatile @Nullable Handler sSelfFreezeHandler; /** Called by the native side to add native callback. */ @CalledByNative @@ -104,9 +109,8 @@ } public static void removeSelfFreezeCallback(SelfFreezeCallback callback) { - assert sSelfFreezeCallbacks != null; - assert sSelfFreezeHandler.getLooper() == Looper.myLooper(); - sSelfFreezeCallbacks.removeObserver(callback); + assert assumeNonNull(sSelfFreezeHandler).getLooper() == Looper.myLooper(); + assumeNonNull(sSelfFreezeCallbacks).removeObserver(callback); } /**
diff --git a/base/android/java/src/org/chromium/base/MutableBooleanParamWithSafeDefault.java b/base/android/java/src/org/chromium/base/MutableBooleanParamWithSafeDefault.java index fa38895..800bbf5 100644 --- a/base/android/java/src/org/chromium/base/MutableBooleanParamWithSafeDefault.java +++ b/base/android/java/src/org/chromium/base/MutableBooleanParamWithSafeDefault.java
@@ -4,7 +4,10 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + /** Boolean {@link FeatureParam} that will return a default value before native is loaded. */ +@NullMarked public class MutableBooleanParamWithSafeDefault extends MutableParamWithSafeDefault<Boolean> { public MutableBooleanParamWithSafeDefault( FeatureMap featureMap, String featureName, String paramName, boolean defaultValue) {
diff --git a/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java b/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java index 4f39576..5ce7314e 100644 --- a/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java +++ b/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java
@@ -4,6 +4,9 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * Flags of this type are un-cached flags that may be called before native, * but not primarily. They have good default values to use before native is loaded, @@ -13,9 +16,10 @@ * or * if (!FeatureList.isInitialized() || SomeFeatureMap.isEnabled(featureName)). */ +@NullMarked public class MutableFlagWithSafeDefault extends Flag { private final boolean mDefaultValue; - private Boolean mInMemoryCachedValue; + private @Nullable Boolean mInMemoryCachedValue; public MutableFlagWithSafeDefault( FeatureMap featureMap, String featureName, boolean defaultValue) {
diff --git a/base/android/java/src/org/chromium/base/MutableIntParamWithSafeDefault.java b/base/android/java/src/org/chromium/base/MutableIntParamWithSafeDefault.java index 1b2dbd6..a944141 100644 --- a/base/android/java/src/org/chromium/base/MutableIntParamWithSafeDefault.java +++ b/base/android/java/src/org/chromium/base/MutableIntParamWithSafeDefault.java
@@ -4,7 +4,10 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + /** Boolean {@link FeatureParam} that will return a default value before native is loaded. */ +@NullMarked public class MutableIntParamWithSafeDefault extends MutableParamWithSafeDefault<Integer> { public MutableIntParamWithSafeDefault( FeatureMap featureMap, String featureName, String paramName, int defaultValue) {
diff --git a/base/android/java/src/org/chromium/base/MutableParamWithSafeDefault.java b/base/android/java/src/org/chromium/base/MutableParamWithSafeDefault.java index 2adc1c9..3de85fda 100644 --- a/base/android/java/src/org/chromium/base/MutableParamWithSafeDefault.java +++ b/base/android/java/src/org/chromium/base/MutableParamWithSafeDefault.java
@@ -4,7 +4,7 @@ package org.chromium.base; -import androidx.annotation.NonNull; +import org.chromium.build.annotations.NullMarked; /** * Abstract class for params that have a safe default before native is loaded. Because param values @@ -24,9 +24,10 @@ * * @param <T> The boxed type of data behind held. */ +@NullMarked public abstract class MutableParamWithSafeDefault<T> extends FeatureParam<T> { public MutableParamWithSafeDefault( - FeatureMap featureMap, String featureName, String paramName, @NonNull T defaultValue) { + FeatureMap featureMap, String featureName, String paramName, T defaultValue) { super(featureMap, featureName, paramName, defaultValue); } @@ -35,13 +36,13 @@ * converts it to the correct data type. Should never return a null value, because caching * relies on null checks. */ - protected abstract @NonNull T readValueFromFeatureMap(); + protected abstract T readValueFromFeatureMap(); /** * Returns the current value. Guaranteed to never be null. Subclasses should override this to * safely convert to their primitive type. */ - protected @NonNull T getValueBoxed() { + protected T getValueBoxed() { if (mInMemoryCachedValue != null) return mInMemoryCachedValue; if (FeatureList.hasTestParam(mFeatureName, mParamName)) {
diff --git a/base/android/java/src/org/chromium/base/ObserverList.java b/base/android/java/src/org/chromium/base/ObserverList.java index 1b383b3..2ae0ba4 100644 --- a/base/android/java/src/org/chromium/base/ObserverList.java +++ b/base/android/java/src/org/chromium/base/ObserverList.java
@@ -4,6 +4,8 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -28,6 +30,7 @@ * * @param <E> The type of observers that this list should hold. */ +@NullMarked @NotThreadSafe public class ObserverList<E> implements Iterable<E> { /** Extended iterator interface that provides rewind functionality. */
diff --git a/base/android/java/src/org/chromium/base/PackageManagerUtils.java b/base/android/java/src/org/chromium/base/PackageManagerUtils.java index a467d72a..65a12055 100644 --- a/base/android/java/src/org/chromium/base/PackageManagerUtils.java +++ b/base/android/java/src/org/chromium/base/PackageManagerUtils.java
@@ -10,10 +10,14 @@ import android.net.Uri; import android.os.TransactionTooLargeException; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.util.Collections; import java.util.List; /** This class provides Android PackageManager related utility methods. */ +@NullMarked public class PackageManagerUtils { public static final String XR_IMMERSIVE_FEATURE_NAME = "android.software.xr.immersive"; @@ -38,7 +42,7 @@ * @param flags The PackageManager flags to pass to resolveActivity(). * @return ResolveInfo of the Activity that will handle the Intent, or null if it failed. */ - public static ResolveInfo resolveActivity(Intent intent, int flags) { + public static @Nullable ResolveInfo resolveActivity(Intent intent, int flags) { // On KitKat, calling PackageManager#resolveActivity() causes disk reads and // writes. Temporarily allow this while resolving the intent. try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { @@ -102,7 +106,7 @@ /** * @return Default ResolveInfo to handle a VIEW intent for a url. */ - public static ResolveInfo resolveDefaultWebBrowserActivity() { + public static @Nullable ResolveInfo resolveDefaultWebBrowserActivity() { return resolveActivity(BROWSER_INTENT, PackageManager.MATCH_DEFAULT_ONLY); }
diff --git a/base/android/java/src/org/chromium/base/PackageUtils.java b/base/android/java/src/org/chromium/base/PackageUtils.java index 25bdfb6e..7535931 100644 --- a/base/android/java/src/org/chromium/base/PackageUtils.java +++ b/base/android/java/src/org/chromium/base/PackageUtils.java
@@ -10,9 +10,11 @@ import android.content.pm.Signature; import android.os.Build; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.io.ByteArrayInputStream; import java.io.InputStream; import java.lang.reflect.Method; @@ -25,6 +27,7 @@ import java.util.List; /** This class provides package checking related methods. */ +@NullMarked public class PackageUtils { private static final String TAG = "PackageUtils"; private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray(); @@ -109,7 +112,8 @@ */ @SuppressLint("PackageManagerGetSignatures") // https://stackoverflow.com/questions/39192844/android-studio-warning-when-using-packagemanager-get-signatures - public static List<String> getCertificateSHA256FingerprintForPackage(String packageName) { + public static @Nullable List<String> getCertificateSHA256FingerprintForPackage( + String packageName) { PackageInfo packageInfo = getPackageInfo(packageName, PackageManager.GET_SIGNATURES); if (packageInfo == null) return null;
diff --git a/base/android/java/src/org/chromium/base/PathService.java b/base/android/java/src/org/chromium/base/PathService.java index bbbe04d..7bdf868 100644 --- a/base/android/java/src/org/chromium/base/PathService.java +++ b/base/android/java/src/org/chromium/base/PathService.java
@@ -8,7 +8,10 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** This class provides java side access to the native PathService. */ +@NullMarked @JNINamespace("base::android") public abstract class PathService {
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java index ab8cb7c..639eaf5 100644 --- a/base/android/java/src/org/chromium/base/PathUtils.java +++ b/base/android/java/src/org/chromium/base/PathUtils.java
@@ -14,14 +14,17 @@ import android.system.Os; import android.text.TextUtils; -import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import org.jni_zero.CalledByNative; import org.chromium.base.task.AsyncTask; +import org.chromium.build.annotations.NullUnmarked; +import org.chromium.build.annotations.Nullable; +import org.chromium.build.annotations.RequiresNonNull; import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -30,6 +33,7 @@ import java.util.concurrent.atomic.AtomicBoolean; /** This class provides the path related methods for the native library. */ +@NullUnmarked // Too hard to annotated this class. public abstract class PathUtils { private static final String TAG = "PathUtils"; private static final String THUMBNAIL_DIRECTORY_NAME = "textures"; @@ -39,15 +43,15 @@ private static final int CACHE_DIRECTORY = 2; private static final int NUM_DIRECTORIES = 3; private static final AtomicBoolean sInitializationStarted = new AtomicBoolean(); - private static FutureTask<String[]> sDirPathFetchTask; + private static @Nullable FutureTask<String[]> sDirPathFetchTask; // If the FutureTask started in setPrivateDataDirectorySuffix() fails to complete by the time we // need the values, we will need the suffix so that we can restart the task synchronously on // the UI thread. - private static String sDataDirectorySuffix; - private static String sCacheSubDirectory; - private static String sDataDirectoryBasePath; - private static String sCacheDirectoryBasePath; + private static @Nullable String sDataDirectorySuffix; + private static @Nullable String sCacheSubDirectory; + private static @Nullable String sDataDirectoryBasePath; + private static @Nullable String sCacheDirectoryBasePath; // Prevent instantiation. private PathUtils() {} @@ -69,6 +73,7 @@ * above to guarantee thread-safety as part of the initialization-on-demand holder idiom. */ private static String[] getOrComputeDirectoryPaths() { + assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first."; if (!sDirPathFetchTask.isDone()) { try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { // No-op if already ran. @@ -98,8 +103,10 @@ File dataDir = context.getDataDir(); File externalDir = ContextUtils.getApplicationContext().getExternalFilesDir(null); try { - return (file.toPath().toRealPath().startsWith(dataDir.toPath().toRealPath()) - || file.toPath().toRealPath().startsWith(externalDir.toPath().toRealPath())); + Path fileRealPath = file.toPath().toRealPath(); + return (fileRealPath.startsWith(dataDir.toPath().toRealPath()) + || (externalDir != null + && fileRealPath.startsWith(externalDir.toPath().toRealPath()))); } catch (Exception e) { return false; } @@ -113,6 +120,7 @@ * * @see Context#getDir(String, int) */ + @RequiresNonNull("sDataDirectorySuffix") private static String[] setPrivateDirectoryPathInternal() { String[] paths = new String[NUM_DIRECTORIES]; File dataDir = null; @@ -170,7 +178,10 @@ * @see Context#getDir(String, int) */ public static void setPrivateDirectoryPath( - String dataBasePath, String cacheBasePath, String dataDirSuffix, String cacheSubDir) { + @Nullable String dataBasePath, + @Nullable String cacheBasePath, + String dataDirSuffix, + @Nullable String cacheSubDir) { // This method should only be called once, but many tests end up calling it multiple times, // so adding a guard here. if (!sInitializationStarted.getAndSet(true)) { @@ -210,7 +221,7 @@ * @param cacheSubDir The subdirectory in the cache directory to use, if non-null. * @see Context#getDir(String, int) */ - public static void setPrivateDataDirectorySuffix(String suffix, String cacheSubDir) { + public static void setPrivateDataDirectorySuffix(String suffix, @Nullable String cacheSubDir) { setPrivateDirectoryPath(null, null, suffix, cacheSubDir); } @@ -232,7 +243,6 @@ */ @CalledByNative public static String getDataDirectory() { - assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first."; return getDirectoryPath(DATA_DIRECTORY); } @@ -241,7 +251,6 @@ */ @CalledByNative public static String getCacheDirectory() { - assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first."; return getDirectoryPath(CACHE_DIRECTORY); } @@ -249,7 +258,6 @@ // environment. @CalledByNative public static String getThumbnailCacheDirectory() { - assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first."; return getDirectoryPath(THUMBNAIL_DIRECTORY); } @@ -261,7 +269,7 @@ */ @SuppressWarnings("unused") @CalledByNative - public static @NonNull String getDownloadsDirectory() { + public static String getDownloadsDirectory() { // TODO(crbug.com/41187555): Move calls to getDownloadsDirectory() to background thread. try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { @@ -285,7 +293,7 @@ */ @SuppressWarnings("unused") @CalledByNative - public static @NonNull String[] getAllPrivateDownloadsDirectories() { + public static String[] getAllPrivateDownloadsDirectories() { List<File> files = new ArrayList<>(); try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { File[] externalDirs = @@ -304,7 +312,7 @@ */ @RequiresApi(Build.VERSION_CODES.R) @CalledByNative - public static @NonNull String[] getExternalDownloadVolumesNames() { + public static String[] getExternalDownloadVolumesNames() { ArrayList<File> files = new ArrayList<>(); Set<String> volumes = MediaStore.getExternalVolumeNames(ContextUtils.getApplicationContext()); @@ -336,7 +344,7 @@ return toAbsolutePathStrings(files); } - private static @NonNull String[] toAbsolutePathStrings(@NonNull List<File> files) { + private static String[] toAbsolutePathStrings(List<File> files) { ArrayList<String> absolutePaths = new ArrayList<String>(); for (File file : files) { if (file == null || TextUtils.isEmpty(file.getAbsolutePath())) continue;
diff --git a/base/android/java/src/org/chromium/base/PiiElider.java b/base/android/java/src/org/chromium/base/PiiElider.java index 561b49a57..97068304 100644 --- a/base/android/java/src/org/chromium/base/PiiElider.java +++ b/base/android/java/src/org/chromium/base/PiiElider.java
@@ -7,10 +7,13 @@ import android.text.TextUtils; import android.util.Patterns; +import org.chromium.build.annotations.NullMarked; + import java.util.regex.Matcher; import java.util.regex.Pattern; /** Provides public methods for detecting and eliding sensitive PII. */ +@NullMarked public class PiiElider { private static final String EMAIL_ELISION = "XXX@EMAIL.ELIDED";
diff --git a/base/android/java/src/org/chromium/base/PostNativeFlag.java b/base/android/java/src/org/chromium/base/PostNativeFlag.java index 031450c1..7f8a3958 100644 --- a/base/android/java/src/org/chromium/base/PostNativeFlag.java +++ b/base/android/java/src/org/chromium/base/PostNativeFlag.java
@@ -4,11 +4,15 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * Flags of this type assume native is loaded and the value can be retrieved directly from native. */ +@NullMarked public class PostNativeFlag extends Flag { - private Boolean mInMemoryCachedValue; + private @Nullable Boolean mInMemoryCachedValue; public PostNativeFlag(FeatureMap featureMap, String featureName) { super(featureMap, featureName);
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java index 931f793..6bfe1de 100644 --- a/base/android/java/src/org/chromium/base/PowerMonitor.java +++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -19,11 +19,13 @@ import org.chromium.base.power_monitor.BatteryPowerStatus; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; +import org.chromium.build.annotations.NullMarked; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** Integrates native PowerMonitor with the java side. */ +@NullMarked @JNINamespace("base::android") public class PowerMonitor { private static boolean sIsInitRequested; @@ -68,7 +70,7 @@ @Override public void onReceive(Context context, Intent intent) { PowerMonitor.onBatteryChargingChanged( - intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)); + Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())); } }, powerConnectedFilter);
diff --git a/base/android/java/src/org/chromium/base/PowerMonitorForQ.java b/base/android/java/src/org/chromium/base/PowerMonitorForQ.java index cebea1bd..eed0732 100644 --- a/base/android/java/src/org/chromium/base/PowerMonitorForQ.java +++ b/base/android/java/src/org/chromium/base/PowerMonitorForQ.java
@@ -9,11 +9,14 @@ import androidx.annotation.RequiresApi; +import org.chromium.build.annotations.NullMarked; + /** * Utility class to use new APIs that were added in Q (API level 29). These need to exist in a * separate class so that Android framework can successfully verify the PowerMonitor class without * encountering the new APIs. */ +@NullMarked @RequiresApi(Build.VERSION_CODES.Q) public final class PowerMonitorForQ { private PowerMonitorForQ() {}
diff --git a/base/android/java/src/org/chromium/base/Promise.java b/base/android/java/src/org/chromium/base/Promise.java index 5d8176d..27cf986 100644 --- a/base/android/java/src/org/chromium/base/Promise.java +++ b/base/android/java/src/org/chromium/base/Promise.java
@@ -8,6 +8,9 @@ import androidx.annotation.IntDef; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.LinkedList; @@ -15,11 +18,13 @@ import java.util.function.Function; /** - * A Promise class to be used as a placeholder for a result that will be provided asynchronously. - * It must only be accessed from a single thread. + * A Promise class to be used as a placeholder for a result that will be provided asynchronously. It + * must only be accessed from a single thread. + * * @param <T> The type the Promise will be fulfilled with. */ -public class Promise<T> { +@NullMarked +public class Promise<T extends @Nullable Object> { // TODO(peconn): Implement rejection handlers that can recover from rejection. @IntDef({PromiseState.UNFULFILLED, PromiseState.FULFILLED, PromiseState.REJECTED}) @@ -32,10 +37,10 @@ @PromiseState private int mState = PromiseState.UNFULFILLED; - private T mResult; + private @Nullable T mResult; private final List<Callback<T>> mFulfillCallbacks = new LinkedList<>(); - private Exception mRejectReason; + private @Nullable Exception mRejectReason; private final List<Callback<Exception>> mRejectCallbacks = new LinkedList<>(); private final Thread mThread = Thread.currentThread(); @@ -55,7 +60,7 @@ * to a subsequent Promise. */ public static class UnhandledRejectionException extends RuntimeException { - public UnhandledRejectionException(String message, Throwable cause) { + public UnhandledRejectionException(String message, @Nullable Throwable cause) { super(message, cause); } } @@ -139,7 +144,8 @@ * Queues a {@link Function} to be run when the Promise is fulfilled. When this Promise is * fulfilled, the function will be run and its result will be place in the returned Promise. */ - public <RT> Promise<RT> then(final Function<T, RT> function) { + public <RT extends @Nullable Object> Promise<RT> then( + final Function<@Nullable T, RT> function) { checkThread(); // Create a new Promise to store the result of the function. @@ -169,7 +175,7 @@ * Promise is fulfilled, the AsyncFunction will be run. When the result of the AsyncFunction is * available, it will be placed in the returned Promise. */ - public <RT> Promise<RT> then(final AsyncFunction<T, RT> function) { + public <RT extends @Nullable Object> Promise<RT> then(final AsyncFunction<T, RT> function) { checkThread(); // Create a new Promise to be returned. @@ -214,7 +220,7 @@ * Fulfills the Promise with the result and passes it to any {@link Callback}s previously queued * on the next iteration of the message loop. */ - public void fulfill(final T result) { + public void fulfill(final @Nullable T result) { checkThread(); assert mState == PromiseState.UNFULFILLED; @@ -235,7 +241,7 @@ * important to make it explicit when a Promise may be rejected, so that users of that Promise * know to provide rejection handling. */ - public void reject(final Exception reason) { + public void reject(final @Nullable Exception reason) { checkThread(); assert mState == PromiseState.UNFULFILLED; @@ -276,7 +282,7 @@ * * @return The promised result. */ - public T getResult() { + public @Nullable T getResult() { assert isFulfilled(); return mResult; } @@ -300,7 +306,8 @@ } // We use a different template parameter here so this can be used for both T and Throwables. - private <S> void postCallbackToLooper(final Callback<S> callback, final S result) { + private <S extends @Nullable Object> void postCallbackToLooper( + final Callback<@Nullable S> callback, @Nullable S result) { // Post the callbacks to the Thread looper so we don't get a long chain of callbacks // holding up the thread. mHandler.post(callback.bind(result));
diff --git a/base/android/java/src/org/chromium/base/RadioUtils.java b/base/android/java/src/org/chromium/base/RadioUtils.java index 117a53f..244e4ac 100644 --- a/base/android/java/src/org/chromium/base/RadioUtils.java +++ b/base/android/java/src/org/chromium/base/RadioUtils.java
@@ -20,13 +20,17 @@ import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** Exposes radio related information about the current device. */ +@NullMarked @JNINamespace("base::android") public class RadioUtils { // Cached value indicating if app has ACCESS_NETWORK_STATE permission. - private static Boolean sHaveAccessNetworkState; + private static @Nullable Boolean sHaveAccessNetworkState; // Cached value indicating if app has ACCESS_WIFI_STATE permission. - private static Boolean sHaveAccessWifiState; + private static @Nullable Boolean sHaveAccessWifiState; private RadioUtils() {}
diff --git a/base/android/java/src/org/chromium/base/RequiredCallback.java b/base/android/java/src/org/chromium/base/RequiredCallback.java index 20d847a7..2533b2b 100644 --- a/base/android/java/src/org/chromium/base/RequiredCallback.java +++ b/base/android/java/src/org/chromium/base/RequiredCallback.java
@@ -4,7 +4,8 @@ package org.chromium.base; -import androidx.annotation.NonNull; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * A simple single-argument callback to handle the result of a computation that must be called @@ -12,12 +13,13 @@ * * @param <T> The type of the computation's result. */ -public class RequiredCallback<T> implements Callback<T> { +@NullMarked +public class RequiredCallback<T extends @Nullable Object> implements Callback<T> { // Enforces (under test) that this callback is invoked before it is GC'd. - private final LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); - private Callback<T> mCallback; + private final @Nullable LifetimeAssert mLifetimeAssert = LifetimeAssert.create(this); + private @Nullable Callback<T> mCallback; - public RequiredCallback(@NonNull Callback<T> callback) { + public RequiredCallback(Callback<T> callback) { mCallback = callback; }
diff --git a/base/android/java/src/org/chromium/base/ResettersForTesting.java b/base/android/java/src/org/chromium/base/ResettersForTesting.java index c9bdc394..8ef2a64 100644 --- a/base/android/java/src/org/chromium/base/ResettersForTesting.java +++ b/base/android/java/src/org/chromium/base/ResettersForTesting.java
@@ -8,6 +8,8 @@ import androidx.annotation.IntDef; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.Initializer; +import org.chromium.build.annotations.NullMarked; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -83,6 +85,7 @@ * } * </code> */ +@NullMarked public class ResettersForTesting { @IntDef({ @@ -235,6 +238,7 @@ } /** Enables calls to register(). */ + @Initializer public static void enable() { assert BuildConfig.IS_FOR_TEST; synchronized (sLock) {
diff --git a/base/android/java/src/org/chromium/base/StreamUtil.java b/base/android/java/src/org/chromium/base/StreamUtil.java index d1cff595..19f8f0e8e 100644 --- a/base/android/java/src/org/chromium/base/StreamUtil.java +++ b/base/android/java/src/org/chromium/base/StreamUtil.java
@@ -4,10 +4,13 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + import java.io.Closeable; import java.io.IOException; /** Helper methods to deal with stream related tasks. */ +@NullMarked public class StreamUtil { /** * Handle closing a {@link java.io.Closeable} via {@link java.io.Closeable#close()} and catch
diff --git a/base/android/java/src/org/chromium/base/StrictModeContext.java b/base/android/java/src/org/chromium/base/StrictModeContext.java index e694cd1c..a3412fc 100644 --- a/base/android/java/src/org/chromium/base/StrictModeContext.java +++ b/base/android/java/src/org/chromium/base/StrictModeContext.java
@@ -8,6 +8,8 @@ import android.os.StrictMode; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.io.Closeable; @@ -24,12 +26,15 @@ * } * </pre> */ +@NullMarked public class StrictModeContext implements Closeable { private static class Impl extends StrictModeContext { - private final StrictMode.ThreadPolicy mThreadPolicy; - private final StrictMode.VmPolicy mVmPolicy; + private final StrictMode.@Nullable ThreadPolicy mThreadPolicy; + private final StrictMode.@Nullable VmPolicy mVmPolicy; - private Impl(StrictMode.ThreadPolicy threadPolicy, StrictMode.VmPolicy vmPolicy) { + private Impl( + StrictMode.@Nullable ThreadPolicy threadPolicy, + StrictMode.@Nullable VmPolicy vmPolicy) { mThreadPolicy = threadPolicy; mVmPolicy = vmPolicy; }
diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java index 725ae9e..61466927 100644 --- a/base/android/java/src/org/chromium/base/SysUtils.java +++ b/base/android/java/src/org/chromium/base/SysUtils.java
@@ -14,6 +14,8 @@ import org.jni_zero.NativeMethods; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.io.BufferedReader; import java.io.FileReader; @@ -21,14 +23,15 @@ import java.util.regex.Pattern; /** Exposes system related information about the current device. */ +@NullMarked @JNINamespace("base::android") public class SysUtils { // A device reporting strictly more total memory in megabytes cannot be considered 'low-end'. private static final int LOW_MEMORY_DEVICE_THRESHOLD_MB = 1024; private static final String TAG = "SysUtils"; - private static Boolean sLowEndDevice; - private static Integer sAmountOfPhysicalMemoryKB; + private static @Nullable Boolean sLowEndDevice; + private static @Nullable Integer sAmountOfPhysicalMemoryKB; private SysUtils() {}
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java index 53036b9..c5cec09 100644 --- a/base/android/java/src/org/chromium/base/ThreadUtils.java +++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -13,22 +13,25 @@ import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; /** Helper methods to deal with threading related tasks. */ +@NullMarked public class ThreadUtils { private static final Object sLock = new Object(); private static volatile boolean sWillOverride; - private static volatile Handler sUiThreadHandler; + private static volatile @Nullable Handler sUiThreadHandler; - private static Throwable sUiThreadInitializer; + private static @Nullable Throwable sUiThreadInitializer; private static boolean sThreadAssertsDisabledForTesting; - private static Thread sInstrumentationThreadForTesting; + private static @Nullable Thread sInstrumentationThreadForTesting; /** * A helper object to ensure that interactions with a particular object only happens on a @@ -48,7 +51,7 @@ */ // TODO(b/274802355): Add @CheckDiscard once R8 can remove this. public static class ThreadChecker { - private Thread mThread; + private @Nullable Thread mThread; public ThreadChecker() { resetThreadId(); @@ -161,6 +164,7 @@ throw new RuntimeException("Did not yet override the UI thread"); } setUiThread(Looper.getMainLooper()); + assert sUiThreadHandler != null; return sUiThreadHandler; }
diff --git a/base/android/java/src/org/chromium/base/TimeUtils.java b/base/android/java/src/org/chromium/base/TimeUtils.java index a5d95008..b914b1d0 100644 --- a/base/android/java/src/org/chromium/base/TimeUtils.java +++ b/base/android/java/src/org/chromium/base/TimeUtils.java
@@ -7,11 +7,14 @@ import android.os.SystemClock; import org.chromium.build.annotations.CheckDiscard; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * Utilities related to timestamps, including the ability to use fake time for tests via * FakeTimeTestRule. */ +@NullMarked public class TimeUtils { /** * Interval timer using SystemClock.uptimeMillis() (excludes deep sleep). @@ -91,7 +94,7 @@ // Used by FakeTimeTestRule. Visibility is restricted to ensure tests use the rule, which // restores the value to null in its clean-up logic. - static FakeClock sFakeClock; + static @Nullable FakeClock sFakeClock; /** * Wrapper for System.currentTimeMillis() (milliseconds since the epoch).
diff --git a/base/android/java/src/org/chromium/base/TimezoneUtils.java b/base/android/java/src/org/chromium/base/TimezoneUtils.java index 606b72e..b8aa1a8 100644 --- a/base/android/java/src/org/chromium/base/TimezoneUtils.java +++ b/base/android/java/src/org/chromium/base/TimezoneUtils.java
@@ -9,8 +9,11 @@ import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; +import org.chromium.build.annotations.NullMarked; + import java.util.TimeZone; +@NullMarked @JNINamespace("base::android") class TimezoneUtils { /** Guards this class from being instantiated. */
diff --git a/base/android/java/src/org/chromium/base/Token.java b/base/android/java/src/org/chromium/base/Token.java index b6205f9..2f49ac5 100644 --- a/base/android/java/src/org/chromium/base/Token.java +++ b/base/android/java/src/org/chromium/base/Token.java
@@ -13,7 +13,10 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** Java counterpart to the native base::Token. A {@link Token} is a random 128-bit integer. */ +@NullMarked @JNINamespace("base::android") @DoNotMock("This is a simple value object.") public final class Token extends TokenBase {
diff --git a/base/android/java/src/org/chromium/base/TokenBase.java b/base/android/java/src/org/chromium/base/TokenBase.java index 8310de4..61c52895 100644 --- a/base/android/java/src/org/chromium/base/TokenBase.java +++ b/base/android/java/src/org/chromium/base/TokenBase.java
@@ -4,12 +4,14 @@ package org.chromium.base; -import androidx.annotation.Nullable; - import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** Base class for Token and UnguessableToken. */ +@NullMarked @JNINamespace("base::android") public abstract class TokenBase { protected final long mHigh;
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java index a09bcb5..075e469b 100644 --- a/base/android/java/src/org/chromium/base/TraceEvent.java +++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -22,6 +22,8 @@ import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.ArrayList; @@ -41,6 +43,7 @@ * It is OK to use tracing before the native library has loaded, in a slightly restricted fashion. * @see EarlyTraceEvent for details. */ +@NullMarked @JNINamespace("base::android") public class TraceEvent implements AutoCloseable { private static volatile boolean sEnabled; // True when tracing into Chrome's tracing service. @@ -56,7 +59,7 @@ static final String FILTERED_EVENT_NAME = LOOPER_TASK_PREFIX + "EVENT_NAME_FILTERED"; private static final int SHORTEST_LOG_PREFIX_LENGTH = "<<<<< Finished to ".length(); - private String mCurrentTarget; + private @Nullable String mCurrentTarget; @Override public void println(final String line) { @@ -260,7 +263,7 @@ private final String mName; /** Constructor used to support the "try with resource" construct. */ - private TraceEvent(String name, String arg) { + private TraceEvent(String name, @Nullable String arg) { mName = name; begin(name, arg); } @@ -285,7 +288,7 @@ * @param arg The arguments of the event. * @return a TraceEvent, or null if tracing is not enabled. */ - public static TraceEvent scoped(String name, String arg) { + public static @Nullable TraceEvent scoped(String name, @Nullable String arg) { if (!(EarlyTraceEvent.enabled() || enabled())) return null; return new TraceEvent(name, arg); } @@ -299,13 +302,13 @@ * @param arg An integer argument of the event. * @return a TraceEvent, or null if tracing is not enabled. */ - public static TraceEvent scoped(String name, int arg) { + public static @Nullable TraceEvent scoped(String name, int arg) { if (!(EarlyTraceEvent.enabled() || enabled())) return null; return new TraceEvent(name, arg); } /** Similar to {@link #scoped(String, String arg)}, but uses null for |arg|. */ - public static TraceEvent scoped(String name) { + public static @Nullable TraceEvent scoped(String name) { return scoped(name, null); } @@ -560,7 +563,7 @@ * @param name The name of the event. * @param arg The arguments of the event. */ - public static void begin(String name, String arg) { + public static void begin(String name, @Nullable String arg) { EarlyTraceEvent.begin(name, /* isToplevel= */ false); if (sEnabled) { TraceEventJni.get().begin(name, arg); @@ -592,7 +595,7 @@ * @param name The name of the event. * @param arg The arguments of the event. */ - public static void end(String name, String arg) { + public static void end(String name, @Nullable String arg) { end(name, arg, 0); } @@ -602,7 +605,7 @@ * @param arg The arguments of the event. * @param flow The flow ID to associate with this event (0 is treated as invalid). */ - public static void end(String name, String arg, long flow) { + public static void end(String name, @Nullable String arg, long flow) { EarlyTraceEvent.end(name, /* isToplevel= */ false); if (sEnabled) { TraceEventJni.get().end(arg, flow); @@ -630,13 +633,13 @@ interface Natives { void registerEnabledObserver(); - void instant(String name, String arg); + void instant(String name, @Nullable String arg); - void begin(String name, String arg); + void begin(String name, @Nullable String arg); void beginWithIntArg(String name, int arg); - void end(String arg, long flow); + void end(@Nullable String arg, long flow); void beginToplevel(String target); @@ -793,8 +796,7 @@ */ private static final class ViewHierarchyDumper implements MessageQueue.IdleHandler { private static final long MIN_VIEW_DUMP_INTERVAL_MILLIS = 1000L; - private static boolean sEnabled; - private static ViewHierarchyDumper sInstance; + private static @Nullable ViewHierarchyDumper sInstance; private long mLastDumpTs; @Override @@ -812,18 +814,7 @@ public static void updateEnabledState() { PostTask.runOrPostTask( TaskTraits.UI_DEFAULT, - () -> { - if (TraceEventJni.get().viewHierarchyDumpEnabled()) { - if (sInstance == null) { - sInstance = new ViewHierarchyDumper(); - } - enable(); - } else { - if (sInstance != null) { - disable(); - } - } - }); + () -> setEnabled(TraceEventJni.get().viewHierarchyDumpEnabled())); } private static void dumpView(ActivityInfo collection, int parentId, View v) { @@ -846,19 +837,14 @@ } } - private static void enable() { + private static void setEnabled(boolean value) { ThreadUtils.assertOnUiThread(); - if (!sEnabled) { + if (sInstance == null && value) { + sInstance = new ViewHierarchyDumper(); Looper.myQueue().addIdleHandler(sInstance); - sEnabled = true; - } - } - - private static void disable() { - ThreadUtils.assertOnUiThread(); - if (sEnabled) { + } else if (sInstance != null && !value) { Looper.myQueue().removeIdleHandler(sInstance); - sEnabled = false; + sInstance = null; } } }
diff --git a/base/android/java/src/org/chromium/base/UnguessableToken.java b/base/android/java/src/org/chromium/base/UnguessableToken.java index 0d98e60..99c2e1b 100644 --- a/base/android/java/src/org/chromium/base/UnguessableToken.java +++ b/base/android/java/src/org/chromium/base/UnguessableToken.java
@@ -12,6 +12,9 @@ import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * This class mirrors unguessable_token.h. Since tokens are passed by value, we don't bother to * maintain a native token. This implements Parcelable so that it may be sent via binder. @@ -19,6 +22,7 @@ * <p>To get one of these from native, one must start with a base::UnguessableToken, then create a * Java object from it. See unguessable_token_android.h for information. */ +@NullMarked @DoNotMock("This is a simple value object.") @JNINamespace("base::android") public final class UnguessableToken extends TokenBase implements Parcelable { @@ -47,7 +51,7 @@ public static final Parcelable.Creator<UnguessableToken> CREATOR = new Parcelable.Creator<UnguessableToken>() { @Override - public UnguessableToken createFromParcel(Parcel source) { + public @Nullable UnguessableToken createFromParcel(Parcel source) { long high = source.readLong(); long low = source.readLong(); if (high == 0 || low == 0) {
diff --git a/base/android/java/src/org/chromium/base/UnownedUserData.java b/base/android/java/src/org/chromium/base/UnownedUserData.java index bc8c7bb5..64ffcdbd 100644 --- a/base/android/java/src/org/chromium/base/UnownedUserData.java +++ b/base/android/java/src/org/chromium/base/UnownedUserData.java
@@ -4,6 +4,8 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + /** * Marker interface to be implemented by classes which makes them attachable to a host class that * holds {@link UnownedUserDataHost} entries. @@ -19,6 +21,7 @@ * @see UnownedUserDataHost for more details on ownership and typical usage. * @see UnownedUserDataKey for information about the type of key that is required. */ +@NullMarked public interface UnownedUserData { /** * Invoked whenever the particular UnownedUserData has been removed from a particular host. If
diff --git a/base/android/java/src/org/chromium/base/UnownedUserDataHost.java b/base/android/java/src/org/chromium/base/UnownedUserDataHost.java index ec14532..71410c4 100644 --- a/base/android/java/src/org/chromium/base/UnownedUserDataHost.java +++ b/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
@@ -7,11 +7,14 @@ import android.os.Handler; import android.os.Looper; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.chromium.base.lifetime.DestroyChecker; +import org.chromium.build.annotations.EnsuresNonNull; +import org.chromium.build.annotations.EnsuresNonNullIf; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.NullUnmarked; +import org.chromium.build.annotations.Nullable; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -141,6 +144,7 @@ * @see UnownedUserDataKey for information about the type of key that is required. * @see UnownedUserData for the marker interface used for this type of data. */ +@NullMarked public final class UnownedUserDataHost { private static Looper retrieveNonNullLooperOrThrow() { Looper looper = Looper.myLooper(); @@ -155,10 +159,10 @@ * Handler to use to post {@link UnownedUserData#onDetachedFromHost(UnownedUserDataHost)} * invocations to. */ - private Handler mHandler; + private @Nullable Handler mHandler; /** The core data structure within this host. */ - private HashMap<UnownedUserDataKey<?>, WeakReference<? extends UnownedUserData>> + private @Nullable HashMap<UnownedUserDataKey<?>, WeakReference<? extends UnownedUserData>> mUnownedUserDataMap = new HashMap<>(); public UnownedUserDataHost() { @@ -179,8 +183,7 @@ * @param newValue the object to store. * @param <T> the type of {@link UnownedUserData}. */ - /* package */ <T extends UnownedUserData> void set( - @NonNull UnownedUserDataKey<T> key, @NonNull T newValue) { + /* package */ <T extends UnownedUserData> void set(UnownedUserDataKey<T> key, T newValue) { checkState(); // If we already have data, we might want to detach that first. @@ -200,8 +203,8 @@ * @param <T> the type of {@link UnownedUserData}. * @return the stored version or {@code null} if it is not stored or has been garbage collected. */ - @Nullable - /* package */ <T extends UnownedUserData> T get(@NonNull UnownedUserDataKey<T> key) { + + /* package */ <T extends UnownedUserData> @Nullable T get(UnownedUserDataKey<T> key) { checkState(); WeakReference<? extends UnownedUserData> valueWeakRef = mUnownedUserDataMap.get(key); @@ -221,7 +224,7 @@ * @param key the key to use for the object. * @param <T> the type of {@link UnownedUserData}. */ - /* package */ <T extends UnownedUserData> void remove(@NonNull UnownedUserDataKey<T> key) { + /* package */ <T extends UnownedUserData> void remove(UnownedUserDataKey<T> key) { checkState(); WeakReference<? extends UnownedUserData> valueWeakRef = mUnownedUserDataMap.remove(key); @@ -250,7 +253,7 @@ mThreadChecker.assertOnValidThread(); // Protect against potential races. - if (mDestroyChecker.isDestroyed()) return; + if (isDestroyed()) return; // Create a shallow copy of all keys to ensure each held object can safely remove itself // from the map while iterating over their keys. @@ -272,10 +275,16 @@ return mUnownedUserDataMap.size(); } + @NullUnmarked // NullAway cannot validate postconditions. + @EnsuresNonNullIf( + value = {"mUnownedUserDataMap", "mHandler"}, + result = false) /* package */ boolean isDestroyed() { return mDestroyChecker.isDestroyed(); } + @NullUnmarked // NullAway cannot validate postconditions. + @EnsuresNonNull({"mUnownedUserDataMap", "mHandler"}) private void checkState() { mThreadChecker.assertOnValidThread(); mDestroyChecker.checkNotDestroyed();
diff --git a/base/android/java/src/org/chromium/base/UnownedUserDataKey.java b/base/android/java/src/org/chromium/base/UnownedUserDataKey.java index 9a6b5b6..9d9f979 100644 --- a/base/android/java/src/org/chromium/base/UnownedUserDataKey.java +++ b/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
@@ -4,11 +4,11 @@ package org.chromium.base; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -61,8 +61,9 @@ * @see UnownedUserDataHost for more details on ownership and typical usage. * @see UnownedUserData for the marker interface used for this type of data. */ +@NullMarked public final class UnownedUserDataKey<T extends UnownedUserData> { - @NonNull private final Class<T> mClazz; + private final Class<T> mClazz; // A Set that uses WeakReference<UnownedUserDataHost> internally. private final Set<UnownedUserDataHost> mWeakHostAttachments = Collections.newSetFromMap(new WeakHashMap<>()); @@ -72,11 +73,10 @@ * * @param clazz The particular {@link UnownedUserData} class. */ - public UnownedUserDataKey(@NonNull Class<T> clazz) { + public UnownedUserDataKey(Class<T> clazz) { mClazz = clazz; } - @NonNull /* package */ final Class<T> getValueClass() { return mClazz; } @@ -88,7 +88,7 @@ * @param host The host to attach the {@code object} to. * @param object The object to attach. */ - public final void attachToHost(@NonNull UnownedUserDataHost host, @NonNull T object) { + public final void attachToHost(UnownedUserDataHost host, T object) { Objects.requireNonNull(object); // Setting a new value might lead to detachment of previously attached data, including // re-entry to this key, to happen before we update the {@link #mHostAttachments}. @@ -108,8 +108,7 @@ * @param host The host to retrieve the {@link UnownedUserData} from. * @return The current {@link UnownedUserData} stored in the {@code host}, or {@code null}. */ - @Nullable - public final T retrieveDataFromHost(@NonNull UnownedUserDataHost host) { + public final @Nullable T retrieveDataFromHost(UnownedUserDataHost host) { assertNoDestroyedAttachments(); for (UnownedUserDataHost attachedHost : mWeakHostAttachments) { if (host.equals(attachedHost)) { @@ -125,7 +124,7 @@ * * @param host The host to detach from. */ - public final void detachFromHost(@NonNull UnownedUserDataHost host) { + public final void detachFromHost(UnownedUserDataHost host) { assertNoDestroyedAttachments(); for (UnownedUserDataHost attachedHost : new ArrayList<>(mWeakHostAttachments)) { if (host.equals(attachedHost)) { @@ -140,7 +139,7 @@ * * @param object The object to detach from all hosts. */ - public final void detachFromAllHosts(@NonNull T object) { + public final void detachFromAllHosts(T object) { assertNoDestroyedAttachments(); for (UnownedUserDataHost attachedHost : new ArrayList<>(mWeakHostAttachments)) { if (object.equals(attachedHost.get(this))) { @@ -155,7 +154,7 @@ * @param host The host to check if the {@link UnownedUserData} is attached to. * @return true if currently attached, false otherwise. */ - public final boolean isAttachedToHost(@NonNull UnownedUserDataHost host) { + public final boolean isAttachedToHost(UnownedUserDataHost host) { T t = retrieveDataFromHost(host); return t != null; } @@ -163,12 +162,12 @@ /** * @return Whether the {@link UnownedUserData} is currently attached to any hosts with this key. */ - public final boolean isAttachedToAnyHost(@NonNull T object) { + public final boolean isAttachedToAnyHost(T object) { return getHostAttachmentCount(object) > 0; } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - /* package */ int getHostAttachmentCount(@NonNull T object) { + /* package */ int getHostAttachmentCount(T object) { assertNoDestroyedAttachments(); int ret = 0; for (UnownedUserDataHost attachedHost : mWeakHostAttachments) {
diff --git a/base/android/java/src/org/chromium/base/UserData.java b/base/android/java/src/org/chromium/base/UserData.java index 53d8f29..7060d6a9 100644 --- a/base/android/java/src/org/chromium/base/UserData.java +++ b/base/android/java/src/org/chromium/base/UserData.java
@@ -4,10 +4,13 @@ package org.chromium.base; +import org.chromium.build.annotations.NullMarked; + /** * Interface to be implemented by the classes make themselves attacheable to * a host class that holds {@link UserDataHost}. */ +@NullMarked public interface UserData { /** * Called when {@link UserData} object needs to be destroyed.
diff --git a/base/android/java/src/org/chromium/base/UserDataHost.java b/base/android/java/src/org/chromium/base/UserDataHost.java index aa173cb..64d54cf 100644 --- a/base/android/java/src/org/chromium/base/UserDataHost.java +++ b/base/android/java/src/org/chromium/base/UserDataHost.java
@@ -5,6 +5,9 @@ package org.chromium.base; import org.chromium.base.ThreadUtils.ThreadChecker; +import org.chromium.build.annotations.EnsuresNonNull; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.HashMap; @@ -48,18 +51,13 @@ * * </code> */ +@NullMarked public final class UserDataHost { private final ThreadChecker mThreadChecker = new ThreadChecker(); - private HashMap<Class<? extends UserData>, UserData> mUserDataMap = new HashMap<>(); + private @Nullable HashMap<Class<? extends UserData>, UserData> mUserDataMap = new HashMap<>(); - private static void checkArgument(boolean condition) { - if (!condition) { - throw new IllegalArgumentException( - "Neither key nor object of UserDataHost can be null."); - } - } - + @EnsuresNonNull("mUserDataMap") private void checkThreadAndState() { mThreadChecker.assertOnValidThread(); if (mUserDataMap == null) { @@ -73,9 +71,11 @@ * @param object Object to be associated with the specified key. * @return the object just stored, or {@code null} if storing the object failed. */ - public <T extends UserData> T setUserData(Class<T> key, T object) { + public <T extends UserData> @Nullable T setUserData(Class<T> key, T object) { checkThreadAndState(); - checkArgument(key != null && object != null); + if (key == null || object == null) { + throw new IllegalArgumentException(); + } mUserDataMap.put(key, object); return getUserData(key); @@ -88,9 +88,11 @@ * @return the value to which the specified key is mapped, or null if this map * contains no mapping for {@code key}. */ - public <T extends UserData> T getUserData(Class<T> key) { + public <T extends UserData> @Nullable T getUserData(Class<T> key) { checkThreadAndState(); - checkArgument(key != null); + if (key == null) { + throw new IllegalArgumentException(); + } return key.cast(mUserDataMap.get(key)); } @@ -103,7 +105,9 @@ */ public <T extends UserData> T removeUserData(Class<T> key) { checkThreadAndState(); - checkArgument(key != null); + if (key == null) { + throw new IllegalArgumentException(); + } if (!mUserDataMap.containsKey(key)) { throw new IllegalStateException("UserData for the key is not present.");
diff --git a/base/android/java/src/org/chromium/base/ValueChangedCallback.java b/base/android/java/src/org/chromium/base/ValueChangedCallback.java index 4317cf6..ce62ebf 100644 --- a/base/android/java/src/org/chromium/base/ValueChangedCallback.java +++ b/base/android/java/src/org/chromium/base/ValueChangedCallback.java
@@ -4,10 +4,9 @@ package org.chromium.base; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.Objects; @@ -21,6 +20,7 @@ * * @param <T> The type to observe. */ +@NullMarked public class ValueChangedCallback<T> implements Callback<T> { /** * Interface for observers that care about monitoring both the old and new values when a @@ -40,13 +40,13 @@ public void onValueChanged(@Nullable T newValue, @Nullable T oldValue); } - private final @NonNull ValueChangedObserver<T> mValueChangedObserver; + private final ValueChangedObserver<T> mValueChangedObserver; private @Nullable T mLastValue; /** * @param onValueChangedObserver The {@link ValueChangedObserver} that receives updates. */ - public ValueChangedCallback(@NonNull ValueChangedObserver<T> onValueChangedObserver) { + public ValueChangedCallback(ValueChangedObserver<T> onValueChangedObserver) { mValueChangedObserver = onValueChangedObserver; }
diff --git a/base/android/java/src/org/chromium/base/WrappedClassLoader.java b/base/android/java/src/org/chromium/base/WrappedClassLoader.java index 45a6bb0..4d64225 100644 --- a/base/android/java/src/org/chromium/base/WrappedClassLoader.java +++ b/base/android/java/src/org/chromium/base/WrappedClassLoader.java
@@ -6,10 +6,14 @@ import dalvik.system.BaseDexClassLoader; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * This class wraps two given ClassLoader objects and delegates findClass() and findLibrary() calls * to the first one that returns a match. */ +@NullMarked public class WrappedClassLoader extends ClassLoader { private final ClassLoader mPrimaryClassLoader; private final ClassLoader mSecondaryClassLoader; @@ -34,7 +38,7 @@ } @Override - public String findLibrary(String name) { + public @Nullable String findLibrary(String name) { String path = null; // BaseDexClassLoader has a public findLibrary method, but ClassLoader's is protected // so we can only do this for classloaders that actually do extend BaseDexClassLoader.
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java index 30c7aec..e429f78c 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
@@ -18,6 +18,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.TimeUtils; import org.chromium.base.TraceEvent; +import org.chromium.build.annotations.NullMarked; import java.util.concurrent.atomic.AtomicBoolean; @@ -25,6 +26,7 @@ * This class receives OnFrameMetricsAvailableListener.onFrameMetricsAvailable() callbacks and * records frame durations in a FrameMetricsStore instance. */ +@NullMarked @RequiresApi(api = VERSION_CODES.N) public class FrameMetricsListener implements OnFrameMetricsAvailableListener { private class DisplayListenerBackend implements DisplayListener {
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java index 0643b76..c7db03b 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
@@ -8,6 +8,7 @@ import org.chromium.base.TimeUtils; import org.chromium.base.TraceEvent; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; import java.util.ArrayList; import java.util.Collections; @@ -17,6 +18,7 @@ /** * This class stores relevant metrics from FrameMetrics between the calls to UMA reporting methods. */ +@NullMarked public class FrameMetricsStore { private final ThreadChecker mThreadChecker = new ThreadChecker(); // An arbitrary value from which to create a trace event async track. The only risk if this
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java index 25286eb..9857c8d 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
@@ -14,6 +14,7 @@ import org.chromium.base.ApplicationStatus.ActivityStateListener; import org.chromium.base.ThreadUtils.ThreadChecker; import org.chromium.base.lifetime.DestroyChecker; +import org.chromium.build.annotations.NullMarked; import java.lang.ref.WeakReference; @@ -22,6 +23,7 @@ * periodic jank metric reporting and frame metric recording based on the Activity's lifecycle * events. */ +@NullMarked @RequiresApi(api = VERSION_CODES.N) class JankActivityTracker extends JankTrackerStateController implements ActivityStateListener { private final ThreadChecker mThreadChecker = new ThreadChecker();
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java b/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java index d2d1a9e..d6033bc 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankEndScenarioTime.java
@@ -4,16 +4,20 @@ package org.chromium.base.jank_tracker; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * A simple Data structure that holds a uptimeNanos that we wish to have data up until, and a delay * to wait for this data from the Android FrameMetrics API. */ +@NullMarked public final class JankEndScenarioTime { public final long endScenarioTimeNs; // 100ms should be long enough to receive frame metric timeline if they haven't been dropped. public final long timeoutDelayMs = 100; - public static JankEndScenarioTime endAt(long uptimeNanos) { + public static @Nullable JankEndScenarioTime endAt(long uptimeNanos) { if (uptimeNanos <= 0) { return null; }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java b/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java index 5512f7e..5709e7a9 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
@@ -7,7 +7,10 @@ import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** Sends Android jank metrics to native to be recorded using UMA. */ +@NullMarked @JNINamespace("base::android") public class JankMetricUMARecorder { public static void recordJankMetricsToUMA(
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java b/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java index 62daec4..7820769 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankMetrics.java
@@ -4,10 +4,13 @@ package org.chromium.base.jank_tracker; +import org.chromium.build.annotations.NullMarked; + /** * This class is a container for jank metrics, which are processed FrameMetrics ready to be uploaded * to UMA. */ +@NullMarked class JankMetrics { public final long[] timestampsNs; public final long[] durationsNs;
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java index 15cf69e..51e707d7 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java
@@ -7,12 +7,15 @@ import android.os.Handler; import org.chromium.base.TraceEvent; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * This runnable receives a FrameMetricsStore instance and starts/stops tracking a given scenario. * When a scenario stops it takes its metrics and sends them to native to be recorded in UMA. * This is executed by JankReportingScheduler on its own thread. */ +@NullMarked class JankReportingRunnable implements Runnable { private final FrameMetricsStore mMetricsStore; private final JankScenario mScenario; @@ -21,7 +24,7 @@ private final Handler mHandler; // If metrics should be collected based on the state (scrolling) specify a // JankEndScenarioTime. - private final JankEndScenarioTime mJankEndScenarioTime; + private final @Nullable JankEndScenarioTime mJankEndScenarioTime; // When a JankEndScenarioTime is specified we don't immediately collect the metrics but instead // post a task (this runnable). However to keep code reuse the same between delay/no-delay we @@ -67,7 +70,7 @@ JankScenario scenario, boolean isStartingTracking, Handler handler, - JankEndScenarioTime endScenarioTime) { + @Nullable JankEndScenarioTime endScenarioTime) { mMetricsStore = metricsStore; mScenario = scenario; mIsStartingTracking = isStartingTracking; @@ -92,13 +95,10 @@ mMetricsStore.startTrackingScenario(mScenario); return; } - boolean dataIsReady = - mJankEndScenarioTime == null - || (mJankEndScenarioTime != null - && mMetricsStore.hasReceivedMetricsPast( - mJankEndScenarioTime.endScenarioTimeNs)); - - if (dataIsReady) { + if (mJankEndScenarioTime == null + || mMetricsStore.hasReceivedMetricsPast( + mJankEndScenarioTime.endScenarioTimeNs)) { + // Data is ready. new FinalReportingRunnable().run(); } else { mHandler.postDelayed(
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java index d90c83bb..2158d2db6 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java
@@ -7,12 +7,16 @@ import android.os.Handler; import android.os.HandlerThread; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.util.concurrent.atomic.AtomicBoolean; /** * This class receives requests to start and stop jank scenario tracking and runs them in a * HandlerThread it creates. In addition it handles the recording of periodic jank metrics. */ +@NullMarked public class JankReportingScheduler { private static final long PERIODIC_METRIC_DELAY_MS = 5_000; private final FrameMetricsStore mFrameMetricsStore; @@ -77,7 +81,8 @@ finishTrackingScenario(scenario, JankEndScenarioTime.endAt(endScenarioTimeNs)); } - public void finishTrackingScenario(JankScenario scenario, JankEndScenarioTime endScenarioTime) { + public void finishTrackingScenario( + JankScenario scenario, @Nullable JankEndScenarioTime endScenarioTime) { // We store the stop task in case the delay is greater than zero and we start this scenario // again. JankReportingRunnable runnable =
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java b/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java index 42e7b4c4..6827d5db 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java
@@ -6,10 +6,13 @@ import androidx.annotation.IntDef; +import org.chromium.build.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; +@NullMarked public class JankScenario { /** * A list of jank scenarios to be tracked, each scenario corresponds to a specific user journey
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java index b3f22ce..e3344c4 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java
@@ -4,7 +4,10 @@ package org.chromium.base.jank_tracker; +import org.chromium.build.annotations.NullMarked; + /** Interface for Android UI jank tracking. */ +@NullMarked public interface JankTracker { /** * Starts tracking UI jank for a specific use scenario (e.g. Tab switcher, Omnibox, etc.),
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java index dbef27b1..27a4d23 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java
@@ -9,6 +9,9 @@ import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; +import org.chromium.build.annotations.EnsuresNonNullIf; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.ref.WeakReference; @@ -19,15 +22,14 @@ * based on activity state. When the activity is being destroyed {@link #destroy()} should be called * to clear the activity state observer. All methods should be called from the UI thread. */ +@NullMarked public class JankTrackerImpl implements JankTracker { // We use the DEADLINE field in the Android FrameMetrics which was added in S. private static final boolean IS_TRACKING_ENABLED = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; - private boolean mIsInitialized; - private JankTrackerStateController mController; - private JankReportingScheduler mReportingScheduler; - private boolean mDestroyed; + private @Nullable JankTrackerStateController mController; + private @Nullable JankReportingScheduler mReportingScheduler; /** * Creates a new JankTracker instance tracking UI rendering of an activity. Metric recording @@ -44,7 +46,9 @@ public void run() { // If we've been destroyed or the Activity is gone early out. Activity innerActivity = ref.get(); - if (mDestroyed || innerActivity == null || innerActivity.isDestroyed()) { + if (mController == null + || innerActivity == null + || innerActivity.isDestroyed()) { return; } @@ -78,6 +82,7 @@ constructInternalFinal(controller); } + @EnsuresNonNullIf("mReportingScheduler") private boolean constructInternalPreController(JankReportingScheduler scheduler) { if (!IS_TRACKING_ENABLED) { mReportingScheduler = null; @@ -88,15 +93,23 @@ return true; } + @EnsuresNonNullIf({"mController", "mReportingScheduler"}) + private boolean isInitialized() { + if (mController == null) { + return false; + } + assert mReportingScheduler != null; + return true; + } + private void constructInternalFinal(JankTrackerStateController controller) { mController = controller; mController.initialize(); - mIsInitialized = true; } @Override public void startTrackingScenario(JankScenario scenario) { - if (!IS_TRACKING_ENABLED || !mIsInitialized) return; + if (!isInitialized()) return; mReportingScheduler.startTrackingScenario(scenario); } @@ -108,7 +121,7 @@ @Override public void finishTrackingScenario(JankScenario scenario, long endScenarioTimeNs) { - if (!IS_TRACKING_ENABLED || !mIsInitialized) return; + if (!isInitialized()) return; mReportingScheduler.finishTrackingScenario(scenario, endScenarioTimeNs); } @@ -116,8 +129,8 @@ /** Stops listening for Activity state changes. */ @Override public void destroy() { - mDestroyed = true; - if (!IS_TRACKING_ENABLED || !mIsInitialized) return; + if (!isInitialized()) return; mController.destroy(); + mController = null; } }
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java index 2de3d2cd..28bc35ec 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java
@@ -7,6 +7,8 @@ import android.view.Window; import org.chromium.base.Log; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * A simple holder class to enable easy starting and stopping of metric listening as well as @@ -14,6 +16,7 @@ * should be hooked up to some sort of listener to when to start/stop listening and periodic * metrics. */ +@NullMarked public class JankTrackerStateController { private static final String TAG = "JankTracker"; protected final FrameMetricsListener mFrameMetricsListener; @@ -33,7 +36,7 @@ mReportingScheduler.stopReportingPeriodicMetrics(); } - public void startMetricCollection(Window window) { + public void startMetricCollection(@Nullable Window window) { mFrameMetricsListener.setIsListenerRecording(true); if (window != null) { window.addOnFrameMetricsAvailableListener( @@ -41,7 +44,7 @@ } } - public void stopMetricCollection(Window window) { + public void stopMetricCollection(@Nullable Window window) { mFrameMetricsListener.setIsListenerRecording(false); if (window != null) { try {
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java index 1fd9124..5b2cd29 100644 --- a/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java +++ b/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java
@@ -4,7 +4,10 @@ package org.chromium.base.jank_tracker; +import org.chromium.build.annotations.NullMarked; + /** Placeholder implementation of JankTracker. */ +@NullMarked public class PlaceholderJankTracker implements JankTracker { @Override public void startTrackingScenario(JankScenario scenario) {}
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index 8ca2fc3..0022222 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -34,6 +34,8 @@ import org.chromium.base.metrics.UmaRecorderHolder; import org.chromium.build.BuildConfig; import org.chromium.build.NativeLibraries; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -52,6 +54,7 @@ * <p>See also base/android/library_loader/library_loader_hooks.cc, which contains the native * counterpart to this class. */ +@NullMarked @JNINamespace("base::android") public class LibraryLoader { private static final String TAG = "LibraryLoader"; @@ -119,10 +122,10 @@ // Always accessed via getLinker() because the choice of the class can be influenced by // public setLinkerImplementation() below. @GuardedBy("mLock") - private Linker mLinker; + private @Nullable Linker mLinker; @GuardedBy("mLock") - private NativeLibraryPreloader mLibraryPreloader; + private @Nullable NativeLibraryPreloader mLibraryPreloader; @GuardedBy("mLock") private boolean mLibraryPreloaderCalled; @@ -152,7 +155,7 @@ @VisibleForTesting public static boolean sOverrideNativeLibraryCannotBeLoadedForTesting; // Allow embedders to register a callback to handle native library load failures. - public static Callback<UnsatisfiedLinkError> sLoadFailedCallback; + public static @Nullable Callback<UnsatisfiedLinkError> sLoadFailedCallback; // Returns true when sharing RELRO between the browser process and the app zygote should *not* // be attempted.
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java b/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java index 15d5cc1..1f1684e 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java
@@ -13,6 +13,7 @@ import org.chromium.base.TraceEvent; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; +import org.chromium.build.annotations.NullMarked; import java.util.concurrent.atomic.AtomicBoolean; @@ -22,6 +23,7 @@ * See also base/android/library_loader/library_prefetcher_hooks.cc, which contains * the native counterpart to this class. */ +@NullMarked @JNINamespace("base::android") public class LibraryPrefetcher {
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java index 70b176b..7be4710b 100644 --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -4,6 +4,8 @@ package org.chromium.base.library_loader; +import static org.chromium.build.NullUtil.assumeNonNull; + import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Parcel; @@ -11,7 +13,6 @@ import android.os.Parcelable; import androidx.annotation.IntDef; -import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import org.jni_zero.AccessedByNative; @@ -19,6 +20,8 @@ import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -68,6 +71,7 @@ * available to then send the Bundle to Linkers in other processes, consumed * by takeSharedRelrosFromBundle(). */ +@NullMarked class Linker { private static final String TAG = "Linker"; @@ -93,12 +97,12 @@ // process is a "RELRO producer". @GuardedBy("mLock") @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - protected LibInfo mLocalLibInfo; + protected @Nullable LibInfo mLocalLibInfo; // The library info that was transferred from another process. Only useful if it contains RELRO // FD. @GuardedBy("mLock") - private LibInfo mRemoteLibInfo; + private @Nullable LibInfo mRemoteLibInfo; // Whether this Linker instance should potentially create the RELRO region. Even if true, the // library loading can fall back to the system linker without producing the region. The default @@ -153,7 +157,7 @@ } } - private static Linker sLinkerForAssert; + private static @Nullable Linker sLinkerForAssert; Linker() { // Only one instance is allowed in a given process because effects of loading a library are @@ -246,7 +250,10 @@ if (mState != State.UNINITIALIZED) return; chooseAndReserveMemoryRange(asRelroProducer, preference, addressHint); if (DEBUG) { - Log.i(TAG, "ensureInitialized: chose address=0x%x", mLocalLibInfo.mLoadAddress); + Log.i( + TAG, + "ensureInitialized: chose address=0x%x", + assumeNonNull(mLocalLibInfo).mLoadAddress); } mState = State.INITIALIZED; } @@ -333,7 +340,7 @@ // being ignored in native anyway. It seems the only effect of removing this check here // will be extra added samples to the RelroSharingStatus2 histogram. This will be a tiny // bit smoother to do after M99. - return mLocalLibInfo.mLoadAddress != 0; + return assumeNonNull(mLocalLibInfo).mLoadAddress != 0; } return false; } @@ -386,7 +393,7 @@ Log.w(TAG, "Failed to load native library with shared RELRO, retrying without"); try { // Retry without relocation sharing. - mLocalLibInfo.mLoadAddress = 0; + assumeNonNull(mLocalLibInfo).mLoadAddress = 0; attemptLoadLibraryLocked(library, RelroSharingMode.NO_SHARING); } catch (UnsatisfiedLinkError e2) { Log.w(TAG, "Failed to load native library without RELRO sharing"); @@ -406,10 +413,11 @@ if (DEBUG) Log.i(TAG, "putSharedRelrosToBundle: state=%d", mState); if (mState == State.DONE_PROVIDE_RELRO) { assert mRelroProducer; - relros = mLocalLibInfo.toBundle(); + relros = assumeNonNull(mLocalLibInfo).toBundle(); } bundle.putBundle(SHARED_RELROS, relros); if (DEBUG && relros != null) { + assert mLocalLibInfo != null; Log.i( TAG, "putSharedRelrosToBundle() puts mLoadAddress=0x%x, mLoadSize=%d, " @@ -474,6 +482,7 @@ @GuardedBy("mLock") private void loadWithoutProducingRelro(String libFilePath) { assert mRemoteLibInfo == null || libFilePath.equals(mRemoteLibInfo.mLibFilePath); + assert mLocalLibInfo != null; if (!getLinkerJni() .loadLibrary(libFilePath, mLocalLibInfo, /* spawnRelroRegion= */ false)) { resetAndThrow(String.format("Unable to load library: %s", libFilePath), null); @@ -485,22 +494,23 @@ // System.loadLibrary() is useful. Records a histogram to count failures. @GuardedBy("mLock") private void loadAndProduceSharedRelro(String libFilePath) { - mLocalLibInfo.mLibFilePath = libFilePath; - if (getLinkerJni().loadLibrary(libFilePath, mLocalLibInfo, /* spawnRelroRegion= */ true)) { + var localLibInfo = assumeNonNull(mLocalLibInfo); + localLibInfo.mLibFilePath = libFilePath; + if (getLinkerJni().loadLibrary(libFilePath, localLibInfo, /* spawnRelroRegion= */ true)) { if (DEBUG) { Log.i( TAG, "Successfully spawned RELRO: mLoadAddress=0x%x, mLoadSize=%d", - mLocalLibInfo.mLoadAddress, - mLocalLibInfo.mLoadSize); + localLibInfo.mLoadAddress, + localLibInfo.mLoadSize); } } else { Log.e(TAG, "Unable to load with Linker, using the system linker instead"); // System.loadLibrary() below implements the fallback. - mLocalLibInfo.mRelroFd = -1; + localLibInfo.mRelroFd = -1; } RecordHistogram.recordBooleanHistogram( - "ChromiumAndroidLinker.RelroProvidedSuccessfully", mLocalLibInfo.mRelroFd != -1); + "ChromiumAndroidLinker.RelroProvidedSuccessfully", localLibInfo.mRelroFd != -1); } /** @@ -567,18 +577,18 @@ */ @GuardedBy("mLock") private void atomicReplaceRelroLocked(boolean relroAvailableImmediately) { - assert mRemoteLibInfo != null; assert mState == State.DONE; - if (mRemoteLibInfo.mRelroFd == -1) return; + var remoteLibInfo = assumeNonNull(mRemoteLibInfo); + if (remoteLibInfo.mRelroFd == -1) return; if (DEBUG) { Log.i( TAG, "Received mRemoteLibInfo: mLoadAddress=0x%x, mLoadSize=%d", - mRemoteLibInfo.mLoadAddress, - mRemoteLibInfo.mLoadSize); + remoteLibInfo.mLoadAddress, + remoteLibInfo.mLoadSize); } if (mLocalLibInfo == null) return; - getLinkerJni().useRelros(mLocalLibInfo.mLoadAddress, mRemoteLibInfo); + getLinkerJni().useRelros(mLocalLibInfo.mLoadAddress, remoteLibInfo); // *Not* closing the RELRO FD after using it because the FD may need to be transferred to // another process after this point. if (DEBUG) Log.i(TAG, "Immediate RELRO availability: %b", relroAvailableImmediately); @@ -619,7 +629,7 @@ } @GuardedBy("mLock") - private void resetAndThrow(String message, UnsatisfiedLinkError cause) { + private void resetAndThrow(String message, @Nullable UnsatisfiedLinkError cause) { mState = State.INITIALIZED; Log.e(TAG, message); var e = new UnsatisfiedLinkError(message); @@ -670,7 +680,7 @@ } } - public static LibInfo fromBundle(Bundle bundle) { + public static @Nullable LibInfo fromBundle(Bundle bundle) { bundle.setClassLoader(Linker.class.getClassLoader()); return bundle.getParcelable(EXTRA_LINKER_LIB_INFO); } @@ -721,7 +731,7 @@ } }; - public String mLibFilePath; + public @Nullable String mLibFilePath; // IMPORTANT: Don't change these fields without modifying the // native code that accesses them directly! @@ -743,7 +753,7 @@ * @param libInfo holds the output values: |mLoadAddress| and |mLoadSize|. On failure sets * the |libInfo.mLoadAddress| to 0. */ - void findMemoryRegionAtRandomAddress(@NonNull LibInfo libInfo); + void findMemoryRegionAtRandomAddress(LibInfo libInfo); /** * Reserves the fixed address range starting at |libInfo.mLoadAddress| big enough to load @@ -754,7 +764,7 @@ * returns the size in |libInfo.mLoadSize|. On failure sets the * |libInfo.mLoadAddress| to 0. */ - void reserveMemoryForLibrary(@NonNull LibInfo libInfo); + void reserveMemoryForLibrary(LibInfo libInfo); /** * Finds the (named) address range reservation made by the system zygote and dedicated for @@ -765,7 +775,7 @@ * the start address and the size of the webview memory reservation to them. * @return whether the region was found. */ - boolean findRegionReservedByWebViewZygote(@NonNull LibInfo libInfo); + boolean findRegionReservedByWebViewZygote(LibInfo libInfo); /** * Load the native library. @@ -796,7 +806,7 @@ int getRelroSharingResult(); } - private static Linker.Natives sNativesInstance; + private static Linker.@Nullable Natives sNativesInstance; static void setLinkerNativesForTesting(Natives instance) { sNativesInstance = instance;
diff --git a/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java b/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java index 981650dc..d1c77a5 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java +++ b/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java
@@ -4,7 +4,7 @@ package org.chromium.base.library_loader; -import androidx.annotation.NonNull; +import org.chromium.build.annotations.NullMarked; /** * Mockable stub for all native methods in Linker. @@ -12,19 +12,20 @@ * This functionality is usually generated from @NativeMethods, which cannot be used for the * auxiliary native library used by classes in Linker and other classes in this package. */ +@NullMarked class LinkerJni implements Linker.Natives { @Override - public void findMemoryRegionAtRandomAddress(@NonNull Linker.LibInfo libInfo) { + public void findMemoryRegionAtRandomAddress(Linker.LibInfo libInfo) { nativeFindMemoryRegionAtRandomAddress(libInfo); } @Override - public void reserveMemoryForLibrary(@NonNull Linker.LibInfo libInfo) { + public void reserveMemoryForLibrary(Linker.LibInfo libInfo) { nativeReserveMemoryForLibrary(libInfo); } @Override - public boolean findRegionReservedByWebViewZygote(@NonNull Linker.LibInfo libInfo) { + public boolean findRegionReservedByWebViewZygote(Linker.LibInfo libInfo) { return nativeFindRegionReservedByWebViewZygote(libInfo); } @@ -46,13 +47,11 @@ // Does not use JNI Generator because the native side is in libchromium_linker.so rather // libmonochrome.so - private static native void nativeFindMemoryRegionAtRandomAddress( - @NonNull Linker.LibInfo libInfo); + private static native void nativeFindMemoryRegionAtRandomAddress(Linker.LibInfo libInfo); - private static native void nativeReserveMemoryForLibrary(@NonNull Linker.LibInfo libInfo); + private static native void nativeReserveMemoryForLibrary(Linker.LibInfo libInfo); - private static native boolean nativeFindRegionReservedByWebViewZygote( - @NonNull Linker.LibInfo libInfo); + private static native boolean nativeFindRegionReservedByWebViewZygote(Linker.LibInfo libInfo); private static native boolean nativeLoadLibrary( String libFilePath, Linker.LibInfo libInfo, boolean spawnRelroRegion);
diff --git a/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java b/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java index 43523bb..bd36e2f 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java +++ b/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java
@@ -6,10 +6,13 @@ import androidx.annotation.IntDef; +import org.chromium.build.annotations.NullMarked; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** These are the possible failures from the LibraryLoader */ +@NullMarked @IntDef({ LoaderErrors.NORMAL_COMPLETION, LoaderErrors.FAILED_TO_REGISTER_JNI,
diff --git a/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java b/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java index f476014..1f05768 100644 --- a/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java +++ b/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java
@@ -4,6 +4,8 @@ package org.chromium.base.library_loader; +import org.chromium.build.annotations.NullMarked; + /** * This is interface to preload the native library before calling System.loadLibrary. * @@ -13,6 +15,7 @@ * dlopen() later called by System.loadLibrary() becomes a noop. This is what the * only subclass (WebViewLibraryPreloader) is doing. */ +@NullMarked public abstract class NativeLibraryPreloader { public abstract int loadLibrary(String packageName); }
diff --git a/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java b/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java index 6e7f422..4724f4cd 100644 --- a/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java +++ b/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java
@@ -4,7 +4,10 @@ package org.chromium.base.library_loader; +import org.chromium.build.annotations.NullMarked; + /** The exception that is thrown when the initialization of a process has failed. */ +@NullMarked public class ProcessInitException extends RuntimeException { /** * @param errorCode This will be one of the LoaderErrors error codes.
diff --git a/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java b/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java index e23437a6..3f0430cb3 100644 --- a/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java +++ b/base/android/java/src/org/chromium/base/lifetime/DestroyChecker.java
@@ -4,6 +4,8 @@ package org.chromium.base.lifetime; +import org.chromium.build.annotations.NullMarked; + /** * Utility class that help ensure destruction of objects happens only once. * @@ -20,6 +22,7 @@ * It is therefore not necessary to call {@link #checkNotDestroyed()} in that case. It is also * not allowed to call {@link #destroy()} more than once. */ +@NullMarked public class DestroyChecker implements Destroyable { private boolean mIsDestroyed;
diff --git a/base/android/java/src/org/chromium/base/lifetime/Destroyable.java b/base/android/java/src/org/chromium/base/lifetime/Destroyable.java index 4efa150..d977be055 100644 --- a/base/android/java/src/org/chromium/base/lifetime/Destroyable.java +++ b/base/android/java/src/org/chromium/base/lifetime/Destroyable.java
@@ -4,7 +4,10 @@ package org.chromium.base.lifetime; +import org.chromium.build.annotations.NullMarked; + /** Interface for items that require a controlled clean up. */ +@NullMarked public interface Destroyable { /** Cleans up resources held by the implementing object. */ void destroy();
diff --git a/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java b/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java index 147b6ab..2dcb141f 100644 --- a/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java +++ b/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java
@@ -9,10 +9,12 @@ import org.jni_zero.CalledByNative; import org.chromium.base.Log; +import org.chromium.build.annotations.NullMarked; import java.io.IOException; /** Enables the generation of hprof files from heap dumps. */ +@NullMarked public final class JavaHeapDumpGenerator { private static final String TAG = "JavaHprofGenerator";
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java b/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java index 7cd8cb3..437d93a 100644 --- a/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java +++ b/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java
@@ -9,13 +9,14 @@ import android.os.Debug; import android.os.Process; -import androidx.annotation.Nullable; - import org.jni_zero.CalledByNative; import org.chromium.base.ContextUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** Allows calling ActivityManager#getProcessMemoryInfo() from native. */ +@NullMarked public class MemoryInfoBridge { /** * Returns the result of ActivityManager#getProcessMemoryInfo() on itself. @@ -25,7 +26,7 @@ * throttling handling code there would become incorrect otherwise. */ @CalledByNative - public static @Nullable Debug.MemoryInfo getActivityManagerMemoryInfoForSelf() { + public static Debug.@Nullable MemoryInfo getActivityManagerMemoryInfoForSelf() { ActivityManager activityManager = (ActivityManager) ContextUtils.getApplicationContext()
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java index fd8a0b8..ed32ee27 100644 --- a/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java +++ b/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java
@@ -5,8 +5,10 @@ package org.chromium.base.memory; import org.chromium.base.MemoryPressureLevel; +import org.chromium.build.annotations.NullMarked; /** Memory pressure callback interface. */ +@NullMarked @FunctionalInterface public interface MemoryPressureCallback { public void onPressure(@MemoryPressureLevel int pressure);
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java index e0a5e84..caf4aa4 100644 --- a/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java +++ b/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java
@@ -18,6 +18,8 @@ import org.chromium.base.supplier.Supplier; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * @@ -74,6 +76,7 @@ * NOTE: This class should only be used on UiThread as defined by ThreadUtils (which is * Android main thread for Chrome, but can be some other thread for WebView).</pre> */ +@NullMarked public class MemoryPressureMonitor { private static final int DEFAULT_THROTTLING_INTERVAL_MS = 60 * 1000; @@ -84,7 +87,7 @@ // Pressure received (but not reported) during the current throttling interval, // or null if no pressure was received. - private @MemoryPressureLevel Integer mThrottledPressure; + private @MemoryPressureLevel @Nullable Integer mThrottledPressure; // Whether we need to throttle pressure signals. private boolean mIsInsideThrottlingInterval; @@ -94,8 +97,8 @@ // That's for an experiment to run the broadcast receiver in the background private boolean mPostToBackgroundIsEnabled; - private Supplier<Integer> mCurrentPressureSupplierForTesting; - private MemoryPressureCallback mReportingCallbackForTesting; + private @Nullable Supplier<Integer> mCurrentPressureSupplierForTesting; + private @Nullable MemoryPressureCallback mReportingCallbackForTesting; private final Runnable mThrottlingIntervalTask = this::onThrottlingIntervalFinished; @@ -270,7 +273,7 @@ * Queries current memory pressure. * Returns null if the pressure couldn't be determined. */ - private static @MemoryPressureLevel Integer getCurrentMemoryPressure() { + private static @MemoryPressureLevel @Nullable Integer getCurrentMemoryPressure() { // We used to have a histogram here to measure the duration of each successful // ActivityManager.getMyMemoryState() call called // Android.MemoryPressureMonitor.GetMyMemoryState.Succeeded.Time. 50th percentile was 0.8ms. @@ -290,7 +293,7 @@ * Returns null if |level| couldn't be mapped and should be ignored. */ @VisibleForTesting - public static @MemoryPressureLevel Integer memoryPressureFromTrimLevel(int level) { + public static @MemoryPressureLevel @Nullable Integer memoryPressureFromTrimLevel(int level) { if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE || level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) { return MemoryPressureLevel.CRITICAL;
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java index 355bf8c..a7e71db 100644 --- a/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java +++ b/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java
@@ -12,11 +12,14 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** Centralizes UMA data collection for Android-specific memory conditions. */ +@NullMarked public class MemoryPressureUma implements ComponentCallbacks2 { @IntDef({ Notification.UNKNOWN_TRIM_LEVEL, @@ -50,7 +53,7 @@ private final String mHistogramName; - private static MemoryPressureUma sInstance; + private static @Nullable MemoryPressureUma sInstance; public static void initializeForBrowser() { initializeInstance("Browser");
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java b/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java index 9b3f769c..b1946da 100644 --- a/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java +++ b/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java
@@ -17,6 +17,7 @@ import org.chromium.base.TimeUtils; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.build.annotations.NullMarked; /** * This class is similar in principle to MemoryPurgeManager in blink, but on the browser process @@ -25,6 +26,7 @@ * * <p>UI thread only. */ +@NullMarked public class MemoryPurgeManager implements ApplicationStatus.ApplicationStateListener { private boolean mStarted; private long mLastBackgroundPeriodStart = NEVER;
diff --git a/base/android/java/src/org/chromium/base/memory/SelfFreezeCallback.java b/base/android/java/src/org/chromium/base/memory/SelfFreezeCallback.java index 8eec553..0f75d39a 100644 --- a/base/android/java/src/org/chromium/base/memory/SelfFreezeCallback.java +++ b/base/android/java/src/org/chromium/base/memory/SelfFreezeCallback.java
@@ -4,7 +4,10 @@ package org.chromium.base.memory; +import org.chromium.build.annotations.NullMarked; + /** self freeze callback interface. */ +@NullMarked @FunctionalInterface public interface SelfFreezeCallback { public void onSelfFreeze();
diff --git a/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java index 9343cdec..fd33870 100644 --- a/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java +++ b/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
@@ -7,12 +7,13 @@ import android.annotation.SuppressLint; import androidx.annotation.IntDef; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; import org.chromium.base.Log; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -31,7 +32,8 @@ * Stores metrics until given an {@link UmaRecorder} to forward the samples to. After flushing, no * longer stores metrics, instead immediately forwards them to the given {@link UmaRecorder}. */ -/* package */ final class CachingUmaRecorder implements UmaRecorder { +/* package */ @NullMarked +final class CachingUmaRecorder implements UmaRecorder { private static final String TAG = "CachingUmaRecorder"; /** @@ -240,12 +242,10 @@ * The read lock must be held while invoking methods on {@code mDelegate}. */ @GuardedBy("mRwLock") - @Nullable - private UmaRecorder mDelegate; + private @Nullable UmaRecorder mDelegate; @GuardedBy("mRwLock") - @Nullable - private List<Callback<String>> mUserActionCallbacksForTesting; + private @Nullable List<Callback<String>> mUserActionCallbacksForTesting; /** * Sets the current delegate to {@code recorder}. Forwards and clears all cached metrics if @@ -254,7 +254,7 @@ * @param recorder new delegate. * @return the previous delegate. */ - public UmaRecorder setDelegate(@Nullable final UmaRecorder recorder) { + public @Nullable UmaRecorder setDelegate(@Nullable final UmaRecorder recorder) { UmaRecorder previous; Map<String, Histogram> histogramCache = null; int droppedHistogramSampleCount = 0;
diff --git a/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java b/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java index 2f9aab6..b942684 100644 --- a/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java +++ b/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java
@@ -4,7 +4,10 @@ package org.chromium.base.metrics; +import org.chromium.build.annotations.NullMarked; + /** Represents one single bucket of a histogram, with the count of records in that bucket. */ +@NullMarked public class HistogramBucket { public final int mMin; public final long mMax;
diff --git a/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java index 88d3888..4106a11 100644 --- a/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java +++ b/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
@@ -10,6 +10,8 @@ import org.chromium.base.Callback; import org.chromium.base.TimeUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -23,6 +25,7 @@ * Note: the JNI calls are relatively costly - avoid calling these methods in performance-critical * code. */ +@NullMarked @JNINamespace("base::android") /* package */ final class NativeUmaRecorder implements UmaRecorder { /** @@ -34,7 +37,7 @@ private final Map<String, Long> mNativeHints = Collections.synchronizedMap(new HashMap<String, Long>()); - private Map<Callback<String>, Long> mUserActionTestingCallbackNativePtrs; + private @Nullable Map<Callback<String>, Long> mUserActionTestingCallbackNativePtrs; @Override public void recordBooleanHistogram(String name, boolean sample) {
diff --git a/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java index 78340cd..d7f64bc 100644 --- a/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java +++ b/base/android/java/src/org/chromium/base/metrics/NoopUmaRecorder.java
@@ -5,12 +5,14 @@ package org.chromium.base.metrics; import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; import java.util.Collections; import java.util.List; /** An empty implementation of {@link UmaRecorder}. */ -/* package */ class NoopUmaRecorder implements UmaRecorder { +/* package */ @NullMarked +class NoopUmaRecorder implements UmaRecorder { @Override public void recordBooleanHistogram(String name, boolean sample) {}
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java index 41ba92e1..e2fbdc17 100644 --- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java +++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -6,11 +6,14 @@ import android.text.format.DateUtils; +import org.chromium.build.annotations.NullMarked; + import java.util.List; /** * Java API for recording UMA histograms. * */ +@NullMarked public class RecordHistogram { /** * Records a sample in a boolean UMA histogram of the given name. Boolean histogram has two
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java index c0a8b80..3e8e8ba 100644 --- a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java +++ b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
@@ -5,6 +5,7 @@ package org.chromium.base.metrics; import org.chromium.base.TimeUtils; +import org.chromium.build.annotations.NullMarked; /** * Java API for recording UMA actions. @@ -16,6 +17,7 @@ * We use a script ({@code extract_actions.py{}) to scan the source code and extract actions. A * string literal (not a variable) must be passed to {@link #record(String)}. */ +@NullMarked public class RecordUserAction { /** * Similar to {@code base::RecordAction()} in C++.
diff --git a/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java b/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java index 8b3b746..ad81842 100644 --- a/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java +++ b/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java
@@ -6,6 +6,8 @@ import android.os.Trace; +import org.chromium.build.annotations.NullMarked; + /** * An alternative to @{TraceEvent} that allows us to trace events before native initialization. * @@ -13,6 +15,7 @@ * directly purges to the kernel debug message but that method does not allow tracing events to be * written *after* the event occurrence. */ +@NullMarked public class ScopedSysTraceEvent implements AutoCloseable { /** The maximum length of a section name. Longer names will be truncated. */ // From:
diff --git a/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java b/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java index ac867ee..9ed8c531 100644 --- a/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java +++ b/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java
@@ -8,7 +8,10 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.NullMarked; + /** Java API which exposes the registered histograms on the native side as JSON test. */ +@NullMarked @JNINamespace("base::android") public final class StatisticsRecorderAndroid { private StatisticsRecorderAndroid() {}
diff --git a/base/android/java/src/org/chromium/base/metrics/TimingMetric.java b/base/android/java/src/org/chromium/base/metrics/TimingMetric.java index 97ac4f1f..79242a1a1 100644 --- a/base/android/java/src/org/chromium/base/metrics/TimingMetric.java +++ b/base/android/java/src/org/chromium/base/metrics/TimingMetric.java
@@ -5,9 +5,9 @@ package org.chromium.base.metrics; import androidx.annotation.IntDef; -import androidx.annotation.NonNull; import org.chromium.base.TimeUtils; +import org.chromium.build.annotations.NullMarked; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -17,6 +17,7 @@ * block. Measures time elapsed between instantiation and the call to close using supplied time * source. */ +@NullMarked public class TimingMetric implements AutoCloseable { @IntDef({TimerType.SHORT_UPTIME, TimerType.MEDIUM_UPTIME, TimerType.SHORT_THREAD_TIME}) @Retention(RetentionPolicy.SOURCE) @@ -36,7 +37,7 @@ * * @param metricName The name of the histogram to record. */ - public static TimingMetric shortUptime(@NonNull String metricName) { + public static TimingMetric shortUptime(String metricName) { TimingMetric ret = new TimingMetric(metricName, TimerType.SHORT_UPTIME); ret.mStartTime = TimeUtils.uptimeMillis(); return ret; @@ -48,7 +49,7 @@ * * @param metricName The name of the histogram to record. */ - public static TimingMetric mediumUptime(@NonNull String metricName) { + public static TimingMetric mediumUptime(String metricName) { TimingMetric ret = new TimingMetric(metricName, TimerType.MEDIUM_UPTIME); ret.mStartTime = TimeUtils.uptimeMillis(); return ret; @@ -60,7 +61,7 @@ * * @param metricName The name of the histogram to record. */ - public static TimingMetric shortThreadTime(@NonNull String metricName) { + public static TimingMetric shortThreadTime(String metricName) { TimingMetric ret = new TimingMetric(metricName, TimerType.SHORT_THREAD_TIME); ret.mStartTime = TimeUtils.currentThreadTimeMillis(); return ret;
diff --git a/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java index 369b312..80d3c4e7 100644 --- a/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java +++ b/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java
@@ -7,10 +7,12 @@ import com.google.errorprone.annotations.DoNotMock; import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; import java.util.List; /** Common interface for code recording UMA metrics. */ +@NullMarked @DoNotMock("Use HistogramWatcher for histograms or UserActionTester for user actions instead.") public interface UmaRecorder { /** Records a single sample of a boolean histogram. */
diff --git a/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java b/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java index b938fbe..ef8ece0 100644 --- a/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java +++ b/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java
@@ -4,7 +4,10 @@ package org.chromium.base.metrics; +import org.chromium.build.annotations.NullMarked; + /** Holds the {@link CachingUmaRecorder} used by {@link RecordHistogram}. */ +@NullMarked public class UmaRecorderHolder { private UmaRecorderHolder() {}
diff --git a/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java b/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java index e250f983..00aa33c7 100644 --- a/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/DestroyableObservableSupplier.java
@@ -5,6 +5,7 @@ package org.chromium.base.supplier; import org.chromium.base.lifetime.Destroyable; +import org.chromium.build.annotations.NullMarked; /** * An {@link ObservableSupplier} that may be destroyed by anyone with a reference to the object. @@ -14,4 +15,5 @@ * * @param <E> The type of the wrapped object. */ +@NullMarked public interface DestroyableObservableSupplier<E> extends ObservableSupplier<E>, Destroyable {}
diff --git a/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplier.java b/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplier.java index 9f29d76..9fb0c1e 100644 --- a/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplier.java
@@ -4,9 +4,9 @@ package org.chromium.base.supplier; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * Wraps a lazy-loaded nullable object, notifying observers a single time when the dependency @@ -15,6 +15,7 @@ * * @param <T> The type of the wrapped object. */ +@NullMarked public interface LazyOneshotSupplier<T> { /** * Add a callback that's called when the object owned by this supplier is available. If the
diff --git a/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplierImpl.java b/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplierImpl.java index a2fab0f..ba08ecc 100644 --- a/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplierImpl.java +++ b/base/android/java/src/org/chromium/base/supplier/LazyOneshotSupplierImpl.java
@@ -4,11 +4,11 @@ package org.chromium.base.supplier; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; import org.chromium.base.Promise; import org.chromium.base.ThreadUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * Abstract implementation of {@link LazySupplier} to be used by classes providing it as a @@ -37,6 +37,7 @@ * * @param <T> The type of the wrapped object. */ +@NullMarked public abstract class LazyOneshotSupplierImpl<T> implements LazyOneshotSupplier<T> { private final Promise<T> mPromise = new Promise<>(); private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker();
diff --git a/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java b/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java index f429eab..0a65f004 100644 --- a/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java
@@ -5,6 +5,8 @@ package org.chromium.base.supplier; import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * ObservableSupplier wraps an asynchronously provided object E, notifying observers when the @@ -26,6 +28,7 @@ * * @param <E> The type of the wrapped object. */ +@NullMarked public interface ObservableSupplier<E> extends Supplier<E> { /** * @param obs An observer to be notified when the object owned by this supplier is available. @@ -33,6 +36,7 @@ * current message loop (so long as the object hasn't changed). * @return The current object or null if it hasn't been set yet. */ + @Nullable E addObserver(Callback<E> obs); /**
diff --git a/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java b/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java index 319e6c35..3d008300a 100644 --- a/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java +++ b/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java
@@ -6,12 +6,12 @@ import android.os.Handler; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils.ThreadChecker; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.Objects; @@ -30,11 +30,12 @@ * * @param <E> The type of the wrapped object. */ -public class ObservableSupplierImpl<E> implements ObservableSupplier<E> { +@NullMarked +public class ObservableSupplierImpl<E extends @Nullable Object> implements ObservableSupplier<E> { private final ThreadChecker mThreadChecker = new ThreadChecker(); private final Handler mHandler = new Handler(); - private E mObject; + private @Nullable E mObject; private final ObserverList<Callback<E>> mObservers = new ObserverList<>(); public ObservableSupplierImpl() { @@ -47,7 +48,7 @@ } @Override - public E addObserver(Callback<E> obs) { + public @Nullable E addObserver(Callback<E> obs) { // ObserverList has its own ThreadChecker. mObservers.addObserver(obs); @@ -85,7 +86,7 @@ mObject = object; for (Callback<E> observer : mObservers) { - observer.onResult(mObject); + observer.onResult(object); } }
diff --git a/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java b/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java index 2c0c8ca9..5934a9b6 100644 --- a/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java +++ b/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java
@@ -4,9 +4,8 @@ package org.chromium.base.supplier; -import androidx.annotation.NonNull; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; import java.lang.ref.WeakReference; @@ -27,6 +26,7 @@ * * @param <E> The type of the wrapped object. */ +@NullMarked public class OneShotCallback<E> { private final Callback<E> mCallbackWrapper = new CallbackWrapper(); private final WeakReference<ObservableSupplier<E>> mWeakSupplier; @@ -38,7 +38,7 @@ * @param supplier The {@link ObservableSupplier} to wait for. * @param callback The {@link Callback} to notify with a valid value. */ - public OneShotCallback(@NonNull ObservableSupplier<E> supplier, @NonNull Callback<E> callback) { + public OneShotCallback(ObservableSupplier<E> supplier, Callback<E> callback) { mWeakSupplier = new WeakReference<>(supplier); mCallback = callback;
diff --git a/base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java b/base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java index 5b7a72a..c6c51f1 100644 --- a/base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/OneshotSupplier.java
@@ -4,9 +4,9 @@ package org.chromium.base.supplier; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * OneshotSupplier wraps an asynchronously provided, non-null object {@code T}, notifying @@ -39,6 +39,7 @@ * * @param <T> The type of the wrapped object. */ +@NullMarked public interface OneshotSupplier<T> extends Supplier<T> { /** * Add a callback that's called when the object owned by this supplier is available.
diff --git a/base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java b/base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java index 234f29f..d0a3fb4 100644 --- a/base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java +++ b/base/android/java/src/org/chromium/base/supplier/OneshotSupplierImpl.java
@@ -4,12 +4,11 @@ package org.chromium.base.supplier; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; import org.chromium.base.Promise; import org.chromium.base.ThreadUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * Concrete implementation of {@link OneshotSupplier} to be used by classes owning a @@ -26,12 +25,13 @@ * * @param <T> The type of the wrapped object. */ +@NullMarked public class OneshotSupplierImpl<T> implements OneshotSupplier<T> { private final Promise<T> mPromise = new Promise<>(); private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker(); @Override - public T onAvailable(Callback<T> callback) { + public @Nullable T onAvailable(Callback<T> callback) { mThreadChecker.assertOnValidThread(); mPromise.then(callback); return get(); @@ -50,7 +50,7 @@ * * @param object The object to supply. */ - public void set(@NonNull T object) { + public void set(T object) { mThreadChecker.assertOnValidThread(); assert !mPromise.isFulfilled(); assert object != null;
diff --git a/base/android/java/src/org/chromium/base/supplier/Supplier.java b/base/android/java/src/org/chromium/base/supplier/Supplier.java index 2e0a5f69..9c7c8a3 100644 --- a/base/android/java/src/org/chromium/base/supplier/Supplier.java +++ b/base/android/java/src/org/chromium/base/supplier/Supplier.java
@@ -4,13 +4,17 @@ package org.chromium.base.supplier; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** - * Based on Java 8's java.util.function.Supplier. - * Similar to Callable<T>, but without a checked Exception and with #hasValue(). + * Based on Java 8's java.util.function.Supplier. Similar to Callable<T>, but without a checked + * Exception and with #hasValue(). * * @param <T> Return type. */ -public interface Supplier<T> extends java.util.function.Supplier<T> { +@NullMarked +public interface Supplier<T extends @Nullable Object> extends java.util.function.Supplier<T> { /** Returns whether the supplier holds a value currently. */ default boolean hasValue() { return get() != null;
diff --git a/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java b/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java index b4fe503..f2f8627 100644 --- a/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java +++ b/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java
@@ -4,19 +4,20 @@ package org.chromium.base.supplier; -import androidx.annotation.NonNull; - import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** Utilities for interactions with Suppliers. */ +@NullMarked public class SupplierUtils { private SupplierUtils() {} private static class Barrier { private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker(); private int mWaitingCount; - private Runnable mCallback; + private @Nullable Runnable mCallback; void waitForAll(Runnable callback, Supplier... suppliers) { mThreadChecker.assertOnValidThread(); @@ -75,7 +76,7 @@ * @param callback The callback to be notified when all suppliers have values set. * @param suppliers The list of suppliers to check for values. */ - public static void waitForAll(@NonNull Runnable callback, Supplier... suppliers) { + public static void waitForAll(Runnable callback, Supplier... suppliers) { assert callback != null; new Barrier().waitForAll(callback, suppliers); }
diff --git a/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplier.java b/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplier.java index 6ad7f81..bb522f9c 100644 --- a/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplier.java
@@ -4,9 +4,9 @@ package org.chromium.base.supplier; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** * SyncOneshotSupplier wraps an asynchronously provided, non-null object {@code T}, synchronously @@ -27,6 +27,7 @@ * * @param <T> The type of the wrapped object. */ +@NullMarked public interface SyncOneshotSupplier<T> extends Supplier<T> { /** * Add a callback that's synchronously called when the object owned by this supplier is
diff --git a/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplierImpl.java b/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplierImpl.java index 287ad42..9e8b7c3 100644 --- a/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplierImpl.java +++ b/base/android/java/src/org/chromium/base/supplier/SyncOneshotSupplierImpl.java
@@ -4,11 +4,10 @@ package org.chromium.base.supplier; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.ArrayList; @@ -29,6 +28,7 @@ * * @param <T> The type of the wrapped object. */ +@NullMarked public class SyncOneshotSupplierImpl<T> implements SyncOneshotSupplier<T> { private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker(); @@ -65,7 +65,7 @@ * * @param object The object to supply. */ - public void set(@NonNull T object) { + public void set(T object) { mThreadChecker.assertOnValidThread(); assert mObject == null; assert object != null;
diff --git a/base/android/java/src/org/chromium/base/supplier/TransitiveObservableSupplier.java b/base/android/java/src/org/chromium/base/supplier/TransitiveObservableSupplier.java index 80b4107..708765d 100644 --- a/base/android/java/src/org/chromium/base/supplier/TransitiveObservableSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/TransitiveObservableSupplier.java
@@ -4,10 +4,9 @@ package org.chromium.base.supplier; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.function.Function; @@ -24,18 +23,18 @@ * @param <P> The parent object that's holding a reference to the target. * @param <T> The target type that the client wants to observe. */ -public class TransitiveObservableSupplier<P, T> implements ObservableSupplier<T> { +@NullMarked +public class TransitiveObservableSupplier<P extends @Nullable Object, T extends @Nullable Object> + implements ObservableSupplier<T> { // Used to hold observers and current state. However the current value is only valid when there // are observers, otherwise is may be stale. - private final @NonNull ObservableSupplierImpl<T> mDelegateSupplier = + private final ObservableSupplierImpl<@Nullable T> mDelegateSupplier = new ObservableSupplierImpl<>(); - private final @NonNull Callback<P> mOnParentSupplierChangeCallback = - this::onParentSupplierChange; - private final @NonNull Callback<T> mOnTargetSupplierChangeCallback = - this::onTargetSupplierChange; - private final @NonNull ObservableSupplier<P> mParentSupplier; - private final @NonNull Function<P, ObservableSupplier<T>> mUnwrapFunction; + private final Callback<P> mOnParentSupplierChangeCallback = this::onParentSupplierChange; + private final Callback<T> mOnTargetSupplierChangeCallback = this::onTargetSupplierChange; + private final ObservableSupplier<P> mParentSupplier; + private final Function<P, ObservableSupplier<T>> mUnwrapFunction; // When this is set, then mOnTargetSupplierChangeCallback is an observer of the object // referenced by mCurrentTargetSupplier. When this value is changed, the observer must be @@ -50,7 +49,7 @@ } @Override - public T addObserver(Callback<T> obs) { + public @Nullable T addObserver(Callback<T> obs) { if (!mDelegateSupplier.hasObservers()) { onParentSupplierChange(mParentSupplier.addObserver(mOnParentSupplierChangeCallback)); }
diff --git a/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java b/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java index c11b78a..1c6a3c80 100644 --- a/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
@@ -5,13 +5,13 @@ package org.chromium.base.supplier; import androidx.annotation.CallSuper; -import androidx.annotation.NonNull; import org.chromium.base.UnownedUserData; import org.chromium.base.UnownedUserDataHost; import org.chromium.base.UnownedUserDataKey; import org.chromium.base.lifetime.DestroyChecker; import org.chromium.base.lifetime.Destroyable; +import org.chromium.build.annotations.NullMarked; /** * UnownedUserDataSupplier handles the combined lifecycle management for {@link UnownedUserData} and @@ -42,6 +42,7 @@ * @see UnownedUserDataKey for information about the type of key that is required. * @see UnownedUserData for the marker interface used for this type of data. */ +@NullMarked public abstract class UnownedUserDataSupplier<E> extends ObservableSupplierImpl<E> implements Destroyable, UnownedUserData { private final UnownedUserDataKey<UnownedUserDataSupplier<E>> mUudKey; @@ -52,7 +53,7 @@ * @param uudKey The {@link UnownedUserDataKey}, which is defined in subclasses. */ protected UnownedUserDataSupplier( - @NonNull UnownedUserDataKey<? extends UnownedUserDataSupplier<E>> uudKey) { + UnownedUserDataKey<? extends UnownedUserDataSupplier<E>> uudKey) { mUudKey = (UnownedUserDataKey<UnownedUserDataSupplier<E>>) uudKey; } @@ -60,7 +61,7 @@ * Attach to the specified host. * @param host The host to attach the supplier to. */ - public void attach(@NonNull UnownedUserDataHost host) { + public void attach(UnownedUserDataHost host) { mDestroyChecker.checkNotDestroyed(); mUudKey.attachToHost(host, this); }
diff --git a/base/android/java/src/org/chromium/base/supplier/UnwrapObservableSupplier.java b/base/android/java/src/org/chromium/base/supplier/UnwrapObservableSupplier.java index 79fc876..8bf2f26f 100644 --- a/base/android/java/src/org/chromium/base/supplier/UnwrapObservableSupplier.java +++ b/base/android/java/src/org/chromium/base/supplier/UnwrapObservableSupplier.java
@@ -4,10 +4,9 @@ package org.chromium.base.supplier; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.util.function.Function; @@ -43,20 +42,20 @@ * @param <P> The parent object that's holding the target value somehow. * @param <T> The target type that the client wants to observe. */ -public class UnwrapObservableSupplier<P, T> implements ObservableSupplier<T> { - private final @NonNull ObservableSupplierImpl<T> mDelegateSupplier = - new ObservableSupplierImpl<>(); - private final @NonNull Callback<P> mOnParentSupplierChangeCallback = - this::onParentSupplierChange; - private final @NonNull ObservableSupplier<P> mParentSupplier; - private final @NonNull Function<P, T> mUnwrapFunction; +@NullMarked +public class UnwrapObservableSupplier<P extends @Nullable Object, T extends @Nullable Object> + implements ObservableSupplier<T> { + private final ObservableSupplierImpl<T> mDelegateSupplier = new ObservableSupplierImpl<>(); + private final Callback<P> mOnParentSupplierChangeCallback = this::onParentSupplierChange; + private final ObservableSupplier<P> mParentSupplier; + private final Function<@Nullable P, T> mUnwrapFunction; /** * @param parentSupplier The parent observable supplier. * @param unwrapFunction Converts the parent value to target value. Should handle null values. */ public UnwrapObservableSupplier( - @NonNull ObservableSupplier<P> parentSupplier, @NonNull Function<P, T> unwrapFunction) { + ObservableSupplier<P> parentSupplier, Function<P, T> unwrapFunction) { mParentSupplier = parentSupplier; mUnwrapFunction = unwrapFunction; } @@ -67,7 +66,7 @@ } @Override - public T addObserver(Callback<T> obs) { + public @Nullable T addObserver(Callback<T> obs) { // Can use mDelegateSupplier.hasObservers() to tell if we are subscribed or not to // mParentSupplier. This is safe because we never expose outside callers, and completely // control when we add/remove observers to it.
diff --git a/base/android/java/src/org/chromium/base/task/AsyncTask.java b/base/android/java/src/org/chromium/base/task/AsyncTask.java index f4666bf7e..bce74082 100644 --- a/base/android/java/src/org/chromium/base/task/AsyncTask.java +++ b/base/android/java/src/org/chromium/base/task/AsyncTask.java
@@ -16,6 +16,8 @@ import org.chromium.base.TraceEvent; import org.chromium.base.metrics.RecordHistogram; import org.chromium.build.annotations.DoNotInline; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -33,10 +35,12 @@ /** * A Chromium version of android.os.AsyncTask. * - * The API is quite close to Android's Oreo version, but with a number of things removed. + * <p>The API is quite close to Android's Oreo version, but with a number of things removed. + * * @param <Result> Return type of the background task. */ -public abstract class AsyncTask<Result> { +@NullMarked +public abstract class AsyncTask<Result extends @Nullable Object> { private static final String TAG = "AsyncTask"; private static final String GET_STATUS_UMA_HISTOGRAM = @@ -139,14 +143,14 @@ mFuture = new NamedFutureTask(mWorker); } - private void postResultIfNotInvoked(Result result) { + private void postResultIfNotInvoked(@Nullable Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } - private void postResult(Result result) { + private void postResult(@Nullable Result result) { // We check if this task is of a type which does not require post-execution. if (this instanceof BackgroundOnlyAsyncTask) { mStatus = Status.FINISHED; @@ -218,7 +222,7 @@ */ @SuppressWarnings({"UnusedDeclaration"}) @MainThread - protected abstract void onPostExecute(Result result); + protected abstract void onPostExecute(@Nullable Result result); /** * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and @@ -236,7 +240,7 @@ */ @SuppressWarnings({"UnusedParameters"}) @MainThread - protected void onCancelled(Result result) { + protected void onCancelled(@Nullable Result result) { onCancelled(); } @@ -459,7 +463,7 @@ return this; } - private void finish(Result result) { + private void finish(@Nullable Result result) { if (isCancelled()) { onCancelled(result); } else {
diff --git a/base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java b/base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java index 4ff2068..c69276b 100644 --- a/base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java +++ b/base/android/java/src/org/chromium/base/task/BackgroundOnlyAsyncTask.java
@@ -4,17 +4,22 @@ package org.chromium.base.task; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + /** * An AsyncTask which does not require post-execution. * - * The addition of this class is only temporary with the eventual goal of - * transitioning all such tasks to FutureTasks / Runnables. + * <p>The addition of this class is only temporary with the eventual goal of transitioning all such + * tasks to FutureTasks / Runnables. * * @param <Result> Return type of the background task. */ -public abstract class BackgroundOnlyAsyncTask<Result> extends AsyncTask<Result> { +@NullMarked +public abstract class BackgroundOnlyAsyncTask<Result extends @Nullable Object> + extends AsyncTask<Result> { @Override - protected final void onPostExecute(Result result) { + protected final void onPostExecute(@Nullable Result result) { // This method should never be executed for background-only tasks. assert false; }
diff --git a/base/android/java/src/org/chromium/base/task/ChainedTasks.java b/base/android/java/src/org/chromium/base/task/ChainedTasks.java index d807e4b3..4aaf737 100644 --- a/base/android/java/src/org/chromium/base/task/ChainedTasks.java +++ b/base/android/java/src/org/chromium/base/task/ChainedTasks.java
@@ -7,6 +7,7 @@ import android.util.Pair; import org.chromium.base.TraceEvent; +import org.chromium.build.annotations.NullMarked; import java.util.LinkedList; @@ -24,6 +25,7 @@ * may run with arbitrary TaskTraits, unless tasks are coalesced, in which case all tasks must run * on the same thread. */ +@NullMarked public class ChainedTasks { private final LinkedList<Pair<Integer, Runnable>> mTasks = new LinkedList<>();
diff --git a/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java b/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java index e191d24..1f7f5ca7 100644 --- a/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java +++ b/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
@@ -8,6 +8,8 @@ import androidx.annotation.VisibleForTesting; +import org.chromium.build.annotations.NullMarked; + import java.util.HashMap; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; @@ -18,6 +20,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +@NullMarked class ChromeThreadPoolExecutor extends ThreadPoolExecutor { private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
diff --git a/base/android/java/src/org/chromium/base/task/PostTask.java b/base/android/java/src/org/chromium/base/task/PostTask.java index 361ca8b..d863975 100644 --- a/base/android/java/src/org/chromium/base/task/PostTask.java +++ b/base/android/java/src/org/chromium/base/task/PostTask.java
@@ -4,7 +4,7 @@ package org.chromium.base.task; -import androidx.annotation.Nullable; +import static org.chromium.build.NullUtil.assumeNonNull; import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; @@ -14,6 +14,9 @@ import org.chromium.base.ResettersForTesting; import org.chromium.base.ThreadUtils; import org.chromium.build.BuildConfig; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.NullUnmarked; +import org.chromium.build.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -29,6 +32,7 @@ * initialization, but task prioritization is extremely limited. Once the native scheduler is ready, * tasks will be migrated over. */ +@NullMarked @JNINamespace("base") public class PostTask { private static final String TAG = "PostTask"; @@ -36,7 +40,7 @@ private static final Object sPreNativeTaskRunnerLock = new Object(); @GuardedBy("sPreNativeTaskRunnerLock") - private static List<TaskRunnerImpl> sPreNativeTaskRunners = new ArrayList<>(); + private static @Nullable List<TaskRunnerImpl> sPreNativeTaskRunners = new ArrayList<>(); // Volatile is sufficient for synchronization here since we never need to read-write. This is a // one-way switch (outside of testing) and volatile makes writes to it immediately visible to @@ -44,8 +48,8 @@ private static volatile boolean sNativeInitialized; private static ChromeThreadPoolExecutor sPrenativeThreadPoolExecutor = new ChromeThreadPoolExecutor(); - private static volatile Executor sPrenativeThreadPoolExecutorForTesting; - private static final ThreadLocal<TaskOriginException> sTaskOrigin = + private static volatile @Nullable Executor sPrenativeThreadPoolExecutorForTesting; + private static final @Nullable ThreadLocal<TaskOriginException> sTaskOrigin = ENABLE_TASK_ORIGINS ? new ThreadLocal<>() : null; private static final TaskRunner[] sTraitsToRunnerMap = new TaskRunner[TaskTraits.UI_TRAITS_END + 1]; @@ -73,13 +77,14 @@ @Override public void run() { - sTaskOrigin.set(mTaskOrigin); + var taskOrigin = assumeNonNull(sTaskOrigin); + taskOrigin.set(mTaskOrigin); try { mWrappedRunnable.run(); } catch (Throwable t) { JavaUtils.throwUnchecked(maybeAddTaskOrigin(t)); } finally { - sTaskOrigin.remove(); + taskOrigin.remove(); } } } @@ -219,6 +224,7 @@ return sPrenativeThreadPoolExecutor; } + @NullUnmarked public static @Nullable Exception getTaskOrigin() { return ENABLE_TASK_ORIGINS ? sTaskOrigin.get() : null; } @@ -281,6 +287,7 @@ sNativeInitialized = true; List<TaskRunnerImpl> preNativeTaskRunners; synchronized (sPreNativeTaskRunnerLock) { + assert sPreNativeTaskRunners != null; preNativeTaskRunners = sPreNativeTaskRunners; sPreNativeTaskRunners = null; }
diff --git a/base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java b/base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java index d8b9c46..16d07e9 100644 --- a/base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java +++ b/base/android/java/src/org/chromium/base/task/SequencedTaskRunner.java
@@ -4,6 +4,8 @@ package org.chromium.base.task; +import org.chromium.build.annotations.NullMarked; + /** * Tasks posted will be run in order with respect to this sequence, but they may be executed * on arbitrary threads. Unless specified otherwise by the provider of a given @@ -11,4 +13,5 @@ * guarantees w.r.t. other SequencedTaskRunners. They have destroy() automatically called whenever * they go empty, so calling destroy() on them is not needed. */ +@NullMarked public interface SequencedTaskRunner extends TaskRunner {}
diff --git a/base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java b/base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java index ce5fede..e2ccbe9 100644 --- a/base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java +++ b/base/android/java/src/org/chromium/base/task/SequencedTaskRunnerImpl.java
@@ -4,12 +4,15 @@ package org.chromium.base.task; +import org.chromium.build.annotations.NullMarked; + import java.util.concurrent.atomic.AtomicInteger; /** * Implementation of the abstract class {@link SequencedTaskRunner}. Uses AsyncTasks until * native APIs are available. */ +@NullMarked public class SequencedTaskRunnerImpl extends TaskRunnerImpl implements SequencedTaskRunner { private AtomicInteger mPendingTasks = new AtomicInteger();
diff --git a/base/android/java/src/org/chromium/base/task/SerialExecutor.java b/base/android/java/src/org/chromium/base/task/SerialExecutor.java index c43acee0..f1b67a6 100644 --- a/base/android/java/src/org/chromium/base/task/SerialExecutor.java +++ b/base/android/java/src/org/chromium/base/task/SerialExecutor.java
@@ -4,12 +4,16 @@ package org.chromium.base.task; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + import java.util.ArrayDeque; import java.util.concurrent.Executor; +@NullMarked class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); - Runnable mActive; + @Nullable Runnable mActive; @Override public synchronized void execute(final Runnable r) {
diff --git a/base/android/java/src/org/chromium/base/task/TaskOriginException.java b/base/android/java/src/org/chromium/base/task/TaskOriginException.java index 3546621..82d2389 100644 --- a/base/android/java/src/org/chromium/base/task/TaskOriginException.java +++ b/base/android/java/src/org/chromium/base/task/TaskOriginException.java
@@ -4,7 +4,10 @@ package org.chromium.base.task; +import org.chromium.build.annotations.NullMarked; + /** Used to capture stacks of where tasks are posted from. */ +@NullMarked class TaskOriginException extends Exception { TaskOriginException() {
diff --git a/base/android/java/src/org/chromium/base/task/TaskRunner.java b/base/android/java/src/org/chromium/base/task/TaskRunner.java index 763f281..f18143d 100644 --- a/base/android/java/src/org/chromium/base/task/TaskRunner.java +++ b/base/android/java/src/org/chromium/base/task/TaskRunner.java
@@ -4,6 +4,8 @@ package org.chromium.base.task; +import org.chromium.build.annotations.NullMarked; + import java.util.concurrent.Executor; /** @@ -11,6 +13,7 @@ * be backed by an {@link android.os.Handler} or the java thread pool. The TaskQueue interface * provides no guarantee over the order or the thread on which the task will be executed. */ +@NullMarked public interface TaskRunner extends Executor { /**
diff --git a/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java b/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java index d8ebd3e..95066dd 100644 --- a/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java +++ b/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java
@@ -4,15 +4,17 @@ package org.chromium.base.task; -import android.util.Pair; +import static org.chromium.build.NullUtil.assumeNonNull; -import androidx.annotation.Nullable; +import android.util.Pair; import org.jni_zero.JNINamespace; import org.jni_zero.JniType; import org.jni_zero.NativeMethods; import org.chromium.base.TraceEvent; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -29,6 +31,7 @@ * Implementation of the abstract class {@link TaskRunnerImpl}. Uses AsyncTasks until native APIs * are available. */ +@NullMarked @JNINamespace("base") public class TaskRunnerImpl implements TaskRunner { @@ -56,21 +59,20 @@ @GuardedBy("mPreNativeTaskLock") private boolean mDidOneTimeInitialization; - @Nullable @GuardedBy("mPreNativeTaskLock") - private Queue<Runnable> mPreNativeTasks; + private @Nullable Queue<Runnable> mPreNativeTasks; - @Nullable @GuardedBy("mPreNativeTaskLock") - private List<Pair<Runnable, Long>> mPreNativeDelayedTasks; + private @Nullable List<Pair<Runnable, Long>> mPreNativeDelayedTasks; int clearTaskQueueForTesting() { int taskCount = 0; synchronized (mPreNativeTaskLock) { if (mPreNativeTasks != null) { - taskCount = mPreNativeTasks.size() + mPreNativeDelayedTasks.size(); + var preNativeDelayedTasks = assumeNonNull(mPreNativeDelayedTasks); + taskCount = mPreNativeTasks.size() + preNativeDelayedTasks.size(); mPreNativeTasks.clear(); - mPreNativeDelayedTasks.clear(); + preNativeDelayedTasks.clear(); } } return taskCount; @@ -171,11 +173,11 @@ // pre-native task runner. Tasks scheduled to run with a delay will // wait until the native task runner is initialised. if (delay == 0) { - mPreNativeTasks.add(task); + assumeNonNull(mPreNativeTasks).add(task); schedulePreNativeTask(); } else if (!schedulePreNativeDelayedTask(task, delay)) { Pair<Runnable, Long> preNativeDelayedTask = new Pair<>(task, delay); - mPreNativeDelayedTasks.add(preNativeDelayedTask); + assumeNonNull(mPreNativeDelayedTasks).add(preNativeDelayedTask); } } }
diff --git a/base/android/java/src/org/chromium/base/task/UiThreadTaskRunnerImpl.java b/base/android/java/src/org/chromium/base/task/UiThreadTaskRunnerImpl.java index 4f4b41f..5945d9f 100644 --- a/base/android/java/src/org/chromium/base/task/UiThreadTaskRunnerImpl.java +++ b/base/android/java/src/org/chromium/base/task/UiThreadTaskRunnerImpl.java
@@ -7,8 +7,10 @@ import org.jni_zero.JNINamespace; import org.chromium.base.ThreadUtils; +import org.chromium.build.annotations.NullMarked; /** TaskRunner for UI thread. */ +@NullMarked @JNINamespace("base") public class UiThreadTaskRunnerImpl extends TaskRunnerImpl implements SequencedTaskRunner { /**
diff --git a/base/android/jni_string.cc b/base/android/jni_string.cc index 008cef4..54010a0f 100644 --- a/base/android/jni_string.cc +++ b/base/android/jni_string.cc
@@ -30,9 +30,7 @@ namespace android { void ConvertJavaStringToUTF8(JNIEnv* env, jstring str, std::string* result) { - DCHECK(str); if (!str) { - LOG(WARNING) << "ConvertJavaStringToUTF8 called with null string."; result->clear(); return; } @@ -98,9 +96,7 @@ void ConvertJavaStringToUTF16(JNIEnv* env, jstring str, std::u16string* result) { - DCHECK(str); if (!str) { - LOG(WARNING) << "ConvertJavaStringToUTF16 called with null string."; result->clear(); return; }
diff --git a/base/big_endian_perftest.cc b/base/big_endian_perftest.cc index 22723660..8c68c03 100644 --- a/base/big_endian_perftest.cc +++ b/base/big_endian_perftest.cc
@@ -41,17 +41,14 @@ auto value = T{0}; for (auto _ : state) { if constexpr (sizeof(T) == 1) { - buffer.subspan(offset).first<sizeof(T)>().copy_from(U8ToBigEndian(value)); + buffer.subspan(offset).copy_prefix_from(U8ToBigEndian(value)); } else if constexpr (sizeof(T) == 2) { - buffer.subspan(offset).first<sizeof(T)>().copy_from( - U16ToBigEndian(value)); + buffer.subspan(offset).copy_prefix_from(U16ToBigEndian(value)); } else if constexpr (sizeof(T) == 4) { - buffer.subspan(offset).first<sizeof(T)>().copy_from( - U32ToBigEndian(value)); + buffer.subspan(offset).copy_prefix_from(U32ToBigEndian(value)); } else { static_assert(sizeof(T) == 8); - buffer.subspan(offset).first<sizeof(T)>().copy_from( - U64ToBigEndian(value)); + buffer.subspan(offset).copy_prefix_from(U64ToBigEndian(value)); } offset += sizeof(T); static_assert(kSize % sizeof(T) == 0u);
diff --git a/base/containers/buffer_iterator_unittest.cc b/base/containers/buffer_iterator_unittest.cc index 27efd254..15996e7 100644 --- a/base/containers/buffer_iterator_unittest.cc +++ b/base/containers/buffer_iterator_unittest.cc
@@ -216,8 +216,7 @@ for (int i = 0; i < kNumCopies; i++) { as_writable_bytes(span(buffer)) .subspan(i * sizeof(TestStruct)) - .first<sizeof(TestStruct)>() - .copy_from(byte_span_from_ref(expected)); + .copy_prefix_from(byte_span_from_ref(expected)); } BufferIterator<char> iterator(buffer);
diff --git a/base/containers/span.h b/base/containers/span.h index 2ddae455..30289e7b 100644 --- a/base/containers/span.h +++ b/base/containers/span.h
@@ -210,6 +210,8 @@ // `StrictNumeric<size_type>`. // - For convenience, provides `span::split_at()` to split a single span into // two at a given offset. +// - For convenience, provides `span::take_first[_elem]()` to remove the first +// portion of a dynamic-extent span and return it. // // Differences from [span.obs]: // - For convenience, provides `span::operator==()` to check whether two spans @@ -1114,6 +1116,33 @@ return std::pair(first(offset), subspan(offset)); } + // Returns a span of the first N elements, removing them. + // When `Offset` is outside the span, the underlying call will `CHECK()`. For + // a non-fatal alternative, consider `SpanReader`. + // + // (Not in `std::span`; convenient for processing a stream of disparate + // objects or looping over elements.) + template <size_t Offset> + constexpr auto take_first() { + const auto [first, rest] = split_at<Offset>(); + *this = rest; + return first; + } + // When `offset` is outside the span, the underlying call will `CHECK()`. + constexpr auto take_first(StrictNumeric<size_type> offset) { + const auto [first, rest] = split_at(offset); + *this = rest; + return first; + } + + // Returns the first element, removing it. + // When `empty()`, the underlying call will `CHECK()`. For a non-fatal + // alternative, consider `SpanReader`. + // + // (Not in `std::span`; convenient for processing a stream of disparate + // objects or looping over elements.) + constexpr auto take_first_elem() { return take_first<1>().front(); } + // [span.obs]: Observers // Size. constexpr size_type size() const noexcept { return size_; }
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc index 913f45d..33332121 100644 --- a/base/containers/span_unittest.cc +++ b/base/containers/span_unittest.cc
@@ -2523,6 +2523,92 @@ EXPECT_CHECK_DEATH({ dynamic_span.split_at<4u>(); }); } +TEST(SpanTest, TakeFirst) { + { + span<int> empty; + auto first = empty.take_first(0u); + EXPECT_TRUE(first.empty()); + EXPECT_TRUE(empty.empty()); + } + + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first(0u); + EXPECT_TRUE(first.empty()); + EXPECT_THAT(dynamic_span, ElementsAre(4, 5, 6)); + } + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first(1u); + EXPECT_THAT(first, ElementsAre(4)); + EXPECT_THAT(dynamic_span, ElementsAre(5, 6)); + } + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first(3u); + EXPECT_THAT(first, ElementsAre(4, 5, 6)); + EXPECT_TRUE(dynamic_span.empty()); + } + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + // Invalid take will fail at runtime. + EXPECT_CHECK_DEATH({ dynamic_span.take_first(4u); }); + } + + // Fixed-size takes. + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first<0>(); + static_assert(std::same_as<decltype(first), span<int, 0>>); + EXPECT_THAT(dynamic_span, ElementsAre(4, 5, 6)); + } + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first<1>(); + static_assert(std::same_as<decltype(first), span<int, 1>>); + EXPECT_THAT(first, ElementsAre(4)); + EXPECT_THAT(dynamic_span, ElementsAre(5, 6)); + } + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first<3>(); + static_assert(std::same_as<decltype(first), span<int, 3>>); + EXPECT_THAT(first, ElementsAre(4, 5, 6)); + EXPECT_TRUE(dynamic_span.empty()); + } + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + // Invalid fixed-size take will fail at runtime. + EXPECT_CHECK_DEATH({ dynamic_span.take_first<4>(); }); + } +} + +TEST(SpanTest, TakeFirstElem) { + { + span<int> empty; + // Invalid take will fail at runtime. + EXPECT_CHECK_DEATH({ empty.take_first_elem(); }); + } + + { + std::vector<int> vec = {4, 5, 6}; + span<int> dynamic_span = span(vec); + auto first = dynamic_span.take_first_elem(); + static_assert(std::same_as<decltype(first), int>); + EXPECT_EQ(first, 4); + EXPECT_EQ(dynamic_span.size(), 2u); + EXPECT_EQ(dynamic_span.front(), 5); + } +} + TEST(SpanTest, CompareEquality) { static_assert(std::equality_comparable<int>); int32_t arr2[] = {1, 2}; @@ -3029,21 +3115,15 @@ uint8_t array1[12]; uint8_t array2[16]; uint64_t array3[2]; - span(array1).first(4u).copy_from(span(array2).subspan(8u, 4u)); - span(array1).subspan(4u).copy_from(as_byte_span(array3).first(8u)); + base::span<uint8_t> span1(array1); + span1.take_first<4>().copy_from(base::span(array2).subspan<8, 4>()); + span1.copy_from(base::as_byte_span(array3).first<8>()); { // Use `split_at()` to ensure `array1` is fully written. - auto [from2, from3] = span(array1).split_at(4u); - from2.copy_from(span(array2).subspan(8u, 4u)); - from3.copy_from(as_byte_span(array3).first(8u)); - } - { - // This can even be ensured at compile time (if sizes and offsets are all - // constants). - auto [from2, from3] = span(array1).split_at<4u>(); - from2.copy_from(span(array2).subspan<8u, 4u>()); - from3.copy_from(as_byte_span(array3).first<8u>()); + auto [from2, from3] = base::span(array1).split_at<4>(); + from2.copy_from(base::span(array2).subspan<8, 4>()); + from3.copy_from(base::as_byte_span(array3).first<8>()); } } @@ -3060,9 +3140,9 @@ uint8_t array1[12]; uint64_t array2[2]; Object array3[4]; - std::ranges::fill(array1, 0u); - std::ranges::fill(array2, 0u); - std::ranges::fill(as_writable_byte_span(array3), 0u); + std::ranges::fill(array1, 0); + std::ranges::fill(array2, 0); + std::ranges::fill(as_writable_byte_span(array3), 0); } UNSAFE_BUFFERS({
diff --git a/base/files/file_unittest.cc b/base/files/file_unittest.cc index 057f0d5..6acf729 100644 --- a/base/files/file_unittest.cc +++ b/base/files/file_unittest.cc
@@ -639,12 +639,12 @@ std::string data("test"); size_t first_chunk_size = data.size() / 2; - std::optional<size_t> result = - file.WriteAtCurrentPos(as_byte_span(data).first(first_chunk_size)); + const auto [first, second] = as_byte_span(data).split_at(first_chunk_size); + std::optional<size_t> result = file.WriteAtCurrentPos(first); ASSERT_TRUE(result.has_value()); EXPECT_EQ(first_chunk_size, result.value()); - result = file.WriteAtCurrentPos(as_byte_span(data).subspan(first_chunk_size)); + result = file.WriteAtCurrentPos(second); ASSERT_TRUE(result.has_value()); EXPECT_EQ(first_chunk_size, result.value());
diff --git a/base/test/android/javatests/src/stub/org/chromium/base/test/ClangProfiler.java b/base/test/android/javatests/src/stub/org/chromium/base/test/ClangProfiler.java index cc3d7a6..46fdd98b 100644 --- a/base/test/android/javatests/src/stub/org/chromium/base/test/ClangProfiler.java +++ b/base/test/android/javatests/src/stub/org/chromium/base/test/ClangProfiler.java
@@ -4,7 +4,10 @@ package org.chromium.base.test; +import org.chromium.build.annotations.NullMarked; + /** Placeholder class used when clang profiling is not enabled at building. */ +@NullMarked public class ClangProfiler { private ClangProfiler() {}
diff --git a/base/test/test_trace_processor.cc b/base/test/test_trace_processor.cc index 84abcf8..2c424814 100644 --- a/base/test/test_trace_processor.cc +++ b/base/test/test_trace_processor.cc
@@ -10,6 +10,7 @@ #include "base/files/file_util.h" #include "base/test/chrome_track_event.descriptor.h" #include "base/test/perfetto_sql_stdlib.h" +#include "base/threading/thread_restrictions.h" #include "base/trace_event/trace_log.h" #include "third_party/perfetto/protos/perfetto/trace/extension_descriptor.pbzero.h"
diff --git a/base/test/test_trace_processor.h b/base/test/test_trace_processor.h index 0ad592b..d68ccab 100644 --- a/base/test/test_trace_processor.h +++ b/base/test/test_trace_processor.h
@@ -13,10 +13,12 @@ #include <string_view> +#include "base/run_loop.h" #include "base/test/test_trace_processor_impl.h" #include "base/test/trace_test_utils.h" #include "base/types/expected.h" #include "build/build_config.h" +#include "third_party/perfetto/include/perfetto/tracing/tracing.h" #if !BUILDFLAG(IS_WIN) #define TEST_TRACE_PROCESSOR_ENABLED
diff --git a/base/test/trace_test_utils.cc b/base/test/trace_test_utils.cc index fda6c47..4020257b 100644 --- a/base/test/trace_test_utils.cc +++ b/base/test/trace_test_utils.cc
@@ -1,94 +1,20 @@ // 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. + #include "base/test/trace_test_utils.h" -#include "base/no_destructor.h" -#include "base/task/sequenced_task_runner.h" -#include "base/tracing/perfetto_platform.h" +#include "base/trace_event/trace_log.h" #include "third_party/perfetto/include/perfetto/tracing/core/data_source_config.h" namespace base { namespace test { -namespace { - -// A proxy task runner which can be dynamically pointed to route tasks into a -// different task runner. -class RebindableTaskRunner : public base::SequencedTaskRunner { - public: - RebindableTaskRunner(); - - void set_task_runner(scoped_refptr<base::SequencedTaskRunner> task_runner) { - task_runner_ = task_runner; - } - - // base::SequencedTaskRunner implementation. - bool PostDelayedTask(const base::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) override; - bool PostNonNestableDelayedTask(const base::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) override; - bool RunsTasksInCurrentSequence() const override; - - private: - ~RebindableTaskRunner() override; - - scoped_refptr<base::SequencedTaskRunner> task_runner_; -}; - -RebindableTaskRunner::RebindableTaskRunner() = default; -RebindableTaskRunner::~RebindableTaskRunner() = default; - -bool RebindableTaskRunner::PostDelayedTask(const base::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) { - return task_runner_->PostDelayedTask(from_here, std::move(task), delay); -} - -bool RebindableTaskRunner::PostNonNestableDelayedTask( - const base::Location& from_here, - base::OnceClosure task, - base::TimeDelta delay) { - return task_runner_->PostNonNestableDelayedTask(from_here, std::move(task), - delay); -} - -bool RebindableTaskRunner::RunsTasksInCurrentSequence() const { - return task_runner_->RunsTasksInCurrentSequence(); -} - -RebindableTaskRunner* GetClientLibTaskRunner() { - static base::NoDestructor<scoped_refptr<RebindableTaskRunner>> task_runner( - MakeRefCounted<RebindableTaskRunner>()); - return task_runner.get()->get(); -} - -} // namespace TracingEnvironment::TracingEnvironment() { trace_event::TraceLog::GetInstance()->ResetForTesting(); } -TracingEnvironment::TracingEnvironment( - TaskEnvironment& task_environment, - scoped_refptr<SequencedTaskRunner> task_runner) - : task_environment_(&task_environment) { - // Since Perfetto's platform backend can only be initialized once in a - // process, we give it a task runner that can outlive the per-test task - // environment. - auto* client_lib_task_runner = GetClientLibTaskRunner(); - client_lib_task_runner->set_task_runner(std::move(task_runner)); - - // Wait for any posted construction tasks to execute. - task_environment_->RunUntilIdle(); -} - TracingEnvironment::~TracingEnvironment() { - if (task_environment_) { - // Wait for any posted destruction tasks to execute. - task_environment_->RunUntilIdle(); - } perfetto::Tracing::ResetForTesting(); }
diff --git a/base/test/trace_test_utils.h b/base/test/trace_test_utils.h index fcf235d..f13207d 100644 --- a/base/test/trace_test_utils.h +++ b/base/test/trace_test_utils.h
@@ -5,10 +5,6 @@ #ifndef BASE_TEST_TRACE_TEST_UTILS_H_ #define BASE_TEST_TRACE_TEST_UTILS_H_ -#include "base/memory/raw_ptr.h" -#include "base/task/thread_pool.h" -#include "base/test/task_environment.h" -#include "base/trace_event/trace_log.h" #include "third_party/perfetto/protos/perfetto/config/trace_config.gen.h" namespace base { @@ -23,19 +19,10 @@ // Construct a tracing environment using the default Perfetto tracing // platform. TracingEnvironment(); - - // Constructs a tracing environment with the given task runner and Perfetto - // tracing platform. - explicit TracingEnvironment(TaskEnvironment&, - scoped_refptr<SequencedTaskRunner> = - ThreadPool::CreateSequencedTaskRunner({})); ~TracingEnvironment(); // Builds a default Perfetto trace config with track events enabled. static perfetto::protos::gen::TraceConfig GetDefaultTraceConfig(); - - private: - raw_ptr<TaskEnvironment> task_environment_ = nullptr; }; } // namespace test
diff --git a/base/tracing/protos/chrome_track_event.proto b/base/tracing/protos/chrome_track_event.proto index 454a5b2..68781fe2 100644 --- a/base/tracing/protos/chrome_track_event.proto +++ b/base/tracing/protos/chrome_track_event.proto
@@ -1959,6 +1959,8 @@ optional int64 blocking_duration_ms = 1; optional int64 duration_ms = 2; optional int64 num_scripts = 3; + // Id for the BeginFrame, which triggered this animation frame. + optional BeginFrameId begin_frame_id = 4; } message AnimationFrameScriptTimingInfo { @@ -2320,7 +2322,7 @@ message ChromeTrackEvent { // Extension range for Chrome: 1000-1999 - // Next ID: 1072 + // Next ID: 1075 extend TrackEvent { optional ChromeAppState chrome_app_state = 1000; @@ -2477,5 +2479,7 @@ optional WebExposedIsolationInfo web_exposed_isolation_info = 1072; optional UrlInfo url_info = 1073; + + optional BeginFrameId begin_frame_id = 1074; } }
diff --git a/build/OWNERS b/build/OWNERS index 2d7f77a..382120b 100644 --- a/build/OWNERS +++ b/build/OWNERS
@@ -17,6 +17,7 @@ smaier@chromium.org wnwen@chromium.org mheikal@chromium.org +hnakashima@chromium.org # NOTE: keep this in sync with global-owners-override@chromium.org owners # by emailing lsc-policy@chromium.org when this list changes.
diff --git a/build/android/fast_local_dev_server.py b/build/android/fast_local_dev_server.py index dd5e6cf..6573ee3e 100755 --- a/build/android/fast_local_dev_server.py +++ b/build/android/fast_local_dev_server.py
@@ -705,20 +705,6 @@ return 0 -def _get_build_id_for_outdir(outdir): - """Returns the latest BUILD_ID for given output dir.""" - outdir = pathlib.Path(outdir) - latest_logfile = outdir / f'{_LOGFILE_NAME}.0' - if latest_logfile.exists(): - with latest_logfile.open('rt') as f: - first_line = f.readline() - if log_build_id := BUILD_ID_RE.search(first_line): - print(log_build_id.group('build_id')) - return 0 - print(f'Failed to find a valid logfile in {outdir}') - return 1 - - def _register_builder(build_id, builder_pid): for _attempt in range(3): try: @@ -770,7 +756,6 @@ def main(): - # pylint: disable=too-many-return-statements parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( '--fail-if-not-running', @@ -799,9 +784,6 @@ parser.add_argument('--cancel-build', metavar='BUILD_ID', help='Cancel all pending and running tasks for BUILD_ID.') - parser.add_argument('--get-build-id-for-outdir', - metavar='OUTDIR', - help='Return the latest BUILD_ID for given output dir.') args = parser.parse_args() if args.fail_if_not_running: return _check_if_running() @@ -813,8 +795,6 @@ return _register_builder(args.register_build_id, args.builder_pid) if args.cancel_build: return _send_cancel_build(args.cancel_build) - if args.get_build_id_for_outdir: - return _get_build_id_for_outdir(args.get_build_id_for_outdir) return _wait_for_task_requests(args)
diff --git a/build/android/gyp/bytecode_processor.py b/build/android/gyp/bytecode_processor.py index d28641c..22224766 100755 --- a/build/android/gyp/bytecode_processor.py +++ b/build/android/gyp/bytecode_processor.py
@@ -244,9 +244,6 @@ parser.add_argument('--use-build-server', action='store_true', help='Always use the build server.') - parser.add_argument('--experimental-build-server', - action='store_true', - help='Use experimental build server features.') parser.add_argument('--gn-target', required=True) parser.add_argument('--input-jar', required=True) parser.add_argument('--direct-classpath-jars') @@ -268,8 +265,7 @@ if server_utils.MaybeRunCommand(name=args.target_name, argv=sys.argv, stamp_file=args.stamp, - force=args.use_build_server, - experimental=args.experimental_build_server): + use_build_server=args.use_build_server): return args.sdk_classpath_jars = action_helpers.parse_gn_list(
diff --git a/build/android/gyp/compile_java.py b/build/android/gyp/compile_java.py index 58c51f47..9e990f2 100755 --- a/build/android/gyp/compile_java.py +++ b/build/android/gyp/compile_java.py
@@ -349,13 +349,11 @@ logging.info('Starting _OnStaleMd5') # Use the build server for errorprone runs. - if (options.enable_errorprone and not options.skip_build_server - and server_utils.MaybeRunCommand( - name=options.target_name, - argv=sys.argv, - stamp_file=options.jar_path, - force=options.use_build_server, - experimental=options.experimental_build_server)): + if (options.enable_errorprone and not options.skip_build_server and + server_utils.MaybeRunCommand(name=options.target_name, + argv=sys.argv, + stamp_file=options.jar_path, + use_build_server=options.use_build_server)): logging.info('Using build server') return @@ -591,9 +589,6 @@ parser.add_option('--use-build-server', action='store_true', help='Always use the build server.') - parser.add_option('--experimental-build-server', - action='store_true', - help='Use experimental build server features.') parser.add_option('--java-srcjars', action='append', default=[],
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py index 2bb9728..973bacc 100755 --- a/build/android/gyp/lint.py +++ b/build/android/gyp/lint.py
@@ -415,9 +415,6 @@ parser.add_argument('--use-build-server', action='store_true', help='Always use the build server.') - parser.add_argument('--experimental-build-server', - action='store_true', - help='Use experimental build server features.') parser.add_argument('--lint-jar-path', required=True, help='Path to the lint jar.') @@ -522,12 +519,10 @@ # the purpose of creating the cache in the first place. Forward the command # after the depfile has been written as siso requires it. if (not args.create_cache and not args.skip_build_server - and server_utils.MaybeRunCommand( - name=args.target_name, - argv=sys.argv, - stamp_file=args.stamp, - force=args.use_build_server, - experimental=args.experimental_build_server)): + and server_utils.MaybeRunCommand(name=args.target_name, + argv=sys.argv, + stamp_file=args.stamp, + use_build_server=args.use_build_server)): return _RunLint(args.custom_lint_jar_path,
diff --git a/build/android/gyp/util/server_utils.py b/build/android/gyp/util/server_utils.py index 53653887..bc8a96b8 100644 --- a/build/android/gyp/util/server_utils.py +++ b/build/android/gyp/util/server_utils.py
@@ -32,7 +32,7 @@ ) / 'build' / 'android' / 'fast_local_dev_server.py' -def MaybeRunCommand(name, argv, stamp_file, force, experimental=False): +def MaybeRunCommand(name, argv, stamp_file, use_build_server=False): """Returns True if the command was successfully sent to the build server.""" if platform.system() == "Darwin": @@ -46,12 +46,11 @@ if BUILD_SERVER_ENV_VARIABLE in os.environ: return False + if not use_build_server: + return False + autoninja_tty = os.environ.get('AUTONINJA_STDOUT_NAME') autoninja_build_id = os.environ.get('AUTONINJA_BUILD_ID') - if experimental and not autoninja_tty: - raise RuntimeError('experimental_build_server=true is set but autoninja ' - 'is not patched. Please make sure you are using a ' - 'patched autoninja script.') with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock: try: @@ -60,13 +59,9 @@ # [Errno 111] Connection refused. Either the server has not been started # or the server is not currently accepting new connections. if e.errno == 111: - if force: - raise RuntimeError( - '\n\nBuild server is not running and ' - 'android_static_analysis="build_server" is set.\nPlease run ' - 'this command in a separate terminal:\n\n' - '$ build/android/fast_local_dev_server.py\n\n') from None - return False + raise RuntimeError( + '\n\nBuild server is not running and ' + 'android_static_analysis="build_server" is set.\n\n') from None raise e SendMessage(
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index b0851f86..db37625 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -92,9 +92,6 @@ } else { android_static_analysis = "on" } - - # Enables teamfooding of new experimental build_server changes. - experimental_build_server = false } # Our build system no longer supports legacy multidex.
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 0fcf0d0..ce03743 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1152,9 +1152,6 @@ args += [ "--skip-build-server" ] } else if (android_static_analysis == "build_server") { args += [ "--use-build-server" ] - if (experimental_build_server) { - args += [ "--experimental-build-server" ] - } } if (defined(invoker.lint_suppressions_file)) { @@ -1925,9 +1922,6 @@ } if (android_static_analysis == "build_server") { args += [ "--use-build-server" ] - if (experimental_build_server) { - args += [ "--experimental-build-server" ] - } } if (invoker.include_android_sdk) { args += [ "--sdk-classpath-jars=@FileArg($_rebased_build_config:android:sdk_jars)" ] @@ -3212,9 +3206,6 @@ args += [ "--skip-build-server" ] } else if (android_static_analysis == "build_server") { args += [ "--use-build-server" ] - if (experimental_build_server) { - args += [ "--experimental-build-server" ] - } } foreach(e, _processor_args) {
diff --git a/build/config/siso/clang_unix.star b/build/config/siso/clang_unix.star index 599edf7f..8062cb4e 100644 --- a/build/config/siso/clang_unix.star +++ b/build/config/siso/clang_unix.star
@@ -46,6 +46,10 @@ if args[0] == "/bin/sh": args = args[2].split(" ") for i, arg in enumerate(args): + if i == 0 and not "python3" in arg: + clang_base = ctx.fs.canonpath(path.dir(path.dir(arg))) + inputs.append(clang_base + ":link") + continue if i == 1: driver = ctx.fs.canonpath(arg) # driver script if ctx.fs.exists(driver): @@ -264,6 +268,23 @@ "timeout": "2m", }, { + "name": "clang/solink_module", + "action": "(.*)?solink_module", + "handler": "clang_link", + "exclude_input_patterns": [ + "*.cc", + "*.h", + "*.js", + "*.pak", + "*.py", + "*.stamp", + ], + "remote": config.get(ctx, "remote-link"), + "canonicalize_dir": True, + "platform_ref": "large", + "timeout": "2m", + }, + { "name": "clang/link", "action": "(.*_)?link", "handler": "clang_link",
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index a037f96..9ec0880 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision var in //DEPS. - libcxx_revision = "643441dc2f2da5fe3e09c7559249b558f224a2dc" + libcxx_revision = "2d9b9a9eea77b09fe4bc7a41b33140fa7298d39f" }
diff --git a/chrome/VERSION b/chrome/VERSION index ad41f29..32003bec 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=133 MINOR=0 -BUILD=6893 +BUILD=6894 PATCH=0
diff --git a/chrome/android/expectations/monochrome_64_32_public_bundle__chrome.AndroidManifest.expected b/chrome/android/expectations/monochrome_64_32_public_bundle__chrome.AndroidManifest.expected index 8471da0d..8e15136 100644 --- a/chrome/android/expectations/monochrome_64_32_public_bundle__chrome.AndroidManifest.expected +++ b/chrome/android/expectations/monochrome_64_32_public_bundle__chrome.AndroidManifest.expected
@@ -392,6 +392,7 @@ <activity # DIFF-ANCHOR: 6e34d703 android:name="org.chromium.chrome.browser.task_manager.ui.TaskManagerActivity" android:exported="false" + android:launchMode="singleInstance" android:theme="@style/Theme.Chromium.Activity"> </activity> # DIFF-ANCHOR: 6e34d703 <activity # DIFF-ANCHOR: 43bfa5de
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserver.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserver.java index e3b4816..70fd044 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserver.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserver.java
@@ -11,8 +11,8 @@ import org.chromium.base.lifetime.Destroyable; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.components.collaboration.CollaborationService; import org.chromium.components.data_sharing.DataSharingService; -import org.chromium.components.data_sharing.DataSharingService.GroupDataOrFailureOutcome; import org.chromium.components.data_sharing.GroupData; import org.chromium.components.data_sharing.GroupMember; import org.chromium.components.tab_group_sync.LocalTabGroupId; @@ -51,18 +51,20 @@ private final ObservableSupplierImpl<String> mCurrentCollaborationIdSupplier = new ObservableSupplierImpl<>(); private final LocalTabGroupId mLocalTabGroupId; - private final DataSharingService mDataSharingService; private final TabGroupSyncService mTabGroupSyncService; + private final DataSharingService mDataSharingService; /** * @param tabGroupId The id of the tab group. * @param tabGroupSyncService Used to fetch the current collaboration id of the group. - * @param dataSharingService Used to fetch and observe current share data. + * @param dataSharingService Used to observe current share data. + * @param collaborationService Used to fetch current share data. */ public SharedGroupObserver( @NonNull Token tabGroupId, @NonNull TabGroupSyncService tabGroupSyncService, - @NonNull DataSharingService dataSharingService) { + @NonNull DataSharingService dataSharingService, + @NonNull CollaborationService collaborationService) { mTabGroupSyncService = tabGroupSyncService; mDataSharingService = dataSharingService; mLocalTabGroupId = new LocalTabGroupId(tabGroupId); @@ -73,7 +75,9 @@ mGroupMembersSupplier.set(null); } else { mCurrentCollaborationIdSupplier.set(group.collaborationId); - dataSharingService.readGroup(group.collaborationId, this::onReadGroup); + @Nullable + GroupData groupData = collaborationService.getGroupData(group.collaborationId); + updateOurGroupData(groupData); } dataSharingService.addObserver(mObserver); @@ -110,15 +114,14 @@ return mCurrentCollaborationIdSupplier; } - private void onReadGroup(@NonNull GroupDataOrFailureOutcome outcome) { - mGroupSharedStateSupplier.set(TabShareUtils.discernSharedGroupState(outcome)); - mGroupMembersSupplier.set(TabShareUtils.getGroupMembers(outcome)); + private void updateOurGroupData(@Nullable GroupData groupData) { + mGroupSharedStateSupplier.set(TabShareUtils.discernSharedGroupState(groupData)); + mGroupMembersSupplier.set(TabShareUtils.getGroupMembers(groupData)); } private void updateForNonDeletedGroupData(@Nullable GroupData groupData) { if (isOurGroup(groupData)) { - mGroupSharedStateSupplier.set(TabShareUtils.discernSharedGroupState(groupData)); - mGroupMembersSupplier.set(TabShareUtils.getGroupMembers(groupData)); + updateOurGroupData(groupData); } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserverUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserverUnitTest.java index 4711951..b8460d64 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserverUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SharedGroupObserverUnitTest.java
@@ -16,7 +16,6 @@ import androidx.annotation.Nullable; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -31,8 +30,8 @@ import org.chromium.base.Callback; import org.chromium.base.Token; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.components.collaboration.CollaborationService; import org.chromium.components.data_sharing.DataSharingService; -import org.chromium.components.data_sharing.PeopleGroupActionFailure; import org.chromium.components.data_sharing.SharedGroupTestHelper; import org.chromium.components.tab_group_sync.LocalTabGroupId; import org.chromium.components.tab_group_sync.SavedTabGroup; @@ -47,23 +46,23 @@ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Mock private DataSharingService mDataSharingService; @Mock private TabGroupSyncService mTabGroupSyncService; + @Mock private DataSharingService mDataSharingService; + @Mock private CollaborationService mCollaborationService; @Mock private Callback<Integer> mOnSharedGroupStateChanged; @Captor private ArgumentCaptor<DataSharingService.Observer> mSharingObserverCaptor; private SharedGroupTestHelper mSharedGroupTestHelper; - @Before - public void setUp() { - mSharedGroupTestHelper = new SharedGroupTestHelper(mDataSharingService); - } - @Test public void testDestroy() { SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); verify(mDataSharingService).addObserver(any()); observer.destroy(); @@ -74,7 +73,11 @@ public void testGet_nullGroup() { when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(null); SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); @GroupSharedState int state = observer.getGroupSharedStateSupplier().get(); assertEquals(GroupSharedState.NOT_SHARED, state); @@ -90,7 +93,11 @@ savedTabGroup.collaborationId = null; when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(savedTabGroup); SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); @GroupSharedState int state = observer.getGroupSharedStateSupplier().get(); assertEquals(GroupSharedState.NOT_SHARED, state); @@ -101,15 +108,18 @@ } @Test - public void testGet_failedReadGroup() { + public void testGet_emptyGetGroupData() { SavedTabGroup savedTabGroup = new SavedTabGroup(); savedTabGroup.collaborationId = COLLABORATION_ID1; when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(savedTabGroup); - SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + when(mCollaborationService.getGroupData(COLLABORATION_ID1)).thenReturn(null); - mSharedGroupTestHelper.respondToReadGroup( - COLLABORATION_ID1, PeopleGroupActionFailure.TRANSIENT_FAILURE); + SharedGroupObserver observer = + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); @GroupSharedState int state = observer.getGroupSharedStateSupplier().get(); assertEquals(GroupSharedState.NOT_SHARED, state); @@ -125,10 +135,16 @@ SavedTabGroup savedTabGroup = new SavedTabGroup(); savedTabGroup.collaborationId = COLLABORATION_ID1; when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(savedTabGroup); - SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + when(mCollaborationService.getGroupData(COLLABORATION_ID1)) + .thenReturn(SharedGroupTestHelper.newGroupData(COLLABORATION_ID1, GROUP_MEMBER1)); - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID1, GROUP_MEMBER1); + SharedGroupObserver observer = + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); + @GroupSharedState int state = observer.getGroupSharedStateSupplier().get(); assertEquals(GroupSharedState.COLLABORATION_ONLY, state); @@ -143,10 +159,18 @@ SavedTabGroup savedTabGroup = new SavedTabGroup(); savedTabGroup.collaborationId = COLLABORATION_ID1; when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(savedTabGroup); - SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + when(mCollaborationService.getGroupData(COLLABORATION_ID1)) + .thenReturn( + SharedGroupTestHelper.newGroupData( + COLLABORATION_ID1, GROUP_MEMBER1, GROUP_MEMBER2)); - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID1, GROUP_MEMBER1, GROUP_MEMBER2); + SharedGroupObserver observer = + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); + @GroupSharedState int state = observer.getGroupSharedStateSupplier().get(); assertEquals(GroupSharedState.HAS_OTHER_USERS, state); @@ -163,7 +187,11 @@ savedTabGroup.collaborationId = null; when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(savedTabGroup); SharedGroupObserver observer = - new SharedGroupObserver(TAB_GROUP_ID, mTabGroupSyncService, mDataSharingService); + new SharedGroupObserver( + TAB_GROUP_ID, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); observer.getGroupSharedStateSupplier().addObserver(mOnSharedGroupStateChanged); ShadowLooper.runUiThreadTasks();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java index 9261951..8cc22f3 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java
@@ -104,6 +104,8 @@ (preference, newValue) -> { boolean enabled = (boolean) newValue; mArchiveSettings.setArchiveDuplicateTabsEnabled(enabled); + RecordHistogram.recordBooleanHistogram( + "Tabs.ArchiveSettings.ArchiveDuplicateTabsEnabled", enabled); return true; }); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java index 4a57de4..e27d7f0 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java
@@ -136,10 +136,17 @@ TabArchiveSettingsFragment.PREF_TAB_ARCHIVE_INCLUDE_DUPLICATE_TABS); assertFalse(enableArchiveDuplicateTabs.isChecked()); + histogramWatcher = + HistogramWatcher.newSingleRecordWatcher( + "Tabs.ArchiveSettings.ArchiveDuplicateTabsEnabled", true); enableArchiveDuplicateTabs.onClick(); assertTrue(mArchiveSettings.isArchiveDuplicateTabsEnabled()); + histogramWatcher = + HistogramWatcher.newSingleRecordWatcher( + "Tabs.ArchiveSettings.ArchiveDuplicateTabsEnabled", false); enableArchiveDuplicateTabs.onClick(); + histogramWatcher.assertExpected(); assertFalse(mArchiveSettings.isArchiveDuplicateTabsEnabled()); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java index 4817a7c..19feeab 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -188,9 +188,9 @@ private final ValueChangedCallback<TabGroupModelFilter> mOnTabGroupModelFilterChanged = new ValueChangedCallback<>(this::onTabGroupModelFilterChanged); + private final Callback<String> mOnCollaborationIdChanged = this::onCollaborationIdChanged; private final Callback<Integer> mOnGroupSharedStateChanged = this::onGroupSharedStateChanged; private final Callback<List<GroupMember>> mOnGroupMembersChanged = this::onGroupMembersChanged; - private final Callback<String> mOnCollaborationIdChanged = this::onCollaborationIdChanged; private final Activity mActivity; private final DialogController mDialogController; private final PropertyModel mModel; @@ -275,16 +275,18 @@ && ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SHARING)) { mDataSharingService = DataSharingServiceFactory.getForProfile(mOriginalProfile); mTransitiveSharedGroupObserver = - new TransitiveSharedGroupObserver(mTabGroupSyncService, mDataSharingService); + new TransitiveSharedGroupObserver( + mTabGroupSyncService, mDataSharingService, mCollaborationService); + // This should be the first supplier set as the other suppliers depend on its value. + mTransitiveSharedGroupObserver + .getCollaborationIdSupplier() + .addObserver(mOnCollaborationIdChanged); mTransitiveSharedGroupObserver .getGroupSharedStateSupplier() .addObserver(mOnGroupSharedStateChanged); mTransitiveSharedGroupObserver .getGroupMembersSupplier() .addObserver(mOnGroupMembersChanged); - mTransitiveSharedGroupObserver - .getCollaborationIdSupplier() - .addObserver(mOnCollaborationIdChanged); mMessagingBackendService = MessagingBackendServiceFactory.getForProfile(mOriginalProfile); mPersistentMessageObserver = @@ -1052,19 +1054,6 @@ mTransitiveSharedGroupObserver.setTabGroupId(tab.getTabGroupId()); } - private void onGroupMembersChanged(@Nullable List<GroupMember> members) { - if (mSharedImageTilesCoordinator == null) return; - - @Nullable - String collaborationId = mTransitiveSharedGroupObserver.getCollaborationIdSupplier().get(); - if (members != null && TabShareUtils.isCollaborationIdValid(collaborationId)) { - mSharedImageTilesCoordinator.onGroupMembersChanged(collaborationId, members); - } else { - mSharedImageTilesCoordinator.onGroupMembersChanged( - /* collaborationId= */ null, /* members= */ null); - } - } - private void onCollaborationIdChanged(@Nullable String collaborationId) { if (TabShareUtils.isCollaborationIdValid(collaborationId)) { showOrUpdateCollaborationActivityMessageCard(); @@ -1098,6 +1087,19 @@ } } + private void onGroupMembersChanged(@Nullable List<GroupMember> members) { + if (mSharedImageTilesCoordinator == null) return; + + @Nullable + String collaborationId = mTransitiveSharedGroupObserver.getCollaborationIdSupplier().get(); + if (members != null && TabShareUtils.isCollaborationIdValid(collaborationId)) { + mSharedImageTilesCoordinator.onGroupMembersChanged(collaborationId, members); + } else { + mSharedImageTilesCoordinator.onGroupMembersChanged( + /* collaborationId= */ null, /* members= */ null); + } + } + private List<Tab> getRelatedTabs(int tabId) { return mCurrentTabGroupModelFilterSupplier.get().getRelatedTabList(tabId); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupColorViewProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupColorViewProvider.java index a3c9b7d..2cd6eec5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupColorViewProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupColorViewProvider.java
@@ -79,7 +79,11 @@ if (servicesExist && collaborationService.getServiceStatus().isAllowedToJoin()) { mDataSharingService = dataSharingService; mSharedGroupObserver = - new SharedGroupObserver(tabGroupId, tabGroupSyncService, dataSharingService); + new SharedGroupObserver( + tabGroupId, + tabGroupSyncService, + dataSharingService, + collaborationService); mSharedGroupObserver.getGroupMembersSupplier().addObserver(mOnGroupMembersChanged); mSharedGroupObserver .getGroupSharedStateSupplier()
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java index 05d3ac94..4e72982 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -21,6 +21,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.supplier.OneshotSupplier; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.collaboration.CollaborationServiceFactory; import org.chromium.chrome.browser.data_sharing.DataSharingServiceFactory; import org.chromium.chrome.browser.data_sharing.ui.shared_image_tiles.SharedImageTilesCoordinator; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -50,6 +51,7 @@ import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator.BottomControlsVisibilityController; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; +import org.chromium.components.collaboration.CollaborationService; import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.data_sharing.GroupMember; import org.chromium.components.embedder_support.util.UrlConstants; @@ -158,8 +160,11 @@ TabGroupSyncServiceFactory.getForProfile(originalProfile); DataSharingService dataSharingService = DataSharingServiceFactory.getForProfile(originalProfile); + CollaborationService collaborationService = + CollaborationServiceFactory.getForProfile(originalProfile); mTransitiveSharedGroupObserver = - new TransitiveSharedGroupObserver(tabGroupSyncService, dataSharingService); + new TransitiveSharedGroupObserver( + tabGroupSyncService, dataSharingService, collaborationService); mTransitiveSharedGroupObserver .getGroupSharedStateSupplier() .addObserver(mOnGroupSharedStateChanged);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserver.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserver.java index 1419c38..7e8104d 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserver.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserver.java
@@ -12,6 +12,7 @@ import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.supplier.TransitiveObservableSupplier; +import org.chromium.components.collaboration.CollaborationService; import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.data_sharing.GroupMember; import org.chromium.components.tab_group_sync.TabGroupSyncService; @@ -29,20 +30,24 @@ mGroupMembersSupplier; private final TransitiveObservableSupplier<SharedGroupObserver, String> mCollaborationIdSupplier; - private final DataSharingService mDataSharingService; private final TabGroupSyncService mTabGroupSyncService; + private final DataSharingService mDataSharingService; + private final CollaborationService mCollaborationService; private @Nullable Token mCurrentTabGroupId; /** * @param tabGroupSyncService Used to fetch the current collaboration id of the group. - * @param dataSharingService Used to fetch and observe current share data. + * @param dataSharingService Used to observe current share data. + * @param collaborationService Used to fetch current shared data. */ public TransitiveSharedGroupObserver( @NonNull TabGroupSyncService tabGroupSyncService, - @NonNull DataSharingService dataSharingService) { + @NonNull DataSharingService dataSharingService, + @NonNull CollaborationService collaborationService) { mTabGroupSyncService = tabGroupSyncService; mDataSharingService = dataSharingService; + mCollaborationService = collaborationService; mGroupSharedStateSupplier = new TransitiveObservableSupplier<>( @@ -78,7 +83,10 @@ tabGroupId == null ? null : new SharedGroupObserver( - tabGroupId, mTabGroupSyncService, mDataSharingService); + tabGroupId, + mTabGroupSyncService, + mDataSharingService, + mCollaborationService); swapSharedGroupObserver(newObserver); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserverUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserverUnitTest.java index 7e8bf36..a6b1388f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserverUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TransitiveSharedGroupObserverUnitTest.java
@@ -6,7 +6,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -15,7 +14,6 @@ import static org.chromium.components.data_sharing.SharedGroupTestHelper.GROUP_MEMBER1; import static org.chromium.components.data_sharing.SharedGroupTestHelper.GROUP_MEMBER2; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,6 +24,7 @@ import org.chromium.base.Callback; import org.chromium.base.Token; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.components.collaboration.CollaborationService; import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.data_sharing.GroupMember; import org.chromium.components.data_sharing.SharedGroupTestHelper; @@ -44,23 +43,20 @@ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Mock private DataSharingService mDataSharingService; @Mock private TabGroupSyncService mTabGroupSyncService; + @Mock private DataSharingService mDataSharingService; + @Mock private CollaborationService mCollaborationService; @Mock private Callback<Integer> mOnSharedGroupStateChanged; @Mock private Callback<String> mOnSharedGroupCollaborationIdChanged; @Mock private Callback<List<GroupMember>> mOnGroupMembersChanged; private SharedGroupTestHelper mSharedGroupTestHelper; - @Before - public void setUp() { - mSharedGroupTestHelper = new SharedGroupTestHelper(mDataSharingService); - } - @Test public void testDestroy_NoTabGroupId() { TransitiveSharedGroupObserver observer = - new TransitiveSharedGroupObserver(mTabGroupSyncService, mDataSharingService); + new TransitiveSharedGroupObserver( + mTabGroupSyncService, mDataSharingService, mCollaborationService); verify(mDataSharingService, never()).addObserver(any()); observer.destroy(); @@ -70,7 +66,8 @@ @Test public void testDestroy_WithTabGroupId() { TransitiveSharedGroupObserver observer = - new TransitiveSharedGroupObserver(mTabGroupSyncService, mDataSharingService); + new TransitiveSharedGroupObserver( + mTabGroupSyncService, mDataSharingService, mCollaborationService); observer.setTabGroupId(TAB_GROUP_ID_1); verify(mDataSharingService).addObserver(any()); @@ -81,7 +78,8 @@ @Test public void testChangeTabGroupId_WithData() { TransitiveSharedGroupObserver observer = - new TransitiveSharedGroupObserver(mTabGroupSyncService, mDataSharingService); + new TransitiveSharedGroupObserver( + mTabGroupSyncService, mDataSharingService, mCollaborationService); observer.getGroupSharedStateSupplier().addObserver(mOnSharedGroupStateChanged); observer.getGroupMembersSupplier().addObserver(mOnGroupMembersChanged); observer.getCollaborationIdSupplier().addObserver(mOnSharedGroupCollaborationIdChanged); @@ -89,16 +87,20 @@ SavedTabGroup savedTabGroup = new SavedTabGroup(); savedTabGroup.collaborationId = COLLABORATION_ID1; when(mTabGroupSyncService.getGroup(any(LocalTabGroupId.class))).thenReturn(savedTabGroup); + when(mCollaborationService.getGroupData(COLLABORATION_ID1)) + .thenReturn(SharedGroupTestHelper.newGroupData(COLLABORATION_ID1, GROUP_MEMBER1)); observer.setTabGroupId(TAB_GROUP_ID_1); - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID1, GROUP_MEMBER1); verify(mOnSharedGroupStateChanged).onResult(GroupSharedState.COLLABORATION_ONLY); verify(mOnGroupMembersChanged).onResult(List.of(GROUP_MEMBER1)); verify(mOnSharedGroupCollaborationIdChanged).onResult(COLLABORATION_ID1); savedTabGroup.collaborationId = COLLABORATION_ID2; + when(mCollaborationService.getGroupData(COLLABORATION_ID2)) + .thenReturn( + SharedGroupTestHelper.newGroupData( + COLLABORATION_ID1, GROUP_MEMBER1, GROUP_MEMBER2)); observer.setTabGroupId(TAB_GROUP_ID_2); - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID2, GROUP_MEMBER1, GROUP_MEMBER2); verify(mOnSharedGroupStateChanged).onResult(GroupSharedState.HAS_OTHER_USERS); verify(mOnGroupMembersChanged).onResult(List.of(GROUP_MEMBER1, GROUP_MEMBER2)); @@ -108,7 +110,7 @@ observer.setTabGroupId(TAB_GROUP_ID_3); verify(mOnSharedGroupStateChanged).onResult(GroupSharedState.NOT_SHARED); - verify(mOnGroupMembersChanged, times(2)).onResult(null); + verify(mOnGroupMembersChanged).onResult(null); verify(mOnSharedGroupCollaborationIdChanged).onResult(null); observer.destroy();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java index 59386db..5f37004 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -11,6 +11,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -108,6 +109,7 @@ import org.chromium.components.collaboration.messaging.TabMessageMetadata; import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.data_sharing.DataSharingUIDelegate; +import org.chromium.components.data_sharing.GroupData; import org.chromium.components.data_sharing.GroupMember; import org.chromium.components.data_sharing.SharedGroupTestHelper; import org.chromium.components.signin.base.CoreAccountInfo; @@ -187,6 +189,7 @@ @Captor private ArgumentCaptor<PropertyModel> mCollaborationActivityMessageCardCaptor; @Captor private ArgumentCaptor<DataSharingService.Observer> mSharingObserverCaptor; @Captor private ArgumentCaptor<PropertyModel> mMessageCardModelCaptor; + @Captor private ArgumentCaptor<DataSharingService.Observer> mDataSharingServiceObserverCaptor; @Captor private ArgumentCaptor<MessagingBackendService.PersistentMessageObserver> @@ -201,7 +204,6 @@ private Activity mActivity; private PropertyModel mModel; private TabGridDialogMediator mMediator; - private SharedGroupTestHelper mSharedGroupTestHelper; @Before public void setUp() { @@ -221,7 +223,6 @@ when(mCollaborationService.getServiceStatus()).thenReturn(mServiceStatus); MessagingBackendServiceFactory.setForTesting(mMessagingBackendService); mockPersistentMessages(/* added= */ 1, /* navigated= */ 2, /* removed= */ 3); - mSharedGroupTestHelper = new SharedGroupTestHelper(mDataSharingService); mTab1 = prepareTab(TAB1_ID, TAB1_TITLE); mTab2 = prepareTab(TAB2_ID, TAB2_TITLE); @@ -1573,11 +1574,12 @@ @Test public void testUpdateShareData_Incognito() { - reset(mSharedImageTilesCoordinator); assertFalse(mModel.get(TabGridDialogProperties.SHOW_SHARE_BUTTON)); assertFalse(mModel.get(TabGridDialogProperties.SHOW_IMAGE_TILES)); resetForDataSharing(/* isShared= */ true, GROUP_MEMBER1); + verify(mSharedImageTilesCoordinator) + .onGroupMembersChanged(COLLABORATION_ID1, List.of(GROUP_MEMBER1)); when(mTabGroupModelFilter.isIncognitoBranded()).thenReturn(true); resetForDataSharing(/* isShared= */ false); @@ -1589,7 +1591,6 @@ @Test public void testShowOrUpdateCollaborationActivityMessageCard() { - reset(mSharedImageTilesCoordinator); assertFalse(mModel.get(TabGridDialogProperties.SHOW_SHARE_BUTTON)); assertFalse(mModel.get(TabGridDialogProperties.SHOW_IMAGE_TILES)); @@ -1767,12 +1768,24 @@ List<Tab> tabGroup = new ArrayList<>(Arrays.asList(mTab1, mTab2)); createTabGroup(tabGroup, rootId, TAB_GROUP_ID); + GroupData groupData = SharedGroupTestHelper.newGroupData(COLLABORATION_ID1, members); + if (isShared) { + when(mCollaborationService.getGroupData(COLLABORATION_ID1)).thenReturn(groupData); + } else { + when(mCollaborationService.getGroupData(any())).thenReturn(null); + } + setupSyncedGroup(isShared); mMediator.onReset(tabGroup); - + verify(mDataSharingService, atLeastOnce()) + .addObserver(mDataSharingServiceObserverCaptor.capture()); + DataSharingService.Observer observer = mDataSharingServiceObserverCaptor.getValue(); + assertNotNull(observer); if (isShared) { - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID1, members); + observer.onGroupChanged(groupData); + } else { + observer.onGroupRemoved(COLLABORATION_ID1); } }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java index ed445ba..5ce6299 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -62,6 +62,7 @@ import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.R; +import org.chromium.chrome.browser.collaboration.CollaborationServiceFactory; import org.chromium.chrome.browser.data_sharing.DataSharingServiceFactory; import org.chromium.chrome.browser.data_sharing.ui.shared_image_tiles.SharedImageTilesCoordinator; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -90,6 +91,7 @@ import org.chromium.chrome.browser.theme.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; +import org.chromium.components.collaboration.CollaborationService; import org.chromium.components.data_sharing.DataSharingService; import org.chromium.components.data_sharing.DataSharingUIDelegate; import org.chromium.components.data_sharing.SharedGroupTestHelper; @@ -128,6 +130,7 @@ @Mock private TabGroupSyncService mTabGroupSyncService; @Mock private DataSharingService mDataSharingService; @Mock private DataSharingUIDelegate mDataSharingUiDelegate; + @Mock private CollaborationService mCollaborationService; @Mock private BottomControlsCoordinator.BottomControlsVisibilityController mVisibilityController; @@ -291,6 +294,7 @@ doReturn(true).when(mTabGroupSyncFeaturesJniMock).isTabGroupSyncEnabled(mProfile); TabGroupSyncServiceFactory.setForTesting(mTabGroupSyncService); DataSharingServiceFactory.setForTesting(mDataSharingService); + CollaborationServiceFactory.setForTesting(mCollaborationService); when(mDataSharingService.getUiDelegate()).thenReturn(mDataSharingUiDelegate); mSharedGroupTestHelper = new SharedGroupTestHelper(mDataSharingService); @@ -1127,9 +1131,11 @@ @Test public void testImageTiles_2Members() { setupSyncedGroup(/* isShared= */ true); - + when(mCollaborationService.getGroupData(COLLABORATION_ID1)) + .thenReturn( + SharedGroupTestHelper.newGroupData( + COLLABORATION_ID1, GROUP_MEMBER1, GROUP_MEMBER2)); initAndAssertProperties(mTab2); - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID1, GROUP_MEMBER1, GROUP_MEMBER2); assertFalse(mModel.get(TabGroupUiProperties.SHOW_GROUP_DIALOG_BUTTON_VISIBLE)); assertTrue(mModel.get(TabGroupUiProperties.IMAGE_TILES_CONTAINER_VISIBLE)); @@ -1148,9 +1154,9 @@ @Test public void testImageTiles_1Member() { setupSyncedGroup(/* isShared= */ true); - + when(mCollaborationService.getGroupData(COLLABORATION_ID1)) + .thenReturn(SharedGroupTestHelper.newGroupData(COLLABORATION_ID1, GROUP_MEMBER1)); initAndAssertProperties(mTab2); - mSharedGroupTestHelper.respondToReadGroup(COLLABORATION_ID1, GROUP_MEMBER1); assertTrue(mModel.get(TabGroupUiProperties.SHOW_GROUP_DIALOG_BUTTON_VISIBLE)); assertFalse(mModel.get(TabGroupUiProperties.IMAGE_TILES_CONTAINER_VISIBLE));
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index cdcf3bb7..7151c54 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -1096,7 +1096,8 @@ <activity android:name="org.chromium.chrome.browser.task_manager.ui.TaskManagerActivity" android:exported="false" - android:theme="@style/Theme.Chromium.Activity"> + android:theme="@style/Theme.Chromium.Activity" + android:launchMode="singleInstance"> </activity> <receiver android:name="org.chromium.chrome.browser.notifications.scheduler.DisplayAgent$Receiver"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java index 5e108eb8..f65a11d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -275,6 +275,8 @@ private static final String PACKAGE_WHATSAPP = "com.whatsapp"; private static final String PACKAGE_YAHOO_MAIL = "com.yahoo.mobile.client.android.mail"; private static final String PACKAGE_VIBER = "com.viber.voip"; + private static final String PACKAGE_PIXEL_LAUNCHER = "com.google.android.apps.nexuslauncher"; + private static final String THIRD_PARTY_LAUNCHER_SUFFIX = "launcher"; private static final String FACEBOOK_REFERRER_URL = "android-app://m.facebook.com"; private static final String FACEBOOK_INTERNAL_BROWSER_REFERRER = "http://m.facebook.com"; private static final String TWITTER_LINK_PREFIX = "http://t.co/"; @@ -310,6 +312,8 @@ ExternalAppId.VIBER, ExternalAppId.YOUTUBE, ExternalAppId.CAMERA, + ExternalAppId.PIXEL_LAUNCHER, + ExternalAppId.THIRD_PARTY_LAUNCHER, ExternalAppId.NUM_ENTRIES }) @Retention(RetentionPolicy.SOURCE) @@ -331,8 +335,10 @@ int VIBER = 14; int YOUTUBE = 15; int CAMERA = 16; + int PIXEL_LAUNCHER = 17; + int THIRD_PARTY_LAUNCHER = 18; // Update ClientAppId in enums.xml when adding new items. - int NUM_ENTRIES = 17; + int NUM_ENTRIES = 19; } /** @@ -494,9 +500,15 @@ if (externalId == ExternalAppId.OTHER && activity != null) { String activityReferrer = getActivityReferrer(intent, activity); - if (activityReferrer != null - && activityReferrer.toLowerCase(Locale.getDefault()).endsWith("camera")) { - return ExternalAppId.CAMERA; + if (activityReferrer != null) { + String referrer = activityReferrer.toLowerCase(Locale.getDefault()); + if (referrer.endsWith("camera")) { + return ExternalAppId.CAMERA; + } else if (referrer.endsWith(PACKAGE_PIXEL_LAUNCHER)) { + return ExternalAppId.PIXEL_LAUNCHER; + } else if (referrer.endsWith(THIRD_PARTY_LAUNCHER_SUFFIX)) { + return ExternalAppId.THIRD_PARTY_LAUNCHER; + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index 5daf4b1..e48ac2dff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -2257,9 +2257,9 @@ void createAndStartDetachedResourceRequest( @JniType("Profile*") Profile profile, CustomTabsSessionToken session, - String packageName, - String url, - String origin, + @JniType("std::string") String packageName, + @JniType("std::string") String url, + @JniType("std::string") String origin, int referrerPolicy, @DetachedResourceRequestMotivation int motivation); @@ -2268,10 +2268,12 @@ void textFragmentLookup( CustomTabsSessionToken session, WebContents webContents, - String stateKey, + @JniType("std::string") String stateKey, String[] textFragment); void textFragmentFindScrollAndHighlight( - CustomTabsSessionToken session, WebContents webContents, String textFragment); + CustomTabsSessionToken session, + WebContents webContents, + @JniType("std::string") String textFragment); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiver.java index 6ffe4d7..1b5f5b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiver.java
@@ -405,6 +405,9 @@ : false; RecordHistogram.recordCount1000Histogram( "Tabs.TabArchiveEligibilityCheck.AfterNDays", tabAgeDays); + if (isDuplicateTabEligibleForArchive) { + RecordUserAction.record("Tabs.ArchivedDuplicateTab"); + } return isTabTimestampEligibleForArchive || isDuplicateTabEligibleForArchive; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlagsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlagsTest.java index 8f4ced5..96b7f93e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlagsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlagsTest.java
@@ -72,8 +72,7 @@ ChromeFeatureList.sTabStripGroupCollapse, ChromeFeatureList.sTraceBinderIpc, OmniboxFeatures.sAndroidHubSearch, - OmniboxFeatures.sOmniboxAnswerActions, - OmniboxFeatures.sRetainOmniboxOnFocus); + OmniboxFeatures.sOmniboxAnswerActions); /** * Tests that the |defaultValueForTests| in the CachedFlag declaration matches
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java index 55c4b06..9c01d02 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
@@ -337,7 +337,8 @@ @MediumTest public void testEditingText() { testEditingText( - /* expectRetainOmniboxOnFocus= */ OmniboxFeatures.shouldRetainOmniboxOnFocus()); + /* expectRetainOmniboxOnFocus= */ ThreadUtils.runOnUiThreadBlocking( + OmniboxFeatures::shouldRetainOmniboxOnFocus)); } @Test @@ -635,7 +636,8 @@ @Restriction(DeviceFormFactor.TABLET) public void testFocusLogic_buttonVisibilityTablet() { testFocusLogic_buttonVisibilityTablet( - /* expectRetainOmniboxOnFocus= */ OmniboxFeatures.shouldRetainOmniboxOnFocus()); + /* expectRetainOmniboxOnFocus= */ ThreadUtils.runOnUiThreadBlocking( + OmniboxFeatures::shouldRetainOmniboxOnFocus)); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java index 77d5fcf8..3e0224f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
@@ -141,39 +141,4 @@ RecordHistogram.getHistogramValueCountForTesting( "interstitial.ssl_error_handler", UMAEvent.OS_REPORTS_CAPTIVE_PORTAL)); } - - /** - * When CaptivePortalInterstitial feature is disabled, the result of OS captive portal APIs - * should be ignored, and a generic SSL interstitial should be displayed. - */ - @Test - @CommandLineFlags.Add({"disable-features=CaptivePortalInterstitial"}) - public void testOSReportsCaptivePortal_FeatureDisabled() throws Exception { - CaptivePortalHelper.setOSReportsCaptivePortalForTesting(true); - - Tab tab = mActivityTestRule.getActivity().getActivityTab(); - ChromeTabUtils.loadUrlOnUiThread( - tab, mServer.getURL("/chrome/test/data/android/navigate/simple.html")); - - new TabTitleObserver(tab, SSL_INTERSTITIAL_TITLE) - .waitForTitleUpdate(INTERSTITIAL_TITLE_UPDATE_TIMEOUT_SECONDS); - - Assert.assertEquals( - 1, - RecordHistogram.getHistogramValueCountForTesting( - "interstitial.ssl_error_handler", UMAEvent.HANDLE_ALL)); - Assert.assertEquals( - 1, - RecordHistogram.getHistogramValueCountForTesting( - "interstitial.ssl_error_handler", - UMAEvent.SHOW_SSL_INTERSTITIAL_OVERRIDABLE)); - Assert.assertEquals( - 0, - RecordHistogram.getHistogramValueCountForTesting( - "interstitial.ssl_error_handler", UMAEvent.CAPTIVE_PORTAL_CERT_FOUND)); - Assert.assertEquals( - 0, - RecordHistogram.getHistogramValueCountForTesting( - "interstitial.ssl_error_handler", UMAEvent.OS_REPORTS_CAPTIVE_PORTAL)); - } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java index 2086b39..526919b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java
@@ -5,9 +5,11 @@ package org.chromium.chrome.browser.tab; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; @@ -488,6 +490,8 @@ // Check that tab 2 has been archived. assertEquals(0, mArchivedTabModel.getTabAt(0).getTimestampMillis()); watcher.assertExpected(); + String action = "Tabs.ArchivedDuplicateTab"; + assertTrue(mUserActionTester.getActions().contains(action)); } @Test @@ -586,6 +590,8 @@ CriteriaHelper.pollUiThread(() -> 4 == mRegularTabModel.getCount()); assertEquals(0, mArchivedTabModel.getCount()); watcher.assertExpected(); + String action = "Tabs.ArchivedDuplicateTab"; + assertFalse(mUserActionTester.getActions().contains(action)); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/IntentHandlerRobolectricTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/IntentHandlerRobolectricTest.java index 2408f5b5..cdaa7c7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/IntentHandlerRobolectricTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/IntentHandlerRobolectricTest.java
@@ -30,6 +30,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; @@ -48,6 +49,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; +import org.chromium.chrome.browser.IntentHandler.ExternalAppId; import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.customtabs.CustomTabsIntentTestUtils; @@ -719,4 +721,23 @@ GOOGLE_URL, IntentHandler.getReferrerUrlIncludingExtraHeaders(trustedIntent)); Assert.assertNull(IntentHandler.getExtraHeadersFromIntent(trustedIntent)); } + + @Test + @SmallTest + @Feature({"Android-AppBase"}) + public void testDetermineExternalIntentSource() { + Activity activity = Mockito.mock(Activity.class); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.putExtra( + IntentHandler.EXTRA_ACTIVITY_REFERRER, + "android-app://com.google.android.apps.nexuslauncher"); + assertEquals( + ExternalAppId.PIXEL_LAUNCHER, + IntentHandler.determineExternalIntentSource(intent, activity)); + + intent.putExtra(IntentHandler.EXTRA_ACTIVITY_REFERRER, "android.app.launcher"); + assertEquals( + ExternalAppId.THIRD_PARTY_LAUNCHER, + IntentHandler.determineExternalIntentSource(intent, activity)); + } }
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 5406a3b..bcd9e96c 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -3227,46 +3227,31 @@ </message> <!-- Android apps page (OS settings) --> - <message name="IDS_SETTINGS_ANDROID_APPS_LABEL" desc="The text associated with the primary section setting."> - Google Play Store - </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_LABEL" desc="The text associated with the primary section setting."> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_LABEL" desc="The text associated with the primary section setting."> Manage Google Play preferences </message> <message name="IDS_SETTINGS_ANDROID_APPS_ENABLE_BUTTON_ROLE" desc="Role description of the button which starts the Google Play Store Terms of Service screen. Spoken aloud by screen readers when the Turn On button is focused"> Turn on Google Play Store </message> - <message name="IDS_SETTINGS_ANDROID_APPS_MANAGE_APPS" desc="Label for launching Android apps settings."> - Manage Android preferences - </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_MANAGE_APPS" desc="Label for launching Android apps settings."> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_MANAGE_APPS" desc="Label for launching Android apps settings."> Android Settings </message> - <message name="IDS_SETTINGS_ANDROID_APPS_REMOVE" desc="Label for the control to open a dialog confirming removal of the Google Play Store."> - Remove Google Play Store - </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_REMOVE" desc="Label for the control to open a dialog confirming removal of the Google Play Store."> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_REMOVE" desc="Label for the control to open a dialog confirming removal of the Google Play Store."> Remove Google Play and Android apps </message> <message name="IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON" desc="Label for the button for the removal of the Google Play Store"> Remove </message> - <message name="IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE" desc="Title of the confirmation dialog for disabling android apps."> - Remove Android apps? - </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_TITLE" desc="Title of the confirmation dialog for disabling android apps."> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE" desc="Title of the confirmation dialog for disabling android apps."> Remove Google Play and Android apps? </message> - <message name="IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE" desc="Label for confirmation button in the disable android apps dialog."> - Remove Android apps - </message> <message name="IDS_SETTINGS_ANDROID_APPS_MANAGE_APP_LINKS" desc="Label for accessing app preferrences on ARC side."> Manage Play app links </message> <message name="IDS_SETTINGS_APPS_ARC_VM_SHARED_USB_DEVICES_DESCRIPTION" desc="Description for managing shared USB devices. Do not translate 'ARCVM'."> Let Android apps access USB devices on this Chromebook. Permission will be requested each time you plug in a USB device. Individual Android apps will ask for additional permissions. </message> - <message name="IDS_OS_SETTINGS_REVAMP_OPEN_GOOGLE_PLAY" desc="Label for launching Google Play Store."> + <message name="IDS_OS_SETTINGS_OPEN_GOOGLE_PLAY" desc="Label for launching Google Play Store."> Open Google Play </message> @@ -5160,22 +5145,16 @@ <message name="IDS_SETTINGS_USERS_MANAGED_LABEL" desc="Label saying settings is managed by enterprise and thus can't be modified."> These settings are controlled by enterprise policy. Please contact your administrator for more information. </message> - <message name="IDS_SETTINGS_USERS_GUEST_BROWSING_LABEL" desc="Label for the guest browsing setting."> - Enable Guest browsing - </message> - <message name="IDS_OS_SETTINGS_REVAMP_USERS_GUEST_BROWSING_LABEL" desc="Label for the guest browsing setting."> + <message name="IDS_OS_SETTINGS_USERS_GUEST_BROWSING_LABEL" desc="Label for the guest browsing setting."> Guest browsing </message> <message name="IDS_SETTINGS_USERS_SHOW_ON_SIGNIN_LABEL" desc="Label for the 'show users on sign-in screen' setting."> Show usernames and photos on the sign-in screen </message> - <message name="IDS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL" desc="Label for the setting for restricting sign in to specific users."> - Restrict sign-in to the following users: - </message> - <message name="IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_LABEL" desc="Label for the setting for restricting sign in to specific users."> + <message name="IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL" desc="Label for the setting for restricting sign in to specific users."> Limit who can sign in </message> - <message name="IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_DESCRIPTION" desc="Description for the setting for restricting sign in to specific users."> + <message name="IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_DESCRIPTION" desc="Description for the setting for restricting sign in to specific users."> You can limit sign-in to certain users. This removes the "Add person" option on the sign-in screen. You can also remove current users. </message> <message name="IDS_SETTINGS_USERS_DEVICE_OWNER_LABEL" desc="Label for a user who is the device owner."> @@ -6606,19 +6585,19 @@ <message name="IDS_SETTINGS_APPS_LINK_TEXT" desc="The label for the button which links to the App Management page."> Manage your apps </message> - <message name="IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_TITLE" desc="The label for the settings row button in the App section of OS Settings which links to the App Notifications page."> + <message name="IDS_OS_SETTINGS_APP_NOTIFICATIONS_TITLE" desc="The label for the settings row button in the App section of OS Settings which links to the App Notifications page."> Allow notifications </message> - <message name="IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_ANDROID" desc="Label for a link to more settings and permissions for an app with type Android."> + <message name="IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_ANDROID" desc="Label for a link to more settings and permissions for an app with type Android."> More Android settings and permissions </message> - <message name="IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_WEB_APP" desc="Label for a link to more settings and permissions for an app with type web app."> + <message name="IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_WEB_APP" desc="Label for a link to more settings and permissions for an app with type web app."> More web app settings and permissions </message> - <message name="IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_CHROME_APP" desc="Label for a link to more settings and permissions for an app with type Chrome app."> + <message name="IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_CHROME_APP" desc="Label for a link to more settings and permissions for an app with type Chrome app."> More Chrome app settings and permissions </message> - <message name="IDS_OS_SETTINGS_REVAMP_OPEN_IN_APP_TITLE" desc="Label for the intent sharing option to open in a specified app."> + <message name="IDS_OS_SETTINGS_OPEN_IN_APP_TITLE" desc="Label for the intent sharing option to open in a specified app."> Open in <ph name="APP_NAME">$1<ex>Calculator</ex></ph> app </message> <message name="IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TEXT" desc="The label for the settings row button in the App section of OS Settings which links to the App Notifications page."> @@ -6633,7 +6612,7 @@ <message name="IDS_SETTINGS_ISOLATED_WEB_APPS_DESCRIPTION" desc="A short description for Isolated Web Apps and a link for additional information."> Packaged web applications with enhanced capabilities. <ph name="BEGIN_LINK_LEARN_MORE"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK_LEARN_MORE"></a></ph> </message> - <message name="IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION" desc="The description for the settings row button in the App section of OS Settings which links to the App Notifications page."> + <message name="IDS_OS_SETTINGS_APP_NOTIFICATIONS_LINK_DESCRIPTION" desc="The description for the settings row button in the App section of OS Settings which links to the App Notifications page."> Manage app notifications, Do Not Disturb, and app badging </message> <message name="IDS_SETTINGS_APP_NOTIFICATIONS_SUBLABEL_TEXT" desc="The sublabel for the settings row button in the App section of OS Settings which links to the App Notifications page indicating the number of ChromeOS apps installed."> @@ -6697,12 +6676,9 @@ <message name="IDS_OS_SETTINGS_APP_PARENTAL_CONTROLS_PIN_NUMERIC_ERROR_TEXT" desc="The text displayed under the PIN input section that notifies the user that the PIN should only consist of digits"> PIN must use numbers only </message> - <message name="IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION" desc="The text description of the Do Not Disturb toggle within help icon tooltip."> + <message name="IDS_OS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION" desc="The text description of the Do Not Disturb toggle within help icon tooltip."> Notifications won't pop up on the screen. You can still see notifications by clicking the Do Not Disturb icon on the bottom right of your screen. </message> - <message name="IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION" desc="The text description of the DoNotDisturb toggle within help icon tooltip."> - When turned on, all notifications will be silenced - </message> <message name="IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TO_BROWSER_SETTINGS_DESCRIPTION" desc="In notifications OS Settings subpage, explanatory text for website notifications link."> For browser notifications, go to <ph name="LINK_BEGIN"><a href="#"></ph>Chrome browser Settings<ph name="LINK_END"></a></ph> </message> @@ -6712,10 +6688,10 @@ <message name="IDS_SETTINGS_APP_BADGING_TOGGLE_SUBLABEL" desc="The sublabel for the app badging toggle in the App Notifications page of OS Settings."> Show dot on app icon for app alerts </message> - <message name="IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LABEL" desc="The label for the settings row button in the App Notifications section of OS Settings which links to the Manage App Notifications page."> + <message name="IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LABEL" desc="The label for the settings row button in the App Notifications section of OS Settings which links to the Manage App Notifications page."> Manage app notifications </message> - <message name="IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION" desc="The sublabel for the settings row button in the App Notifications section of OS Settings which links to the Manage App Notifications page."> + <message name="IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION" desc="The sublabel for the settings row button in the App Notifications section of OS Settings which links to the Manage App Notifications page."> <ph name="NUM_ALLOWED_APPS">$1<ex>1</ex></ph> of <ph name="TOTAL_NUM_APPS">$2<ex>2</ex></ph> apps can send notifications </message> <message name="IDS_SETTINGS_ENABLE_ISOLATED_WEB_APPS_LABEL" desc="The label for the enable Isolated Web Apps toggle in the Manage Isolated Web Apps page of OS Settings."> @@ -6733,22 +6709,15 @@ <message name="IDS_SETTINGS_ANDROID_APPS_SUBTEXT_DESCRIPTION" desc="Accessibility description for the section for enabling and managing Google Play Store (Android) apps." is_accessibility_with_no_ui="true"> Install apps and games from Google Play on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT" desc="Description for the section for enabling and managing Google Play Store (Android) apps."> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_SUBTEXT" desc="Description for the section for enabling and managing Google Play Store (Android) apps."> You can download Android apps and games through the Play Store. <ph name="LINK_BEGIN"><a target="_blank" href="$1<ex>https://google.com/</ex>"></ph>Learn more<ph name="LINK_END"></a></ph> </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT_DESCRIPTION" desc="Accessibility description for the section for enabling and managing Google Play Store (Android) apps." is_accessibility_with_no_ui="true"> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_SUBTEXT_DESCRIPTION" desc="Accessibility description for the section for enabling and managing Google Play Store (Android) apps." is_accessibility_with_no_ui="true"> You can download Android apps and games through the Play Store. </message> <!-- TODO(jamescook): Use device type instead of "Chromebook", which may require changing ArcPlayTermsOfServiceConsent resource id handling. --> - <message name="IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE" desc="Describes what will happen if the user opts out of android apps."> - Apps you’ve downloaded from Google Play will be deleted from this Chromebook. - <ph name="LINE_BREAKS1"><br><br></ph> - Content you’ve purchased such as movies, TV shows, music, books, or other in-app purchases may also be deleted. - <ph name="LINE_BREAKS2"><br><br></ph> - This doesn’t affect apps or content on other devices. - </message> - <message name="IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_MESSAGE" desc="Describes what will happen if the user opts out of android apps."> + <message name="IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE" desc="Describes what will happen if the user opts out of android apps."> Google Play and apps you've downloaded from Google Play will be deleted from this Chromebook. <ph name="LINE_BREAKS1"><br><br></ph> Content you've purchased through Google Play such as movies, TV shows, music, books, as well as purchases from other apps may also be deleted.
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_MESSAGE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_MESSAGE.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_TITLE.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_LABEL.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_LABEL.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_LABEL.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_MANAGE_APPS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_MANAGE_APPS.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_MANAGE_APPS.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_MANAGE_APPS.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_REMOVE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_REMOVE.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_REMOVE.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_REMOVE.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_SUBTEXT.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_ANDROID_APPS_SUBTEXT.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_NOTIFICATIONS_LINK_DESCRIPTION.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_NOTIFICATIONS_LINK_DESCRIPTION.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_NOTIFICATIONS_TITLE.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_TITLE.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_NOTIFICATIONS_TITLE.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_ANDROID.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_ANDROID.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_ANDROID.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_ANDROID.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_CHROME_APP.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_CHROME_APP.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_CHROME_APP.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_CHROME_APP.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_WEB_APP.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_WEB_APP.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_WEB_APP.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_WEB_APP.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LABEL.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LABEL.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LABEL.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_OPEN_GOOGLE_PLAY.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_OPEN_GOOGLE_PLAY.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_OPEN_GOOGLE_PLAY.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_OPEN_GOOGLE_PLAY.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_OPEN_IN_APP_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_OPEN_IN_APP_TITLE.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_OPEN_IN_APP_TITLE.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_OPEN_IN_APP_TITLE.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_USERS_GUEST_BROWSING_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_USERS_GUEST_BROWSING_LABEL.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_USERS_GUEST_BROWSING_LABEL.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_USERS_GUEST_BROWSING_LABEL.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_DESCRIPTION.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_DESCRIPTION.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_DESCRIPTION.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_LABEL.png.sha1 rename to chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1 deleted file mode 100644 index fe01eb8..0000000 --- a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -932e8cc21fbd6099aadb74763151c1ce11850d24 \ No newline at end of file
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index 9f4c92c..716f97e 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -154,9 +154,7 @@ </if> </if> <structure type="chrome_scaled_image" name="IDR_PLUGINS_FAVICON" file="common/favicon_plugins.png" /> - <if expr="not is_android"> - <structure type="chrome_scaled_image" name="IDR_PRERENDER" file="common/prerender_succeed_icon.png" /> - </if> + <structure type="chrome_scaled_image" name="IDR_PRERENDER" file="common/prerender_succeed_icon.png" /> <structure type="chrome_scaled_image" name="IDR_PRODUCT_LOGO_32" file="${branding_path_component}/product_logo_32.png" /> <if expr="_google_chrome"> <then>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index b8316b3..46ae979 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -84,6 +84,7 @@ "fullscreen.icon", "fullscreen_refresh.icon", "generic_stop.icon", + "glic_button.icon", "globe.icon", "guardian.icon", "guest_menu_art.icon",
diff --git a/chrome/app/vector_icons/glic_button.icon b/chrome/app/vector_icons/glic_button.icon new file mode 100644 index 0000000..8b1c934 --- /dev/null +++ b/chrome/app/vector_icons/glic_button.icon
@@ -0,0 +1,29 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 24, +MOVE_TO, 11, 15, +R_H_LINE_TO, 2, +R_V_LINE_TO, 2, +R_H_LINE_TO, -2, +R_V_LINE_TO, -2, +CLOSE, +R_MOVE_TO, 0, -8, +R_H_LINE_TO, 2, +R_V_LINE_TO, 6, +R_H_LINE_TO, -2, +V_LINE_TO, 7, +CLOSE, +R_MOVE_TO, 0.99f, -5, +CUBIC_TO, 6.47f, 2, 2, 6.48f, 2, 12, +R_CUBIC_TO, 0, 5.52f, 4.47f, 10, 9.99f, 10, +CUBIC_TO, 17.52f, 22, 22, 17.52f, 22, 12, +CUBIC_TO_SHORTHAND, 17.52f, 2, 11.99f, 2, +CLOSE, +MOVE_TO, 12, 20, +R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8, +R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8, +R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8, +R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8, +CLOSE \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index c5b88da..dfe3bc0 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -8660,7 +8660,6 @@ "//chrome/browser/sharing:buildflags", "//chrome/browser/ui/webui/app_service_internals:mojo_bindings", "//chrome/browser/ui/webui/data_sharing_internals:mojo_bindings", - "//chrome/browser/ui/webui/internals/user_education:mojo_bindings", "//chrome/browser/ui/webui/location_internals:mojo_bindings", "//chrome/browser/ui/webui/omnibox:mojo_bindings", "//chrome/browser/ui/webui/privacy_sandbox:mojo_bindings", @@ -8668,6 +8667,7 @@ "//chrome/browser/ui/webui/segmentation_internals:mojo_bindings", "//chrome/browser/ui/webui/suggest_internals:mojo_bindings", "//chrome/browser/ui/webui/usb_internals:mojo_bindings", + "//chrome/browser/ui/webui/user_education_internals:mojo_bindings", "//chrome/browser/v8_compile_hints/proto", "//chrome/browser/web_applications/mojom:mojom_web_apps_enum", ] @@ -8697,7 +8697,6 @@ "//chrome/browser/ui/webui/data_sharing:mojo_bindings", "//chrome/browser/ui/webui/discards:mojo_bindings", "//chrome/browser/ui/webui/downloads:mojo_bindings", - "//chrome/browser/ui/webui/internals/user_education:mojo_bindings", "//chrome/browser/ui/webui/new_tab_page:mojo_bindings", "//chrome/browser/ui/webui/new_tab_page_third_party:mojo_bindings", "//chrome/browser/ui/webui/on_device_internals:mojom", @@ -8709,6 +8708,7 @@ "//chrome/browser/ui/webui/side_panel/reading_list:mojo_bindings", "//chrome/browser/ui/webui/tab_search:mojo_bindings", "//chrome/browser/ui/webui/tab_strip:mojo_bindings", + "//chrome/browser/ui/webui/user_education_internals:mojo_bindings", "//chrome/browser/ui/webui/web_app_internals:mojo_bindings", "//chrome/browser/ui/webui/whats_new:mojo_bindings", "//chrome/browser/webauthn/proto",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 3771b0f..70f7926 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -6645,7 +6645,7 @@ flag_descriptions::kOptimizationGuideOnDeviceModelName, flag_descriptions::kOptimizationGuideOnDeviceModelDescription, kOsDesktop, FEATURE_WITH_PARAMS_VALUE_TYPE( - optimization_guide::features::kOptimizationGuideOnDeviceModel, + optimization_guide::features::kOnDeviceModelPerformanceParams, kOptimizationGuideOnDeviceModelVariations, "OptimizationGuideOnDeviceModel")}, @@ -7873,6 +7873,11 @@ flag_descriptions::kBlockTelephonyDevicePhoneMuteDescription, kOsCrOS, FEATURE_VALUE_TYPE(ui::kBlockTelephonyDevicePhoneMute)}, + {"enable-doze-mode-power-scheduler", + flag_descriptions::kEnableDozeModePowerSchedulerName, + flag_descriptions::kEnableDozeModePowerSchedulerDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kEnableDozeModePowerScheduler)}, + {"enable-fast-ink-for-software-cursor", flag_descriptions::kEnableFastInkForSoftwareCursorName, flag_descriptions::kEnableFastInkForSoftwareCursorDescription, kOsCrOS,
diff --git a/chrome/browser/android/customtabs/custom_tabs_connection.cc b/chrome/browser/android/customtabs/custom_tabs_connection.cc index 3ee7aab..8369352 100644 --- a/chrome/browser/android/customtabs/custom_tabs_connection.cc +++ b/chrome/browser/android/customtabs/custom_tabs_connection.cc
@@ -80,24 +80,18 @@ JNIEnv* env, Profile* native_profile, const base::android::JavaParamRef<jobject>& session, - const base::android::JavaParamRef<jstring>& package_name, - const base::android::JavaParamRef<jstring>& url, - const base::android::JavaParamRef<jstring>& origin, + std::string& package_name, + std::string& url, + std::string& origin, jint referrer_policy, jint motivation) { DCHECK(native_profile); - DCHECK(url); - DCHECK(origin); - GURL native_url(base::android::ConvertJavaStringToUTF8(env, url)); - GURL native_origin(base::android::ConvertJavaStringToUTF8(env, origin)); + GURL native_url(url); + GURL native_origin(origin); DCHECK(native_url.is_valid()); DCHECK(native_origin.is_valid()); - std::string native_package; - if (!package_name.is_null()) - base::android::ConvertJavaStringToUTF8(env, package_name, &native_package); - // Java only knows about the blink referrer policy. net::ReferrerPolicy url_request_referrer_policy = content::Referrer::ReferrerPolicyForUrlRequest( @@ -114,7 +108,7 @@ DetachedResourceRequest::CreateAndStart( native_profile, native_url, native_origin, url_request_referrer_policy, - request_motivation, native_package, std::move(cb)); + request_motivation, package_name, std::move(cb)); } static void JNI_CustomTabsConnection_SetClientDataHeader( @@ -131,7 +125,7 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& session, const base::android::JavaParamRef<jobject>& jweb_contents, - const base::android::JavaParamRef<jstring>& jstate_key, + std::string& state_key, const base::android::JavaParamRef<jobjectArray>& jtext_fragments) { auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); @@ -145,8 +139,7 @@ TextFragmentLookupStateTracker::CreateForWebContents(web_contents); TextFragmentLookupStateTracker::FromWebContents(web_contents) ->LookupTextFragment( - base::android::ConvertJavaStringToUTF8(jstate_key), - ConvertJavaStringArrayToListValue(env, jtext_fragments), + state_key, ConvertJavaStringArrayToListValue(env, jtext_fragments), std::move(cb)); } @@ -154,13 +147,12 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& session, const base::android::JavaParamRef<jobject>& jweb_contents, - const base::android::JavaParamRef<jstring>& jtext_fragment) { + std::string& text_fragment) { auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); TextFragmentLookupStateTracker::CreateForWebContents(web_contents); TextFragmentLookupStateTracker::FromWebContents(web_contents) - ->FindScrollAndHighlight( - base::android::ConvertJavaStringToUTF8(jtext_fragment)); + ->FindScrollAndHighlight(text_fragment); } } // namespace customtabs
diff --git a/chrome/browser/ash/accessibility/facegaze_browsertest.cc b/chrome/browser/ash/accessibility/facegaze_browsertest.cc index 31371d3..57355e6 100644 --- a/chrome/browser/ash/accessibility/facegaze_browsertest.cc +++ b/chrome/browser/ash/accessibility/facegaze_browsertest.cc
@@ -9,6 +9,7 @@ #include "ash/accessibility/ui/accessibility_confirmation_dialog.h" #include "ash/constants/ash_pref_names.h" #include "ash/shell.h" +#include "ash/system/accessibility/accessibility_feature_disable_dialog.h" #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" @@ -683,7 +684,7 @@ GetPrefs()->GetDict(prefs::kAccessibilityFaceGazeGesturesToConfidence); ASSERT_EQ(gestures_to_macros.size(), 2u); ASSERT_EQ(gestures_to_confidences.size(), 2u); - ASSERT_EQ(/* MOUTH_SMILE */ 35, + ASSERT_EQ(/* MOUSE_CLICK_LEFT */ 35, gestures_to_macros.FindInt( FaceGazeTestUtils::ToString(FaceGazeGesture::MOUTH_SMILE))); ASSERT_EQ(/* SCROLL */ 50, @@ -695,4 +696,341 @@ FaceGazeTestUtils::ToString(FaceGazeGesture::JAW_OPEN))); } +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, EnableNoDialog) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Setting sentinel value to true should enable the feature without showing + // the feature disable dialog. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel, true); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, DisableDialogAccept) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + + // Setting sentinel value to false should show the feature disable dialog and + // leave the behavior pref unchanged. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel, false); + dialog_waiter.Run(); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_FALSE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_NE(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeEnabled, + pref_waiter.QuitClosure()); + + // Accepting the dialog should turn off FaceGaze. + controller->GetFeatureDisableDialogForTest()->Accept(); + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_FALSE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_FALSE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, DisableDialogNoShow) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeEnabled, + pref_waiter.QuitClosure()); + + // Setting show dialog value to false should allow the feature to be set to + // false when the sentinel is set to false. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog, + false); + prefs->SetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel, false); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_FALSE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_FALSE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, DisableDialogCancel) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + + // Setting sentinel value to false should show the feature disable dialog and + // leave the behavior pref unchanged. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel, false); + dialog_waiter.Run(); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_NE(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeEnabledSentinel, + pref_waiter.QuitClosure()); + + // Cancelling the dialog should leave FaceGaze on and set the sentinel to + // true. + controller->GetFeatureDisableDialogForTest()->Cancel(); + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); +} + +// TODO(crbug.com/383757982): Add test API for .WithCursorControlEnabled() and +// .WithActionsEnabled() and update tests accordingly. +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, EnableCursorControlNoDialog) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + + // Setting sentinel value to true should not show the feature disable dialog. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + true); + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, + DisableCursorControlDialogAccept) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + prefs->SetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled, true); + ASSERT_TRUE(prefs->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel)); + + // Setting sentinel value to false should show the feature disable dialog and + // leave the behavior pref unchanged. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + false); + dialog_waiter.Run(); + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled)); + ASSERT_FALSE(prefs->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel)); + ASSERT_NE(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeCursorControlEnabled, + pref_waiter.QuitClosure()); + + // Accepting the dialog should turn off FaceGaze cursor control. + controller->GetFeatureDisableDialogForTest()->Accept(); + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_FALSE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled)); + ASSERT_FALSE(prefs->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel)); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, + DisableCursorControlDialogCancel) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + prefs->SetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled, true); + ASSERT_TRUE(prefs->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel)); + + // Setting sentinel value to false should show the feature disable dialog and + // leave the behavior pref unchanged. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + false); + dialog_waiter.Run(); + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled)); + ASSERT_NE(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + pref_waiter.QuitClosure()); + + // Cancelling the dialog should leave FaceGaze cursor control on and set the + // sentinel to true. + controller->GetFeatureDisableDialogForTest()->Cancel(); + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeCursorControlEnabled)); + ASSERT_TRUE(prefs->GetBoolean( + prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel)); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, EnableActionsNoDialog) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Enabling FaceGaze should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + + // Setting sentinel value to true should not show the feature disable dialog. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel, true); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, DisableActionsDialogAccept) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Setting sentinel value to true should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + prefs->SetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled, true); + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel)); + + // Setting sentinel value to false should show the feature disable dialog and + // leave the behavior pref unchanged. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel, false); + dialog_waiter.Run(); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled)); + ASSERT_FALSE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel)); + ASSERT_NE(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeActionsEnabled, + pref_waiter.QuitClosure()); + + // Accepting the dialog should turn off FaceGaze actions. + controller->GetFeatureDisableDialogForTest()->Accept(); + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_FALSE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled)); + ASSERT_FALSE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel)); +} + +IN_PROC_BROWSER_TEST_F(FaceGazeIntegrationTest, DisableActionsDialogCancel) { + auto* controller = ash::Shell::Get()->accessibility_controller(); + auto* prefs = GetPrefs(); + + base::RunLoop dialog_waiter; + controller->AddFeatureDisableDialogCallbackForTesting( + base::BindLambdaForTesting([&dialog_waiter]() { dialog_waiter.Quit(); })); + + // Setting sentinel value to true should not show the feature disable dialog. + utils()->EnableFaceGaze(Config().Default()); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabled)); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeEnabledSentinel)); + ASSERT_EQ(nullptr, controller->GetFeatureDisableDialogForTest()); + prefs->SetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled, true); + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel)); + + // Setting sentinel value to false should show the feature disable dialog and + // leave the behavior pref unchanged. + prefs->SetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel, false); + dialog_waiter.Run(); + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled)); + ASSERT_NE(nullptr, controller->GetFeatureDisableDialogForTest()); + + base::RunLoop pref_waiter; + PrefChangeRegistrar change_observer; + change_observer.Init(prefs); + change_observer.Add(prefs::kAccessibilityFaceGazeActionsEnabledSentinel, + pref_waiter.QuitClosure()); + + // Cancelling the dialog should leave FaceGaze actions on and set the sentinel + // to true. + controller->GetFeatureDisableDialogForTest()->Cancel(); + pref_waiter.Run(); + + // Assert behavior and sentinel prefs are in sync. + ASSERT_TRUE(prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabled)); + ASSERT_TRUE( + prefs->GetBoolean(prefs::kAccessibilityFaceGazeActionsEnabledSentinel)); +} + } // namespace ash
diff --git a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler.cc b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler.cc index ae5ee72..1a9ff10e 100644 --- a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler.cc +++ b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler.cc
@@ -147,9 +147,9 @@ UserConsentTypes::ArcPlayTermsOfServiceConsent play_consent; play_consent.set_status(UserConsentTypes::NOT_GIVEN); play_consent.set_confirmation_grd_id( - IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE); + IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON); play_consent.add_description_grd_ids( - IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE); + IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE); play_consent.set_consent_flow( UserConsentTypes::ArcPlayTermsOfServiceConsent::SETTING_CHANGE); ConsentAuditorFactory::GetForProfile(profile_)->RecordArcPlayConsent(
diff --git a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc index dd4882c..fd74307 100644 --- a/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc +++ b/chrome/browser/ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc
@@ -210,10 +210,9 @@ ArcPlayTermsOfServiceConsent play_consent; play_consent.set_status(UserConsentTypes::NOT_GIVEN); - play_consent.set_confirmation_grd_id( - IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE); + play_consent.set_confirmation_grd_id(IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON); play_consent.add_description_grd_ids( - IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE); + IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE); play_consent.set_consent_flow( UserConsentTypes::ArcPlayTermsOfServiceConsent::SETTING_CHANGE); EXPECT_CALL(*auditor, RecordArcPlayConsent(
diff --git a/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc b/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc index b33cda4..6efafbe 100644 --- a/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc +++ b/chrome/browser/ash/arc/tracing/arc_tracing_bridge.cc
@@ -111,7 +111,6 @@ perfetto_task_runner_(tracing::PerfettoTracedProcess::Get() ->GetTaskRunner() ->GetOrCreateTaskRunner()) { - tracing::PerfettoTracedProcess::Get()->AddDataSource(this); perfetto::DataSourceDescriptor dsd; dsd.set_name(tracing::mojom::kArcTraceDataSourceName); DataSourceProxy::Register(dsd, this);
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc index 2861c85f..e9fb80b0 100644 --- a/chrome/browser/ash/crosapi/browser_manager.cc +++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -38,8 +38,6 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "base/path_service.h" #include "base/posix/eintr_wrapper.h" @@ -106,15 +104,6 @@ namespace { -// The names of the UMA metrics to track Daily LaunchMode changes. -const char kLacrosLaunchModeDaily[] = "Ash.Lacros.Launch.Mode.Daily"; -const char kLacrosLaunchModeAndSourceDaily[] = - "Ash.Lacros.Launch.ModeAndSource.Daily"; - -// The interval at which the daily UMA reporting function should be -// called. De-duping of events will be happening on the server side. -constexpr base::TimeDelta kDailyLaunchModeTimeDelta = base::Minutes(30); - // Pointer to the global instance of BrowserManager. BrowserManager* g_instance = nullptr; @@ -173,9 +162,6 @@ // Ensure this isn't run multiple times. session_manager::SessionManager::Get()->RemoveObserver(this); - // Perform the UMA recording for the current Lacros launch mode. - RecordLacrosLaunchMode(); - crosapi::lacros_startup_state::SetLacrosStartupState(false); SetState(State::UNAVAILABLE); browser_loader_->Unload(); @@ -263,78 +249,4 @@ } } -void BrowserManager::SetLacrosLaunchMode() { - LacrosLaunchMode lacros_mode; - LacrosLaunchModeAndSource lacros_mode_and_source; - - if (!browser_util::IsAshWebBrowserEnabled()) { - // As Ash is disabled, Lacros is the only available browser. - lacros_mode = LacrosLaunchMode::kLacrosOnly; - lacros_mode_and_source = - LacrosLaunchModeAndSource::kPossiblySetByUserLacrosOnly; - } else { - lacros_mode = LacrosLaunchMode::kLacrosDisabled; - lacros_mode_and_source = - LacrosLaunchModeAndSource::kPossiblySetByUserLacrosDisabled; - } - - crosapi::browser_util::LacrosLaunchSwitchSource source = - crosapi::browser_util::GetLacrosLaunchSwitchSource(); - - // Make sure we have always the policy loaded before we get here. - DCHECK(source != crosapi::browser_util::LacrosLaunchSwitchSource::kUnknown); - - LacrosLaunchModeAndSource source_offset; - if (source == - crosapi::browser_util::LacrosLaunchSwitchSource::kPossiblySetByUser) { - source_offset = LacrosLaunchModeAndSource::kPossiblySetByUserLacrosDisabled; - } else if (source == - crosapi::browser_util::LacrosLaunchSwitchSource::kForcedByUser) { - source_offset = LacrosLaunchModeAndSource::kForcedByUserLacrosDisabled; - } else { - source_offset = LacrosLaunchModeAndSource::kForcedByPolicyLacrosDisabled; - } - - // The states are comprised of the basic four Lacros options and the - // source of the mode selection (By user, by Policy, by System). These - // combinations are "nibbled together" here in one status value. - lacros_mode_and_source = static_cast<LacrosLaunchModeAndSource>( - static_cast<int>(source_offset) + - static_cast<int>(lacros_mode_and_source)); - - LOG(WARNING) << "Using LacrosLaunchModeAndSource " - << static_cast<int>(lacros_mode_and_source); - - if (!lacros_mode_.has_value() || !lacros_mode_and_source_.has_value() || - lacros_mode != *lacros_mode_ || - lacros_mode_and_source != *lacros_mode_and_source_) { - // Remember new values. - lacros_mode_ = lacros_mode; - lacros_mode_and_source_ = lacros_mode_and_source; - } -} - -void BrowserManager::RecordLacrosLaunchMode() { - SetLacrosLaunchMode(); - - base::UmaHistogramEnumeration("Ash.Lacros.Launch.Mode", *lacros_mode_); - base::UmaHistogramEnumeration("Ash.Lacros.Launch.ModeAndSource", - *lacros_mode_and_source_); - - // Call our Daily reporting once now to make sure we have an event. If it's a - // dupe, the server will de-dupe. - OnDailyLaunchModeTimer(); - if (!daily_event_timer_.IsRunning()) { - daily_event_timer_.Start(FROM_HERE, kDailyLaunchModeTimeDelta, this, - &BrowserManager::OnDailyLaunchModeTimer); - } -} - -// Callback called when the daily event happens. -void BrowserManager::OnDailyLaunchModeTimer() { - base::UmaHistogramEnumeration(kLacrosLaunchModeDaily, *lacros_mode_); - base::UmaHistogramEnumeration(kLacrosLaunchModeAndSourceDaily, - *lacros_mode_and_source_); -} - } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/browser_manager.h b/chrome/browser/ash/crosapi/browser_manager.h index 40bd0ee..4f67a87 100644 --- a/chrome/browser/ash/crosapi/browser_manager.h +++ b/chrome/browser/ash/crosapi/browser_manager.h
@@ -18,7 +18,6 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/scoped_observation.h" -#include "base/time/time.h" #include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/ash/crosapi/crosapi_id.h" #include "chrome/browser/ui/browser_navigator_params.h" @@ -74,39 +73,6 @@ void Shutdown(); protected: - // The actual Lacros launch mode. - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - enum class LacrosLaunchMode { - // Indicates that Lacros is disabled. - kLacrosDisabled = 0, - // Lacros is the only browser and Ash is disabled. - kLacrosOnly = 3, - - kMaxValue = kLacrosOnly - }; - - // The actual Lacros launch mode. - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - enum class LacrosLaunchModeAndSource { - // Either set by user or system/flags, indicates that Lacros is disabled. - kPossiblySetByUserLacrosDisabled = 0, - // Either set by user or system/flags, Lacros is the only browser and Ash is - // disabled. - kPossiblySetByUserLacrosOnly = 3, - // Enforced by the user, indicates that Lacros is disabled. - kForcedByUserLacrosDisabled = 4 + kPossiblySetByUserLacrosDisabled, - // Enforced by the user, Lacros is the only browser and Ash is disabled. - kForcedByUserLacrosOnly = 4 + kPossiblySetByUserLacrosOnly, - // Enforced by policy, indicates that Lacros is disabled. - kForcedByPolicyLacrosDisabled = 8 + kPossiblySetByUserLacrosDisabled, - // Enforced by policy, Lacros is the only browser and Ash is disabled. - kForcedByPolicyLacrosOnly = 8 + kPossiblySetByUserLacrosOnly, - - kMaxValue = kForcedByPolicyLacrosOnly - }; - // NOTE: You may have to update tests if you make changes to State, as state_ // is exposed via autotest_private. enum class State { @@ -132,19 +98,9 @@ NewWindowReloadsWhenUpdateAvailable); FRIEND_TEST_ALL_PREFIXES(BrowserManagerTest, OnLacrosUserDataDirRemoved); - // Remembers lacros launch mode by calling `SetLacrosLaunchMode()`, then kicks - // off the daily reporting for the metrics. - void RecordLacrosLaunchMode(); - // Sets `lacros_mode_` and `lacros_mode_and_source_`. - void SetLacrosLaunchMode(); - // session_manager::SessionManagerObserver: void OnSessionStateChanged() override; - // Sending the LaunchMode state at least once a day. - // multiple events will get de-duped on the server side. - void OnDailyLaunchModeTimer(); - // Start a sequence to clear Lacros related data. It posts a task to remove // Lacros user data directory and if that is successful, calls // `OnLacrosUserDataDirRemoved()` to clear some prefs set by Lacros in Ash. @@ -164,15 +120,6 @@ // new or existing lacros startup tasks are not executed during shutdown. bool shutdown_requested_ = false; - // The timer used to periodically check if the daily event should be - // triggered. - base::RepeatingTimer daily_event_timer_; - - // The launch mode and the launch mode with source which were used after - // deciding if Lacros should be used or not. - std::optional<LacrosLaunchMode> lacros_mode_; - std::optional<LacrosLaunchModeAndSource> lacros_mode_and_source_; - base::WeakPtrFactory<BrowserManager> weak_factory_{this}; };
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index b19d75a..9e4827c8 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -9,96 +9,33 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" -#include "base/auto_reset.h" -#include "base/check_is_test.h" -#include "base/command_line.h" -#include "base/containers/contains.h" -#include "base/containers/fixed_flat_map.h" -#include "base/containers/flat_map.h" -#include "base/debug/dump_without_crashing.h" #include "base/files/file_util.h" #include "base/json/json_reader.h" #include "base/json/values_util.h" -#include "base/metrics/histogram_macros.h" #include "base/path_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/system/sys_info.h" #include "base/values.h" #include "base/version.h" -#include "chrome/browser/browser_process.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" -#include "chromeos/ash/components/channel/channel_info.h" #include "chromeos/ash/components/standalone_browser/lacros_availability.h" -#include "chromeos/ash/components/standalone_browser/standalone_browser_features.h" #include "chromeos/crosapi/cpp/crosapi_constants.h" -#include "chromeos/crosapi/mojom/crosapi.mojom.h" -#include "components/component_updater/component_updater_service.h" #include "components/exo/shell_surface_util.h" -#include "components/policy/core/common/policy_map.h" -#include "components/policy/policy_constants.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" -#include "components/prefs/scoped_user_pref_update.h" -#include "components/user_manager/known_user.h" -#include "components/user_manager/user.h" -#include "components/user_manager/user_manager.h" #include "components/version_info/channel.h" #include "components/version_info/version_info.h" -#include "google_apis/gaia/gaia_auth_util.h" -using ash::standalone_browser::IsGoogleInternal; using ash::standalone_browser::LacrosAvailability; using user_manager::User; -using user_manager::UserManager; -using version_info::Channel; namespace crosapi::browser_util { namespace { -// At session start the value for LacrosAvailability logic is applied and the -// result is stored in this variable which is used after that as a cache. -std::optional<LacrosAvailability> g_lacros_availability_cache; - // The rootfs lacros-chrome metadata keys. constexpr char kLacrosMetadataContentKey[] = "content"; constexpr char kLacrosMetadataVersionKey[] = "version"; -// Returns primary user's User instance. -const user_manager::User* GetPrimaryUser() { - // TODO(crbug.com/40753373): TaskManagerImplTest is not ready to run with - // Lacros enabled. - // UserManager is not initialized for unit tests by default, unless a fake - // user manager is constructed. - if (!UserManager::IsInitialized()) { - return nullptr; - } - - // GetPrimaryUser works only after user session is started. - // May return nullptr, if this is called beforehand. - return UserManager::Get()->GetPrimaryUser(); -} - -// Returns the lacros integration suggested by the policy lacros-availability. -// There are several reasons why we might choose to ignore the -// lacros-availability policy. -// 1. The user has set a command line or chrome://flag for -// kLacrosAvailabilityIgnore. -// 2. The user is a Googler and they are not opted into the -// kLacrosGooglePolicyRollout trial and they did not have the -// kLacrosDisallowed policy. -LacrosAvailability GetCachedLacrosAvailability() { - // TODO(crbug.com/40210811): add DCHECK for production use to avoid the - // same inconsistency for the future. - if (g_lacros_availability_cache.has_value()) - return g_lacros_availability_cache.value(); - // It could happen in some browser tests that value is not cached. Return - // default in that case. - return LacrosAvailability::kUserChoice; -} - } // namespace base::FilePath GetUserDataDir() { @@ -166,39 +103,4 @@ return base::Version{*version}; } -void CacheLacrosAvailability(const policy::PolicyMap& map) { - if (g_lacros_availability_cache.has_value()) { - // Some browser tests might call this multiple times. - LOG(ERROR) << "Trying to cache LacrosAvailability and the value was set"; - return; - } - - const base::Value* value = - map.GetValue(policy::key::kLacrosAvailability, base::Value::Type::STRING); - g_lacros_availability_cache = - ash::standalone_browser::DetermineLacrosAvailabilityFromPolicyValue( - GetPrimaryUser(), value ? value->GetString() : std::string_view()); -} - -void ClearLacrosAvailabilityCacheForTest() { - g_lacros_availability_cache.reset(); -} - -LacrosLaunchSwitchSource GetLacrosLaunchSwitchSource() { - if (!g_lacros_availability_cache.has_value()) - return LacrosLaunchSwitchSource::kUnknown; - - // Note: this check needs to be consistent with the one in - // DetermineLacrosAvailabilityFromPolicyValue. - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(ash::switches::kLacrosAvailabilityIgnore) && - IsGoogleInternal(UserManager::Get()->GetPrimaryUser())) { - return LacrosLaunchSwitchSource::kForcedByUser; - } - - return GetCachedLacrosAvailability() == LacrosAvailability::kUserChoice - ? LacrosLaunchSwitchSource::kPossiblySetByUser - : LacrosLaunchSwitchSource::kForcedByPolicy; -} - } // namespace crosapi::browser_util
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h index 1fb5d04..32ad8d5b 100644 --- a/chrome/browser/ash/crosapi/browser_util.h +++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -25,29 +25,9 @@ enum class Channel; } // namespace version_info -namespace policy { -class PolicyMap; -} // namespace policy - // These methods are used by ash-chrome. namespace crosapi::browser_util { -// Indicates how the decision for the usage of Lacros has been made. -enum class LacrosLaunchSwitchSource { - // It is unknown yet if and how Lacros will be used. - kUnknown = 0, - // Either there were no policies, or the system had a special condition in - // which the policy got ignored and the user could have set the mode. - kPossiblySetByUser = 1, - // The Lacros usage was enforced by the user via #lacros-availability-ignore - // flag override. - kForcedByUser = 2, - // The Lacros usage was enforced using the policy. Note that in this case - // the policy might still not be used, but it is programmatically overridden - // and not by the user (e.g. special Googler user case). - kForcedByPolicy = 3 -}; - // Returns the user directory for lacros-chrome. base::FilePath GetUserDataDir(); @@ -68,10 +48,6 @@ base::Version GetRootfsLacrosVersionMayBlock( const base::FilePath& version_file_path); -// To be called at primary user login, to cache the policy value for lacros -// availability. -void CacheLacrosAvailability(const policy::PolicyMap& map); - // Returns the update channel associated with the given loaded lacros selection. version_info::Channel GetLacrosSelectionUpdateChannel( ash::standalone_browser::LacrosSelection selection); @@ -82,13 +58,6 @@ base::Version GetInstalledLacrosComponentVersion( const component_updater::ComponentUpdateService* component_update_service); -// Clears the cached values for lacros availability policy. -void ClearLacrosAvailabilityCacheForTest(); - -// Returns who decided how Lacros should be used - or not: The User, the policy -// or another edge case. -LacrosLaunchSwitchSource GetLacrosLaunchSwitchSource(); - } // namespace crosapi::browser_util #endif // CHROME_BROWSER_ASH_CROSAPI_BROWSER_UTIL_H_
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc index 84fc73d9..b74ec9b 100644 --- a/chrome/browser/ash/crosapi/browser_util_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -12,7 +12,6 @@ #include "base/containers/fixed_flat_map.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/json/json_reader.h" #include "base/memory/raw_ptr.h" #include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" @@ -21,10 +20,6 @@ #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" -#include "chromeos/ash/components/standalone_browser/lacros_availability.h" -#include "chromeos/ash/components/standalone_browser/lacros_selection.h" -#include "chromeos/ash/components/standalone_browser/standalone_browser_features.h" -#include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "components/account_id/account_id.h" #include "components/policy/policy_constants.h" #include "components/user_manager/known_user.h" @@ -33,42 +28,10 @@ #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" -using ash::standalone_browser::LacrosAvailability; -using crosapi::browser_util::LacrosLaunchSwitchSource; using user_manager::User; namespace crosapi { -namespace { -// This implementation of RAII for LacrosAvailability is to make it easy reset -// the state between runs. -class ScopedLacrosAvailabilityCache { - public: - explicit ScopedLacrosAvailabilityCache( - LacrosAvailability lacros_launch_switch) { - SetLacrosAvailability(lacros_launch_switch); - } - ScopedLacrosAvailabilityCache(const ScopedLacrosAvailabilityCache&) = delete; - ScopedLacrosAvailabilityCache& operator=( - const ScopedLacrosAvailabilityCache&) = delete; - ~ScopedLacrosAvailabilityCache() { - browser_util::ClearLacrosAvailabilityCacheForTest(); - } - - private: - void SetLacrosAvailability(LacrosAvailability lacros_availability) { - policy::PolicyMap policy; - policy.Set( - policy::key::kLacrosAvailability, policy::POLICY_LEVEL_MANDATORY, - policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, - base::Value(GetLacrosAvailabilityPolicyName(lacros_availability)), - /*external_data_fetcher=*/nullptr); - browser_util::CacheLacrosAvailability(policy); - } -}; - -} // namespace - class BrowserUtilTest : public testing::Test { public: BrowserUtilTest() = default; @@ -119,7 +82,6 @@ TEST_F(BrowserUtilTest, IsAshWebBrowserDisabled) { AddRegularUser("user@managedchrome.com"); - ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly); EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled()); } @@ -175,65 +137,6 @@ EXPECT_FALSE(browser_util::GetRootfsLacrosVersionMayBlock(path).IsValid()); } -TEST_F(BrowserUtilTest, GetLacrosLaunchSwitchSourceNonGoogle) { - AddRegularUser("user@random.com"); - - // If LaunchSwitch is not set, the source is unknown. - EXPECT_EQ(LacrosLaunchSwitchSource::kUnknown, - browser_util::GetLacrosLaunchSwitchSource()); - - // If the policy says UserChoice, lacros state may be set by user. - { - ScopedLacrosAvailabilityCache cache(LacrosAvailability::kUserChoice); - EXPECT_EQ(LacrosLaunchSwitchSource::kPossiblySetByUser, - browser_util::GetLacrosLaunchSwitchSource()); - } - - // The policy cannot be ignored by command line flag. - { - ScopedLacrosAvailabilityCache cache(LacrosAvailability::kUserChoice); - base::test::ScopedCommandLine cmd_line; - cmd_line.GetProcessCommandLine()->AppendSwitch( - ash::switches::kLacrosAvailabilityIgnore); - EXPECT_EQ(LacrosLaunchSwitchSource::kPossiblySetByUser, - browser_util::GetLacrosLaunchSwitchSource()); - } - - // Otherwise, the LaunchSwitch is set by the policy. - for (const auto launch_switch : {LacrosAvailability::kLacrosDisallowed, - LacrosAvailability::kLacrosOnly}) { - ScopedLacrosAvailabilityCache cache(launch_switch); - EXPECT_EQ(LacrosLaunchSwitchSource::kForcedByPolicy, - browser_util::GetLacrosLaunchSwitchSource()) - << static_cast<int>(launch_switch); - } -} - -TEST_F(BrowserUtilTest, GetLacrosLaunchSwitchSourceGoogle) { - AddRegularUser("user@google.com"); - - // If LaunchSwitch is not set, the source is unknown. - EXPECT_EQ(LacrosLaunchSwitchSource::kUnknown, - browser_util::GetLacrosLaunchSwitchSource()); - - // If the policy says UserChoice, lacros state may be set by user. - { - ScopedLacrosAvailabilityCache cache(LacrosAvailability::kUserChoice); - EXPECT_EQ(LacrosLaunchSwitchSource::kPossiblySetByUser, - browser_util::GetLacrosLaunchSwitchSource()); - } - - // The policy can be ignored by command line flag. - { - ScopedLacrosAvailabilityCache cache(LacrosAvailability::kUserChoice); - base::test::ScopedCommandLine cmd_line; - cmd_line.GetProcessCommandLine()->AppendSwitch( - ash::switches::kLacrosAvailabilityIgnore); - EXPECT_EQ(LacrosLaunchSwitchSource::kForcedByUser, - browser_util::GetLacrosLaunchSwitchSource()); - } -} - // Lacros availability has an effect on googlers TEST_F(BrowserUtilTest, LacrosAvailabilityIgnoreGoogleEnableToUserChoice) { AddRegularUser("user@google.com"); @@ -241,7 +144,6 @@ base::test::ScopedCommandLine cmd_line; cmd_line.GetProcessCommandLine()->AppendSwitch( ash::switches::kLacrosAvailabilityIgnore); - ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly); EXPECT_FALSE(browser_util::IsLacrosEnabled()); }
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index 733ef837..e4ab0c4b 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -3820,6 +3820,7 @@ ASSERT_TRUE(timezone); auto* user = user_manager::UserManager::Get()->GetActiveUser(); ash::system::SetSystemTimezone(user, *timezone); + base::RunLoop().RunUntilIdle(); return; }
diff --git a/chrome/browser/ash/file_manager/trash_auto_cleanup.cc b/chrome/browser/ash/file_manager/trash_auto_cleanup.cc index 5e66662..d2c86e4 100644 --- a/chrome/browser/ash/file_manager/trash_auto_cleanup.cc +++ b/chrome/browser/ash/file_manager/trash_auto_cleanup.cc
@@ -7,6 +7,7 @@ #include "base/barrier_callback.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" +#include "base/metrics/histogram_functions_internal_overloads.h" #include "base/system/sys_info.h" #include "base/task/thread_pool.h" #include "base/time/time.h" @@ -16,8 +17,15 @@ namespace { +constexpr char kCleanupFileCountMetricName[] = + "FileBrowser.TrashAutoCleanup.FileCount"; +constexpr char kCleanupErrorsMetricName[] = + "FileBrowser.TrashAutoCleanup.Errors"; +constexpr char kCleanupTimeMetricName[] = "FileBrowser.TrashAutoCleanup.Time"; + // Enumerates Trash info files (supported .Trash/info/ locations) and returns // the list of trashinfo files corresponding to the trash entries to delete. +// A maximum of `kMaxBatchSize` trashinfo files is returned. std::vector<base::FilePath> GetTrashInfoFilesToDeleteOnBlockingThread( const std::vector<base::FilePath>& trash_info_directories) { std::vector<base::FilePath> trash_info_paths_to_delete; @@ -34,17 +42,28 @@ base::File::FLAG_OPEN | base::File::FLAG_READ); if (!file.IsValid()) { ++invalid_file_counter; + base::UmaHistogramEnumeration(kCleanupErrorsMetricName, + AutoCleanupError::kInvalidTrashInfoFile); continue; } base::File::Info info; if (!file.GetInfo(&info)) { ++file_get_info_failed_counter; + base::UmaHistogramEnumeration( + kCleanupErrorsMetricName, + AutoCleanupError::kFailedToGetTrashInfoFileModifiedTime); continue; } if (now - info.last_modified >= kMaxTrashAge) { trash_info_paths_to_delete.push_back(trash_info_path); + if (trash_info_paths_to_delete.size() >= kMaxBatchSize) { + break; + } } } + if (trash_info_paths_to_delete.size() >= kMaxBatchSize) { + break; + } } if (invalid_file_counter) { LOG(ERROR) << invalid_file_counter << " invalid trashinfo files"; @@ -53,6 +72,8 @@ LOG(ERROR) << "Could not get info from " << file_get_info_failed_counter << " trashinfo files"; } + base::UmaHistogramCounts1000(kCleanupFileCountMetricName, + trash_info_paths_to_delete.size()); return trash_info_paths_to_delete; } @@ -62,7 +83,12 @@ for (const ParsedTrashInfoData& trash_info_data : to_delete) { if (!base::DeleteFile(trash_info_data.trashed_file_path) || !base::DeleteFile(trash_info_data.trash_info_path)) { + base::UmaHistogramEnumeration(kCleanupErrorsMetricName, + AutoCleanupError::kFailedToDeleteTrashFile); success = false; + } else { + base::UmaHistogramEnumeration(kCleanupErrorsMetricName, + AutoCleanupError::kSuccessfullyDeleted); } } return success; @@ -95,7 +121,10 @@ } void TrashAutoCleanup::Init() { - // TODO: Start the cleanup process. + cleanup_repeating_timer_.Start( + FROM_HERE, kCleanupCheckInterval, + base::BindRepeating(&TrashAutoCleanup::StartCleanup, + weak_ptr_factory_.GetWeakPtr())); } void TrashAutoCleanup::StartCleanup() { @@ -103,6 +132,19 @@ if (!file_manager::trash::IsTrashEnabledForProfile(profile_)) { return; } + + if (!last_cleanup_time_.is_null() && + base::Time::Now() - last_cleanup_time_ < kCleanupInterval) { + // Skip cleanup iteration if it last happened less than a day earlier. + if (cleanup_done_closure_for_test_) { + std::move(cleanup_done_closure_for_test_) + .Run(AutoCleanupResult::kWaitingForNextCleanupIteration); + } + return; + } + last_cleanup_time_ = base::Time::Now(); + cleanup_start_time_ = base::TimeTicks::Now(); + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, @@ -122,6 +164,12 @@ } return; } + if (trash_info_paths_to_delete.size() == kMaxBatchSize) { + // The maximum batch size has been reached: there is more likely going to be + // more files to cleanup. Unset the last cleanup time to force the next + // iteration. + last_cleanup_time_ = base::Time(); + } validator_ = std::make_unique<file_manager::trash::TrashInfoValidator>(profile_); auto barrier_callback = @@ -142,10 +190,9 @@ for (auto& trash_info_data_or_error : parsed_data_or_error) { if (!trash_info_data_or_error.has_value()) { ++parse_error_counter; - if (cleanup_done_closure_for_test_) { - std::move(cleanup_done_closure_for_test_) - .Run(AutoCleanupResult::kTrashInfoParsingError); - } + base::UmaHistogramEnumeration( + kCleanupErrorsMetricName, + AutoCleanupError::kFailedToParseTrashInfoFile); continue; } to_delete.push_back(std::move(trash_info_data_or_error.value())); @@ -153,6 +200,10 @@ if (parse_error_counter) { LOG(ERROR) << "Failed to parse " << parse_error_counter << " trash info files"; + if (cleanup_done_closure_for_test_) { + std::move(cleanup_done_closure_for_test_) + .Run(AutoCleanupResult::kTrashInfoParsingError); + } } if (to_delete.empty()) { return; @@ -174,6 +225,8 @@ : AutoCleanupResult::kDeletionError; std::move(cleanup_done_closure_for_test_).Run(result); } + base::UmaHistogramTimes(kCleanupTimeMetricName, + base::TimeTicks::Now() - cleanup_start_time_); } void TrashAutoCleanup::SetCleanupDoneCallbackForTest(
diff --git a/chrome/browser/ash/file_manager/trash_auto_cleanup.h b/chrome/browser/ash/file_manager/trash_auto_cleanup.h index 21be7a28..10b0178 100644 --- a/chrome/browser/ash/file_manager/trash_auto_cleanup.h +++ b/chrome/browser/ash/file_manager/trash_auto_cleanup.h
@@ -5,19 +5,37 @@ #ifndef CHROME_BROWSER_ASH_FILE_MANAGER_TRASH_AUTO_CLEANUP_H_ #define CHROME_BROWSER_ASH_FILE_MANAGER_TRASH_AUTO_CLEANUP_H_ +#include "base/timer/timer.h" #include "chrome/browser/ash/file_manager/trash_common_util.h" #include "chrome/browser/ash/file_manager/trash_info_validator.h" #include "chrome/browser/profiles/profile.h" namespace file_manager::trash { +inline constexpr base::TimeDelta kCleanupInterval = base::Days(1); +inline constexpr base::TimeDelta kCleanupCheckInterval = base::Hours(1); inline constexpr base::TimeDelta kMaxTrashAge = base::Days(30); +inline constexpr int kMaxBatchSize = 500; +// List of UMA enum values for the errors encountered during the auto cleanup +// process. The enum values must be kept in sync with TrashAutoCleanupError in +// tools/metrics/histograms/metadata/file/enums.xml. +enum class AutoCleanupError { + kSuccessfullyDeleted = 0, + kInvalidTrashInfoFile = 1, + kFailedToGetTrashInfoFileModifiedTime = 2, + kFailedToParseTrashInfoFile = 3, + kFailedToDeleteTrashFile = 4, + kMaxValue = kFailedToDeleteTrashFile, +}; + +// Used for tests to provide the outcome of a cleanup iteration. enum class AutoCleanupResult { - kCleanupSuccessful = 0, + kWaitingForNextCleanupIteration = 0, kNoOldFilesToCleanup, kTrashInfoParsingError, kDeletionError, + kCleanupSuccessful, }; // Handles the 30-day Trash files autocleanup. @@ -50,6 +68,9 @@ raw_ptr<Profile> profile_; std::unique_ptr<file_manager::trash::TrashInfoValidator> validator_ = nullptr; std::vector<base::FilePath> trash_info_directories_; + base::RepeatingTimer cleanup_repeating_timer_; + base::Time last_cleanup_time_; + base::TimeTicks cleanup_start_time_; base::OnceCallback<void(AutoCleanupResult result)> cleanup_done_closure_for_test_;
diff --git a/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc b/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc index 7d04b43..65a899c 100644 --- a/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc +++ b/chrome/browser/ash/file_manager/trash_auto_cleanup_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ash/file_manager/trash_auto_cleanup.h" +#include <vector> + #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/i18n/time_formatting.h" @@ -39,8 +41,7 @@ void TearDown() override { trash_auto_cleanup_.reset(); - storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems(); - profile_.reset(); + file_manager::io_task::TrashBaseTest::TearDown(); } void SetupFileTrashedFromDownloads(const std::string& file_name) { @@ -99,6 +100,8 @@ void StartCleanup() { trash_auto_cleanup_->StartCleanup(); } + void InitAutoCleanup() { trash_auto_cleanup_->Init(); } + std::string GenerateTrashInfoContents(const base::Time& deletion_time) { return base::StrCat( {"[Trash Info]\nPath=", "/Downloads/bar/", "original_file.txt", @@ -172,4 +175,113 @@ CheckFileExistsInTrash(second_file_name, /*should_exist=*/false); } +TEST_F(TrashAutoCleanupTest, PeriodicCleanup) { + // Setup files in trash directory. + const std::string first_file_name = "first_file.txt"; + const std::string second_file_name = "second_file.txt"; + + // Setup trashed files. The first file is trashed at T = 0, the second file is + // trashed a bit later at T = 10 minutes. + SetupFileTrashedFromDownloads(first_file_name); + task_environment_.FastForwardBy(base::Minutes(10)); + SetupFileTrashedFromDownloads(second_file_name); + + // Init the autocleanup process at T = 30 days (minus kCleanupCheckInterval, + // the delay before the initial cleanup iteration). Only the first file should + // be removed. + task_environment_.FastForwardBy(base::Minutes(50) + base::Hours(23) + + base::Days(29) - kCleanupCheckInterval); + // Init periodic cleanup. + base::test::TestFuture<AutoCleanupResult> future; + SetCleanupDoneCallbackForTest(future.GetCallback<AutoCleanupResult>()); + InitAutoCleanup(); + ASSERT_TRUE(future.Wait()); + // Check that the first file has been removed. + ASSERT_EQ(future.Take(), AutoCleanupResult::kCleanupSuccessful); + CheckFileExistsInTrash(first_file_name, /*should_exist=*/false); + CheckFileExistsInTrash(second_file_name, /*should_exist=*/true); + + // The second file should persist while we are within `kCleanupInterval` of + // the last cleanup iteration. + // Note: the mocked time stays constant until `future.Wait()` is called, so + // `last_cleanup_iteration` is accurate. + const base::Time last_cleanup_iteration = base::Time::Now(); + task_environment_.FastForwardBy(kCleanupInterval - kCleanupCheckInterval); + CheckFileExistsInTrash(second_file_name, /*should_exist=*/true); + // The next cleanup check should happen `kCleanupInterval` after the last + // iteration. Check that the second file has now been removed. + SetCleanupDoneCallbackForTest(future.GetCallback<AutoCleanupResult>()); + ASSERT_TRUE(future.Wait()); + ASSERT_EQ(base::Time::Now() - last_cleanup_iteration, kCleanupInterval); + ASSERT_EQ(future.Take(), AutoCleanupResult::kCleanupSuccessful); + CheckFileExistsInTrash(second_file_name, /*should_exist=*/false); +} + +TEST_F(TrashAutoCleanupTest, MultipleBatchesCleanup) { + // Setup a number of files in trash directory that equals more than twice the + // batch size. + std::vector<std::string> file_names; + const int n_files = 2.5 * kMaxBatchSize; + for (int i = 0; i < n_files; ++i) { + const std::string file_name = "file" + base::NumberToString(i); + file_names.emplace_back(file_name); + SetupFileTrashedFromDownloads(file_name); + } + + task_environment_.FastForwardBy(base::Days(30)); + base::test::TestFuture<AutoCleanupResult> future; + SetCleanupDoneCallbackForTest(future.GetCallback<AutoCleanupResult>()); + InitAutoCleanup(); + ASSERT_TRUE(future.Wait()); + base::Time last_cleanup_iteration = base::Time::Now(); + // Check that the first batch of files has been removed. + ASSERT_EQ(future.Take(), AutoCleanupResult::kCleanupSuccessful); + // Check that `kMaxBatchSize` files have been removed. + int n_remaining_files = 0; + for (int i = 0; i < n_files; ++i) { + const std::string file_name = "file" + base::NumberToString(i); + if (!base::PathExists(GetTrashedFilePath(file_name))) { + ASSERT_FALSE(base::PathExists(GetInfoFilePath(file_name))); + } else { + ASSERT_TRUE(base::PathExists(GetInfoFilePath(file_name))); + ++n_remaining_files; + } + } + ASSERT_EQ(n_remaining_files, n_files - kMaxBatchSize); + + // After this iteration, the next batch of files should be processed. + SetCleanupDoneCallbackForTest(future.GetCallback<AutoCleanupResult>()); + ASSERT_TRUE(future.Wait()); + // This iteration should happen `kCleanupCheckInterval` after the preview one, + // instead of the next day, since not all the batches have been processed + // yet. + ASSERT_EQ(base::Time::Now() - last_cleanup_iteration, kCleanupCheckInterval); + last_cleanup_iteration = base::Time::Now(); + // Check that the second batch of files has been removed. + ASSERT_EQ(future.Take(), AutoCleanupResult::kCleanupSuccessful); + // Check that `2 * kMaxBatchSize` files have been removed. + n_remaining_files = 0; + for (int i = 0; i < n_files; ++i) { + const std::string file_name = "file" + base::NumberToString(i); + if (!base::PathExists(GetTrashedFilePath(file_name))) { + ASSERT_FALSE(base::PathExists(GetInfoFilePath(file_name))); + } else { + ASSERT_TRUE(base::PathExists(GetInfoFilePath(file_name))); + ++n_remaining_files; + } + } + ASSERT_EQ(n_remaining_files, n_files - 2 * kMaxBatchSize); + + // After the last iteration, no file should be remaining. + SetCleanupDoneCallbackForTest(future.GetCallback<AutoCleanupResult>()); + ASSERT_TRUE(future.Wait()); + ASSERT_EQ(base::Time::Now() - last_cleanup_iteration, kCleanupCheckInterval); + // Check that all files have been removed. + ASSERT_EQ(future.Take(), AutoCleanupResult::kCleanupSuccessful); + for (int i = 0; i < n_files; ++i) { + const std::string file_name = "file" + base::NumberToString(i); + CheckFileExistsInTrash(file_name, /*should_exist=*/false); + } +} + } // namespace file_manager::trash
diff --git a/chrome/browser/ash/performance/BUILD.gn b/chrome/browser/ash/performance/BUILD.gn index 67a0fd4..cbb5de36 100644 --- a/chrome/browser/ash/performance/BUILD.gn +++ b/chrome/browser/ash/performance/BUILD.gn
@@ -18,9 +18,12 @@ deps = [ "//ash", "//ash/components/arc", + "//ash/constants", "//ash/public/cpp", "//base", "//chrome/browser/ash/arc/session", + "//chrome/browser/ash/profiles", + "//chromeos/ash/components/dbus/concierge:concierge", "//chromeos/dbus/power", "//chromeos/dbus/power:power_manager_proto", "//components/arc",
diff --git a/chrome/browser/ash/performance/DEPS b/chrome/browser/ash/performance/DEPS index a3664eec..45497456 100644 --- a/chrome/browser/ash/performance/DEPS +++ b/chrome/browser/ash/performance/DEPS
@@ -15,4 +15,5 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/arc/session", -] + "+chrome/browser/ash/profiles", +] \ No newline at end of file
diff --git a/chrome/browser/ash/performance/doze_mode_power_status_scheduler.cc b/chrome/browser/ash/performance/doze_mode_power_status_scheduler.cc index 992f7b1..bdac7d9 100644 --- a/chrome/browser/ash/performance/doze_mode_power_status_scheduler.cc +++ b/chrome/browser/ash/performance/doze_mode_power_status_scheduler.cc
@@ -6,6 +6,7 @@ #include <string_view> +#include "ash/constants/ash_features.h" #include "ash/shell.h" #include "base/functional/bind.h" #include "base/location.h" @@ -14,6 +15,8 @@ #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "chrome/browser/ash/performance/pref_names.h" +#include "chrome/browser/ash/profiles/profile_helper.h" +#include "chromeos/ash/components/dbus/concierge/concierge_client.h" namespace ash { @@ -41,6 +44,8 @@ constexpr base::TimeDelta kCompensatedRealPowerStatusDuration = base::Minutes(10); +constexpr int kFakeBatteryCapacityLimit = 20; + base::TimeDelta GetAndResetPref(PrefService* pref_service, std::string_view pref_name) { const base::TimeDelta unreported_duration = @@ -57,6 +62,18 @@ pref_service->SetTimeDelta(pref_name, unreported_duration + time_delta); } +void OnModifyFakePowerConfigResponse( + std::optional<vm_tools::concierge::SuccessFailureResponse> reply) { + if (!reply.has_value()) { + LOG(ERROR) << "Failed to modify fake power config: empty reply"; + } else if (!reply.value().success()) { + LOG(ERROR) << "Failed to modify fake power config: request failed; failure " + "reason: " + << reply.value().failure_reason(); + } + return; +} + } // namespace // This class observes notifications from a DailyEvent and forwards @@ -148,6 +165,9 @@ simulated_battery_timer_.set_remaining_duration( kMaxSimulatedBatteryStatusDuration); force_real_power_timer_.set_remaining_duration(base::TimeDelta()); + + user_id_hash_ = ProfileHelper::GetUserIdHashFromProfile( + arc::ArcSessionManager::Get()->profile()); } void DozeModePowerStatusScheduler::Stop() { @@ -173,8 +193,10 @@ } void DozeModePowerStatusScheduler::OnArcStarted() { - // When ARC started, initialize this class. - Start(); + if (features::IsDozeModePowerSchedulerEnabled()) { + // When ARC started, initialize this class. + Start(); + } } void DozeModePowerStatusScheduler::OnArcSessionStopped( @@ -219,8 +241,8 @@ } void DozeModePowerStatusScheduler::OnVideoStateChanged( - ash::VideoDetector::State state) { - video_playing_ = (state != ash::VideoDetector::State::NOT_PLAYING); + VideoDetector::State state) { + video_playing_ = (state != VideoDetector::State::NOT_PLAYING); MaybeUpdatePowerStatus(); } @@ -309,9 +331,29 @@ } void DozeModePowerStatusScheduler::SendPowerStatus(PowerStatus status) { - /* - TODO(b/351086080): Add logics of sending power status to crosvm here. - */ + auto* client = ConciergeClient::Get(); + if (!client) { + LOG(ERROR) << "Cannot get ConciergeClient"; + return; + } + + vm_tools::concierge::ModifyFakePowerConfigRequest request; + request.set_name(arc::kArcVmName); + request.set_owner_id(user_id_hash_); + switch (status) { + case PowerStatus::kRealBattery: + [[fallthrough]]; + case PowerStatus::kRealPower: + request.set_action(vm_tools::concierge::FakePowerAction::CANCEL); + break; + case PowerStatus::kSimulatedBattery: + request.set_action(vm_tools::concierge::FakePowerAction::SET); + request.set_capacity_limit(kFakeBatteryCapacityLimit); + break; + } + + client->ModifyFakePowerConfig( + request, base::BindOnce(&OnModifyFakePowerConfigResponse)); const base::Time power_status_sent_time = base::Time::Now(); if (last_power_status_sent_.has_value()) {
diff --git a/chrome/browser/ash/performance/doze_mode_power_status_scheduler.h b/chrome/browser/ash/performance/doze_mode_power_status_scheduler.h index cd6b70d..384a4ae1 100644 --- a/chrome/browser/ash/performance/doze_mode_power_status_scheduler.h +++ b/chrome/browser/ash/performance/doze_mode_power_status_scheduler.h
@@ -106,7 +106,7 @@ // Calculate power status based on current conditions. PowerStatus CalculatePowerStatus(); - // Send power status to crosvm. + // Send a request to crosvm to modify the fake power config. void SendPowerStatus(PowerStatus status); base::ScopedObservation<arc::ArcPowerBridge, arc::ArcPowerBridge::Observer> @@ -140,6 +140,8 @@ const raw_ptr<PrefService> local_state_; std::optional<metrics::DailyEvent> daily_event_; base::RepeatingTimer daily_event_timer_; + + std::string user_id_hash_; }; } // namespace ash
diff --git a/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.cc b/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.cc index 92ec251..1a9f71f 100644 --- a/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.cc +++ b/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.cc
@@ -75,3 +75,8 @@ bool MallSystemAppDelegate::ShouldCaptureNavigations() const { return true; } + +gfx::Size MallSystemAppDelegate::GetMinimumWindowSize() const { + // 688px is the minimum width of the Mall website. + return gfx::Size(/*width=*/688, /*height=*/300); +}
diff --git a/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.h b/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.h index 3777d13..d7395412 100644 --- a/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.h +++ b/chrome/browser/ash/system_web_apps/apps/mall_system_web_app_info.h
@@ -16,6 +16,7 @@ bool IsAppEnabled() const override; std::vector<std::string> GetAppIdsToUninstallAndReplace() const override; bool ShouldCaptureNavigations() const override; + gfx::Size GetMinimumWindowSize() const override; }; #endif // CHROME_BROWSER_ASH_SYSTEM_WEB_APPS_APPS_MALL_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc b/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc index ec1ca9c..7e789b6 100644 --- a/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc +++ b/chrome/browser/autofill_ai/chrome_autofill_ai_client.cc
@@ -103,9 +103,13 @@ if (!filling_engine_) { Profile* profile = Profile::FromBrowserContext(web_contents_->GetBrowserContext()); + OptimizationGuideKeyedService* optimization_guide_keyed_service = + OptimizationGuideKeyedServiceFactory::GetForProfile(profile); filling_engine_ = std::make_unique<autofill_ai::AutofillAiModelExecutorImpl>( - OptimizationGuideKeyedServiceFactory::GetForProfile(profile), + optimization_guide_keyed_service, + optimization_guide_keyed_service + ->GetModelQualityLogsUploaderService(), UserAnnotationsServiceFactory::GetForProfile(profile)); } return filling_engine_.get();
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc index 896b61d5..c0972d9 100644 --- a/chrome/browser/captive_portal/captive_portal_browsertest.cc +++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -13,7 +13,6 @@ #include <vector> #include "base/base_switches.h" -#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -26,7 +25,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -946,7 +944,6 @@ } protected: - base::test::ScopedFeatureList feature_list_; std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_; std::unique_ptr<base::RunLoop> run_loop_; // Only accessed on the UI thread. @@ -970,7 +967,6 @@ scoped_domain_(false), #endif browser_list_(BrowserList::GetInstance()) { - feature_list_.InitAndEnableFeature(kCaptivePortalInterstitial); } CaptivePortalBrowserTest::~CaptivePortalBrowserTest() = default;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index ace43cd..260cea9f 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -163,7 +163,6 @@ #include "chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.h" #include "chrome/browser/ui/webui/downloads/downloads.mojom.h" #include "chrome/browser/ui/webui/downloads/downloads_ui.h" -#include "chrome/browser/ui/webui/internals/internals_ui.h" #include "chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.h" #include "chrome/browser/ui/webui/web_app_internals/web_app_internals.mojom.h" #include "chrome/browser/ui/webui/web_app_internals/web_app_internals_ui.h" @@ -178,7 +177,6 @@ #include "chrome/browser/ui/webui/data_sharing/data_sharing.mojom.h" #include "chrome/browser/ui/webui/data_sharing/data_sharing_ui.h" #include "chrome/browser/ui/webui/history/history_ui.h" -#include "chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" #include "chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.h" @@ -199,6 +197,8 @@ #include "chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h" #include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h" #include "chrome/browser/ui/webui/tab_search/tab_search_ui.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.h" #include "chrome/browser/ui/webui/webui_gallery/webui_gallery_ui.h" #include "chrome/browser/web_applications/web_install_service_impl.h" #include "chrome/common/webui_url_constants.h" @@ -1036,7 +1036,7 @@ policy::local_user_files::LocalFilesMigrationUI, #endif NewTabPageUI, OmniboxPopupUI, BookmarksSidePanelUI, CustomizeChromeUI, - InternalsUI, ReadingListUI, TabSearchUI, WebuiGalleryUI, + UserEducationInternalsUI, ReadingListUI, TabSearchUI, WebuiGalleryUI, HistoryClustersSidePanelUI, ShoppingInsightsSidePanelUI, media_router::AccessCodeCastUI, commerce::ProductSpecificationsUI>(map); @@ -1111,7 +1111,7 @@ #endif // BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI) RegisterWebUIControllerInterfaceBinder< - help_bubble::mojom::HelpBubbleHandlerFactory, InternalsUI, + help_bubble::mojom::HelpBubbleHandlerFactory, UserEducationInternalsUI, settings::SettingsUI, ReadingListUI, NewTabPageUI, CustomizeChromeUI, PasswordManagerUI, HistoryUI, lens::LensOverlayUntrustedUI, lens::LensSidePanelUntrustedUI @@ -1212,7 +1212,7 @@ RegisterWebUIControllerInterfaceBinder< ::mojom::user_education_internals::UserEducationInternalsPageHandler, - InternalsUI>(map); + UserEducationInternalsUI>(map); RegisterWebUIControllerInterfaceBinder< ::mojom::app_service_internals::AppServiceInternalsPageHandler,
diff --git a/chrome/browser/extensions/api/developer_private/OWNERS b/chrome/browser/extensions/api/developer_private/OWNERS index aad0b92..c66e2301 100644 --- a/chrome/browser/extensions/api/developer_private/OWNERS +++ b/chrome/browser/extensions/api/developer_private/OWNERS
@@ -1 +1,2 @@ +kelvinjiang@chromium.org rdevlin.cronin@chromium.org
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_api.cc b/chrome/browser/extensions/api/omnibox/omnibox_api.cc index ca4bb79..7ec78599 100644 --- a/chrome/browser/extensions/api/omnibox/omnibox_api.cc +++ b/chrome/browser/extensions/api/omnibox/omnibox_api.cc
@@ -33,7 +33,10 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_prefs_factory.h" #include "extensions/browser/install_prefs_helper.h" +#include "extensions/common/extension_features.h" #include "extensions/common/extension_id.h" +#include "extensions/common/mojom/api_permission_id.mojom.h" +#include "extensions/common/permissions/permissions_data.h" #include "ui/gfx/image/image.h" namespace extensions { @@ -95,6 +98,15 @@ extension_id + "/?q={searchTerms}"; } +bool IsUnscopedModeAllowed(const Extension* extension) { + // The extension can use unscoepd mode if the feature is enabled and the + // permission has been granted. + return base::FeatureList::IsEnabled( + extensions_features::kExperimentalOmniboxLabs) && + extension->permissions_data()->HasAPIPermission( + mojom::APIPermissionID::kOmniboxDirectInput); +} + } // namespace // static @@ -235,10 +247,11 @@ if (url_service_) { url_service_->Load(); if (url_service_->loaded()) { - url_service_->RegisterOmniboxKeyword( + url_service_->RegisterExtensionControlledTURL( extension->id(), extension->short_name(), keyword, GetTemplateURLStringForExtension(extension->id()), - GetLastUpdateTime(ExtensionPrefs::Get(profile_), extension->id())); + GetLastUpdateTime(ExtensionPrefs::Get(profile_), extension->id()), + IsUnscopedModeAllowed(extension)); } else { pending_extensions_.insert(extension); } @@ -267,10 +280,11 @@ // Register keywords for pending extensions. template_url_subscription_ = {}; for (const Extension* i : pending_extensions_) { - url_service_->RegisterOmniboxKeyword( + url_service_->RegisterExtensionControlledTURL( i->id(), i->short_name(), OmniboxInfo::GetKeyword(i), GetTemplateURLStringForExtension(i->id()), - GetLastUpdateTime(ExtensionPrefs::Get(profile_), i->id())); + GetLastUpdateTime(ExtensionPrefs::Get(profile_), i->id()), + IsUnscopedModeAllowed(i)); } pending_extensions_.clear(); }
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 46531b05..4112533 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -781,6 +781,15 @@ settings_api::PrefType::kBoolean; (*s_allowlist)[ash::prefs::kAccessibilityFaceGazePrecisionClickSpeedFactor] = settings_api::PrefType::kNumber; + (*s_allowlist)[ash::prefs::kAccessibilityFaceGazeEnabledSentinel] = + settings_api::PrefType::kBoolean; + (*s_allowlist)[ash::prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog] = + settings_api::PrefType::kBoolean; + (*s_allowlist) + [ash::prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel] = + settings_api::PrefType::kBoolean; + (*s_allowlist)[ash::prefs::kAccessibilityFaceGazeActionsEnabledSentinel] = + settings_api::PrefType::kBoolean; (*s_allowlist)[ash::prefs::kAccessibilityCaretBlinkInterval] = settings_api::PrefType::kNumber; (*s_allowlist)[ash::prefs::kAccessibilityDisableTrackpadEnabled] =
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index d2806344..a7b1526 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -856,10 +856,7 @@ safe_browsing::kExtensionTelemetryReportContactedHosts) && url.SchemeIsHTTPOrHTTPS()) { protocol = safe_browsing::RemoteHostInfo::HTTP_HTTPS; - } else if (base::FeatureList::IsEnabled( - safe_browsing:: - kExtensionTelemetryReportHostsContactedViaWebSocket) && - url.SchemeIsWSOrWSS()) { + } else if (url.SchemeIsWSOrWSS()) { protocol = safe_browsing::RemoteHostInfo::WEBSOCKET; } else { return;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 6559898..487cae41 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2871,6 +2871,11 @@ "expiry_milestone": 116 }, { + "name": "enable-doze-mode-power-scheduler", + "owners": ["yichenz@chromium.org", "cros-sw-perf@google.com"], + "expiry_milestone": 145 + }, + { "name": "enable-drdc", "owners": [ "vikassoni@chromium.org", "sunnyps@chromium.org" ], "expiry_milestone": 130 @@ -4152,7 +4157,7 @@ { "name": "enable-webrtc-hide-local-ips-with-mdns", "owners": [ "hta@chromium.org" ], - "expiry_milestone": 130 + "expiry_milestone": 142 }, { "name": "enable-webrtc-pipewire-camera", @@ -7925,6 +7930,11 @@ "expiry_milestone": 135 }, { + "name": "set-up-list-shortened-duration", + "owners": [ "hiramahmood@google.com", "bling-get-set-up@google.com" ], + "expiry_milestone": 135 + }, + { "name": "settings-app-notification-settings", "owners": [ "yulunwu@chromium.org" ], "expiry_milestone": 96
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index edfcd08..7a4f1bff 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -6416,6 +6416,11 @@ "When enabled, tiled displays will be represented by a single display in " "ChromeOS, rather than each tile being a separate display."; +const char kEnableDozeModePowerSchedulerName[] = + "Enable doze mode power scheduler"; +const char kEnableDozeModePowerSchedulerDescription[] = + "Enable doze mode power scheduler."; + const char kEnableExternalKeyboardsInDiagnosticsAppName[] = "Enable external keyboards in the Diagnostics App"; const char kEnableExternalKeyboardsInDiagnosticsAppDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 2967340c3..947bfce3 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -3709,6 +3709,9 @@ extern const char kTiledDisplaySupportName[]; extern const char kTiledDisplaySupportDescription[]; +extern const char kEnableDozeModePowerSchedulerName[]; +extern const char kEnableDozeModePowerSchedulerDescription[]; + extern const char kEnableExternalKeyboardsInDiagnosticsAppName[]; extern const char kEnableExternalKeyboardsInDiagnosticsAppDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 2ccd5d0..3060c5b 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -67,7 +67,6 @@ #include "components/visited_url_ranking/public/features.h" #include "components/viz/common/features.h" #include "components/webapps/browser/features.h" -#include "content/public/common/buildflags.h" #include "content/public/common/content_features.h" #include "media/base/media_switches.h" #include "services/device/public/cpp/device_features.h" @@ -1088,15 +1087,6 @@ "UseLibunwindstackNativeUnwinderAndroid", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kUserMediaScreenCapturing, - "UserMediaScreenCapturing", -#if BUILDFLAG(ENABLE_SCREEN_CAPTURE) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -); - BASE_FEATURE(kVoiceSearchAudioCapturePolicy, "VoiceSearchAudioCapturePolicy", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 1b47ec816..df79f5c5 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -191,7 +191,6 @@ BASE_DECLARE_FEATURE(kUmaBackgroundSessions); BASE_DECLARE_FEATURE(kUpdateCompositorForSurfaceControl); BASE_DECLARE_FEATURE(kUseLibunwindstackNativeUnwinderAndroid); -BASE_DECLARE_FEATURE(kUserMediaScreenCapturing); BASE_DECLARE_FEATURE(kVoiceSearchAudioCapturePolicy); BASE_DECLARE_FEATURE(kWebOtpCrossDeviceSimpleString);
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 f211ec5..e818aa6 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
@@ -591,7 +591,7 @@ public static final CachedFlag sAndroidAppIntegrationWithFavicon = newCachedFlag(ANDROID_APP_INTEGRATION_WITH_FAVICON, false); public static final CachedFlag sAndroidBottomToolbar = - newCachedFlag(ANDROID_BOTTOM_TOOLBAR, false); + newCachedFlag(ANDROID_BOTTOM_TOOLBAR, false, true); public static final CachedFlag sAndroidElegantTextHeight = newCachedFlag(ANDROID_ELEGANT_TEXT_HEIGHT, false); public static final CachedFlag sAndroidHubFloatingActionButton =
diff --git a/chrome/browser/glic/launcher/BUILD.gn b/chrome/browser/glic/launcher/BUILD.gn index a1166273..eede9eea 100644 --- a/chrome/browser/glic/launcher/BUILD.gn +++ b/chrome/browser/glic/launcher/BUILD.gn
@@ -33,13 +33,13 @@ ":launcher", "//chrome/app:command_ids", "//chrome/app:generated_resources", + "//chrome/app/vector_icons", "//chrome/browser:browser_process", "//chrome/browser/extensions:extensions", "//chrome/browser/glic", "//chrome/browser/ui", "//chrome/common:constants", "//components/keep_alive_registry", - "//components/vector_icons", "//ui/base", "//ui/gfx", ]
diff --git a/chrome/browser/glic/launcher/glic_status_icon.cc b/chrome/browser/glic/launcher/glic_status_icon.cc index da37300..cde9cbe 100644 --- a/chrome/browser/glic/launcher/glic_status_icon.cc +++ b/chrome/browser/glic/launcher/glic_status_icon.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/glic/launcher/glic_status_icon.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/glic/glic_profile_manager.h" #include "chrome/browser/glic/launcher/glic_controller.h" #include "chrome/browser/profiles/profile_manager.h" @@ -13,7 +14,7 @@ #include "chrome/browser/status_icons/status_tray.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/grit/generated_resources.h" -#include "components/vector_icons/vector_icons.h" +#include "components/user_education/common/help_bubble/help_bubble_params.h" #include "glic_status_icon.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image_skia.h" @@ -23,8 +24,8 @@ StatusTray* status_tray) : controller_(controller), status_tray_(status_tray) { // TODO(https://crbug.com/382287104): Use correct icon. - gfx::ImageSkia status_tray_icon = gfx::CreateVectorIcon( - vector_icons::kProductRefreshIcon, gfx::kPlaceholderColor); + gfx::ImageSkia status_tray_icon = + gfx::CreateVectorIcon(kGlicButtonIcon, SK_ColorBLACK); status_icon_ = status_tray_->CreateStatusIcon( StatusTray::GLIC_ICON, status_tray_icon,
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediator.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediator.java index b6bd720..ea577e2 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediator.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediator.java
@@ -123,7 +123,7 @@ int prevColorScheme = mPropertyModel.get(COLOR_SCHEME) == null ? newColorScheme - : mPropertyModel.get(COLOR_SCHEME).previousColorScheme; + : mPropertyModel.get(COLOR_SCHEME).newColorScheme; mPropertyModel.set(COLOR_SCHEME, new HubColorSchemeUpdate(newColorScheme, prevColorScheme)); View view = pane == null ? null : pane.getRootView();
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediatorUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediatorUnitTest.java index 71221ec..e902ac6 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediatorUnitTest.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubPaneHostMediatorUnitTest.java
@@ -13,6 +13,7 @@ import static org.mockito.Mockito.when; import static org.chromium.chrome.browser.hub.HubPaneHostProperties.ACTION_BUTTON_DATA; +import static org.chromium.chrome.browser.hub.HubPaneHostProperties.COLOR_SCHEME; import static org.chromium.chrome.browser.hub.HubPaneHostProperties.EDGE_TO_EDGE_BOTTOM_INSETS; import static org.chromium.chrome.browser.hub.HubPaneHostProperties.PANE_ROOT_VIEW; @@ -47,6 +48,8 @@ @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); private @Mock Pane mPane; + private @Mock Pane mIncognitoPane; + private @Mock PaneManager mPaneManager; private @Mock FullButtonData mButtonData; private @Mock ViewGroup mRootView; private @Mock EdgeToEdgeController mEdgeToEdgeController; @@ -66,6 +69,14 @@ when(mPane.getRootView()).thenReturn(mRootView); when(mPane.getActionButtonDataSupplier()).thenReturn(mActionButtonSupplier); + + when(mPaneManager.getPaneForId(PaneId.TAB_SWITCHER)).thenReturn(mPane); + when(mPaneManager.getPaneForId(PaneId.INCOGNITO_TAB_SWITCHER)).thenReturn(mIncognitoPane); + + when(mPane.getPaneId()).thenReturn(PaneId.TAB_SWITCHER); + when(mPane.getColorScheme()).thenReturn(HubColorScheme.DEFAULT); + when(mIncognitoPane.getPaneId()).thenReturn(PaneId.INCOGNITO_TAB_SWITCHER); + when(mIncognitoPane.getColorScheme()).thenReturn(HubColorScheme.INCOGNITO); } @Test @@ -178,4 +189,24 @@ new HubPaneHostMediator(mModel, mPaneSupplier, mEdgeToEdgeSupplier); assertFalse("Expecting observers for edge to edge.", mEdgeToEdgeSupplier.hasObservers()); } + + @Test + @SmallTest + public void testHubColorScheme() { + new HubPaneHostMediator(mModel, mPaneSupplier, mEdgeToEdgeSupplier); + mPaneSupplier.set(mPane); + assertEquals( + new HubColorSchemeUpdate(HubColorScheme.DEFAULT, HubColorScheme.DEFAULT), + mModel.get(COLOR_SCHEME)); + + mPaneSupplier.set(mIncognitoPane); + assertEquals( + new HubColorSchemeUpdate(HubColorScheme.INCOGNITO, HubColorScheme.DEFAULT), + mModel.get(COLOR_SCHEME)); + + mPaneSupplier.set(null); + assertEquals( + new HubColorSchemeUpdate(HubColorScheme.DEFAULT, HubColorScheme.INCOGNITO), + mModel.get(COLOR_SCHEME)); + } }
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java index ba5885d..8fec5ff 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediator.java
@@ -255,7 +255,7 @@ int prevColorScheme = mPropertyModel.get(COLOR_SCHEME) == null ? newColorScheme - : mPropertyModel.get(COLOR_SCHEME).previousColorScheme; + : mPropertyModel.get(COLOR_SCHEME).newColorScheme; mPropertyModel.set(COLOR_SCHEME, new HubColorSchemeUpdate(newColorScheme, prevColorScheme));
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediatorUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediatorUnitTest.java index 4f15ffb..bd0ab29 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediatorUnitTest.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubToolbarMediatorUnitTest.java
@@ -274,7 +274,7 @@ mFocusedPaneSupplier.set(null); assertEquals( - new HubColorSchemeUpdate(HubColorScheme.DEFAULT, HubColorScheme.DEFAULT), + new HubColorSchemeUpdate(HubColorScheme.DEFAULT, HubColorScheme.INCOGNITO), mModel.get(COLOR_SCHEME)); }
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm b/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm index 2376de9..ef37e1a 100644 --- a/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm +++ b/chrome/browser/local_discovery/service_discovery_client_mac_unittest.mm
@@ -156,9 +156,9 @@ ASSERT_TRUE(ip_address.AssignFromIPLiteral(kIp)); net::IPEndPoint endpoint(ip_address, kPort); net::SockaddrStorage storage; - ASSERT_TRUE(endpoint.ToSockAddr(storage.addr, &storage.addr_len)); - NSData* discoveryHost = - [NSData dataWithBytes:storage.addr length:storage.addr_len]; + ASSERT_TRUE(endpoint.ToSockAddr(storage.addr(), &storage.addr_len)); + NSData* discoveryHost = [NSData dataWithBytes:storage.addr() + length:storage.addr_len]; NSArray* addresses = @[ discoveryHost ]; [test_service setAddresses:addresses]; @@ -194,9 +194,9 @@ ASSERT_TRUE(ip_address.AssignFromIPLiteral(kIp)); net::IPEndPoint endpoint(ip_address, kPort); net::SockaddrStorage storage; - ASSERT_TRUE(endpoint.ToSockAddr(storage.addr, &storage.addr_len)); - NSData* discovery_host = - [NSData dataWithBytes:storage.addr length:storage.addr_len]; + ASSERT_TRUE(endpoint.ToSockAddr(storage.addr(), &storage.addr_len)); + NSData* discovery_host = [NSData dataWithBytes:storage.addr() + length:storage.addr_len]; NSArray* addresses = @[ discovery_host ]; [test_service setAddresses:addresses];
diff --git a/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.cc b/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.cc index a6ce0ee..c0698803 100644 --- a/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.cc +++ b/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.cc
@@ -4,59 +4,92 @@ #include "chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.h" +#include <cstddef> #include <utility> -#include <vector> #include "base/not_fatal_until.h" #include "base/ranges/algorithm.h" - -using openscreen::osp::ServiceInfo; +#include "base/strings/string_split.h" +#include "third_party/openscreen/src/osp/public/osp_constants.h" +#include "third_party/openscreen/src/platform/base/ip_address.h" namespace media_router { + namespace { -const char kOpenScreenServiceType[] = "openscreen_.udp_"; +using openscreen::osp::kOpenScreenServiceType; +using openscreen::osp::ServiceInfo; ServiceInfo ServiceInfoFromServiceDescription( const local_discovery::ServiceDescription& desc) { openscreen::ErrorOr<openscreen::IPAddress> address = - openscreen::IPAddress::Parse(desc.address.host()); + openscreen::IPAddress::Parse(desc.ip_address.ToString()); DCHECK(address); ServiceInfo service_info; - service_info.service_id = desc.service_name; - service_info.friendly_name = desc.instance_name(); - + service_info.instance_name = desc.instance_name(); if (address.value().IsV4()) { service_info.v4_endpoint = openscreen::IPEndpoint{address.value(), desc.address.port()}; - service_info.v6_endpoint = {}; } else { - service_info.v4_endpoint = {}; service_info.v6_endpoint = openscreen::IPEndpoint{address.value(), desc.address.port()}; } + // Parse TXT records, which contain `auth_token` and `fingerprint`. + for (auto& item : desc.metadata) { + std::vector<std::string> results = base::SplitString( + item, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + // We expect to find key/value pairs separated by an equals sign. + if (results.size() != 2u) { + continue; + } + + if (results[0] == "at") { + service_info.auth_token = results[1]; + } else if (results[0] == "fp") { + service_info.fingerprint = results[1]; + } + } + return service_info; } + } // namespace -OpenScreenListener::OpenScreenListener(std::string service_type) - : service_type_(kOpenScreenServiceType) {} +OpenScreenListener::OpenScreenListener( + scoped_refptr<local_discovery::ServiceDiscoverySharedClient> + service_discovery_client) + : service_discovery_client_(service_discovery_client) {} OpenScreenListener::~OpenScreenListener() = default; bool OpenScreenListener::Start() { - is_running_ = true; + if (state_ != State::kStopped) { + return false; + } - // TODO(jophba): instantiate local_discovery::ServiceDiscoveryClient + CreateDeviceLister(); + state_ = State::kRunning; for (auto* observer : observers_) { observer->OnStarted(); } + + device_lister_->DiscoverNewDevices(); + state_ = State::kSearching; + for (auto* observer : observers_) { + observer->OnSearching(); + } return true; } bool OpenScreenListener::StartAndSuspend() { + if (state_ != State::kStopped) { + return false; + } + + CreateDeviceLister(); + state_ = State::kSuspended; for (auto* observer : observers_) { observer->OnStarted(); observer->OnSuspended(); @@ -65,8 +98,12 @@ } bool OpenScreenListener::Stop() { - DCHECK(is_running_); - is_running_ = false; + if (state_ == State::kStopped) { + return false; + } + + device_lister_.reset(); + state_ = State::kStopped; for (auto* observer : observers_) { observer->OnStopped(); } @@ -74,8 +111,14 @@ } bool OpenScreenListener::Suspend() { - DCHECK(is_running_); - is_running_ = false; + if (state_ == State::kStopped || state_ == State::kSuspended) { + return false; + } + + // `device_lister_` does not provide interface for suspending, so we can only + // reset it here. + device_lister_.reset(); + state_ = State::kSuspended; for (auto* observer : observers_) { observer->OnSuspended(); } @@ -83,42 +126,56 @@ } bool OpenScreenListener::Resume() { - DCHECK(!is_running_); - is_running_ = true; - for (auto* observer : observers_) { - observer->OnStarted(); + if (state_ != State::kSuspended) { + return false; } - return true; -} -bool OpenScreenListener::SearchNow() { - is_running_ = true; + // `device_lister_` is reset when calling `Suspend()`, so we need to create it + // again. + if (!device_lister_) { + CreateDeviceLister(); + } + + device_lister_->DiscoverNewDevices(); for (auto* observer : observers_) { observer->OnSearching(); } return true; } +bool OpenScreenListener::SearchNow() { + if (state_ == State::kStopped || !device_lister_) { + return false; + } + + device_lister_->DiscoverNewDevices(); + for (auto* observer : observers_) { + observer->OnSearching(); + } + return true; +} + +void OpenScreenListener::AddObserver( + openscreen::osp::ServiceListener::Observer& observer) { + observers_.push_back(&observer); +} + +void OpenScreenListener::RemoveObserver( + openscreen::osp::ServiceListener::Observer& observer) { + observers_.erase(std::remove(observers_.begin(), observers_.end(), &observer), + observers_.end()); +} + const std::vector<ServiceInfo>& OpenScreenListener::GetReceivers() const { return receivers_; } -void OpenScreenListener::AddObserver(ServiceListener::Observer* observer) { - CHECK(observer); - observers_.push_back(observer); -} - -void OpenScreenListener::RemoveObserver(ServiceListener::Observer* observer) { - CHECK(observer); - std::erase(observers_, observer); -} - void OpenScreenListener::OnDeviceChanged( const std::string& service_type, bool added, const local_discovery::ServiceDescription& service_description) { - CHECK_EQ(service_type, service_type_); - if (!is_running_) { + CHECK_EQ(service_type, kOpenScreenServiceType); + if (state_ == State::kSuspended || state_ == State::kStopped) { return; } @@ -132,9 +189,8 @@ observer->OnReceiverAdded(ref); } } else { - auto it = base::ranges::find(receivers_, service_info.service_id, - &ServiceInfo::service_id); - + auto it = base::ranges::find(receivers_, service_info.instance_name, + &ServiceInfo::instance_name); *it = std::move(service_info); for (auto* observer : observers_) { @@ -145,13 +201,21 @@ void OpenScreenListener::OnDeviceRemoved(const std::string& service_type, const std::string& service_name) { - CHECK(service_type == service_type_); - if (!is_running_) { + CHECK_EQ(service_type, kOpenScreenServiceType); + if (state_ == State::kSuspended || state_ == State::kStopped) { return; } - const auto& removed_it = - base::ranges::find(receivers_, service_name, &ServiceInfo::service_id); + std::vector<std::string> results = base::SplitString( + service_name, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + // We expect the service name follows the format + // <instance_name>.<service_type>. + if (results.size() != 2u) { + return; + } + + auto removed_it = + base::ranges::find(receivers_, results[0], &ServiceInfo::instance_name); // Move the receiver we want to remove to the end, so we don't have to shift. CHECK(removed_it != receivers_.end(), base::NotFatalUntil::M130); @@ -167,11 +231,11 @@ } void OpenScreenListener::OnDeviceCacheFlushed(const std::string& service_type) { - CHECK(service_type == service_type_); + CHECK_EQ(service_type, kOpenScreenServiceType); receivers_.clear(); // We still flush even if not running, since it's not going to be accurate. - if (!is_running_) { + if (state_ == State::kSuspended || state_ == State::kStopped) { return; } @@ -180,4 +244,14 @@ } } +void OpenScreenListener::OnPermissionRejected() {} + +void OpenScreenListener::CreateDeviceLister() { + CHECK(!device_lister_); + + device_lister_ = local_discovery::ServiceDiscoveryDeviceLister::Create( + this, service_discovery_client_.get(), kOpenScreenServiceType); + device_lister_->Start(); +} + } // namespace media_router
diff --git a/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.h b/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.h index 83b64ed..8e70d13 100644 --- a/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.h +++ b/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.h
@@ -5,54 +5,74 @@ #ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_OPENSCREEN_DISCOVERY_OPEN_SCREEN_LISTENER_H_ #define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_OPENSCREEN_DISCOVERY_OPEN_SCREEN_LISTENER_H_ +#include <memory> #include <string> #include <vector> +#include "base/memory/scoped_refptr.h" #include "chrome/browser/local_discovery/service_discovery_device_lister.h" - +#include "chrome/browser/local_discovery/service_discovery_shared_client.h" +#include "chrome/common/buildflags.h" #include "third_party/openscreen/src/osp/public/service_info.h" #include "third_party/openscreen/src/osp/public/service_listener.h" -#include "third_party/openscreen/src/platform/base/ip_address.h" + +static_assert( + BUILDFLAG(ENABLE_SERVICE_DISCOVERY), + "OpenScreenListener requires enable_service_discovery to be true."); namespace media_router { + +// TODO(issuetracker.google.com/383267932): Don't use implementation +// inheritance! class OpenScreenListener : public openscreen::osp::ServiceListener, local_discovery::ServiceDiscoveryDeviceLister::Delegate { public: - explicit OpenScreenListener(std::string service_type); - + explicit OpenScreenListener( + scoped_refptr<local_discovery::ServiceDiscoverySharedClient> + service_discovery_client); OpenScreenListener(const OpenScreenListener&) = delete; OpenScreenListener& operator=(const OpenScreenListener&) = delete; - - // ServiceListener overrides + OpenScreenListener(OpenScreenListener&&) = delete; + OpenScreenListener& operator=(OpenScreenListener&&) = delete; ~OpenScreenListener() override; + // ServiceListener overrides. bool Start() override; bool StartAndSuspend() override; bool Stop() override; bool Suspend() override; bool Resume() override; bool SearchNow() override; - + void AddObserver( + openscreen::osp::ServiceListener::Observer& observer) override; + void RemoveObserver( + openscreen::osp::ServiceListener::Observer& observer) override; const std::vector<openscreen::osp::ServiceInfo>& GetReceivers() const override; - void AddObserver(ServiceListener::Observer* observer) override; - void RemoveObserver(ServiceListener::Observer* observer) override; - // ServiceDiscoveryDeviceLister::Delegate + // ServiceDiscoveryDeviceLister::Delegate overrides. void OnDeviceChanged( const std::string& service_type, bool added, const local_discovery::ServiceDescription& service_description) override; - void OnDeviceRemoved(const std::string& service_type, const std::string& service_name) override; void OnDeviceCacheFlushed(const std::string& service_type) override; + void OnPermissionRejected() override; + + protected: + // Created when start discovering if service discovery is enabled. + std::unique_ptr<local_discovery::ServiceDiscoveryDeviceLister> device_lister_; private: - bool is_running_ = false; - const std::string service_type_; + virtual void CreateDeviceLister(); + std::vector<openscreen::osp::ServiceInfo> receivers_; + + // The client and service type used to create `device_lister_`. + scoped_refptr<local_discovery::ServiceDiscoverySharedClient> + service_discovery_client_; }; } // namespace media_router
diff --git a/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener_unittest.cc b/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener_unittest.cc index 611da5b3..d8df300 100644 --- a/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener_unittest.cc +++ b/chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener_unittest.cc
@@ -5,22 +5,17 @@ #include "chrome/browser/media/router/providers/openscreen/discovery/open_screen_listener.h" #include "base/time/time.h" +#include "chrome/browser/local_discovery/fake_service_discovery_device_lister.h" #include "net/base/host_port_pair.h" #include "net/base/ip_address.h" - #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" - -using openscreen::osp::ServiceInfo; -using ::testing::_; -using ::testing::Invoke; -using ::testing::Return; -using ::testing::StrictMock; -using ::testing::WithArg; +#include "third_party/openscreen/src/osp/public/osp_constants.h" namespace media_router { -const char kServiceType[] = "openscreen_.udp_"; +using openscreen::osp::kOpenScreenServiceType; +using openscreen::osp::ServiceInfo; class MockServiceListenerObserver : public openscreen::osp::ServiceListener::Observer { @@ -35,7 +30,7 @@ MOCK_METHOD1(OnReceiverRemoved, void(const ServiceInfo&)); MOCK_METHOD0(OnAllReceiversRemoved, void()); - MOCK_METHOD1(OnError, void(openscreen::osp::ServiceListenerError)); + MOCK_METHOD1(OnError, void(const openscreen::Error&)); MOCK_METHOD1(OnMetrics, void(openscreen::osp::ServiceListener::Metrics)); }; @@ -43,169 +38,199 @@ // it's difficult to figure out *exactly* what is wrong with the actual // Service Info class. MATCHER_P(ServiceInfoEquals, expected, "") { - return (expected.service_id == arg.service_id) && - (expected.friendly_name == arg.friendly_name) && + return (expected.instance_name == arg.instance_name) && + (expected.auth_token == arg.auth_token) && + (expected.fingerprint == arg.fingerprint) && (expected.network_interface_index == arg.network_interface_index) && (expected.v4_endpoint == arg.v4_endpoint) && (expected.v6_endpoint == arg.v6_endpoint); } +class FakeOpenScreenListener : public OpenScreenListener { + public: + explicit FakeOpenScreenListener( + scoped_refptr<local_discovery::ServiceDiscoverySharedClient> + service_discovery_client) + : OpenScreenListener(service_discovery_client) {} + FakeOpenScreenListener(const FakeOpenScreenListener&) = delete; + FakeOpenScreenListener& operator=(const FakeOpenScreenListener&) = delete; + FakeOpenScreenListener(FakeOpenScreenListener&&) = delete; + FakeOpenScreenListener& operator=(FakeOpenScreenListener&&) = delete; + ~FakeOpenScreenListener() override = default; + + private: + // Use a fake ServiceDiscoveryDeviceLister to avoid performing actual service + // discovery operations. + void CreateDeviceLister() override { + CHECK(!device_lister_); + + device_lister_ = + std::make_unique<local_discovery::FakeServiceDiscoveryDeviceLister>( + /*task_runner=*/nullptr, kOpenScreenServiceType); + device_lister_->Start(); + } +}; + class OpenScreenListenerTest : public ::testing::Test { protected: void SetUp() override { - valid_description_.service_name = "mock_service.test_service_type"; + valid_description_.service_name = "mock_instance_name.test_service_type"; valid_description_.address = net::HostPortPair("192.168.0.10", 8888); - valid_description_.metadata = {"foo", "bar", "baz"}; + valid_description_.metadata = {"at=mock_auth_token", "fp=mock_fingerprint"}; valid_description_.ip_address = net::IPAddress(192, 168, 0, 10); valid_description_.last_seen = base::Time(); - service_info_.service_id = "mock_service.test_service_type"; - service_info_.friendly_name = "mock_service"; + service_info_.instance_name = "mock_instance_name"; + service_info_.auth_token = "mock_auth_token"; + service_info_.fingerprint = "mock_fingerprint"; service_info_.v4_endpoint = openscreen::IPEndpoint{openscreen::IPAddress(192, 168, 0, 10), 8888}; - service_info_.v6_endpoint = {}; } - OpenScreenListenerTest() : listener(kServiceType), observer() { - listener.AddObserver(&observer); + OpenScreenListenerTest() : listener_(nullptr), observer_() { + listener_.AddObserver(observer_); } void ExpectReceiverAdded(const ServiceInfo& info) { - EXPECT_CALL(observer, OnReceiverAdded(ServiceInfoEquals(info))); + EXPECT_CALL(observer_, OnReceiverAdded(ServiceInfoEquals(info))); } void ExpectReceiverChanged(const ServiceInfo& info) { - EXPECT_CALL(observer, OnReceiverChanged(ServiceInfoEquals(info))); + EXPECT_CALL(observer_, OnReceiverChanged(ServiceInfoEquals(info))); } void ExpectReceiverRemoved(const ServiceInfo& info) { - EXPECT_CALL(observer, OnReceiverRemoved(ServiceInfoEquals(info))); + EXPECT_CALL(observer_, OnReceiverRemoved(ServiceInfoEquals(info))); } - OpenScreenListener listener; - StrictMock<MockServiceListenerObserver> observer; + FakeOpenScreenListener listener_; + ::testing::StrictMock<MockServiceListenerObserver> observer_; local_discovery::ServiceDescription valid_description_; ServiceInfo service_info_; }; TEST_F(OpenScreenListenerTest, DeviceAddedNotifiesObserversIfStarted) { - listener.OnDeviceChanged(kServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + listener_.Start(); ExpectReceiverAdded(service_info_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); } TEST_F(OpenScreenListenerTest, DeviceChangedNotifiesObserversIfStarted) { - listener.OnDeviceChanged(kServiceType, false, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, false, valid_description_); - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + listener_.Start(); ExpectReceiverAdded(service_info_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); ExpectReceiverChanged(service_info_); - listener.OnDeviceChanged(kServiceType, false, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, false, valid_description_); } TEST_F(OpenScreenListenerTest, DeviceRemovedNotifiesObserversIfStarted) { - listener.OnDeviceRemoved(kServiceType, valid_description_.service_name); + listener_.OnDeviceRemoved(kOpenScreenServiceType, + valid_description_.service_name); - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + listener_.Start(); ExpectReceiverAdded(service_info_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); ExpectReceiverRemoved(service_info_); - listener.OnDeviceRemoved(kServiceType, valid_description_.service_name); + listener_.OnDeviceRemoved(kOpenScreenServiceType, + valid_description_.service_name); } TEST_F(OpenScreenListenerTest, CachedFlushNotifiesObserversIfStarted) { - listener.OnDeviceCacheFlushed(kServiceType); + listener_.OnDeviceCacheFlushed(kOpenScreenServiceType); - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); - EXPECT_CALL(observer, OnAllReceiversRemoved()).Times(1); - listener.OnDeviceCacheFlushed(kServiceType); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + listener_.Start(); + EXPECT_CALL(observer_, OnAllReceiversRemoved()).Times(1); + listener_.OnDeviceCacheFlushed(kOpenScreenServiceType); } TEST_F(OpenScreenListenerTest, CachedFlushEmptiesReceiverList) { - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + listener_.Start(); ExpectReceiverAdded(service_info_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); ExpectReceiverAdded(service_info_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); - EXPECT_EQ(2ul, listener.GetReceivers().size()); - EXPECT_CALL(observer, OnAllReceiversRemoved()).Times(1); - listener.OnDeviceCacheFlushed(kServiceType); - EXPECT_EQ(0ul, listener.GetReceivers().size()); + EXPECT_EQ(2ul, listener_.GetReceivers().size()); + EXPECT_CALL(observer_, OnAllReceiversRemoved()).Times(1); + listener_.OnDeviceCacheFlushed(kOpenScreenServiceType); + EXPECT_EQ(0ul, listener_.GetReceivers().size()); } TEST_F(OpenScreenListenerTest, StartNotifiesObservers) { - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + listener_.Start(); } TEST_F(OpenScreenListenerTest, StopNotifiesObservers) { - EXPECT_CALL(observer, OnStarted()).Times(1); - EXPECT_CALL(observer, OnStopped()).Times(1); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(1); + EXPECT_CALL(observer_, OnStopped()).Times(1); - listener.Start(); - listener.Stop(); + listener_.Start(); + listener_.Stop(); } -TEST_F(OpenScreenListenerTest, SuspendNotifiesObservers) { - EXPECT_CALL(observer, OnStarted()).Times(2); - EXPECT_CALL(observer, OnSuspended()).Times(2); +TEST_F(OpenScreenListenerTest, SuspendAndResumeNotifyObservers) { + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(2); + EXPECT_CALL(observer_, OnSuspended()).Times(1); - listener.Start(); - listener.Suspend(); - listener.StartAndSuspend(); -} - -TEST_F(OpenScreenListenerTest, ResumeNotifiesObservers) { - EXPECT_CALL(observer, OnStarted()).Times(2); - EXPECT_CALL(observer, OnSuspended()).Times(1); - - listener.Start(); - listener.Suspend(); - listener.Resume(); + listener_.Start(); + listener_.Suspend(); + listener_.Resume(); } TEST_F(OpenScreenListenerTest, SearchingNotifiesObservers) { - EXPECT_CALL(observer, OnStarted()).Times(1); - listener.Start(); - EXPECT_CALL(observer, OnSearching()).Times(1); - listener.SearchNow(); + EXPECT_CALL(observer_, OnStarted()).Times(1); + EXPECT_CALL(observer_, OnSearching()).Times(2); + + listener_.Start(); + listener_.SearchNow(); } TEST_F(OpenScreenListenerTest, RemovedObserversDoNotGetNotified) { - listener.RemoveObserver(&observer); + listener_.RemoveObserver(observer_); - listener.Start(); - listener.Stop(); - listener.StartAndSuspend(); - listener.Resume(); - listener.SearchNow(); - listener.Suspend(); - listener.Resume(); - listener.OnDeviceCacheFlushed(kServiceType); - listener.OnDeviceChanged(kServiceType, true, valid_description_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); - listener.OnDeviceRemoved(kServiceType, valid_description_.service_name); + listener_.Start(); + listener_.Stop(); + listener_.StartAndSuspend(); + listener_.Resume(); + listener_.SearchNow(); + listener_.Suspend(); + listener_.Resume(); + listener_.OnDeviceCacheFlushed(kOpenScreenServiceType); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); + listener_.OnDeviceRemoved(kOpenScreenServiceType, + valid_description_.service_name); } TEST_F(OpenScreenListenerTest, DoesNotRecordReceiversIfNotStarted) { - EXPECT_EQ(0ul, listener.GetReceivers().size()); + EXPECT_EQ(0ul, listener_.GetReceivers().size()); - listener.OnDeviceChanged(kServiceType, true, valid_description_); - listener.OnDeviceChanged(kServiceType, false, valid_description_); - listener.OnDeviceChanged(kServiceType, true, valid_description_); - EXPECT_EQ(0ul, listener.GetReceivers().size()); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, false, valid_description_); + listener_.OnDeviceChanged(kOpenScreenServiceType, true, valid_description_); + EXPECT_EQ(0ul, listener_.GetReceivers().size()); } + } // namespace media_router
diff --git a/chrome/browser/metrics/power/process_monitor_unittest.cc b/chrome/browser/metrics/power/process_monitor_unittest.cc index c3772af..95e9048 100644 --- a/chrome/browser/metrics/power/process_monitor_unittest.cc +++ b/chrome/browser/metrics/power/process_monitor_unittest.cc
@@ -18,14 +18,14 @@ }; for (const auto& [process_type, expectation] : kExpectations) { - content::ChildProcessData data(process_type); - // data.process_type = process_type; + content::ChildProcessData data(process_type, content::ChildProcessId()); EXPECT_EQ(GetMonitoredProcessTypeForNonRendererChildProcessForTesting(data), expectation); } // Special case for network process. - content::ChildProcessData data(content::PROCESS_TYPE_UTILITY); + content::ChildProcessData data(content::PROCESS_TYPE_UTILITY, + content::ChildProcessId()); data.metrics_name = network::mojom::NetworkService::Name_; EXPECT_EQ(GetMonitoredProcessTypeForNonRendererChildProcessForTesting(data), MonitoredProcessType::kNetwork);
diff --git a/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc b/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc index 2b7b725..98fec738 100644 --- a/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc +++ b/chrome/browser/optimization_guide/model_execution/model_execution_browsertest.cc
@@ -690,7 +690,8 @@ scoped_feature_list_.InitWithFeaturesAndParameters( {{features::kOptimizationGuideModelExecution, {}}, {features::kModelQualityLogging, {}}, - {features::kOptimizationGuideOnDeviceModel, + {features::kOptimizationGuideOnDeviceModel, {}}, + {features::kOnDeviceModelPerformanceParams, {{"compatible_on_device_performance_classes", "*"}}}}, {}); }
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc index 0f62982..36b9066 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -205,10 +205,7 @@ base::UmaHistogramEnumeration( "OptimizationGuide.ModelExecution.OnDeviceModelPerformanceClass", perf_class); - ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( - "SyntheticOnDeviceModelPerformanceClass", - SyntheticTrialGroupForPerformanceClass(perf_class), - variations::SyntheticTrialAnnotationMode::kCurrentLog); + RegisterPerformanceClassSyntheticTrial(perf_class); return perf_class; }) .Then(base::BindOnce(&OnDeviceModelComponentStateManager:: @@ -216,6 +213,17 @@ on_device_component_state_manager))); } +// static +void OptimizationGuideKeyedService::RegisterPerformanceClassSyntheticTrial( + OnDeviceModelPerformanceClass perf_class) { + if (perf_class != OnDeviceModelPerformanceClass::kUnknown) { + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + "SyntheticOnDeviceModelPerformanceClass", + SyntheticTrialGroupForPerformanceClass(perf_class), + variations::SyntheticTrialAnnotationMode::kCurrentLog); + } +} + OptimizationGuideKeyedService::OptimizationGuideKeyedService( content::BrowserContext* browser_context) : browser_context_(browser_context) { @@ -387,6 +395,10 @@ on_device_component_manager_->GetWeakPtr()), optimization_guide::features::GetOnDeviceStartupMetricDelay()); } + // If the perf class was previously determined, register that. + RegisterPerformanceClassSyntheticTrial( + optimization_guide::PerformanceClassFromPref( + *g_browser_process->local_state())); auto* variations_service = g_browser_process->variations_service(); auto dogfood_status =
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h index a5042c72..ec6a6209 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -244,6 +244,8 @@ static void DeterminePerformanceClass( base::WeakPtr<optimization_guide::OnDeviceModelComponentStateManager> on_device_component_state_manager); + static void RegisterPerformanceClassSyntheticTrial( + optimization_guide::OnDeviceModelPerformanceClass perf_class); // Initializes |this|. void Initialize();
diff --git a/chrome/browser/os_crypt/app_bound_encryption_provider_win.cc b/chrome/browser/os_crypt/app_bound_encryption_provider_win.cc index 23934ec..4a7dada 100644 --- a/chrome/browser/os_crypt/app_bound_encryption_provider_win.cc +++ b/chrome/browser/os_crypt/app_bound_encryption_provider_win.cc
@@ -5,8 +5,11 @@ #include "chrome/browser/os_crypt/app_bound_encryption_provider_win.h" #include <optional> +#include <string> +#include <tuple> #include "base/base64.h" +#include "base/containers/span.h" #include "base/debug/dump_without_crashing.h" #include "base/logging.h" #include "base/metrics/histogram_functions.h" @@ -38,6 +41,9 @@ // OSCryptAsync to identify that data has been encrypted with this key. constexpr char kAppBoundDataPrefix[] = "v20"; +constexpr ProtectionLevel kCurrentProtectionLevel = + ProtectionLevel::PROTECTION_PATH_VALIDATION; + } // namespace AppBoundEncryptionProviderWin::AppBoundEncryptionProviderWin( @@ -53,15 +59,13 @@ class AppBoundEncryptionProviderWin::COMWorker { public: - std::optional<const std::vector<uint8_t>> EncryptKey( - const std::vector<uint8_t>& decrypted_key) { + OptionalReadOnlyKeyData EncryptKey(ReadOnlyKeyData& decrypted_key) { std::string plaintext_string(decrypted_key.begin(), decrypted_key.end()); std::string ciphertext; DWORD last_error; HRESULT res = os_crypt::EncryptAppBoundString( - ProtectionLevel::PROTECTION_PATH_VALIDATION, plaintext_string, - ciphertext, last_error); + kCurrentProtectionLevel, plaintext_string, ciphertext, last_error); base::UmaHistogramSparse("OSCrypt.AppBoundProvider.Encrypt.ResultCode", res); @@ -75,17 +79,19 @@ return std::nullopt; } - return std::vector<uint8_t>(ciphertext.cbegin(), ciphertext.cend()); + return ReadOnlyKeyData(ciphertext.cbegin(), ciphertext.cend()); } - std::optional<const std::vector<uint8_t>> DecryptKey( - const std::vector<uint8_t>& encrypted_key) { + std::optional<std::tuple<ReadWriteKeyData, OptionalReadOnlyKeyData>> + DecryptKey(ReadOnlyKeyData& encrypted_key) { DWORD last_error; std::string encrypted_key_string(encrypted_key.begin(), encrypted_key.end()); std::string decrypted_key_string; + std::optional<std::string> maybe_new_ciphertext; HRESULT res = os_crypt::DecryptAppBoundString( - encrypted_key_string, decrypted_key_string, last_error); + encrypted_key_string, decrypted_key_string, kCurrentProtectionLevel, + maybe_new_ciphertext, last_error); base::UmaHistogramSparse("OSCrypt.AppBoundProvider.Decrypt.ResultCode", res); @@ -100,11 +106,18 @@ } // Copy data to a vector. - std::vector<uint8_t> data(decrypted_key_string.cbegin(), - decrypted_key_string.cend()); + ReadWriteKeyData data(decrypted_key_string.cbegin(), + decrypted_key_string.cend()); ::SecureZeroMemory(decrypted_key_string.data(), decrypted_key_string.size()); - return data; + + OptionalReadOnlyKeyData maybe_new_ciphertext_data; + if (maybe_new_ciphertext) { + maybe_new_ciphertext_data.emplace(maybe_new_ciphertext->cbegin(), + maybe_new_ciphertext->cend()); + } + return std::make_tuple(std::move(data), + std::move(maybe_new_ciphertext_data)); } }; @@ -135,8 +148,9 @@ // There is a key, perform the decryption on the background worker. com_worker_.AsyncCall(&AppBoundEncryptionProviderWin::COMWorker::DecryptKey) .WithArgs(std::move(encrypted_key_data.value())) - .Then(base::BindOnce(&AppBoundEncryptionProviderWin::ReplyWithKey, - std::move(callback))); + .Then( + base::BindOnce(&AppBoundEncryptionProviderWin::StoreAndReplyWithKey, + weak_factory_.GetWeakPtr(), std::move(callback))); return; } @@ -152,15 +166,15 @@ const auto random_key = crypto::RandBytesAsVector( os_crypt_async::Encryptor::Key::kAES256GCMKeySize); // Take a copy of the key. This will be returned as the unencrypted key for - // the provider, once the encryption operation is complete. - std::vector<uint8_t> decrypted_key(random_key.cbegin(), random_key.cend()); + // the provider, once the encryption operation is complete. This key is + // securely cleared later on in `StoreAndReplyWithKey`. + ReadWriteKeyData decrypted_key(random_key.cbegin(), random_key.cend()); // Perform the encryption on the background worker. com_worker_.AsyncCall(&AppBoundEncryptionProviderWin::COMWorker::EncryptKey) .WithArgs(std::move(random_key)) - .Then(base::BindOnce( - &AppBoundEncryptionProviderWin::StoreEncryptedKeyAndReply, - weak_factory_.GetWeakPtr(), std::move(decrypted_key), - std::move(callback))); + .Then(base::BindOnce(&AppBoundEncryptionProviderWin::HandleEncryptedKey, + weak_factory_.GetWeakPtr(), std::move(decrypted_key), + std::move(callback))); } bool AppBoundEncryptionProviderWin::UseForEncryption() { @@ -173,7 +187,7 @@ return false; } -base::expected<std::vector<uint8_t>, +base::expected<AppBoundEncryptionProviderWin::ReadWriteKeyData, AppBoundEncryptionProviderWin::KeyRetrievalStatus> AppBoundEncryptionProviderWin::RetrieveEncryptedKey() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -184,7 +198,7 @@ const std::string base64_encrypted_key = local_state_->GetString(kEncryptedKeyPrefName); - std::optional<std::vector<uint8_t>> encrypted_key_with_header = + std::optional<ReadWriteKeyData> encrypted_key_with_header = base::Base64Decode(base64_encrypted_key); if (!encrypted_key_with_header) { @@ -198,49 +212,60 @@ } // Trim off the key prefix. - return std::vector<uint8_t>( + return ReadWriteKeyData( encrypted_key_with_header->cbegin() + sizeof(kCryptAppBoundKeyPrefix), encrypted_key_with_header->cend()); } -void AppBoundEncryptionProviderWin::StoreEncryptedKeyAndReply( - const std::vector<uint8_t>& decrypted_key, - KeyCallback callback, - const std::optional<std::vector<uint8_t>>& encrypted_key) { +void AppBoundEncryptionProviderWin::StoreKey( + base::span<const uint8_t> encrypted_key) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + ReadWriteKeyData key(sizeof(kCryptAppBoundKeyPrefix) + encrypted_key.size()); + // Add header indicating this key is encrypted with App Bound provider. + key.insert(key.cbegin(), std::begin(kCryptAppBoundKeyPrefix), + std::end(kCryptAppBoundKeyPrefix)); + key.insert(key.cbegin() + sizeof(kCryptAppBoundKeyPrefix), + encrypted_key.cbegin(), encrypted_key.cend()); + std::string base64_key = base::Base64Encode(key); + // Store key. + local_state_->SetString(kEncryptedKeyPrefName, base64_key); +} + +void AppBoundEncryptionProviderWin::HandleEncryptedKey( + ReadWriteKeyData decrypted_key, + KeyCallback callback, + const OptionalReadOnlyKeyData& encrypted_key) { if (!encrypted_key) { + ::SecureZeroMemory(decrypted_key.data(), decrypted_key.size()); // Failure here causes the provider not to be registered. std::move(callback).Run(kAppBoundDataPrefix, std::nullopt); return; } - std::vector<uint8_t> key(sizeof(kCryptAppBoundKeyPrefix) + - encrypted_key->size()); - key.insert(key.cbegin(), std::begin(kCryptAppBoundKeyPrefix), - std::end(kCryptAppBoundKeyPrefix)); - key.insert(key.cbegin() + sizeof(kCryptAppBoundKeyPrefix), - encrypted_key->cbegin(), encrypted_key->cend()); - // Add header indicating this key is encrypted with App Bound provider. - std::string base64_key = base::Base64Encode(key); - // Store key. - local_state_->SetString(kEncryptedKeyPrefName, base64_key); - - ReplyWithKey(std::move(callback), decrypted_key); + StoreAndReplyWithKey( + std::move(callback), + std::make_tuple(std::move(decrypted_key), encrypted_key)); } -// static -void AppBoundEncryptionProviderWin::ReplyWithKey( +void AppBoundEncryptionProviderWin::StoreAndReplyWithKey( KeyCallback callback, - std::optional<std::vector<uint8_t>> decrypted_key) { - if (decrypted_key) { - // Constructor takes a copy. - Encryptor::Key key(*decrypted_key, mojom::Algorithm::kAES256GCM); - ::SecureZeroMemory(decrypted_key->data(), decrypted_key->size()); - std::move(callback).Run(kAppBoundDataPrefix, std::move(key)); + std::optional<std::tuple<ReadWriteKeyData, const OptionalReadOnlyKeyData&>> + key_pair) { + if (!key_pair) { + // Failure here causes the provider not to be registered. + std::move(callback).Run(kAppBoundDataPrefix, std::nullopt); return; } - // Failure here causes the provider not to be registered. - std::move(callback).Run(kAppBoundDataPrefix, std::nullopt); + auto& [decrypted_key, maybe_encrypted_key] = *key_pair; + + if (maybe_encrypted_key) { + StoreKey(*maybe_encrypted_key); + } + + // Constructor takes a copy. + Encryptor::Key key(decrypted_key, mojom::Algorithm::kAES256GCM); + ::SecureZeroMemory(decrypted_key.data(), decrypted_key.size()); + std::move(callback).Run(kAppBoundDataPrefix, std::move(key)); } } // namespace os_crypt_async
diff --git a/chrome/browser/os_crypt/app_bound_encryption_provider_win.h b/chrome/browser/os_crypt/app_bound_encryption_provider_win.h index 660e2411..a2cc5ec 100644 --- a/chrome/browser/os_crypt/app_bound_encryption_provider_win.h +++ b/chrome/browser/os_crypt/app_bound_encryption_provider_win.h
@@ -7,7 +7,10 @@ #include <optional> #include <string> +#include <tuple> +#include "base/containers/span.h" +#include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" @@ -20,6 +23,10 @@ class PrefService; class PrefRegistrySimple; +namespace os_crypt { +FORWARD_DECLARE_TEST(AppBoundEncryptionWinReencryptTest, KeyProviderTest); +} // namespace os_crypt + namespace os_crypt_async { class AppBoundEncryptionProviderWin : public os_crypt_async::KeyProvider { @@ -36,6 +43,14 @@ static void RegisterLocalPrefs(PrefRegistrySimple* registry); private: + FRIEND_TEST_ALL_PREFIXES(os_crypt::AppBoundEncryptionWinReencryptTest, + KeyProviderTest); + + using ReadOnlyKeyData = const std::vector<uint8_t>; + using ReadWriteKeyData = std::vector<uint8_t>; + using OptionalReadWriteKeyData = std::optional<ReadWriteKeyData>; + using OptionalReadOnlyKeyData = std::optional<ReadOnlyKeyData>; + // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class KeyRetrievalStatus { @@ -53,12 +68,14 @@ base::expected<std::vector<uint8_t>, KeyRetrievalStatus> RetrieveEncryptedKey(); - void StoreEncryptedKeyAndReply( - const std::vector<uint8_t>& decrypted_key, + void HandleEncryptedKey(ReadWriteKeyData decrypted_key, + KeyCallback callback, + const OptionalReadOnlyKeyData& encrypted_key); + void StoreAndReplyWithKey( KeyCallback callback, - const std::optional<std::vector<uint8_t>>& encrypted_key); - static void ReplyWithKey(KeyCallback callback, - std::optional<std::vector<uint8_t>> decrypted_key); + std::optional<std::tuple<ReadWriteKeyData, + const OptionalReadOnlyKeyData&>> key_pair); + void StoreKey(base::span<const uint8_t> encrypted_key); raw_ptr<PrefService> local_state_ GUARDED_BY_CONTEXT(sequence_checker_);
diff --git a/chrome/browser/os_crypt/app_bound_encryption_test_main.cc b/chrome/browser/os_crypt/app_bound_encryption_test_main.cc index 870def7..35034e0f 100644 --- a/chrome/browser/os_crypt/app_bound_encryption_test_main.cc +++ b/chrome/browser/os_crypt/app_bound_encryption_test_main.cc
@@ -4,6 +4,7 @@ #include <windows.h> +#include <optional> #include <string> #include "base/at_exit.h" @@ -47,7 +48,10 @@ hr = EncryptAppBoundString(ProtectionLevel::PROTECTION_PATH_VALIDATION, input_data, output_data, last_error); } else if (cmd_line.HasSwitch(switches::kAppBoundTestModeDecrypt)) { - hr = DecryptAppBoundString(input_data, output_data, last_error); + std::optional<std::string> maybe_new_ciphertext; + hr = DecryptAppBoundString(input_data, output_data, + ProtectionLevel::PROTECTION_PATH_VALIDATION, + maybe_new_ciphertext, last_error); if (SUCCEEDED(hr)) { CHECK_EQ(output_data.compare(0, kTestHeader.length(), kTestHeader), 0); output_data.erase(0, kTestHeader.length());
diff --git a/chrome/browser/os_crypt/app_bound_encryption_win.cc b/chrome/browser/os_crypt/app_bound_encryption_win.cc index 923d9bc..868074b 100644 --- a/chrome/browser/os_crypt/app_bound_encryption_win.cc +++ b/chrome/browser/os_crypt/app_bound_encryption_win.cc
@@ -11,8 +11,10 @@ #include <userenv.h> #include <wrl/client.h> +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/win/com_init_util.h" @@ -21,6 +23,7 @@ #include "chrome/common/chrome_paths_internal.h" #include "chrome/common/pref_names.h" #include "chrome/elevation_service/elevation_service_idl.h" +#include "chrome/elevation_service/elevator.h" #include "chrome/install_static/install_util.h" #include "components/prefs/pref_service.h" #include "components/sync/base/pref_names.h" @@ -31,6 +34,12 @@ bool g_non_standard_user_data_dir_supported_for_testing = false; } +namespace features { +BASE_FEATURE(kAppBoundDataReencrypt, + "AppBoundDataReencrypt", + base::FEATURE_DISABLED_BY_DEFAULT); +} // namespace features + SupportLevel GetAppBoundEncryptionSupportLevel(PrefService* local_state) { // Must be a system install. if (!install_static::IsSystemInstall()) { @@ -157,6 +166,8 @@ HRESULT DecryptAppBoundString(const std::string& ciphertext, std::string& plaintext, + ProtectionLevel protection_level, + std::optional<std::string>& new_ciphertext, DWORD& last_error) { DCHECK(!ciphertext.empty()); base::win::AssertComInitialized(); @@ -187,6 +198,27 @@ return hr; } + new_ciphertext = std::nullopt; + + if (base::FeatureList::IsEnabled(features::kAppBoundDataReencrypt) && + hr == elevation_service::Elevator::kSuccessShouldReencrypt) { + DWORD encrypt_last_error; + base::win::ScopedBstr reencrypted_data; + HRESULT encrypt_hr = + elevator->EncryptData(protection_level, plaintext_data.Get(), + reencrypted_data.Receive(), &encrypt_last_error); + base::UmaHistogramSparse("OSCrypt.AppBound.ReEncrypt.ResultCode", + encrypt_hr); + if (SUCCEEDED(encrypt_hr)) { + new_ciphertext.emplace( + reinterpret_cast<std::string::value_type*>(reencrypted_data.Get()), + reencrypted_data.ByteLength()); + } else { + base::UmaHistogramSparse("OSCrypt.AppBound.ReEncrypt.ResultLastError", + encrypt_last_error); + } + } + plaintext.assign( reinterpret_cast<std::string::value_type*>(plaintext_data.Get()), plaintext_data.ByteLength());
diff --git a/chrome/browser/os_crypt/app_bound_encryption_win.h b/chrome/browser/os_crypt/app_bound_encryption_win.h index 5fee6bf..0a75dac6 100644 --- a/chrome/browser/os_crypt/app_bound_encryption_win.h +++ b/chrome/browser/os_crypt/app_bound_encryption_win.h
@@ -5,8 +5,10 @@ #ifndef CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_WIN_H_ #define CHROME_BROWSER_OS_CRYPT_APP_BOUND_ENCRYPTION_WIN_H_ +#include <optional> #include <string> +#include "base/feature_list.h" #include "base/win/windows_types.h" #include "chrome/elevation_service/elevation_service_idl.h" @@ -14,6 +16,12 @@ namespace os_crypt { +namespace features { +// If enabled, App-Bound encryption will attempt re-encryption of decrypted data +// if signaled that it should be re-encrypted. +BASE_DECLARE_FEATURE(kAppBoundDataReencrypt); +} // namespace features + // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class SupportLevel { @@ -64,9 +72,15 @@ // value returned from the most recent failing Windows API call or // ERROR_GEN_FAILURE. // +// App-Bound may recommend re-encryption of the data, for example if the key has +// been rotated. If so, `new_ciphertext` will contain the re-encrypted data +// according to the `protection_level` specified. +// // This should be called on a COM-enabled thread. HRESULT DecryptAppBoundString(const std::string& ciphertext, std::string& plaintext, + ProtectionLevel protection_level, + std::optional<std::string>& new_ciphertext, DWORD& last_error); // Allow non-standard user data dir for testing.
diff --git a/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc b/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc index c601ae26..9382aee 100644 --- a/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc +++ b/chrome/browser/os_crypt/app_bound_encryption_win_browsertest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/os_crypt/app_bound_encryption_win.h" #include <optional> +#include <string> #include "base/command_line.h" #include "base/containers/span.h" @@ -19,12 +20,15 @@ #include "base/path_service.h" #include "base/process/launch.h" #include "base/process/process_info.h" +#include "base/strings/strcat.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/os_crypt/app_bound_encryption_provider_win.h" #include "chrome/browser/os_crypt/test_support.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/profiles/profile.h" @@ -38,7 +42,13 @@ #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/policy_constants.h" +#include "components/prefs/mock_pref_change_callback.h" +#include "components/prefs/pref_store.h" +#include "components/prefs/testing_pref_service.h" #include "content/public/test/browser_test.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::_; namespace os_crypt { @@ -94,16 +104,12 @@ InProcessBrowserTest::SetUp(); } - void TearDown() override { - InProcessBrowserTest::TearDown(); - } - base::HistogramTester histogram_tester_; + std::optional<base::ScopedClosureRunner> maybe_uninstall_service_; + ScopedLogGrabber log_grabber_; private: - ScopedLogGrabber log_grabber_; install_static::ScopedInstallDetails scoped_install_details_; - std::optional<base::ScopedClosureRunner> maybe_uninstall_service_; }; // Test App-Bound is supported for tests. @@ -126,8 +132,11 @@ ASSERT_HRESULT_SUCCEEDED(hr); std::string returned_plaintext; - hr = DecryptAppBoundString(ciphertext, returned_plaintext, last_error); - + std::optional<std::string> maybe_new_ciphertext; + hr = DecryptAppBoundString(ciphertext, returned_plaintext, + ProtectionLevel::PROTECTION_PATH_VALIDATION, + maybe_new_ciphertext, last_error); + EXPECT_FALSE(maybe_new_ciphertext); ASSERT_HRESULT_SUCCEEDED(hr); EXPECT_EQ(plaintext, returned_plaintext); } @@ -138,8 +147,12 @@ std::string ciphertext("invalidciphertext"); std::string returned_plaintext; DWORD last_error = 0; + std::optional<std::string> maybe_new_ciphertext; const HRESULT hr = - DecryptAppBoundString(ciphertext, returned_plaintext, last_error); + DecryptAppBoundString(ciphertext, returned_plaintext, + ProtectionLevel::PROTECTION_PATH_VALIDATION, + maybe_new_ciphertext, last_error); + EXPECT_FALSE(maybe_new_ciphertext); EXPECT_EQ(elevation_service::Elevator::kErrorCouldNotDecryptWithSystemContext, hr); } @@ -349,13 +362,163 @@ ::testing::Values( /*policy::key::kApplicationBoundEncryptionEnabled=*/std::nullopt)); +class AppBoundEncryptionWinReencryptTest + : public AppBoundEncryptionWinTest, + public ::testing::WithParamInterface< + std::tuple</*fake_reencrypt*/ bool, /*enable_feature*/ bool>> { + public: + AppBoundEncryptionWinReencryptTest() { + feature_list_.InitWithFeatureState(features::kAppBoundDataReencrypt, + std::get<1>(GetParam())); + } + + protected: + // Re-encrypt should only happen if both the feature is enabled, and the + // service is faking the re-encryption signal. + static bool ExpectReencrypt() { + return std::get<0>(GetParam()) && std::get<1>(GetParam()); + } + void SetUp() override { + if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY) { + GTEST_SKIP() << "Elevation is required for this test."; + } + maybe_uninstall_service_ = + InstallService(log_grabber_, std::get<0>(GetParam())); + EXPECT_TRUE(maybe_uninstall_service_.has_value()); + // Note do not call SetUp from AppBoundEncryptionWinTest, call to + // InProcessBrowserTest. + InProcessBrowserTest::SetUp(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Test the basic interface to Encrypt and Decrypt data. +IN_PROC_BROWSER_TEST_P(AppBoundEncryptionWinReencryptTest, EncryptDecrypt) { + ASSERT_TRUE(install_static::IsSystemInstall()); + const std::string plaintext("plaintext"); + std::string ciphertext; + DWORD last_error; + base::HistogramTester histograms; + HRESULT hr = + EncryptAppBoundString(ProtectionLevel::PROTECTION_PATH_VALIDATION, + plaintext, ciphertext, last_error); + + ASSERT_HRESULT_SUCCEEDED(hr); + + std::string returned_plaintext; + std::optional<std::string> maybe_new_ciphertext; + hr = DecryptAppBoundString(ciphertext, returned_plaintext, + ProtectionLevel::PROTECTION_PATH_VALIDATION, + maybe_new_ciphertext, last_error); + ASSERT_HRESULT_SUCCEEDED(hr); + EXPECT_EQ(plaintext, returned_plaintext); + + if (ExpectReencrypt()) { + histograms.ExpectUniqueSample("OSCrypt.AppBound.ReEncrypt.ResultCode", S_OK, + 1u); + ASSERT_TRUE(maybe_new_ciphertext); + + std::optional<std::string> even_newer_ciphertext; + // Verify that the new replacement ciphertext returned can still be + // decrypted. + hr = DecryptAppBoundString(*maybe_new_ciphertext, returned_plaintext, + ProtectionLevel::PROTECTION_PATH_VALIDATION, + even_newer_ciphertext, last_error); + ASSERT_HRESULT_SUCCEEDED(hr); + EXPECT_EQ(plaintext, returned_plaintext); + } else { + histograms.ExpectTotalCount("OSCrypt.AppBound.ReEncrypt.ResultCode", 0); + ASSERT_FALSE(maybe_new_ciphertext); + } + histograms.ExpectTotalCount("OSCrypt.AppBound.ReEncrypt.ResultLastError", 0); +} + +// This could be a unit test, but it needs the service installed to work, so +// makes sense for it to be here alongside the other app-bound encryption tests. +IN_PROC_BROWSER_TEST_P(AppBoundEncryptionWinReencryptTest, KeyProviderTest) { + const char* kPrefName = "os_crypt.app_bound_encrypted_key"; + ASSERT_TRUE(install_static::IsSystemInstall()); + + TestingPrefServiceSimple prefs; + MockPrefChangeCallback observer(&prefs); + PrefChangeRegistrar registrar; + registrar.Init(&prefs); + registrar.Add(kPrefName, observer.GetCallback()); + // The first time the GetKey is called, the provider should generate a random + // key, encrypt it with app-bound, then persist the encrypted key to store. + EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(1); + + os_crypt_async::AppBoundEncryptionProviderWin::RegisterLocalPrefs( + prefs.registry()); + + // `Key` has no public constructor and is move-only so use a std::optional as + // a handy container. + std::optional<os_crypt_async::Encryptor::Key> encryption_key; + std::string encrypted_key; + { + os_crypt_async::AppBoundEncryptionProviderWin provider( + &prefs, /*use_for_encryption=*/true); + base::test::TestFuture<const std::string&, + std::optional<os_crypt_async::Encryptor::Key>> + future; + provider.GetKey(future.GetCallback()); + auto [tag, key] = future.Take(); + EXPECT_EQ(tag, "v20"); + ASSERT_TRUE(key); + encryption_key.emplace(std::move(*key)); + encrypted_key = prefs.GetString(kPrefName); + EXPECT_FALSE(encrypted_key.empty()); + } + ::testing::Mock::VerifyAndClearExpectations(&observer); + + // The second time the GetKey is called, the provider should retrieve the key + // from store then perform a decryption via app-bound. If re-encryption is + // specified then a re-encryption call is made and a second write should + // happen to the store with the new encrypted key. + EXPECT_CALL(observer, OnPreferenceChanged(_)) + .Times(ExpectReencrypt() ? 1 : 0); + { + os_crypt_async::AppBoundEncryptionProviderWin provider( + &prefs, /*use_for_encryption=*/true); + base::test::TestFuture<const std::string&, + std::optional<os_crypt_async::Encryptor::Key>> + future; + provider.GetKey(future.GetCallback()); + const auto& [_, key] = future.Get(); + ASSERT_TRUE(key); + // The key returned should be the same as it's been decrypted from the + // store, regardless of whether it's been re-encrypted or not. + EXPECT_EQ(*key, *encryption_key); + + if (ExpectReencrypt()) { + // Re-encryption should always change the encrypted value, because the + // underlying encryption schemes use random IVs, nonces or salts. + EXPECT_NE(prefs.GetString(kPrefName), encrypted_key); + } else { + EXPECT_EQ(prefs.GetString(kPrefName), encrypted_key); + } + } +} + +INSTANTIATE_TEST_SUITE_P( + , + AppBoundEncryptionWinReencryptTest, + ::testing::Combine(::testing::Bool(), ::testing::Bool()), + [](const auto& info) { + return base::StrCat( + {std::get<0>(info.param) ? "FakeReencrypt" : "NoFakeReencrypt", + std::get<1>(info.param) ? "FeatureOn" : "FeatureOff"}); + }); + class AppBoundEncryptionWinTestFeatureMaybeDisabled : public AppBoundEncryptionWinTest, public ::testing::WithParamInterface</*feature enabled*/ bool> { public: AppBoundEncryptionWinTestFeatureMaybeDisabled() { feature_list_.InitWithFeatureState( - features::kUseAppBoundEncryptionProviderForEncryption, GetParam()); + ::features::kUseAppBoundEncryptionProviderForEncryption, GetParam()); } private:
diff --git a/chrome/browser/os_crypt/test_support.cc b/chrome/browser/os_crypt/test_support.cc index 8bd59edc..c8252350 100644 --- a/chrome/browser/os_crypt/test_support.cc +++ b/chrome/browser/os_crypt/test_support.cc
@@ -77,7 +77,8 @@ } std::optional<base::ScopedClosureRunner> InstallService( - const ScopedLogGrabber& log_grabber) { + const ScopedLogGrabber& log_grabber, + bool fake_reencrypt) { base::FilePath exe_dir; base::PathService::Get(base::DIR_EXE, &exe_dir); base::CommandLine service_cmd( @@ -85,6 +86,10 @@ service_cmd.AppendSwitch( elevation_service::switches::kElevatorClsIdForTestingSwitch); log_grabber.AddLoggingSwitches(service_cmd); + if (fake_reencrypt) { + service_cmd.AppendSwitch( + elevation_service::switches::kFakeReencryptForTestingSwitch); + } installer::InstallServiceWorkItem install_service_work_item( install_static::GetElevationServiceName(), install_static::GetElevationServiceDisplayName(), /*description=*/{},
diff --git a/chrome/browser/os_crypt/test_support.h b/chrome/browser/os_crypt/test_support.h index aca935d..66be728 100644 --- a/chrome/browser/os_crypt/test_support.h +++ b/chrome/browser/os_crypt/test_support.h
@@ -41,9 +41,12 @@ // Install the elevation service corresponding to the set of install details for // the current process, returns a closure that will uninstall the service when // it goes out of scope. Logs from the service will be spooled to the passed -// `log_grabber` which should outlive the lifetime of the service. +// `log_grabber` which should outlive the lifetime of the service. If +// `fake_reencrypt` is true then the elevation service will signal that returned +// data should be re-encrypted by the client if a DecryptData call is made. [[nodiscard]] std::optional<base::ScopedClosureRunner> InstallService( - const ScopedLogGrabber& log_grabber); + const ScopedLogGrabber& log_grabber, + bool fake_reencrypt = false); } // namespace os_crypt
diff --git a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc index aa4ed58..3174a56 100644 --- a/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/third_party_metrics_observer_browsertest.cc
@@ -134,7 +134,6 @@ // TODO(ericrobinson) The following functions all have an assumed frame. // Prefer passing in a frame to make the tests clearer and extendable. - void NavigateFrameAndWaitForFCP( const std::string& host, const std::string& path, @@ -142,10 +141,18 @@ GURL page = https_server()->GetURL(host, path); NavigateFrameAndWaitForFCP(page, waiter); } - void NavigateFrameAndWaitForFCP( const GURL& url, page_load_metrics::PageLoadMetricsTestWaiter* waiter) { + NavigateFrameAndWaitFor(url, waiter, + page_load_metrics::PageLoadMetricsTestWaiter:: + TimingField::kFirstContentfulPaint); + } + + void NavigateFrameAndWaitFor( + const GURL& url, + page_load_metrics::PageLoadMetricsTestWaiter* waiter, + page_load_metrics::PageLoadMetricsTestWaiter::TimingField field) { // Waiting for the frame to navigate ensures that any previous RFHs for this // frame have been deleted and therefore won't pollute any future frame // expectations (such as FCP). @@ -153,9 +160,7 @@ NavigateFrameToUrl(url); waiter->Wait(); - waiter->AddSubFrameExpectation( - page_load_metrics::PageLoadMetricsTestWaiter::TimingField:: - kFirstContentfulPaint); + waiter->AddSubFrameExpectation(field); waiter->Wait(); } @@ -247,14 +252,8 @@ histogram_tester.ExpectTotalCount(kSubframeFCPHistogram, 3); } -// TODO(crbug.com/334416161): Re-enble this test. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) -#define MAYBE_OpaqueOriginSubframe DISABLED_OpaqueOriginSubframe -#else -#define MAYBE_OpaqueOriginSubframe OpaqueOriginSubframe -#endif IN_PROC_BROWSER_TEST_F(ThirdPartyMetricsObserverBrowserTest, - MAYBE_OpaqueOriginSubframe) { + OpaqueOriginSubframe) { base::HistogramTester histogram_tester; page_load_metrics::PageLoadMetricsTestWaiter waiter( @@ -265,7 +264,9 @@ NavigateFrameAndWaitForFCP("b.com", "/select.html", &waiter); // Navigate the frame to an opaque origin URL. - NavigateFrameAndWaitForFCP(GURL("data:,hello"), &waiter); + NavigateFrameAndWaitFor(GURL("data:,hello"), &waiter, + page_load_metrics::PageLoadMetricsTestWaiter:: + TimingField::kLargestContentfulPaint); content::RenderFrameHost* subframe_rfh = ChildFrameAt(web_contents()->GetPrimaryMainFrame(), /*index=*/0);
diff --git a/chrome/browser/performance_manager/frame_node_impl_browsertest.cc b/chrome/browser/performance_manager/frame_node_impl_browsertest.cc index 1b47f632..5138f0f 100644 --- a/chrome/browser/performance_manager/frame_node_impl_browsertest.cc +++ b/chrome/browser/performance_manager/frame_node_impl_browsertest.cc
@@ -16,6 +16,7 @@ #include "components/performance_manager/performance_manager_impl.h" #include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/test_support/graph/mock_frame_node_observer.h" #include "components/performance_manager/test_support/run_in_graph.h" #include "content/public/test/back_forward_cache_util.h" #include "content/public/test/browser_test.h" @@ -262,20 +263,6 @@ run_loop.Run(); } -// For the following tests, listen to OnHadFormInteractionChanged() to ensure -// that the DocumentCoordinationUnit interface is correctly bound. -class MockFrameNodeObserver : public FrameNode::ObserverDefaultImpl { - public: - MockFrameNodeObserver() = default; - ~MockFrameNodeObserver() override = default; - - // FrameNodeObserver: - MOCK_METHOD(void, - OnHadFormInteractionChanged, - (const FrameNode* frame_node), - (override)); -}; - // TODO(https://crbug.com/376315752): Deflake and re-enable. IN_PROC_BROWSER_TEST_F(FrameNodeImplBrowserTest, DISABLED_Bind_SimpleNavigation) { @@ -351,7 +338,7 @@ // Check that a form interaction notification is received through the bound // receiver. - MockFrameNodeObserver obs; + LenientMockFrameNodeObserver obs; RunInGraph([&](Graph* graph) { graph->AddFrameNodeObserver(&obs); }); base::RunLoop run_loop;
diff --git a/chrome/browser/prefs/pref_service_incognito_allowlist.cc b/chrome/browser/prefs/pref_service_incognito_allowlist.cc index 8da23e3f..53cc913c 100644 --- a/chrome/browser/prefs/pref_service_incognito_allowlist.cc +++ b/chrome/browser/prefs/pref_service_incognito_allowlist.cc
@@ -90,6 +90,10 @@ ash::prefs::kAccessibilityFaceGazeVelocityThreshold, ash::prefs::kAccessibilityFaceGazePrecisionClick, ash::prefs::kAccessibilityFaceGazePrecisionClickSpeedFactor, + ash::prefs::kAccessibilityFaceGazeEnabledSentinel, + ash::prefs::kAccessibilityFaceGazeEnabledSentinelShowDialog, + ash::prefs::kAccessibilityFaceGazeCursorControlEnabledSentinel, + ash::prefs::kAccessibilityFaceGazeActionsEnabledSentinel, ash::prefs::kAccessibilityFlashNotificationsEnabled, ash::prefs::kAccessibilityFlashNotificationsColor, ash::prefs::kAccessibilityHighContrastEnabled,
diff --git a/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc index bbe1681..d8ef039 100644 --- a/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc +++ b/chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.cc
@@ -6,15 +6,12 @@ #include "build/build_config.h" #include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h" +#include "chrome/browser/task_manager/web_contents_tags.h" #include "chrome/browser/ui/tab_helpers.h" #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h" #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h" #include "content/public/browser/web_contents.h" -#if !BUILDFLAG(IS_ANDROID) -#include "chrome/browser/task_manager/web_contents_tags.h" -#endif - namespace prerender { // static @@ -35,22 +32,18 @@ DCHECK(web_contents); TabHelpers::AttachTabHelpers(web_contents); -#if !BUILDFLAG(IS_ANDROID) // Tag the NoStatePrefetch contents with the task manager specific prerender // tag, so that it shows up in the task manager. task_manager::WebContentsTags::CreateForNoStatePrefetchContents(web_contents); -#endif } void ChromeNoStatePrefetchContentsDelegate::ReleaseNoStatePrefetchContents( content::WebContents* web_contents) { DCHECK(web_contents); -#if !BUILDFLAG(IS_ANDROID) // Clear the task manager tag we added earlier to our // WebContents since it's no longer a NoStatePrefetch contents. task_manager::WebContentsTags::ClearTag(web_contents); -#endif } } // namespace prerender
diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn index 629914ebe..ee46b0c 100644 --- a/chrome/browser/profiles/BUILD.gn +++ b/chrome/browser/profiles/BUILD.gn
@@ -320,7 +320,6 @@ "//chrome/browser/apps/almanac_api_client", "//chrome/browser/apps/app_preload_service", "//chrome/browser/ash/app_list", - "//chrome/browser/ash/crosapi:browser_util", "//chrome/browser/ash/file_manager", "//chrome/browser/ash/floating_sso", "//chrome/browser/ash/input_method",
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 0cf338f..14f63dc 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -201,7 +201,6 @@ #include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/ash/app_mode/app_launch_utils.h" #include "chrome/browser/ash/arc/session/arc_service_launcher.h" -#include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/ash/locale/locale_change_guard.h" #include "chrome/browser/ash/login/session/user_session_manager.h" #include "chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.h" @@ -663,7 +662,6 @@ ash::ProfileHelper::IsPrimaryProfile(this)) { auto& map = profile_policy_connector_->policy_service()->GetPolicies( policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())); - crosapi::browser_util::CacheLacrosAvailability(map); ash::standalone_browser::CacheLacrosSelection(map); } #endif @@ -1207,7 +1205,6 @@ auto& map = profile_policy_connector_->policy_service()->GetPolicies( policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())); - crosapi::browser_util::CacheLacrosAvailability(map); ash::standalone_browser::CacheLacrosSelection(map); }
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index c50f272..c881c34 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -294,9 +294,9 @@ ] } else { public_deps += [ - "internals:resources", "media_router/internals:resources", "on_device_internals:resources", + "user_education_internals:resources", "webui_js_error:resources", ] } @@ -357,9 +357,9 @@ ] } else { sources += [ - "$root_gen_dir/chrome/internals_resources.pak", "$root_gen_dir/chrome/media_router_internals_resources.pak", "$root_gen_dir/chrome/on_device_internals_resources.pak", + "$root_gen_dir/chrome/user_education_internals_resources.pak", "$root_gen_dir/chrome/webui_js_error_resources.pak", ] }
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_card.html b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_card.html index 39216ae..ef26dff 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_card.html +++ b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_card.html
@@ -44,7 +44,7 @@ <settings-toggle-button id="faceGazeActionsEnabledButton" label="$i18n{faceGazeActionsEnabledLabel}" - pref="{{prefs.settings.a11y.face_gaze.actions_enabled}}" + pref="{{prefs.settings.a11y.face_gaze.actions_enabled_sentinel}}" disabled="[[disabled]]"> </settings-toggle-button> <dom-repeat id="faceGazeActionsCommandPairs"
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_cursor_card.html b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_cursor_card.html index 2a82651..142fcfb 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_cursor_card.html +++ b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_cursor_card.html
@@ -35,7 +35,7 @@ <settings-toggle-button id="faceGazeCursorControlEnabledButton" label="$i18n{faceGazeCursorControlEnabledLabel}" - pref="{{prefs.settings.a11y.face_gaze.cursor_control_enabled}}"> + pref="{{prefs.settings.a11y.face_gaze.cursor_control_enabled_sentinel}}"> </settings-toggle-button> <div class="settings-box short"> $i18n{faceGazeCursorSpeedSectionName}
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.html b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.html index 5d6e96a..4cc8355 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.html +++ b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.html
@@ -19,7 +19,7 @@ <settings-toggle-button id="faceGazeToggle" label="[[toggleLabel_]]" - pref="{{prefs.settings.a11y.face_gaze.enabled}}" + pref="{{prefs.settings.a11y.face_gaze.enabled_sentinel}}" deep-link-focus-id$="[[Setting.kFaceGaze]]"> </settings-toggle-button> </settings-card>
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.ts b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.ts index 0044286..fb8c7ef 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_subpage.ts
@@ -46,7 +46,7 @@ toggleLabel_: { type: String, computed: - 'getToggleLabel_(prefs.settings.a11y.face_gaze.enabled.value)', + 'getToggleLabel_(prefs.settings.a11y.face_gaze.enabled_sentinel.value)', }, supportedSettingIds: { @@ -59,7 +59,7 @@ } private getToggleLabel_(): string { - return this.getPref('settings.a11y.face_gaze.enabled').value ? + return this.getPref('settings.a11y.face_gaze.enabled_sentinel').value ? this.i18n('deviceOn') : this.i18n('deviceOff'); }
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.html b/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.html index be5382b..abb7b5e 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.html +++ b/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.html
@@ -1,24 +1,13 @@ <style include="settings-shared"></style> -<settings-card header-text="[[getHeaderText_()]]"> +<settings-card header-text="$i18n{languagesPageTitle}"> <cr-link-row id="languagesRow" - start-icon="[[rowIcons_.languages]]" + start-icon="os-settings:language" label="$i18n{languagesPageTitle}" sub-label="[[getLanguageDisplayName_( languages.prospectiveUILanguage, languageHelper)]]" on-click="onLanguagesV2Click_" role-description="$i18n{subpageArrowRoleDescription}"> </cr-link-row> - <template is="dom-if" if="[[!isRevampWayfindingEnabled_]]"> - <cr-link-row - id="inputRow" - class="hr" - label="$i18n{inputPageTitle}" - sub-label="[[getInputMethodDisplayName_( - languages.inputMethods.currentId, languageHelper)]]" - on-click="onInputClick_" - role-description="$i18n{subpageArrowRoleDescription}"> - </cr-link-row> - </template> </settings-card>
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.ts b/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.ts index bd5d5a2..eace859 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.ts +++ b/chrome/browser/resources/ash/settings/os_languages_page/language_settings_card.ts
@@ -14,13 +14,11 @@ import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {isRevampWayfindingEnabled} from '../common/load_time_booleans.js'; import {RouteOriginMixin} from '../common/route_origin_mixin.js'; import type {PrefsState} from '../common/types.js'; import {Router, routes} from '../router.js'; import {getTemplate} from './language_settings_card.html.js'; -import {ACCESSIBILITY_COMMON_IME_ID} from './languages.js'; import type {LanguageHelper, LanguagesModel} from './languages_types.js'; const LanguageSettingsCardElementBase = @@ -46,22 +44,6 @@ languages: Object, languageHelper: Object, - - isRevampWayfindingEnabled_: Boolean, - - rowIcons_: { - type: Object, - value() { - if (isRevampWayfindingEnabled()) { - return { - languages: 'os-settings:language-revamp', - }; - } - return { - languages: '', - }; - }, - }, }; } @@ -73,38 +55,20 @@ languages: LanguagesModel|undefined; languageHelper: LanguageHelper|undefined; - // Internal state. - private isRevampWayfindingEnabled_ = isRevampWayfindingEnabled(); - private rowIcons_: Record<string, string>; - // Internal properties for mixins. - // From RouteOriginMixin. This needs to be defined after - // `isRevampWayfindingEnabled_`. - override route = this.isRevampWayfindingEnabled_ ? routes.SYSTEM_PREFERENCES : - routes.OS_LANGUAGES; + // From RouteOriginMixin. + override route = routes.SYSTEM_PREFERENCES; override ready(): void { super.ready(); this.addFocusConfig(routes.OS_LANGUAGES_LANGUAGES, '#languagesRow'); - this.addFocusConfig(routes.OS_LANGUAGES_INPUT, '#inputRow'); - } - - private getHeaderText_(): string { - if (this.isRevampWayfindingEnabled_) { - return this.i18n('languagesPageTitle'); - } - return this.i18n('osLanguagesPageTitle'); } private onLanguagesV2Click_(): void { Router.getInstance().navigateTo(routes.OS_LANGUAGES_LANGUAGES); } - private onInputClick_(): void { - Router.getInstance().navigateTo(routes.OS_LANGUAGES_INPUT); - } - /** * @param code The language code of the language. * @return The display name of the language specified. @@ -119,20 +83,6 @@ } return language.displayName; } - - /** - * @param id The input method ID. - * @return The display name of the input method. - */ - private getInputMethodDisplayName_(id: string|undefined): string { - if (!id || !this.languageHelper) { - return ''; - } - if (id === ACCESSIBILITY_COMMON_IME_ID) { - return ''; - } - return this.languageHelper.getInputMethodDisplayName(id); - } } customElements.define(
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html index fd1f2e8..9138bb9 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html +++ b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html
@@ -24,6 +24,11 @@ iron-icon="cr:delete" on-click="deleteDictionary_" title="DeleteDictionary"></cr-icon-button> + <cr-button on-click="importDictionary_"> + <span> + Import + </span> + </cr-button> <cr-button on-click="exportDictionary_"> <!-- TODO(crbug.com/382344109): Translate UI strings --> <span> @@ -31,6 +36,9 @@ </span> </cr-button> </div> + <!-- hidden element used by importDictionary_ to trigger file upload. --> + <input id="selectFileDialog" + type="file" on-change="handleFileSelectChange_" hidden> </div> <template is="dom-repeat" items="[[dict.entries]]" as="entry"> <os-japanese-dictionary-entry-row
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts index 0f7455b..0e92dfd4 100644 --- a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts +++ b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts
@@ -10,6 +10,8 @@ import 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js'; import type {CrInputElement} from 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js'; +import type {BigBuffer} from 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-webui.js'; +import type {BigString} from 'chrome://resources/mojo/mojo/public/mojom/base/big_string.mojom-webui.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import type {JapaneseDictionary} from '../mojom-webui/user_data_japanese_dictionary.mojom-webui.js'; @@ -18,6 +20,12 @@ import {getTemplate} from './os_japanese_dictionary_expand.html.js'; import {UserDataServiceProvider} from './user_data_service_provider.js'; +interface OsJapaneseDictionaryExpandElement { + $: { + selectFileDialog: HTMLElement, + }; +} + class OsJapaneseDictionaryExpandElement extends PolymerElement { static get is() { return 'os-japanese-dictionary-expand' as const; @@ -91,6 +99,37 @@ a.click(); } + // Imports dictionary. + private importDictionary_(): void { + this.$.selectFileDialog.dispatchEvent(new MouseEvent('click')); + } + + private async handleFileSelectChange_(e: Event): Promise<void> { + const fileInput = e.target as HTMLInputElement; + const fileData = fileInput.files![0]; + // Use bytes for now rather than shared memory for simplicity. + // TODO(b/366101658): Use shared memory when file is too big. + // The limit below is the max size that a mojo BigBuffer can handle via + // directly using the bytes rather than shared memory. + if (fileData.size >= 128 * 1048576) { + return; + } + const fileDataView = new Uint8Array(await fileData.arrayBuffer()); + const fileMojomBigBuffer: BigBuffer = { + bytes: Array.from(fileDataView), + sharedMemory: undefined, + invalidBuffer: undefined, + }; + const fileMojomBigString: BigString = {data: fileMojomBigBuffer}; + + const {status} = + await UserDataServiceProvider.getRemote().importJapaneseDictionary( + this.dict.id, fileMojomBigString); + if (status.success) { + this.dispatchSavedEvent_(); + } + } + // Returns true if this entry is a locally added entry. private locallyAdded_(entryIndex: number): boolean { // This entry falls outside of the range of entries that were initially
diff --git a/chrome/browser/resources/ash/settings/os_settings_icons.html b/chrome/browser/resources/ash/settings/os_settings_icons.html index 6a04b78..fed2ef9 100644 --- a/chrome/browser/resources/ash/settings/os_settings_icons.html +++ b/chrome/browser/resources/ash/settings/os_settings_icons.html
@@ -271,8 +271,7 @@ </g> <!-- Languages section --> - <g id="language" viewBox="0 0 24 24"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"></path></g> - <g id="language-revamp" viewBox="0 0 20 20"><path fill-rule="evenodd" d="m10.167 18.146 3.625-9.667h1.75l3.625 9.667H17.5l-.875-2.48h-3.896l-.896 2.48h-1.666Zm3.062-3.875h2.896l-1.417-4.021h-.083l-1.396 4.02Zm-9.833 1.333-1.063-1.083 4.084-4.042a18.19 18.19 0 0 1-1.438-1.666 11.185 11.185 0 0 1-1.125-1.896h1.73c.263.458.555.889.874 1.291.334.39.667.771 1 1.146A18.405 18.405 0 0 0 8.938 7.5a8.8 8.8 0 0 0 1.104-2.083H.833V3.875h5.854v-2.02H8.23v2.02h5.854v1.542h-2.416a10.189 10.189 0 0 1-1.313 2.708A18.938 18.938 0 0 1 8.5 10.479l1.938 1.917-.605 1.583-2.375-2.396-4.062 4.021Z"/></g> + <g id="language" viewBox="0 0 20 20"><path fill-rule="evenodd" d="m10.167 18.146 3.625-9.667h1.75l3.625 9.667H17.5l-.875-2.48h-3.896l-.896 2.48h-1.666Zm3.062-3.875h2.896l-1.417-4.021h-.083l-1.396 4.02Zm-9.833 1.333-1.063-1.083 4.084-4.042a18.19 18.19 0 0 1-1.438-1.666 11.185 11.185 0 0 1-1.125-1.896h1.73c.263.458.555.889.874 1.291.334.39.667.771 1 1.146A18.405 18.405 0 0 0 8.938 7.5a8.8 8.8 0 0 0 1.104-2.083H.833V3.875h5.854v-2.02H8.23v2.02h5.854v1.542h-2.416a10.189 10.189 0 0 1-1.313 2.708A18.938 18.938 0 0 1 8.5 10.479l1.938 1.917-.605 1.583-2.375-2.396-4.062 4.021Z"/></g> <!-- Offline --> <g id="offline"><path d="M11.91 6.244a.833.833 0 111.18 1.179l-3.334 3.333a.833.833 0 01-1.179 0L6.911 9.089a.833.833 0 011.178-1.178l1.078 1.077 2.744-2.744zM6.75 12a.75.75 0 000 1.5h6.5a.75.75 0 000-1.5h-6.5z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-2 0a6 6 0 11-12 0 6 6 0 0112 0z"></path></g>
diff --git a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts index e0222ad7..1389507 100644 --- a/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts +++ b/chrome/browser/resources/ash/settings/os_settings_menu/os_settings_menu.ts
@@ -419,7 +419,7 @@ { section: Section.kPersonalization, path: `/${routesMojom.PERSONALIZATION_SECTION_PATH}`, - icon: 'os-settings:personalization', + icon: 'os-settings:personalization-menu', label: this.i18n('personalizationPageTitle'), sublabel: this.i18n('personalizationMenuItemDescription'), },
diff --git a/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts b/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts index 4a8214d..b63b1c2 100644 --- a/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts +++ b/chrome/browser/resources/ash/settings/os_settings_search_box/os_search_result_row.ts
@@ -756,7 +756,7 @@ case SearchResultIcon.kKeyboard: return 'os-settings:device-keyboard'; case SearchResultIcon.kLanguage: - return 'os-settings:language-revamp'; + return 'os-settings:language'; case SearchResultIcon.kLaptop: return 'os-settings:laptop-chromebook'; case SearchResultIcon.kLock:
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/constants.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/constants.ts index 27c535d7..a2e5e72 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/constants.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/constants.ts
@@ -11,9 +11,15 @@ ACCELERATOR_DIALOG_HAS_BEEN_ACCEPTED = 'settings.a11y.face_gaze.accelerator_dialog_has_been_accepted', ACTIONS_ENABLED = 'settings.a11y.face_gaze.actions_enabled', + ACTIONS_ENABLED_SENTINEL = 'settings.a11y.face_gaze.actions_enabled_sentinel', CURSOR_CONTROL_ENABLED = 'settings.a11y.face_gaze.cursor_control_enabled', + CURSOR_CONTROL_ENABLED_SENTINEL = + 'settings.a11y.face_gaze.cursor_control_enabled_sentinel', CURSOR_USE_ACCELERATION = 'settings.a11y.face_gaze.cursor_use_acceleration', FACE_GAZE_ENABLED = 'settings.a11y.face_gaze.enabled', + FACE_GAZE_ENABLED_SENTINEL = 'settings.a11y.face_gaze.enabled_sentinel', + FACE_GAZE_ENABLED_SENTINEL_SHOW_DIALOG = + 'settings.a11y.face_gaze.enabled_sentinel_show_dialog', GESTURE_TO_CONFIDENCE = 'settings.a11y.face_gaze.gestures_to_confidence', GESTURE_TO_KEY_COMBO = 'settings.a11y.face_gaze.gestures_to_key_combos', GESTURE_TO_MACRO = 'settings.a11y.face_gaze.gestures_to_macros',
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze.ts index f8219bb..58d031f 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/facegaze.ts
@@ -115,8 +115,13 @@ chrome.settingsPrivate.setPref( PrefNames.ACCELERATOR_DIALOG_HAS_BEEN_ACCEPTED, accepted); if (!accepted) { - // If the dialog was rejected, then disable the FaceGaze feature. - chrome.settingsPrivate.setPref(PrefNames.FACE_GAZE_ENABLED, false); + // If the dialog was rejected, then disable the FaceGaze feature and do + // not show the confirmation dialog for disabling. + chrome.settingsPrivate.setPref( + PrefNames.FACE_GAZE_ENABLED_SENTINEL_SHOW_DIALOG, false, undefined, + () => chrome.settingsPrivate.setPref( + PrefNames.FACE_GAZE_ENABLED_SENTINEL, false)); + return; }
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/web_cam_face_landmarker.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/web_cam_face_landmarker.ts index 1ddac6d3..ff5cb5b 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/web_cam_face_landmarker.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/facegaze/web_cam_face_landmarker.ts
@@ -88,7 +88,10 @@ `Couldn't create FaceLandmarker because FaceGaze assets couldn't be installed.`); - chrome.settingsPrivate.setPref(PrefNames.FACE_GAZE_ENABLED, false); + chrome.settingsPrivate.setPref( + PrefNames.FACE_GAZE_ENABLED_SENTINEL_SHOW_DIALOG, false, undefined, + () => chrome.settingsPrivate.setPref( + PrefNames.FACE_GAZE_ENABLED_SENTINEL, false)); return; }
diff --git a/chrome/browser/resources/chromeos/cryptohome.html b/chrome/browser/resources/chromeos/cryptohome.html index cecffd1..7e86d90 100644 --- a/chrome/browser/resources/chromeos/cryptohome.html +++ b/chrome/browser/resources/chromeos/cryptohome.html
@@ -48,6 +48,10 @@ <h3>Cryptohome recovery:</h3> <table width=200> <tr> + <td>Seed</td> + <td id="recovery_seed"></td> + </tr> + <tr> <td>Latest RecoveryIds</td> <td id="recovery_ids"></td> </tr>
diff --git a/chrome/browser/resources/chromeos/healthd_internals/BUILD.gn b/chrome/browser/resources/chromeos/healthd_internals/BUILD.gn index 84f80e98..6f8ed6b 100644 --- a/chrome/browser/resources/chromeos/healthd_internals/BUILD.gn +++ b/chrome/browser/resources/chromeos/healthd_internals/BUILD.gn
@@ -28,7 +28,9 @@ "view/pages/process.ts", "view/pages/system_trend.ts", "view/pages/telemetry.ts", + "view/settings/chart_category_dialog.ts", "view/settings/config_slider.ts", + "view/settings/data_series_checkbox.ts", "view/settings/settings_dialog.ts", ]
diff --git a/chrome/browser/resources/chromeos/healthd_internals/controller/system_trend_controller.ts b/chrome/browser/resources/chromeos/healthd_internals/controller/system_trend_controller.ts index 14ee823..77111c0 100644 --- a/chrome/browser/resources/chromeos/healthd_internals/controller/system_trend_controller.ts +++ b/chrome/browser/resources/chromeos/healthd_internals/controller/system_trend_controller.ts
@@ -129,6 +129,32 @@ this.element.refreshData(CategoryTypeEnum.ZRAM); } + setSelectedIndices(type: CategoryTypeEnum, selectedIndices: number[]) { + switch (type) { + case CategoryTypeEnum.BATTERY: + this.dataCollection.battery.selectedIndices = selectedIndices; + break; + case CategoryTypeEnum.CPU_FREQUENCY: + this.dataCollection.cpuFrequency.selectedIndices = selectedIndices; + break; + case CategoryTypeEnum.CPU_USAGE: + this.dataCollection.cpuUsage.selectedIndices = selectedIndices; + break; + case CategoryTypeEnum.MEMORY: + this.dataCollection.memory.selectedIndices = selectedIndices; + break; + case CategoryTypeEnum.THERMAL: + this.dataCollection.thermal.selectedIndices = selectedIndices; + break; + case CategoryTypeEnum.ZRAM: + this.dataCollection.zram.selectedIndices = selectedIndices; + break; + case CategoryTypeEnum.CUSTOM: + console.error('SystemTrendController: Got unexpected type.'); + break; + } + } + /** * Get the required data for line chart. *
diff --git a/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.html b/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.html index 9fd1eab..19b422a 100644 --- a/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.html +++ b/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.html
@@ -35,6 +35,10 @@ width: 100%; } </style> + +<healthd-internals-chart-category-dialog id="categoryDialog"> +</healthd-internals-chart-category-dialog> + <div class="full-page"> <div id="pageHeader"> <h1>System Trend</h1> @@ -66,6 +70,9 @@ <b>Time Span: </b> [[displayedStartTime]] ~ [[displayedEndTime]] </label> + <template is="dom-if" if="[[isCustomCategory(selectedCategory)]]"> + <cr-button on-click="openChartCategoryDialog">Choose category</cr-button> + </template> </div> <healthd-internals-line-chart id="lineChart"> </healthd-internals-line-chart>
diff --git a/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.ts b/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.ts index f0b7fa04..b809999 100644 --- a/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.ts +++ b/chrome/browser/resources/chromeos/healthd_internals/view/pages/system_trend.ts
@@ -5,13 +5,16 @@ import '//resources/ash/common/cr_elements/cr_button/cr_button.js'; import '//resources/ash/common/cr_elements/md_select.css.js'; import '../line_chart/line_chart.js'; +import '../settings/chart_category_dialog.js'; +import {assert} from '//resources/js/assert.js'; import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CategoryTypeEnum, SystemTrendController} from '../../controller/system_trend_controller.js'; import {HealthdInternalsPage} from '../../utils/page_interface.js'; import {UiUpdateHelper} from '../../utils/ui_update_helper.js'; import type {HealthdInternalsLineChartElement} from '../line_chart/line_chart.js'; +import {HealthdInternalsChartCategoryDialogElement} from '../settings/chart_category_dialog.js'; import {getTemplate} from './system_trend.html.js'; @@ -35,6 +38,7 @@ $: { categorySelector: HTMLSelectElement, lineChart: HealthdInternalsLineChartElement, + categoryDialog: HealthdInternalsChartCategoryDialogElement, }; } @@ -73,6 +77,11 @@ this.$.lineChart.addEventListener('time-range-changed', () => { this.updateDisplayedTimeInfo(); }); + + this.$.categoryDialog.addEventListener('custom-data-updated', () => { + assert(this.isCustomCategory(this.selectedCategory)); + this.refreshData(this.selectedCategory); + }); } // Controller for this UI element. @@ -95,6 +104,7 @@ CategoryTypeEnum.CUSTOM, ]; + // The current selected category. private selectedCategory: CategoryTypeEnum = this.displayedCategories[0]; // The start and end time in the visible part of line chart. @@ -153,6 +163,21 @@ this.selectedCategory = this.$.categorySelector.value as CategoryTypeEnum; this.refreshData(this.selectedCategory); } + + /** + * Open the dialog to change displayed line for custom category. + */ + private openChartCategoryDialog() { + assert(this.isCustomCategory(this.selectedCategory)); + this.$.categoryDialog.openDialog(this.getController()); + } + + /** + * Returns whether the selected category is custom. + */ + private isCustomCategory(category: CategoryTypeEnum): boolean { + return category === CategoryTypeEnum.CUSTOM; + } } declare global {
diff --git a/chrome/browser/resources/chromeos/healthd_internals/view/settings/chart_category_dialog.html b/chrome/browser/resources/chromeos/healthd_internals/view/settings/chart_category_dialog.html new file mode 100644 index 0000000..712aa0e --- /dev/null +++ b/chrome/browser/resources/chromeos/healthd_internals/view/settings/chart_category_dialog.html
@@ -0,0 +1,26 @@ +<style include="healthd-internals-shared"></style> +<cr-dialog id="dialog"> + <div slot="title">Select displayed categories</div> + <div slot="body"> + <healthd-internals-data-series-checkbox id="cpuUsageCheckbox"> + </healthd-internals-data-series-checkbox> + <healthd-internals-data-series-checkbox id="cpuFrequencyCheckbox"> + </healthd-internals-data-series-checkbox> + <healthd-internals-data-series-checkbox id="memoryCheckbox"> + </healthd-internals-data-series-checkbox> + <healthd-internals-data-series-checkbox id="zramCheckbox"> + </healthd-internals-data-series-checkbox> + <healthd-internals-data-series-checkbox id="batteryCheckbox"> + </healthd-internals-data-series-checkbox> + <healthd-internals-data-series-checkbox id="thermalCheckbox"> + </healthd-internals-data-series-checkbox> + </div> + <div slot="button-container"> + <cr-button class="cancel-button" on-click="onCancelButtonClicked"> + Cancel + </cr-button> + <cr-button class="action-button" on-click="onConfirmButtonClicked"> + Confirm + </cr-button> + </div> +</cr-dialog>
diff --git a/chrome/browser/resources/chromeos/healthd_internals/view/settings/chart_category_dialog.ts b/chrome/browser/resources/chromeos/healthd_internals/view/settings/chart_category_dialog.ts new file mode 100644 index 0000000..7f3c3a3 --- /dev/null +++ b/chrome/browser/resources/chromeos/healthd_internals/view/settings/chart_category_dialog.ts
@@ -0,0 +1,96 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '//resources/ash/common/cr_elements/cr_button/cr_button.js'; +import '//resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; +import './data_series_checkbox.js' + +import type {CrDialogElement} from '//resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; +import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {CategoryTypeEnum, SystemTrendController} from '../../controller/system_trend_controller.js'; + +import {getTemplate} from './chart_category_dialog.html.js'; +import type {HealthdInternalsDataSeriesCheckboxElement} from './data_series_checkbox.js' + +export interface HealthdInternalsChartCategoryDialogElement { + $: { + dialog: CrDialogElement, + batteryCheckbox: HealthdInternalsDataSeriesCheckboxElement, + cpuFrequencyCheckbox: HealthdInternalsDataSeriesCheckboxElement, + cpuUsageCheckbox: HealthdInternalsDataSeriesCheckboxElement, + memoryCheckbox: HealthdInternalsDataSeriesCheckboxElement, + thermalCheckbox: HealthdInternalsDataSeriesCheckboxElement, + zramCheckbox: HealthdInternalsDataSeriesCheckboxElement, + }; +} + +export class HealthdInternalsChartCategoryDialogElement extends PolymerElement { + static get is() { + return 'healthd-internals-chart-category-dialog'; + } + + static get template() { + return getTemplate(); + } + + private controller: SystemTrendController|null = null; + + openDialog(controller: SystemTrendController) { + this.controller = controller; + this.$.batteryCheckbox.init( + 'Battery', this.controller.getData(CategoryTypeEnum.BATTERY)); + this.$.cpuFrequencyCheckbox.init( + 'CPU Frequency', + this.controller.getData(CategoryTypeEnum.CPU_FREQUENCY)); + this.$.cpuUsageCheckbox.init( + 'CPU Usage', this.controller.getData(CategoryTypeEnum.CPU_USAGE)); + this.$.memoryCheckbox.init( + 'Memory', this.controller.getData(CategoryTypeEnum.MEMORY)); + this.$.thermalCheckbox.init( + 'Thermal', this.controller.getData(CategoryTypeEnum.THERMAL)); + this.$.zramCheckbox.init( + 'Zram', this.controller.getData(CategoryTypeEnum.ZRAM)); + this.$.dialog.showModal(); + } + + + private onConfirmButtonClicked() { + this.controller?.setSelectedIndices( + CategoryTypeEnum.BATTERY, this.$.batteryCheckbox.getSelectedIndices()); + this.controller?.setSelectedIndices( + CategoryTypeEnum.CPU_FREQUENCY, + this.$.cpuFrequencyCheckbox.getSelectedIndices()); + this.controller?.setSelectedIndices( + CategoryTypeEnum.CPU_USAGE, + this.$.cpuUsageCheckbox.getSelectedIndices()); + this.controller?.setSelectedIndices( + CategoryTypeEnum.MEMORY, this.$.memoryCheckbox.getSelectedIndices()); + this.controller?.setSelectedIndices( + CategoryTypeEnum.THERMAL, this.$.thermalCheckbox.getSelectedIndices()); + this.controller?.setSelectedIndices( + CategoryTypeEnum.ZRAM, this.$.zramCheckbox.getSelectedIndices()); + + this.dispatchEvent(new CustomEvent( + 'custom-data-updated', {bubbles: true, composed: true})); + this.controller = null; + this.$.dialog.close(); + } + + private onCancelButtonClicked() { + this.controller = null; + this.$.dialog.close(); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'healthd-internals-chart-category-dialog': + HealthdInternalsChartCategoryDialogElement; + } +} + +customElements.define( + HealthdInternalsChartCategoryDialogElement.is, + HealthdInternalsChartCategoryDialogElement);
diff --git a/chrome/browser/resources/chromeos/healthd_internals/view/settings/data_series_checkbox.html b/chrome/browser/resources/chromeos/healthd_internals/view/settings/data_series_checkbox.html new file mode 100644 index 0000000..27347d08 --- /dev/null +++ b/chrome/browser/resources/chromeos/healthd_internals/view/settings/data_series_checkbox.html
@@ -0,0 +1,20 @@ +<style include="healthd-internals-shared"> + .checkbox-container { + display: flex; + flex-direction: column; + gap: 8px; + padding-bottom: 16px; + } + + cr-checkbox { + padding-inline-start: 8px; + } +</style> +<div class="checkbox-container"> + <label>[[checkboxTitle]]</label> + <template is="dom-repeat" items="[[checkboxData]]"> + <cr-checkbox checked="{{item.isChecked}}"> + [[item.name]] + </cr-checkbox> + </template> +</div>
diff --git a/chrome/browser/resources/chromeos/healthd_internals/view/settings/data_series_checkbox.ts b/chrome/browser/resources/chromeos/healthd_internals/view/settings/data_series_checkbox.ts new file mode 100644 index 0000000..c4e5ac42 --- /dev/null +++ b/chrome/browser/resources/chromeos/healthd_internals/view/settings/data_series_checkbox.ts
@@ -0,0 +1,88 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '//resources/ash/common/cr_elements/cr_checkbox/cr_checkbox.js'; + +import {CrCheckboxElement} from '//resources/ash/common/cr_elements/cr_checkbox/cr_checkbox.js'; +import {assert} from '//resources/js/assert.js'; +import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {DataSeriesList} from '../../controller/system_trend_controller.js'; + +import {getTemplate} from './data_series_checkbox.html.js'; + +interface DataSeriesCheckboxData { + name: string; + isChecked: boolean; +} + +export class HealthdInternalsDataSeriesCheckboxElement extends PolymerElement { + static get is() { + return 'healthd-internals-data-series-checkbox'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + checkboxTitle: {type: String}, + checkboxData: {type: Array}, + }; + } + + // Set in `init`. + private checkboxTitle: string = ''; + + // Stored the data from checkboxes. + private checkboxData: DataSeriesCheckboxData[] = []; + + /** + * Init the checkboxes. + * + * @param title - Displayed title for checkboxes. + * @param data - Used to collect data name and selected indices. + */ + init(title: string, data: DataSeriesList[]) { + assert(data.length === 1); + this.checkboxTitle = title; + this.checkboxData = []; + for (const dataSeries of data[0].dataList) { + this.checkboxData.push({name: dataSeries.getTitle(), isChecked: false}); + } + for (const index of data[0].selectedIndices) { + this.checkboxData[index].isChecked = true; + } + + // Create a copy to trigger a change for the new row in table. + this.set('checkboxData', this.checkboxData.slice()); + } + + /** + * Gets the selected indices from the `checkboxData`. + * + * @returns - List of selected indices. + */ + getSelectedIndices(): number[] { + const output: number[] = []; + for (const [index, data] of this.checkboxData.entries()) { + if (data.isChecked) { + output.push(index); + } + } + return output; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'healthd-internals-data-series-checkbox': + HealthdInternalsDataSeriesCheckboxElement; + } +} + +customElements.define( + HealthdInternalsDataSeriesCheckboxElement.is, + HealthdInternalsDataSeriesCheckboxElement);
diff --git a/chrome/browser/resources/data_sharing/data_sharing_app.html b/chrome/browser/resources/data_sharing/data_sharing_app.html index 14f12e6..df1b198f 100644 --- a/chrome/browser/resources/data_sharing/data_sharing_app.html +++ b/chrome/browser/resources/data_sharing/data_sharing_app.html
@@ -4,24 +4,64 @@ min-height: 200px; --skw-color-primary: var(--color-sys-primary); - --skw-color-primary-container: var(--color-sys-primary-container); + --skw-color-surface-tint: var(--color-sys-surface-tint); --skw-color-on-primary: var(--color-sys-on-primary); - --skw-color-inverse-primary: var(--color-sys-inverse-primary); + --skw-color-primary-container: var(--color-sys-primary-container); + --skw-color-on-primary-container: var(--color-sys-on-primary-container); --skw-color-secondary: var(--color-sys-secondary); + --skw-color-on-secondary: var(--color-sys-on-secondary); + --skw-color-secondary-container: var(--color-sys-secondary-container); --skw-color-on-secondary-container: var(--color-sys-on-secondary-container); + --skw-color-tertiary: var(--color-sys-tertiary); + --skw-color-on-tertiary: var(--color-sys-on-tertiary); + --skw-color-tertiary-container: var(--color-sys-tertiary-container); + --skw-color-on-tertiary-container: var(--color-sys-on-tertiary-container); + --skw-color-error: var(--color-sys-error); + --skw-color-on-error: var(--color-sys-on-error); + --skw-color-error-container: var(--color-sys-error-container); + --skw-color-on-error-container: var(--color-sys-on-error-container); + --skw-color-background: var(--color-sys-background); + --skw-color-on-background: var(--color-sys-on-background); --skw-color-surface: var(--color-sys-surface); + --skw-color-on-surface: var(--color-sys-on-surface); + --skw-color-surface-variant: var(--color-sys-surface-variant); + --skw-color-on-surface-variant: var(--color-sys-on-surface-variant); + --skw-color-outline: var(--color-sys-outline); + --skw-color-outline-variant: var(--color-sys-outline-variant); + --skw-color-shadow: var(--color-sys-shadow); + --skw-color-scrim: var(--color-sys-scrim); + --skw-color-inverse-surface: var(--color-sys-inverse-surface); + --skw-color-inverse-on-surface: var(--color-sys-inverse-on-surface); + --skw-color-inverse-primary: var(--color-sys-inverse-primary); + --skw-color-primary-fixed: var(--color-sys-primary-fixed); + --skw-color-on-primary-fixed: var(--color-sys-on-primary-fixed); + --skw-color-primary-fixed-dim: var(--color-sys-primary-fixed-dim); + --skw-color-on-primary-fixed-variant: var( + --color-sys-on-primary-fixed-variant + ); + --skw-color-secondary-fixed: var(--color-sys-secondary-fixed); + --skw-color-on-secondary-fixed: var(--color-sys-on-secondary-fixed); + --skw-color-secondary-fixed-dim: var(--color-sys-secondary-fixed-dim); + --skw-color-on-secondary-fixed-variant: var( + --color-sys-on-secondary-fixed-variant + ); + --skw-color-tertiary-fixed: var(--color-sys-tertiary-fixed); + --skw-color-on-tertiary-fixed: var(--color-sys-on-tertiary-fixed); + --skw-color-tertiary-fixed-dim: var(--color-sys-tertiary-fixed-dim); + --skw-color-on-tertiary-fixed-variant: var( + --color-sys-on-tertiary-fixed-variant + ); + --skw-color-surface-dim: var(--color-sys-surface-dim); + --skw-color-surface-bright: var(--color-sys-surface-bright); + --skw-color-surface-container-lowest: var( + --color-sys-surface-container-lowest + ); + --skw-color-surface-container-low: var(--color-sys-surface-container-low); --skw-color-surface-container: var(--color-sys-surface-container); --skw-color-surface-container-high: var(--color-sys-surface-container-high); --skw-color-surface-container-highest: var( --color-sys-surface-container-highest ); - --skw-color-on-surface: var(--color-sys-on-surface); - --skw-color-on-surface-variant: var(--color-sys-on-surface-variant); - --skw-color-inverse-surface: var(--color-sys-inverse-surface); - --skw-color-inverse-on-surface: var(--color-sys-inverse-on-surface); - --skw-color-scrim: var(--color-sys-scrim); - --skw-color-error-container: var(--color-sys-error-container); - --skw-color-on-error-container: var(--color-sys-on-error-container); } .invite {
diff --git a/chrome/browser/resources/internals/BUILD.gn b/chrome/browser/resources/internals/BUILD.gn deleted file mode 100644 index cdbea0b..0000000 --- a/chrome/browser/resources/internals/BUILD.gn +++ /dev/null
@@ -1,37 +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. - -import("//chrome/common/features.gni") -import("//tools/grit/grit_rule.gni") -import("//ui/webui/resources/tools/generate_grd.gni") - -assert(!is_android) - -generate_grd("build_grd") { - grd_prefix = "internals" - out_grd = "$target_gen_dir/resources.grd" - - input_files = [ "internals.html" ] - input_files_base_dir = rebase_path(".", "//") - - deps = [ "user_education:build_grdp" ] - grdp_files = [ "$target_gen_dir/user_education/resources.grdp" ] -} - -grit("resources") { - defines = chrome_grit_defines - - # These arguments are needed since the grd is generated at build time. - enable_input_discovery_for_gn_analyze = false - source = "$target_gen_dir/resources.grd" - deps = [ ":build_grd" ] - - outputs = [ - "grit/internals_resources.h", - "grit/internals_resources_map.cc", - "grit/internals_resources_map.h", - "internals_resources.pak", - ] - output_dir = "$root_gen_dir/chrome" -}
diff --git a/chrome/browser/resources/internals/internals.html b/chrome/browser/resources/internals/internals.html deleted file mode 100644 index 10b3873..0000000 --- a/chrome/browser/resources/internals/internals.html +++ /dev/null
@@ -1,6 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta http-equiv="refresh" content="0; URL=chrome://chrome-urls/#internals"> - </head> -</html>
diff --git a/chrome/browser/resources/lens/overlay/selection_overlay.ts b/chrome/browser/resources/lens/overlay/selection_overlay.ts index ee62c13..a57f8f1 100644 --- a/chrome/browser/resources/lens/overlay/selection_overlay.ts +++ b/chrome/browser/resources/lens/overlay/selection_overlay.ts
@@ -722,13 +722,13 @@ this.dispatchEvent( new CustomEvent('selection-started', {bubbles: true, composed: true})); - if (this.$.textSelectionLayer.handleGestureStart(this.currentGesture)) { + if (this.$.postSelectionRenderer.handleGestureStart(this.currentGesture)) { + this.draggingRespondent = DragFeature.POST_SELECTION; + } else if (this.$.textSelectionLayer.handleGestureStart( + this.currentGesture)) { // Text is responding to this sequence of gestures. this.draggingRespondent = DragFeature.TEXT; this.$.postSelectionRenderer.clearSelection(); - } else if (this.$.postSelectionRenderer.handleGestureStart( - this.currentGesture)) { - this.draggingRespondent = DragFeature.POST_SELECTION; } }
diff --git a/chrome/browser/resources/new_tab_page/middle_slot_promo.ts b/chrome/browser/resources/new_tab_page/middle_slot_promo.ts index 26d4befcf3..cf90bcfe9 100644 --- a/chrome/browser/resources/new_tab_page/middle_slot_promo.ts +++ b/chrome/browser/resources/new_tab_page/middle_slot_promo.ts
@@ -228,6 +228,7 @@ } private updatePromoVisibility_() { + // `renderPromo()` must be called first to initialize promo data. if (this.hasDefaultPromo_ === null) { return; } @@ -246,8 +247,8 @@ } // Don't fire a load event until we've verified that one or neither of the - // promo types (default or mobile) can show. this.mobilePromoEnabled_ - // becomes false in renderPromo() whenever a default promo is about to + // promo types (default or mobile) can show. `this.mobilePromoEnabled_` + // becomes false in `renderPromo()` whenever a default promo is about to // render. if (!this.mobilePromoEnabled_ || this.hasMobilePromoContent_ !== null) { this.fire('ntp-middle-slot-promo-loaded'); @@ -261,10 +262,10 @@ private onPromoChange_() { if (this.mobilePromoEnabled_) { if (this.hasMobilePromoContent_ && this.hasDefaultPromo_ !== null) { - // Skip calling renderPromo() if we already attempted to render a promo - // before AND there is mobile promo content to display. This prevents - // the default promo from showing if the mobile promo has already been - // displayed, and vice versa. + // Skip calling `renderPromo()` if we already attempted to render a + // promo before AND there is mobile promo content to display. This + // prevents the default promo from showing if the mobile promo has + // already been displayed, and vice versa. return; } } @@ -291,7 +292,12 @@ }); } + // Allow users to undo the dismissal of the default promo using Ctrl+Z (or + // Cmd+Z on macOS). Mobile promo dismissal is handled by `mobile_promo.ts`. private onWindowKeydown_(e: KeyboardEvent) { + if (!this.blocklistedMiddleSlotPromoId_) { + return; + } let ctrlKeyPressed = e.ctrlKey; // <if expr="is_macosx"> ctrlKeyPressed = ctrlKeyPressed || e.metaKey;
diff --git a/chrome/browser/resources/new_tab_page/mobile_promo.ts b/chrome/browser/resources/new_tab_page/mobile_promo.ts index 30b96c51..d7fcc6bae 100644 --- a/chrome/browser/resources/new_tab_page/mobile_promo.ts +++ b/chrome/browser/resources/new_tab_page/mobile_promo.ts
@@ -3,6 +3,7 @@ // found in the LICENSE file. import type {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js'; +import {EventTracker} from 'chrome://resources/js/event_tracker.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import {getCss} from './mobile_promo.css.js'; @@ -46,6 +47,9 @@ protected qrCode: string; + private blocklistedPromo_: boolean = false; + private eventTracker_: EventTracker = new EventTracker(); + constructor() { super(); NewTabPageProxy.getInstance().handler.getMobilePromoQrCode().then( @@ -54,17 +58,44 @@ }); } + override connectedCallback() { + super.connectedCallback(); + this.eventTracker_.add(window, 'keydown', this.onWindowKeydown_.bind(this)); + } + + override disconnectedCallback() { + super.disconnectedCallback(); + this.eventTracker_.removeAll(); + } + protected onDismissButtonClick_() { + this.blocklistedPromo_ = true; NewTabPageProxy.getInstance().handler.onDismissMobilePromo(); this.$.promoContainer.hidden = true; this.$.dismissPromoButtonToast.show(); } protected onUndoDismissPromoButtonClick_() { + this.blocklistedPromo_ = false; NewTabPageProxy.getInstance().handler.onUndoDismissMobilePromo(); this.$.promoContainer.hidden = false; this.$.dismissPromoButtonToast.hide(); } + + // Allow users to undo the dismissal of the mobile promo using Ctrl+Z (or + // Cmd+Z on macOS). + private onWindowKeydown_(e: KeyboardEvent) { + if (!this.blocklistedPromo_) { + return; + } + let ctrlKeyPressed = e.ctrlKey; + // <if expr="is_macosx"> + ctrlKeyPressed = ctrlKeyPressed || e.metaKey; + // </if> + if (ctrlKeyPressed && e.key === 'z') { + this.onUndoDismissPromoButtonClick_(); + } + } } declare global {
diff --git a/chrome/browser/resources/on_device_internals/BUILD.gn b/chrome/browser/resources/on_device_internals/BUILD.gn index 7aaaa4a4..04752bd7 100644 --- a/chrome/browser/resources/on_device_internals/BUILD.gn +++ b/chrome/browser/resources/on_device_internals/BUILD.gn
@@ -16,6 +16,7 @@ mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom-webui.ts", "$root_gen_dir/services/on_device_model/public/mojom/on_device_model.mojom-webui.ts", + "$root_gen_dir/services/on_device_model/public/mojom/on_device_model_service.mojom-webui.ts", ] static_files = [ "on_device_internals.html" ]
diff --git a/chrome/browser/resources/on_device_internals/model_status.html.ts b/chrome/browser/resources/on_device_internals/model_status.html.ts index 6d874c62..d46fb60 100644 --- a/chrome/browser/resources/on_device_internals/model_status.html.ts +++ b/chrome/browser/resources/on_device_internals/model_status.html.ts
@@ -50,8 +50,7 @@ } </tbody> </table> - </div> - ` + </div>` } <h3>Supplementary Models</h3> <div>
diff --git a/chrome/browser/resources/on_device_internals/tools.html b/chrome/browser/resources/on_device_internals/tools.html index 453b10d..7ce390e7 100644 --- a/chrome/browser/resources/on_device_internals/tools.html +++ b/chrome/browser/resources/on_device_internals/tools.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style cr-hidden-style"> +<style include="cr-shared-style cr-hidden-style md-select"> :host { display: block; margin: auto; @@ -110,24 +110,40 @@ cr-expand-button:hover { background-color: var(--cr-hover-background-color); } + + .model-options { + display: flex; + flex-direction: row; + } + + cr-checkbox { + margin-left: 20px; + --cr-checkbox-label-padding-start: 10px; + } </style> <div class="performance-class"> Device performance class: <strong>[[performanceClassText_]]</strong> </div> <cr-input id="modelInput" label="Model directory" placeholder="/tmp/model" disabled="[[isLoading_(loadModelStart_)]]" - on-change="onModelSelected_" error-message="[[error_]]" - invalid="[[error_.length]]" autofocus> + error-message="[[error_]]" invalid="[[error_.length]]" autofocus> <cr-button slot="suffix" disabled="[[isLoading_(loadModelStart_)]]" on-click="onLoadClick_"> Load </cr-button> </cr-input> -<cr-checkbox slot="suffix" checked="{{enableImageInput_}}"> - Enable images -</cr-checkbox> +<div class="model-options"> + <select id="performanceHintSelect" class="md-select" + value="[[performanceHint_]]" on-change="onPerformanceHintChange_"> + <option value="kHighestQuality">Highest Quality</option> + <option value="kFastestInference">Fastest Inference</option> + </select> + <cr-checkbox slot="suffix" checked="{{enableImageInput_}}"> + Enable images + </cr-checkbox> +</div> <div class="model-text"> - [[getModelText_(modelPath_, loadModelDuration_)]] + [[getModelText_(modelPath_, loadModelDuration_, loadedPerformanceHint_)]] <div class="throbber" hidden$="[[!isLoading_(loadModelStart_)]]"></div> </div>
diff --git a/chrome/browser/resources/on_device_internals/tools.ts b/chrome/browser/resources/on_device_internals/tools.ts index bae9a1c5..3c87c64 100644 --- a/chrome/browser/resources/on_device_internals/tools.ts +++ b/chrome/browser/resources/on_device_internals/tools.ts
@@ -10,6 +10,7 @@ import '//resources/cr_elements/cr_input/cr_input.js'; import '//resources/cr_elements/cr_shared_vars.css.js'; import '//resources/cr_elements/cr_textarea/cr_textarea.js'; +import '//resources/cr_elements/md_select.css.js'; import type {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.js'; import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -17,6 +18,7 @@ import {BrowserProxy} from './browser_proxy.js'; import type {InputPiece, ResponseChunk, ResponseSummary} from './on_device_model.mojom-webui.js'; import {LoadModelResult, OnDeviceModelRemote, PerformanceClass, SessionRemote, StreamingResponderCallbackRouter, Token} from './on_device_model.mojom-webui.js'; +import {ModelPerformanceHint} from './on_device_model_service.mojom-webui.js'; import {getTemplate} from './tools.html.js'; interface Response { @@ -34,6 +36,7 @@ textInput: CrInputElement, imageInput: HTMLInputElement, topKInput: CrInputElement, + performanceHintSelect: HTMLSelectElement, }; } @@ -131,6 +134,8 @@ type: Object, value: null, }, + performanceHint_: String, + loadedPerformanceHint_: Number, }; } @@ -159,6 +164,8 @@ private topK_: number = 1; private imageFile_: File|null = null; private enableImageInput_: boolean = false; + private performanceHint_: string = 'kHighestQuality'; + private loadedPerformanceHint_: ModelPerformanceHint|null; private proxy_: BrowserProxy = BrowserProxy.getInstance(); private responseRouter_: StreamingResponderCallbackRouter = @@ -199,6 +206,10 @@ this.$.imageInput.value = ''; } + private onPerformanceHintChange_() { + this.performanceHint_ = this.$.performanceHintSelect.value; + } + private onServiceCrashed_() { if (this.currentResponse_) { this.currentResponse_.error = true; @@ -233,6 +244,8 @@ this.baseModel_ = null; this.model_ = null; this.loadModelStart_ = new Date().getTime(); + const performanceHint = ModelPerformanceHint[( + this.performanceHint_ as keyof typeof ModelPerformanceHint)]; const modelPath = this.$.modelInput.value; // <if expr="is_win"> // Windows file paths are std::wstring, so use Array<Number>. @@ -244,7 +257,8 @@ const baseModel = new OnDeviceModelRemote(); let newModel = new OnDeviceModelRemote(); let {result} = await this.proxy_.handler.loadModel( - {path: processedPath}, baseModel.$.bindNewPipeAndPassReceiver()); + {path: processedPath}, performanceHint, + baseModel.$.bindNewPipeAndPassReceiver()); if (result === LoadModelResult.kSuccess && this.enableImageInput_) { result = (await baseModel.loadAdaptation( { @@ -272,6 +286,7 @@ }); this.startNewSession_(); this.modelPath_ = modelPath; + this.loadedPerformanceHint_ = performanceHint; } } @@ -419,9 +434,13 @@ return ''; } let text = 'Model loaded from ' + this.modelPath_ + ' in ' + - this.loadModelDuration_ + 'ms'; + this.loadModelDuration_ + 'ms '; if (this.imagesEnabled_()) { - text += ' [images enabled]'; + text += '[images enabled]'; + } + if (this.loadedPerformanceHint_ === + ModelPerformanceHint.kFastestInference) { + text += '[fastest inference]'; } return text; }
diff --git a/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_data_handling.css b/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_data_handling.css index 83c403844..90f039b 100644 --- a/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_data_handling.css +++ b/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_data_handling.css
@@ -19,8 +19,8 @@ align-items: center; display: flex; flex-direction: column; - height: 100%; - padding-inline: var(--tangible-sync-style-banner-width); + margin-inline: auto; + max-width: 500px; position: relative; }
diff --git a/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_disclosure.css b/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_disclosure.css index 87085f7..f297f293c 100644 --- a/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_disclosure.css +++ b/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_disclosure.css
@@ -24,7 +24,8 @@ display: flex; flex-direction: column; height: 100%; - padding-inline: var(--tangible-sync-style-banner-width); + margin-inline: auto; + max-width: 500px; position: relative; } @@ -76,7 +77,7 @@ .disclaimer-container { box-sizing: border-box; - flex: 1 1 auto; + flex: 0 0 auto; justify-content: center; margin-block-start: 12px; overflow-y: auto;
diff --git a/chrome/browser/resources/internals/user_education/BUILD.gn b/chrome/browser/resources/user_education_internals/BUILD.gn similarity index 78% rename from chrome/browser/resources/internals/user_education/BUILD.gn rename to chrome/browser/resources/user_education_internals/BUILD.gn index 3f364bba..a800f30 100644 --- a/chrome/browser/resources/internals/user_education/BUILD.gn +++ b/chrome/browser/resources/user_education_internals/BUILD.gn
@@ -26,8 +26,8 @@ "user_education_whats_new_internals_card.css", ] - mojo_files_deps = [ "//chrome/browser/ui/webui/internals/user_education:mojo_bindings_ts__generator" ] - mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom-webui.ts" ] + mojo_files_deps = [ "//chrome/browser/ui/webui/user_education_internals:mojo_bindings_ts__generator" ] + mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom-webui.ts" ] ts_deps = [ "//third_party/lit/v3_0:build_ts", @@ -38,7 +38,5 @@ "//ui/webui/resources/mojo:build_ts", ] - generate_grdp = true - grd_resource_path_prefix = "user-education" webui_context_type = "trusted" }
diff --git a/chrome/browser/resources/internals/user_education/DIR_METADATA b/chrome/browser/resources/user_education_internals/DIR_METADATA similarity index 100% rename from chrome/browser/resources/internals/user_education/DIR_METADATA rename to chrome/browser/resources/user_education_internals/DIR_METADATA
diff --git a/chrome/browser/resources/internals/user_education/OWNERS b/chrome/browser/resources/user_education_internals/OWNERS similarity index 100% rename from chrome/browser/resources/internals/user_education/OWNERS rename to chrome/browser/resources/user_education_internals/OWNERS
diff --git a/chrome/browser/resources/internals/user_education/index.html b/chrome/browser/resources/user_education_internals/index.html similarity index 88% rename from chrome/browser/resources/internals/user_education/index.html rename to chrome/browser/resources/user_education_internals/index.html index 2892fd5..4eaed88 100644 --- a/chrome/browser/resources/internals/user_education/index.html +++ b/chrome/browser/resources/user_education_internals/index.html
@@ -21,7 +21,7 @@ </style> </head> <body> - <script type="module" src="/user-education/user_education_internals.js"></script> + <script type="module" src="./user_education_internals.js"></script> <user-education-internals></user-education-internals> </body> </html>
diff --git a/chrome/browser/resources/internals/user_education/user_education_internals.css b/chrome/browser/resources/user_education_internals/user_education_internals.css similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_internals.css rename to chrome/browser/resources/user_education_internals/user_education_internals.css
diff --git a/chrome/browser/resources/internals/user_education/user_education_internals.html.ts b/chrome/browser/resources/user_education_internals/user_education_internals.html.ts similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_internals.html.ts rename to chrome/browser/resources/user_education_internals/user_education_internals.html.ts
diff --git a/chrome/browser/resources/internals/user_education/user_education_internals.ts b/chrome/browser/resources/user_education_internals/user_education_internals.ts similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_internals.ts rename to chrome/browser/resources/user_education_internals/user_education_internals.ts
diff --git a/chrome/browser/resources/internals/user_education/user_education_internals_card.css b/chrome/browser/resources/user_education_internals/user_education_internals_card.css similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_internals_card.css rename to chrome/browser/resources/user_education_internals/user_education_internals_card.css
diff --git a/chrome/browser/resources/internals/user_education/user_education_internals_card.html.ts b/chrome/browser/resources/user_education_internals/user_education_internals_card.html.ts similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_internals_card.html.ts rename to chrome/browser/resources/user_education_internals/user_education_internals_card.html.ts
diff --git a/chrome/browser/resources/internals/user_education/user_education_internals_card.ts b/chrome/browser/resources/user_education_internals/user_education_internals_card.ts similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_internals_card.ts rename to chrome/browser/resources/user_education_internals/user_education_internals_card.ts
diff --git a/chrome/browser/resources/internals/user_education/user_education_whats_new_internals_card.css b/chrome/browser/resources/user_education_internals/user_education_whats_new_internals_card.css similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_whats_new_internals_card.css rename to chrome/browser/resources/user_education_internals/user_education_whats_new_internals_card.css
diff --git a/chrome/browser/resources/internals/user_education/user_education_whats_new_internals_card.html.ts b/chrome/browser/resources/user_education_internals/user_education_whats_new_internals_card.html.ts similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_whats_new_internals_card.html.ts rename to chrome/browser/resources/user_education_internals/user_education_whats_new_internals_card.html.ts
diff --git a/chrome/browser/resources/internals/user_education/user_education_whats_new_internals_card.ts b/chrome/browser/resources/user_education_internals/user_education_whats_new_internals_card.ts similarity index 100% rename from chrome/browser/resources/internals/user_education/user_education_whats_new_internals_card.ts rename to chrome/browser/resources/user_education_internals/user_education_whats_new_internals_card.ts
diff --git a/chrome/browser/resources_integrity.cc b/chrome/browser/resources_integrity.cc index 59bdc6f..300a850 100644 --- a/chrome/browser/resources_integrity.cc +++ b/chrome/browser/resources_integrity.cc
@@ -11,25 +11,22 @@ #include <array> -#include "base/task/sequenced_task_runner.h" -#include "build/build_config.h" - -#if BUILDFLAG(IS_WIN) -#include <windows.h> -#endif - #include "base/files/file.h" #include "base/functional/bind.h" #include "base/memory/page_size.h" #include "base/metrics/histogram_functions.h" #include "base/path_service.h" #include "base/ranges/algorithm.h" +#include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" +#include "build/build_config.h" #include "chrome/common/chrome_paths.h" #include "crypto/secure_hash.h" #include "ui/base/buildflags.h" #if BUILDFLAG(IS_WIN) +#include <windows.h> + #include "chrome/app/chrome_exe_main_win.h" #else #include "chrome/app/packed_resources_integrity.h" // nogncheck @@ -39,7 +36,7 @@ bool CheckResourceIntegrityInternal( const base::FilePath& path, - const base::span<const uint8_t, crypto::kSHA256Length> expected_signature) { + base::span<const uint8_t, crypto::kSHA256Length> expected_signature) { // Open the file for reading; allowing other consumers to also open it for // reading and deleting. Do not allow others to write to it. base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ | @@ -74,7 +71,7 @@ void CheckResourceIntegrity( const base::FilePath& path, - const base::span<const uint8_t, crypto::kSHA256Length> expected_signature, + base::span<const uint8_t, crypto::kSHA256Length> expected_signature, scoped_refptr<base::SequencedTaskRunner> task_runner, base::OnceCallback<void(bool)> callback) { task_runner->PostTaskAndReplyWithResult( @@ -106,20 +103,17 @@ get_pak_file_hashes(&resources_hash_raw, &chrome_100_hash_raw, &chrome_200_hash_raw); - base::span<const uint8_t, crypto::kSHA256Length> resources_hash( - resources_hash_raw, crypto::kSHA256Length); - base::span<const uint8_t, crypto::kSHA256Length> chrome_100_hash( - chrome_100_hash_raw, crypto::kSHA256Length); - base::span<const uint8_t, crypto::kSHA256Length> chrome_200_hash( - chrome_200_hash_raw, crypto::kSHA256Length); + base::span resources_hash(resources_hash_raw, + base::fixed_extent<crypto::kSHA256Length>()); + base::span chrome_100_hash(chrome_100_hash_raw, + base::fixed_extent<crypto::kSHA256Length>()); + base::span chrome_200_hash(chrome_200_hash_raw, + base::fixed_extent<crypto::kSHA256Length>()); #else - base::span<const uint8_t, crypto::kSHA256Length> resources_hash = - kSha256_resources_pak; - base::span<const uint8_t, crypto::kSHA256Length> chrome_100_hash = - kSha256_chrome_100_percent_pak; + base::span resources_hash = kSha256_resources_pak; + base::span chrome_100_hash = kSha256_chrome_100_percent_pak; #if BUILDFLAG(ENABLE_HIDPI) - base::span<const uint8_t, crypto::kSHA256Length> chrome_200_hash = - kSha256_chrome_200_percent_pak; + base::span chrome_200_hash = kSha256_chrome_200_percent_pak; #endif #endif // BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc index 29dfbce..749d140 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc
@@ -75,7 +75,6 @@ /*enabled_features=*/ {kExtensionTelemetryForEnterprise, kExtensionTelemetryReportContactedHosts, - kExtensionTelemetryReportHostsContactedViaWebSocket, kExtensionTelemetryDeclarativeNetRequestActionSignal, extensions_features::kIncludeJSCallStackInExtensionApiRequest}, /*disabled_features=*/ @@ -872,8 +871,7 @@ scoped_feature_list_.InitWithFeatures( /*enabled_features=*/ {kExtensionTelemetryInterceptRemoteHostsContactedInRenderer, - kExtensionTelemetryReportContactedHosts, - kExtensionTelemetryReportHostsContactedViaWebSocket}, + kExtensionTelemetryReportContactedHosts}, /*disabled_features=*/{}); } };
diff --git a/chrome/browser/safe_browsing/url_lookup_service_browsertest.cc b/chrome/browser/safe_browsing/url_lookup_service_browsertest.cc index d325b3f..47e0fad 100644 --- a/chrome/browser/safe_browsing/url_lookup_service_browsertest.cc +++ b/chrome/browser/safe_browsing/url_lookup_service_browsertest.cc
@@ -4,25 +4,100 @@ #include "components/safe_browsing/core/browser/realtime/url_lookup_service.h" +#include "base/test/metrics/histogram_tester.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/url_lookup_service_factory.h" +#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" +#include "components/safe_browsing/core/common/utils.h" #include "components/variations/pref_names.h" #include "content/public/test/browser_test.h" +#include "net/dns/mock_host_resolver.h" namespace safe_browsing { +namespace { + +constexpr std::string_view kRealtimeEndpoint = "/realtime_endpoint"; + class SafeBrowsingUrlLookupServiceTest : public InProcessBrowserTest { public: - SafeBrowsingUrlLookupServiceTest() = default; + SafeBrowsingUrlLookupServiceTest() { + scoped_feature_list_.InitAndDisableFeature( + kSafeBrowsingRemoveCookiesInAuthRequests); + } SafeBrowsingUrlLookupServiceTest(const SafeBrowsingUrlLookupServiceTest&) = delete; SafeBrowsingUrlLookupServiceTest& operator=( const SafeBrowsingUrlLookupServiceTest&) = delete; + + void SetUp() override { + secure_embedded_test_server_ = std::make_unique<net::EmbeddedTestServer>( + net::EmbeddedTestServer::Type::TYPE_HTTPS); + secure_embedded_test_server_->RegisterRequestHandler(base::BindRepeating( + &SafeBrowsingUrlLookupServiceTest::UrlRequestHandler, + base::Unretained(this))); + ASSERT_TRUE(secure_embedded_test_server_->Start()); + InProcessBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + host_resolver()->AddRule("*", "127.0.0.1"); + identity_test_env_adaptor_ = + std::make_unique<IdentityTestEnvironmentProfileAdaptor>( + browser()->profile()); + } + + void SetUpInProcessBrowserTestFixture() override { + create_services_subscription_ = + BrowserContextDependencyManager::GetInstance() + ->RegisterCreateServicesCallbackForTesting( + base::BindRepeating(&SafeBrowsingUrlLookupServiceTest:: + OnWillCreateBrowserContextServices, + base::Unretained(this))); + } + + signin::IdentityTestEnvironment* identity_test_env() { + return identity_test_env_adaptor_->identity_test_env(); + } + + net::EmbeddedTestServer* secure_embedded_test_server() { + return secure_embedded_test_server_.get(); + } + + const net::test_server::HttpRequest last_realtime_request() { + return last_realtime_request_; + } + + private: + std::unique_ptr<net::test_server::HttpResponse> UrlRequestHandler( + const net::test_server::HttpRequest& request) { + if (request.relative_url == kRealtimeEndpoint) { + auto response = std::make_unique<net::test_server::BasicHttpResponse>(); + response->set_code(net::HTTP_OK); + response->AddCustomHeader("Set-Cookie", "cookie=reset"); + last_realtime_request_ = request; + return response; + } + return nullptr; + } + + void OnWillCreateBrowserContextServices(content::BrowserContext* context) { + IdentityTestEnvironmentProfileAdaptor:: + SetIdentityTestEnvironmentFactoriesOnBrowserContext(context); + } + + base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<net::EmbeddedTestServer> secure_embedded_test_server_; + base::CallbackListSubscription create_services_subscription_; + std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> + identity_test_env_adaptor_; + net::test_server::HttpRequest last_realtime_request_; }; IN_PROC_BROWSER_TEST_F(SafeBrowsingUrlLookupServiceTest, @@ -47,4 +122,67 @@ EXPECT_TRUE(url_lookup_service->CanPerformFullURLLookup()); } +IN_PROC_BROWSER_TEST_F(SafeBrowsingUrlLookupServiceTest, LookupWithToken) { + identity_test_env()->SetPrimaryAccount("test@example.com", + signin::ConsentLevel::kSync); + identity_test_env()->SetRefreshTokenForPrimaryAccount(); + identity_test_env()->SetAutomaticIssueOfAccessTokens(true); + + RealTimeUrlLookupService::OverrideUrlForTesting( + secure_embedded_test_server()->GetURL(kRealtimeEndpoint)); + + safe_browsing::SetSafeBrowsingState( + browser()->profile()->GetPrefs(), + safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION); + auto* url_lookup_service = + RealTimeUrlLookupServiceFactory::GetForProfile(browser()->profile()); + + base::RunLoop run_loop; + base::HistogramTester histogram_tester; + url_lookup_service->StartLookup( + secure_embedded_test_server()->GetURL("/"), + base::IgnoreArgs<bool, bool, std::unique_ptr<RTLookupResponse>>( + run_loop.QuitClosure()), + base::SequencedTaskRunner::GetCurrentDefault(), + SessionID::InvalidValue()); + run_loop.Run(); + + EXPECT_TRUE(base::Contains(last_realtime_request().headers, + net::HttpRequestHeaders::kAuthorization)); + + histogram_tester.ExpectUniqueSample( + "SafeBrowsing.AuthenticatedCookieResetEndpoint", + SafeBrowsingAuthenticatedEndpoint::kRealtimeUrlLookup, 1); +} + +IN_PROC_BROWSER_TEST_F(SafeBrowsingUrlLookupServiceTest, LookupWithoutToken) { + RealTimeUrlLookupService::OverrideUrlForTesting( + secure_embedded_test_server()->GetURL(kRealtimeEndpoint)); + + safe_browsing::SetSafeBrowsingState( + browser()->profile()->GetPrefs(), + safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION); + auto* url_lookup_service = + RealTimeUrlLookupServiceFactory::GetForProfile(browser()->profile()); + + base::RunLoop run_loop; + base::HistogramTester histogram_tester; + url_lookup_service->StartLookup( + secure_embedded_test_server()->GetURL("/"), + base::IgnoreArgs<bool, bool, std::unique_ptr<RTLookupResponse>>( + run_loop.QuitClosure()), + base::SequencedTaskRunner::GetCurrentDefault(), + SessionID::InvalidValue()); + run_loop.Run(); + + EXPECT_FALSE(base::Contains(last_realtime_request().headers, + net::HttpRequestHeaders::kAuthorization)); + + histogram_tester.ExpectUniqueSample( + "SafeBrowsing.AuthenticatedCookieResetEndpoint", + SafeBrowsingAuthenticatedEndpoint::kRealtimeUrlLookup, 0); +} + +} // namespace + } // namespace safe_browsing
diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc index 65ff0eaa..341c45b 100644 --- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
@@ -445,8 +445,8 @@ model()->Add(CreateTestTemplateURL(u"key2", "http://key2.com")); std::string fake_id("blahblahblah"); std::string fake_url = std::string(kOmniboxScheme) + "://" + fake_id; - model()->RegisterOmniboxKeyword(fake_id, "unittest", "key3", fake_url, - Time()); + model()->RegisterExtensionControlledTURL(fake_id, "unittest", "key3", + fake_url, Time(), false); syncer::SyncDataList all_sync_data = model()->GetAllSyncData(syncer::SEARCH_ENGINES); @@ -951,14 +951,14 @@ MergeAndExpectNotify(CreateInitialSyncData(), 1); // Add some extension keywords locally. - model()->RegisterOmniboxKeyword("extension1", "unittest", "keyword1", - "http://extension1", Time()); + model()->RegisterExtensionControlledTURL("extension1", "unittest", "keyword1", + "http://extension1", Time(), false); TemplateURL* extension1 = model()->GetTemplateURLForKeyword(u"keyword1"); ASSERT_TRUE(extension1); EXPECT_EQ(0U, processor()->change_list_size()); - model()->RegisterOmniboxKeyword("extension2", "unittest", "keyword2", - "http://extension2", Time()); + model()->RegisterExtensionControlledTURL("extension2", "unittest", "keyword2", + "http://extension2", Time(), false); TemplateURL* extension2 = model()->GetTemplateURLForKeyword(u"keyword2"); ASSERT_TRUE(extension2); EXPECT_EQ(0U, processor()->change_list_size()); @@ -2579,8 +2579,8 @@ TEST_F(TemplateURLServiceSyncTest, MergePrepopulatedEngineIgnoresId0) { // The newly registered keyword will have prepulate_id 0 since that is the // default value. - model()->RegisterOmniboxKeyword("extension1", "unittest", "keyword1", - "http://extension1", Time()); + model()->RegisterExtensionControlledTURL("extension1", "unittest", "keyword1", + "http://extension1", Time(), false); // Try to merge in a turl with preopulate_id also set to 0. This should work. syncer::SyncDataList initial_data;
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc index a91d32d0..63a019f 100644 --- a/chrome/browser/search_engines/template_url_service_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -569,31 +569,32 @@ std::string(), std::string(), true); AddKeywordWithDate("nonreplaceable", "keyword2", "http://test2", std::string(), std::string(), std::string(), false); - model()->RegisterOmniboxKeyword("test3", "extension", "keyword3", - "http://test3", - Time::FromSecondsSinceUnixEpoch(1)); + model()->RegisterExtensionControlledTURL( + "test3", "extension", "keyword3", "http://test3", + Time::FromSecondsSinceUnixEpoch(1), false); TemplateURL* original3 = model()->GetTemplateURLForKeyword(u"keyword3"); ASSERT_TRUE(original3); // Extension keywords should override replaceable keywords. - model()->RegisterOmniboxKeyword("id1", "test", "keyword1", "http://test4", - Time()); + model()->RegisterExtensionControlledTURL("id1", "test", "keyword1", + "http://test4", Time(), false); TemplateURL* extension1 = model()->FindTemplateURLForExtension( "id1", TemplateURL::OMNIBOX_API_EXTENSION); EXPECT_TRUE(extension1); EXPECT_EQ(extension1, model()->GetTemplateURLForKeyword(u"keyword1")); // They should also override non-replaceable keywords. - model()->RegisterOmniboxKeyword("id2", "test", "keyword2", "http://test5", - Time()); + model()->RegisterExtensionControlledTURL("id2", "test", "keyword2", + "http://test5", Time(), false); TemplateURL* extension2 = model()->FindTemplateURLForExtension( "id2", TemplateURL::OMNIBOX_API_EXTENSION); ASSERT_TRUE(extension2); EXPECT_EQ(extension2, model()->GetTemplateURLForKeyword(u"keyword2")); // They should override extension keywords added earlier. - model()->RegisterOmniboxKeyword("id3", "test", "keyword3", "http://test6", - Time::FromSecondsSinceUnixEpoch(4)); + model()->RegisterExtensionControlledTURL( + "id3", "test", "keyword3", "http://test6", + Time::FromSecondsSinceUnixEpoch(4), false); TemplateURL* extension3 = model()->FindTemplateURLForExtension( "id3", TemplateURL::OMNIBOX_API_EXTENSION); ASSERT_TRUE(extension3); @@ -606,8 +607,8 @@ // Similar to the AddSameKeyword test, but with an extension keyword masking a // replaceable TemplateURL. We should still do correct conflict resolution // between the non-template URLs. - model()->RegisterOmniboxKeyword("test2", "extension", "keyword", - "http://test2", Time()); + model()->RegisterExtensionControlledTURL("test2", "extension", "keyword", + "http://test2", Time(), false); TemplateURL* extension = model()->GetTemplateURLForKeyword(u"keyword"); ASSERT_TRUE(extension); // Adding a keyword that matches the extension. @@ -645,8 +646,8 @@ test_util()->VerifyLoad(); // Register an omnibox keyword. - model()->RegisterOmniboxKeyword("test", "extension", "keyword", - "chrome-extension://test", Time()); + model()->RegisterExtensionControlledTURL( + "test", "extension", "keyword", "chrome-extension://test", Time(), false); ASSERT_TRUE(model()->GetTemplateURLForKeyword(u"keyword")); // Reload the data. @@ -851,6 +852,55 @@ AssertTimesEqual(now, read_url->last_modified()); } +TEST_P(TemplateURLServiceTest, AddAndRemoveExtensionIdWithUnscopedMode) { + test_util()->VerifyLoad(); + + // Register an extension with unscoped mode allowed. + model()->AddToUnscopedModeExtensionIds("id"); + EXPECT_TRUE(model()->IsUnscopedModeExtensionId("id")); + EXPECT_TRUE(model()->GetUnscopedModeExtensionIds().contains("id")); + + // Remove the registered extension. + model()->RemoveFromUnscopedModeExtensionIdsIfPresent("id"); + EXPECT_FALSE(model()->IsUnscopedModeExtensionId("id")); + EXPECT_FALSE(model()->GetUnscopedModeExtensionIds().contains("id")); +} + +TEST_P(TemplateURLServiceTest, ExtensionWithUnscopedModeRegisteredCorrectly) { + test_util()->VerifyLoad(); + + // Register an extension with unscoped mode allowed. + model()->RegisterExtensionControlledTURL("id", "extension", "keyword", + "http://test", Time(), true); + const TemplateURL* extension_with_permission = + model()->GetTemplateURLForKeyword(u"keyword"); + EXPECT_TRUE(extension_with_permission); + EXPECT_EQ(extension_with_permission, + model()->GetTemplateURLForKeyword(u"keyword")); + EXPECT_TRUE(model()->IsUnscopedModeExtensionId("id")); + EXPECT_TRUE(model()->GetUnscopedModeExtensionIds().contains("id")); + + // Remove the registered extension. + model()->RemoveExtensionControlledTURL("id", + TemplateURL::OMNIBOX_API_EXTENSION); + const TemplateURL* removed_extension = + model()->GetTemplateURLForKeyword(u"keyword"); + EXPECT_FALSE(removed_extension); + EXPECT_FALSE(model()->IsUnscopedModeExtensionId("id")); + EXPECT_FALSE(model()->GetUnscopedModeExtensionIds().contains("id")); + + // Register an extension again without allowing unscoped mode. + model()->RegisterExtensionControlledTURL("id", "extension", "keyword", + "http://test", Time(), false); + const TemplateURL* extension_without_permission = + model()->GetTemplateURLForKeyword(u"keyword"); + EXPECT_TRUE(extension_without_permission); + EXPECT_EQ(extension_without_permission, + model()->GetTemplateURLForKeyword(u"keyword")); + EXPECT_FALSE(model()->IsUnscopedModeExtensionId("id")); + EXPECT_FALSE(model()->GetUnscopedModeExtensionIds().contains("id")); +} + #if BUILDFLAG(IS_ANDROID) TEST_P(TemplateURLServicePlayApiTest, CreateFromPlayAPI) { test_util()->VerifyLoad(); @@ -1148,8 +1198,8 @@ EXPECT_FALSE(model()->GetTemplateURLForKeyword(u"bing.com")); // Register an extension with bing keyword. - model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com", - "http://abcdefg", Time()); + model()->RegisterExtensionControlledTURL( + "abcdefg", "extension_name", "bing.com", "http://abcdefg", Time(), false); EXPECT_TRUE(model()->GetTemplateURLForKeyword(u"bing.com")); // Remove yahoo. It will be restored later, but for now verify we removed it. @@ -1354,8 +1404,8 @@ EXPECT_FALSE(model()->GetTemplateURLForKeyword(u"@history")); // Register an extension with @history keyword. - model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "@history", - "http://abcdefg", Time()); + model()->RegisterExtensionControlledTURL( + "abcdefg", "extension_name", "@history", "http://abcdefg", Time(), false); EXPECT_TRUE(model()->GetTemplateURLForKeyword(u"@history")); // Now perform the actual repair that should restore @history. @@ -2063,9 +2113,9 @@ // Use |install_time| value less than in AddExtensionSearchEngine call above // to check that omnibox api keyword is ranked higher even if installed // earlier. - model()->RegisterOmniboxKeyword("omnibox_api_extension_id", "extension_name", - "common_keyword", "http://test3", - Time::FromSecondsSinceUnixEpoch(1)); + model()->RegisterExtensionControlledTURL( + "omnibox_api_extension_id", "extension_name", "common_keyword", + "http://test3", Time::FromSecondsSinceUnixEpoch(1), false); TemplateURL* omnibox_api = model()->FindTemplateURLForExtension( "omnibox_api_extension_id", TemplateURL::OMNIBOX_API_EXTENSION);
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 6542aa75..a67ec16 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -5879,50 +5879,6 @@ EXPECT_TRUE(netwok_connectivity_reported); } -class SSLUITestWithCaptivePortalInterstitialDisabled : public SSLUITest { - public: - SSLUITestWithCaptivePortalInterstitialDisabled() { - feature_list_.InitWithFeatures({} /* enabled */, - {kCaptivePortalInterstitial} /* disabled */); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -// Tests the scenario where the OS reports a captive portal but captive portal -// interstitial feature is disabled. A captive portal interstitial should not be -// displayed. -IN_PROC_BROWSER_TEST_F(SSLUITestWithCaptivePortalInterstitialDisabled, - OSReportsCaptivePortal_FeatureDisabled) { - ASSERT_TRUE(https_server_mismatched_.Start()); - base::HistogramTester histograms; - - SSLErrorHandler::SetOSReportsCaptivePortalForTesting(true); - - // Navigate to an unsafe page on the server. - WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - SSLInterstitialTimerObserver interstitial_timer_observer(tab); - ASSERT_TRUE(ui_test_utils::NavigateToURL( - browser(), https_server_mismatched_.GetURL("/ssl/blank_page.html"))); - - ASSERT_TRUE(chrome_browser_interstitials::IsShowingSSLInterstitial(tab)); - EXPECT_FALSE(interstitial_timer_observer.timer_started()); - - // Check that the histogram for the SSL interstitial was recorded. - histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2); - histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::HANDLE_ALL, 1); - histograms.ExpectBucketCount( - SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); - histograms.ExpectBucketCount( - SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 0); - histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 0); -} - // Tests that the committed interstitial flag triggers the code path to show an // error PageType instead of an interstitial PageType. IN_PROC_BROWSER_TEST_F(SSLUITest, ErrorPage) {
diff --git a/chrome/browser/task_manager/BUILD.gn b/chrome/browser/task_manager/BUILD.gn index a9af112..3b7cc49 100644 --- a/chrome/browser/task_manager/BUILD.gn +++ b/chrome/browser/task_manager/BUILD.gn
@@ -23,6 +23,27 @@ "providers/task.h", "providers/task_provider.h", "providers/task_provider_observer.h", + "providers/web_contents/back_forward_cache_task.h", + "providers/web_contents/devtools_tag.h", + "providers/web_contents/devtools_task.h", + "providers/web_contents/fenced_frame_task.h", + "providers/web_contents/isolated_web_app_task.h", + "providers/web_contents/no_state_prefetch_tag.h", + "providers/web_contents/no_state_prefetch_task.h", + "providers/web_contents/prerender_task.h", + "providers/web_contents/printing_tag.h", + "providers/web_contents/printing_task.h", + "providers/web_contents/renderer_task.h", + "providers/web_contents/subframe_task.h", + "providers/web_contents/tab_contents_tag.h", + "providers/web_contents/tab_contents_task.h", + "providers/web_contents/tool_tag.h", + "providers/web_contents/tool_task.h", + "providers/web_contents/web_app_tag.h", + "providers/web_contents/web_app_task.h", + "providers/web_contents/web_contents_tag.h", + "providers/web_contents/web_contents_tags_manager.h", + "providers/web_contents/web_contents_task_provider.h", "providers/worker_task.h", "providers/worker_task_provider.h", "sampling/shared_sampler.h", @@ -32,6 +53,7 @@ "task_manager_interface.h", "task_manager_metrics_recorder.h", "task_manager_observer.h", + "web_contents_tags.h", ] public_deps = [ "//base", @@ -80,35 +102,13 @@ } if (!is_android) { sources += [ - "providers/web_contents/back_forward_cache_task.h", "providers/web_contents/background_contents_tag.h", "providers/web_contents/background_contents_task.h", - "providers/web_contents/devtools_tag.h", - "providers/web_contents/devtools_task.h", "providers/web_contents/extension_tag.h", "providers/web_contents/extension_task.h", - "providers/web_contents/fenced_frame_task.h", "providers/web_contents/guest_tag.h", "providers/web_contents/guest_task.h", "providers/web_contents/guest_task_mparch.h", - "providers/web_contents/isolated_web_app_task.h", - "providers/web_contents/no_state_prefetch_tag.h", - "providers/web_contents/no_state_prefetch_task.h", - "providers/web_contents/prerender_task.h", - "providers/web_contents/printing_tag.h", - "providers/web_contents/printing_task.h", - "providers/web_contents/renderer_task.h", - "providers/web_contents/subframe_task.h", - "providers/web_contents/tab_contents_tag.h", - "providers/web_contents/tab_contents_task.h", - "providers/web_contents/tool_tag.h", - "providers/web_contents/tool_task.h", - "providers/web_contents/web_app_tag.h", - "providers/web_contents/web_app_task.h", - "providers/web_contents/web_contents_tag.h", - "providers/web_contents/web_contents_tags_manager.h", - "providers/web_contents/web_contents_task_provider.h", - "web_contents_tags.h", ] public_deps += [ "//extensions/browser", @@ -135,6 +135,27 @@ "providers/spare_render_process_host_task_provider.cc", "providers/task.cc", "providers/task_provider.cc", + "providers/web_contents/back_forward_cache_task.cc", + "providers/web_contents/devtools_tag.cc", + "providers/web_contents/devtools_task.cc", + "providers/web_contents/fenced_frame_task.cc", + "providers/web_contents/isolated_web_app_task.cc", + "providers/web_contents/no_state_prefetch_tag.cc", + "providers/web_contents/no_state_prefetch_task.cc", + "providers/web_contents/prerender_task.cc", + "providers/web_contents/printing_tag.cc", + "providers/web_contents/printing_task.cc", + "providers/web_contents/renderer_task.cc", + "providers/web_contents/subframe_task.cc", + "providers/web_contents/tab_contents_tag.cc", + "providers/web_contents/tab_contents_task.cc", + "providers/web_contents/tool_tag.cc", + "providers/web_contents/tool_task.cc", + "providers/web_contents/web_app_tag.cc", + "providers/web_contents/web_app_task.cc", + "providers/web_contents/web_contents_tag.cc", + "providers/web_contents/web_contents_tags_manager.cc", + "providers/web_contents/web_contents_task_provider.cc", "providers/worker_task.cc", "providers/worker_task_provider.cc", "sampling/task_group.cc", @@ -143,6 +164,7 @@ "task_manager_interface.cc", "task_manager_metrics_recorder.cc", "task_manager_observer.cc", + "web_contents_tags.cc", ] deps = [ @@ -231,35 +253,13 @@ "//extensions/common", ] sources += [ - "providers/web_contents/back_forward_cache_task.cc", "providers/web_contents/background_contents_tag.cc", "providers/web_contents/background_contents_task.cc", - "providers/web_contents/devtools_tag.cc", - "providers/web_contents/devtools_task.cc", "providers/web_contents/extension_tag.cc", "providers/web_contents/extension_task.cc", - "providers/web_contents/fenced_frame_task.cc", "providers/web_contents/guest_tag.cc", "providers/web_contents/guest_task.cc", "providers/web_contents/guest_task_mparch.cc", - "providers/web_contents/isolated_web_app_task.cc", - "providers/web_contents/no_state_prefetch_tag.cc", - "providers/web_contents/no_state_prefetch_task.cc", - "providers/web_contents/prerender_task.cc", - "providers/web_contents/printing_tag.cc", - "providers/web_contents/printing_task.cc", - "providers/web_contents/renderer_task.cc", - "providers/web_contents/subframe_task.cc", - "providers/web_contents/tab_contents_tag.cc", - "providers/web_contents/tab_contents_task.cc", - "providers/web_contents/tool_tag.cc", - "providers/web_contents/tool_task.cc", - "providers/web_contents/web_app_tag.cc", - "providers/web_contents/web_app_task.cc", - "providers/web_contents/web_contents_tag.cc", - "providers/web_contents/web_contents_tags_manager.cc", - "providers/web_contents/web_contents_task_provider.cc", - "web_contents_tags.cc", ] } }
diff --git a/chrome/browser/task_manager/providers/child_process_task_unittest.cc b/chrome/browser/task_manager/providers/child_process_task_unittest.cc index dcee84e..18ee3979 100644 --- a/chrome/browser/task_manager/providers/child_process_task_unittest.cc +++ b/chrome/browser/task_manager/providers/child_process_task_unittest.cc
@@ -105,20 +105,19 @@ // The following process which has handle = base::kNullProcessHandle, won't be // added. - ChildProcessData data1(0); + ChildProcessData data1(0, content::ChildProcessId()); ASSERT_FALSE(data1.GetProcess().IsValid()); provider.BrowserChildProcessLaunchedAndConnected(data1); EXPECT_TRUE(provided_tasks_.empty()); - const int unique_id = 245; + const content::ChildProcessId unique_id(245); const std::u16string name(u"Test Task"); const std::u16string expected_name( l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_PREFIX, name)); - ChildProcessData data2(content::PROCESS_TYPE_PPAPI_PLUGIN); + ChildProcessData data2(content::PROCESS_TYPE_PPAPI_PLUGIN, unique_id); data2.SetProcess(base::Process::Current()); data2.name = name; - data2.id = unique_id; provider.BrowserChildProcessLaunchedAndConnected(data2); ASSERT_EQ(1U, provided_tasks_.size()); @@ -128,14 +127,16 @@ EXPECT_EQ(base::GetCurrentProcId(), task->process_id()); EXPECT_EQ(expected_name, task->title()); EXPECT_EQ(Task::PLUGIN, task->GetType()); - EXPECT_EQ(unique_id, task->GetChildProcessUniqueID()); + // TODO(crbug.com/379869738): Remove GetUnsafeValue() usage. + EXPECT_EQ(unique_id.GetUnsafeValue(), task->GetChildProcessUniqueID()); EXPECT_EQ(std::u16string(), task->GetProfileName()); EXPECT_FALSE(task->ReportsSqliteMemory()); EXPECT_FALSE(task->ReportsWebCacheStats()); // Make sure that indexing by child_id works properly. - ASSERT_EQ(task, provider.GetTaskOfUrlRequest(unique_id, 0)); - ASSERT_EQ(task, provider.GetTaskOfUrlRequest(unique_id, 1)); + // TODO(crbug.com/379869738): Remove GetUnsafeValue() usage. + ASSERT_EQ(task, provider.GetTaskOfUrlRequest(unique_id.GetUnsafeValue(), 0)); + ASSERT_EQ(task, provider.GetTaskOfUrlRequest(unique_id.GetUnsafeValue(), 1)); const int64_t bytes_read = 1024; task->OnNetworkBytesRead(bytes_read); @@ -161,7 +162,7 @@ for (const auto& types_pair : process_task_types_pairs) { // Add the task. - ChildProcessData data(types_pair.process_type_); + ChildProcessData data(types_pair.process_type_, content::ChildProcessId()); data.SetProcess(base::Process::Current()); provider.BrowserChildProcessLaunchedAndConnected(data); ASSERT_EQ(1U, provided_tasks_.size());
diff --git a/chrome/browser/task_manager/providers/render_process_host_task_provider.cc b/chrome/browser/task_manager/providers/render_process_host_task_provider.cc index cdd4b23..37a551826 100644 --- a/chrome/browser/task_manager/providers/render_process_host_task_provider.cc +++ b/chrome/browser/task_manager/providers/render_process_host_task_provider.cc
@@ -77,9 +77,9 @@ // TODO(cburn): plumb out something from RPH so the title can be set here. // Create the task and notify the observer. - ChildProcessData data(content::PROCESS_TYPE_RENDERER); + ChildProcessData data(content::PROCESS_TYPE_RENDERER, host->GetID()); data.SetProcess(host->GetProcess().Duplicate()); - data.id = host->GetDeprecatedID(); + task = std::make_unique<ChildProcessTask>( data, ChildProcessTask::ProcessSubtype::kUnknownRenderProcess); NotifyObserverTaskAdded(task.get());
diff --git a/chrome/browser/task_manager/providers/spare_render_process_host_task_provider.cc b/chrome/browser/task_manager/providers/spare_render_process_host_task_provider.cc index 9bd76cd..4814227 100644 --- a/chrome/browser/task_manager/providers/spare_render_process_host_task_provider.cc +++ b/chrome/browser/task_manager/providers/spare_render_process_host_task_provider.cc
@@ -55,9 +55,9 @@ void SpareRenderProcessHostTaskProvider::OnSpareRenderProcessHostReady( RenderProcessHost* host) { - ChildProcessData data(content::PROCESS_TYPE_RENDERER); + ChildProcessData data(content::PROCESS_TYPE_RENDERER, host->GetID()); data.SetProcess(host->GetProcess().Duplicate()); - data.id = host->GetDeprecatedID(); + auto task = std::make_unique<ChildProcessTask>( data, ChildProcessTask::ProcessSubtype::kSpareRenderProcess);
diff --git a/chrome/browser/task_manager/providers/web_contents/tab_contents_task.cc b/chrome/browser/task_manager/providers/web_contents/tab_contents_task.cc index d9b7711..b2339dde 100644 --- a/chrome/browser/task_manager/providers/web_contents/tab_contents_task.cc +++ b/chrome/browser/task_manager/providers/web_contents/tab_contents_task.cc
@@ -7,9 +7,12 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/web_contents.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/browser/process_map.h" -#include "extensions/common/constants.h" + +#if !BUILDFLAG(IS_ANDROID) +#include "extensions/browser/extension_registry.h" // nogncheck +#include "extensions/browser/process_map.h" // nogncheck +#include "extensions/common/constants.h" // nogncheck +#endif // !BUILDFLAG(IS_ANDROID) namespace task_manager { @@ -17,8 +20,12 @@ bool HostsExtension(content::WebContents* web_contents) { DCHECK(web_contents); +#if BUILDFLAG(IS_ANDROID) + return false; +#else // BUILDFLAG(IS_ANDROID) return web_contents->GetLastCommittedURL().SchemeIs( extensions::kExtensionScheme); +#endif // BUILDFLAG(IS_ANDROID) } } // namespace @@ -53,6 +60,10 @@ // Check if the URL is an app and if the tab is hoisting an extension. Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + +#if BUILDFLAG(IS_ANDROID) + bool is_app = false; +#else // BUILDFLAG(IS_ANDROID) extensions::ProcessMap* process_map = extensions::ProcessMap::Get(profile); extensions::ExtensionRegistry* extension_registry = extensions::ExtensionRegistry::Get(profile); @@ -60,6 +71,8 @@ bool is_app = process_map->Contains(GetChildProcessUniqueID()) && extension_registry->enabled_extensions().GetAppByURL(url) != nullptr; +#endif // BUILDFLAG(IS_ANDROID) + bool is_extension = HostsExtension(web_contents()); bool is_incognito = profile->IsOffTheRecord();
diff --git a/chrome/browser/task_manager/providers/web_contents/web_contents_tag.cc b/chrome/browser/task_manager/providers/web_contents/web_contents_tag.cc index ba579ba..4bc3f290 100644 --- a/chrome/browser/task_manager/providers/web_contents/web_contents_tag.cc +++ b/chrome/browser/task_manager/providers/web_contents/web_contents_tag.cc
@@ -29,6 +29,6 @@ } // static -void* WebContentsTag::kTagKey = &WebContentsTag::kTagKey; +const void* WebContentsTag::kTagKey = &WebContentsTag::kTagKey; } // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/web_contents/web_contents_tag.h b/chrome/browser/task_manager/providers/web_contents/web_contents_tag.h index 353601d..b19b4537 100644 --- a/chrome/browser/task_manager/providers/web_contents/web_contents_tag.h +++ b/chrome/browser/task_manager/providers/web_contents/web_contents_tag.h
@@ -54,7 +54,7 @@ private: // The user data key. - static void* kTagKey; + static const void* kTagKey; // The owning WebContents. raw_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc index 5b19881..f80c8a5 100644 --- a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc +++ b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc
@@ -20,7 +20,9 @@ #include "chrome/browser/task_manager/providers/web_contents/prerender_task.h" #include "chrome/browser/task_manager/providers/web_contents/subframe_task.h" #include "chrome/browser/task_manager/providers/web_contents/web_contents_tags_manager.h" +#if !BUILDFLAG(IS_ANDROID) #include "components/guest_view/browser/guest_view_base.h" +#endif // !BUILDFLAG(IS_ANDROID) #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" @@ -42,9 +44,14 @@ if (!base::FeatureList::IsEnabled(features::kGuestViewMPArch)) { return false; } +#if BUILDFLAG(IS_ANDROID) + // Guest view is not enabled on Android. + return false; +#else // BUILDFLAG(IS_ANDROID) auto* guest = guest_view::GuestViewBase::FromRenderFrameHost(render_frame_host); return guest && guest->GetGuestMainFrame() == render_frame_host; +#endif // BUILDFLAG(IS_ANDROID) } } // namespace
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.cc b/chrome/browser/task_manager/sampling/task_manager_impl.cc index 0073bb0d..0f42123 100644 --- a/chrome/browser/task_manager/sampling/task_manager_impl.cc +++ b/chrome/browser/task_manager/sampling/task_manager_impl.cc
@@ -26,11 +26,7 @@ #include "chrome/browser/task_manager/providers/fallback_task_provider.h" #include "chrome/browser/task_manager/providers/render_process_host_task_provider.h" #include "chrome/browser/task_manager/providers/spare_render_process_host_task_provider.h" - -#if !BUILDFLAG(IS_ANDROID) #include "chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.h" -#endif // !BUIDLFLAG(IS_ANDROID) - #include "chrome/browser/task_manager/providers/worker_task_provider.h" #include "chrome/browser/task_manager/sampling/shared_sampler.h" #include "components/nacl/common/buildflags.h" @@ -89,11 +85,7 @@ std::make_unique<SpareRenderProcessHostTaskProvider>()); primary_subproviders.push_back(std::make_unique<WorkerTaskProvider>()); -// TODO(crbug.com/379192565): Research whether the following providers make -// sense on Android and otherwise remove this TODO. -#if !BUILDFLAG(IS_ANDROID) primary_subproviders.push_back(std::make_unique<WebContentsTaskProvider>()); -#endif task_providers_.push_back(std::make_unique<FallbackTaskProvider>( std::move(primary_subproviders),
diff --git a/chrome/browser/task_manager/web_contents_tags.cc b/chrome/browser/task_manager/web_contents_tags.cc index 63d8552..0afed99 100644 --- a/chrome/browser/task_manager/web_contents_tags.cc +++ b/chrome/browser/task_manager/web_contents_tags.cc
@@ -10,7 +10,6 @@ #include "build/build_config.h" #include "chrome/browser/task_manager/providers/web_contents/background_contents_tag.h" #include "chrome/browser/task_manager/providers/web_contents/devtools_tag.h" -#include "chrome/browser/task_manager/providers/web_contents/extension_tag.h" #include "chrome/browser/task_manager/providers/web_contents/guest_tag.h" #include "chrome/browser/task_manager/providers/web_contents/no_state_prefetch_tag.h" #include "chrome/browser/task_manager/providers/web_contents/printing_tag.h" @@ -18,15 +17,19 @@ #include "chrome/browser/task_manager/providers/web_contents/tool_tag.h" #include "chrome/browser/task_manager/providers/web_contents/web_app_tag.h" #include "chrome/browser/task_manager/providers/web_contents/web_contents_tags_manager.h" -#include "components/guest_view/browser/guest_view_base.h" #include "components/webapps/common/web_app_id.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" -#include "extensions/browser/process_manager.h" -#include "extensions/browser/view_type_utils.h" -#include "extensions/common/mojom/view_type.mojom.h" #include "printing/buildflags/buildflags.h" +#if !BUILDFLAG(IS_ANDROID) +#include "chrome/browser/task_manager/providers/web_contents/extension_tag.h" +#include "components/guest_view/browser/guest_view_base.h" +#include "extensions/browser/process_manager.h" // nogncheck +#include "extensions/browser/view_type_utils.h" // nogncheck +#include "extensions/common/mojom/view_type.mojom.h" // nogncheck +#endif // !BUILDFLAG(IS_ANDROID) + namespace task_manager { namespace { @@ -36,7 +39,7 @@ // Note: This will fail if |contents| is already tagged by |tag|. void TagWebContents(content::WebContents* contents, std::unique_ptr<WebContentsTag> tag, - void* tag_key) { + const void* tag_key) { DCHECK(contents); DCHECK(tag); DCHECK(WebContentsTag::FromWebContents(contents) == nullptr); @@ -45,6 +48,7 @@ WebContentsTagsManager::GetInstance()->AddTag(tag_ptr); } +#if !BUILDFLAG(IS_ANDROID) bool IsExtensionWebContents(content::WebContents* contents) { DCHECK(contents); @@ -59,9 +63,11 @@ view_type != extensions::mojom::ViewType::kBackgroundContents && view_type != extensions::mojom::ViewType::kDeveloperTools); } +#endif // !BUILDFLAG(IS_ANDROID) } // namespace +#if !BUILDFLAG(IS_ANDROID) // static void WebContentsTags::CreateForBackgroundContents( content::WebContents* web_contents, @@ -73,6 +79,7 @@ WebContentsTag::kTagKey); } } +#endif // static void WebContentsTags::CreateForDevToolsContents( @@ -115,6 +122,7 @@ #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) } +#if !BUILDFLAG(IS_ANDROID) // static void WebContentsTags::CreateForGuestContents( content::WebContents* web_contents) { @@ -140,6 +148,7 @@ WebContentsTag::kTagKey); } } +#endif // !BUILDFLAG(IS_ANDROID) // static void WebContentsTags::CreateForWebApp(content::WebContents* web_contents,
diff --git a/chrome/browser/task_manager/web_contents_tags.h b/chrome/browser/task_manager/web_contents_tags.h index 399d464..7c472f5 100644 --- a/chrome/browser/task_manager/web_contents_tags.h +++ b/chrome/browser/task_manager/web_contents_tags.h
@@ -5,10 +5,16 @@ #ifndef CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_TAGS_H_ #define CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_TAGS_H_ +#include "build/build_config.h" #include "components/webapps/common/web_app_id.h" -#include "extensions/common/mojom/view_type.mojom.h" +#if !BUILDFLAG(IS_ANDROID) +#include "extensions/common/mojom/view_type.mojom.h" // nogncheck +#endif // !BUILDFLAG(IS_ANDROID) + +#if !BUILDFLAG(IS_ANDROID) class BackgroundContents; +#endif // !BUILDFLAG(IS_ANDROID) namespace content { class WebContents; @@ -28,6 +34,7 @@ WebContentsTags(const WebContentsTags&) = delete; WebContentsTags& operator=(const WebContentsTags&) = delete; +#if !BUILDFLAG(IS_ANDROID) // Tags a BackgroundContents so that it shows up in the task manager. Calling // this function creates a BackgroundContentsTag, and attaches it to // |web_contents|. If an instance is already attached, this does nothing. The @@ -36,6 +43,7 @@ static void CreateForBackgroundContents( content::WebContents* web_contents, BackgroundContents* background_contents); +#endif // !BUILDFLAG(IS_ANDROID) // Tags a DevTools WebContents so that it shows up in the task manager. // Calling this function creates a DevToolsTag, and attaches it to @@ -66,6 +74,7 @@ // up by the caller, as it is owned by |web_contents|. static void CreateForPrintingContents(content::WebContents* web_contents); +#if !BUILDFLAG(IS_ANDROID) // Tags a WebContents owned by a GuestViewBase so that it shows up in the // task manager. Calling this function creates a GuestTag, and attaches it to // |web_contents|. If an instance is already attached, this does nothing. The @@ -82,6 +91,7 @@ // non-background contents Extension. static void CreateForExtension(content::WebContents* web_contents, extensions::mojom::ViewType view_type); +#endif // !BUILDFLAG(IS_ANDROID) // Tags a WebContents created for a tool so that it shows up in the task // manager. Calling this function creates a ToolTag, and attaches it to
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index f3a089e..cea6e13 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -290,6 +290,8 @@ if (enable_session_service) { sources += [ + "webui/internals/internals_ui.cc", + "webui/internals/internals_ui.h", "webui/internals/sessions/session_service_internals_handler.cc", "webui/internals/sessions/session_service_internals_handler.h", ] @@ -1418,10 +1420,6 @@ "webui/identity_internals_ui.h", "webui/inspect_ui.cc", "webui/inspect_ui.h", - "webui/internals/internals_ui.cc", - "webui/internals/internals_ui.h", - "webui/internals/user_education/user_education_internals_page_handler_impl.cc", - "webui/internals/user_education/user_education_internals_page_handler_impl.h", "webui/managed_ui_handler.cc", "webui/managed_ui_handler.h", "webui/management/management_ui.cc", @@ -1622,6 +1620,10 @@ "webui/theme_handler.h", "webui/theme_source.cc", "webui/theme_source.h", + "webui/user_education_internals/user_education_internals_page_handler_impl.cc", + "webui/user_education_internals/user_education_internals_page_handler_impl.h", + "webui/user_education_internals/user_education_internals_ui.cc", + "webui/user_education_internals/user_education_internals_ui.h", "webui/web_app_internals/iwa_internals_handler.cc", "webui/web_app_internals/iwa_internals_handler.h", "webui/web_app_internals/web_app_internals_handler.cc", @@ -2147,6 +2149,7 @@ "//ash/webui/projector_app", "//ash/webui/projector_app/public/mojom:projector_mojo_bindings", "//ash/webui/sanitize_ui", + "//ash/webui/scanner_feedback_ui", "//ash/webui/scanning", "//ash/webui/settings/public/constants", "//ash/webui/settings/public/constants:mojom",
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java index 60aac01..0f11ec0bb 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java
@@ -728,26 +728,62 @@ assertEquals(3, sheetItemListView.getAdapter().getItemCount()); View anaRow = sheetItemListView.getChildAt(0); - float delta = 0.00001f; - assertEquals(anaRow.getAlpha(), 1.f, delta); + assertEquals(anaRow.getAlpha(), 1.f, ALPHA_COMPARISON_DELTA); TextView textView = anaRow.findViewById(R.id.title); assertEquals("Ana Doe", textView.getText()); textView = anaRow.findViewById(R.id.description); assertEquals("ana@email.example", textView.getText()); View nicolasRow = sheetItemListView.getChildAt(1); - assertEquals(nicolasRow.getAlpha(), AccountSelectionViewBinder.DISABLED_OPACITY, delta); + assertEquals( + nicolasRow.getAlpha(), + AccountSelectionViewBinder.DISABLED_OPACITY, + ALPHA_COMPARISON_DELTA); textView = nicolasRow.findViewById(R.id.title); assertEquals("nicolas@example.com", textView.getText()); textView = nicolasRow.findViewById(R.id.description); assertEquals("You can’t sign in using this account", textView.getText()); View addAccountButton = sheetItemListView.getChildAt(2); - assertEquals(addAccountButton.getAlpha(), 1.f, delta); + assertEquals(addAccountButton.getAlpha(), 1.f, ALPHA_COMPARISON_DELTA); textView = addAccountButton.findViewById(R.id.title); assertEquals("Use a different account", textView.getText()); } + @Test + public void testFilteredOutAccountNoContinueButton() { + // Show a newly logged in filtered account. + mMediator.showAccounts( + mTestEtldPlusOne, + mTestEtldPlusOne2, + Arrays.asList(mFilteredOutAccount), + mIdpDataWithUseDifferentAccount, + /* isAutoReauthn= */ false, + Arrays.asList(mFilteredOutAccount)); + // Account chooser is shown. + assertEquals(HeaderType.SIGN_IN, mModel.get(ItemProperties.HEADER).get(TYPE)); + assertEquals(2, mSheetAccountItems.size()); + assertNull(mSheetAccountItems.get(0).model.get(AccountProperties.ON_CLICK_LISTENER)); + + View sheetContainer = mContentView.findViewById(R.id.sheet_item_list_container); + RecyclerView sheetItemListView = sheetContainer.findViewById(R.id.sheet_item_list); + View filteredAccountRow = sheetItemListView.getChildAt(0); + assertEquals( + filteredAccountRow.getAlpha(), + AccountSelectionViewBinder.DISABLED_OPACITY, + ALPHA_COMPARISON_DELTA); + TextView textView = filteredAccountRow.findViewById(R.id.title); + assertEquals("nicolas@example.com", textView.getText()); + textView = filteredAccountRow.findViewById(R.id.description); + assertEquals("You can’t sign in using this account", textView.getText()); + + View addAccountButton = sheetItemListView.getChildAt(1); + assertEquals(addAccountButton.getAlpha(), 1.f, ALPHA_COMPARISON_DELTA); + textView = addAccountButton.findViewById(R.id.title); + assertEquals("Use a different account", textView.getText()); + assertFalse(containsItemOfType(mModel, ItemProperties.CONTINUE_BUTTON)); + } + private void pressBack() { if (mBottomSheetContent.handleBackPress()) return;
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java index ea323210..7648ac0f 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java
@@ -121,6 +121,7 @@ IdentityRequestDialogDisclosureField.EMAIL, IdentityRequestDialogDisclosureField.PICTURE }; + protected static final float ALPHA_COMPARISON_DELTA = 0.00001f; @Mock Callback<Account> mAccountCallback; @Mock AccountSelectionComponent.Delegate mMockDelegate;
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java index adad888..321c77f 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
@@ -316,7 +316,10 @@ View continueButton = contentView.findViewById(R.id.account_selection_continue_btn); - boolean isSingleAccountChooser = mAccounts != null && mAccounts.size() == 1; + boolean isSingleAccountChooser = + mAccounts != null + && mAccounts.size() == 1 + && !mAccounts.get(0).isFilteredOut(); View focusView = mFocusView != null ? mFocusView @@ -895,7 +898,11 @@ private void showAccountsInternal(@Nullable List<Account> newAccounts) { // TODO(crbug.com/356665527): Handle multiple newly signed-in accounts. Account newlySignedInAccount = - newAccounts != null && newAccounts.size() == 1 ? newAccounts.get(0) : null; + newAccounts != null + && newAccounts.size() == 1 + && !newAccounts.get(0).isFilteredOut() + ? newAccounts.get(0) + : null; if (!mIsAutoReauthn && newlySignedInAccount != null && mRpMode == RpMode.ACTIVE) { mSelectedAccount = newlySignedInAccount; @@ -961,7 +968,8 @@ mHeaderType == HeaderType.SIGN_IN && areAccountsClickable && mIdpMetadata.showUseDifferentAccountButton(); - boolean isSingleAccountChooser = accounts != null && accounts.size() == 1; + boolean isSingleAccountChooser = + accounts != null && accounts.size() == 1 && !accounts.get(0).isFilteredOut(); // We add the add account button alongside the accounts if supported in passive mode and in // the multi-account UI of active mode.
diff --git a/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc b/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc index abed48f4..9ae209b 100644 --- a/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc +++ b/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc
@@ -47,7 +47,7 @@ using TestVariantsParam = std::tuple< /*is_apps_collections_enabled=*/bool, - /*is_welcome_tour_v2_enabled=*/bool, + /*is_welcome_tour_v3_enabled=*/bool, /*is_welcome_tour_counterfactaully_enabled=*/bool>; // Matchers -------------------------------------------------------------------- @@ -66,7 +66,7 @@ return std::get<0>(param); } -bool IsWelcomeTourV2Enabled(TestVariantsParam param) { +bool IsWelcomeTourV3Enabled(TestVariantsParam param) { return std::get<1>(param); } @@ -77,7 +77,7 @@ std::string GenerateTestSuffix( const testing::TestParamInfo<TestVariantsParam>& info) { return base::StrCat( - {IsWelcomeTourV2Enabled(info.param) ? "V2" : "V1", "_", + {IsWelcomeTourV3Enabled(info.param) ? "V3" : "V1", "_", IsWelcomeTourCounterfactuallyEnabled(info.param) ? "Counterfactual_" : "", IsAppsCollectionsEnabled(info.param) ? "AppsCollectionsEnabled" @@ -97,12 +97,12 @@ // NOTE: These tests are not concerned with user eligibility, so explicitly // force user eligibility for the Welcome Tour. // Only one of `kWelcomeTourHoldbackArm`, `kWelcomeTourCounterfactualArm` - // and `kWelcomeTourV2` can be enabled at a time. + // and `kWelcomeTourV3` can be enabled at a time. scoped_feature_list_.InitWithFeatureStates( {{ash::features::kWelcomeTour, true}, {ash::features::kWelcomeTourForceUserEligibility, true}, - {ash::features::kWelcomeTourV2, - IsWelcomeTourV2Enabled() && !IsWelcomeTourCounterfactuallyEnabled()}, + {ash::features::kWelcomeTourV3, + IsWelcomeTourV3Enabled() && !IsWelcomeTourCounterfactuallyEnabled()}, {ash::features::kWelcomeTourCounterfactualArm, IsWelcomeTourCounterfactuallyEnabled()}, {ash::features::kWelcomeTourHoldbackArm, false}, @@ -144,10 +144,10 @@ return ::IsAppsCollectionsEnabled(GetParam()); } - // Returns whether the WelcomeTourV2 feature is enabled given test + // Returns whether the WelcomeTourV3 feature is enabled given test // parameterization. - bool IsWelcomeTourV2Enabled() const { - return ::IsWelcomeTourV2Enabled(GetParam()); + bool IsWelcomeTourV3Enabled() const { + return ::IsWelcomeTourV3Enabled(GetParam()); } // Returns whether the WelcomeTour feature is counterfactually enabled given @@ -306,7 +306,7 @@ WelcomeTourInteractiveUiTest, testing::Combine( /*is_apps_collections_enabled=*/testing::Bool(), - /*is_welcome_tour_v2_enabled=*/testing::Bool(), + /*is_welcome_tour_v3_enabled=*/testing::Bool(), /*is_welcome_tour_counterfactually_enabled=*/testing::Bool()), &GenerateTestSuffix); @@ -319,17 +319,12 @@ RunTestSequence( // Step 0: Dialog. InAnyContext(WaitForDialogVisibility(true)), - InSameContext( - Steps(CheckDialogAcceptButtonFocus(true), - CheckDialogAcceptButtonText(), CheckDialogCancelButtonText(), - CheckDialogDescription( - ash::features::IsWelcomeTourV2Enabled() - ? IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT_V2 - : IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT), - CheckDialogTitle(ash::features::IsWelcomeTourV2Enabled() - ? IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT_V2 - : IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT), - PressDialogAcceptButton())), + InSameContext(Steps( + CheckDialogAcceptButtonFocus(true), CheckDialogAcceptButtonText(), + CheckDialogCancelButtonText(), + CheckDialogDescription(IDS_ASH_WELCOME_TOUR_DIALOG_DESCRIPTION_TEXT), + CheckDialogTitle(IDS_ASH_WELCOME_TOUR_DIALOG_TITLE_TEXT), + PressDialogAcceptButton())), // Step 1: Shelf. InAnyContext(WaitForHelpBubble()), @@ -341,17 +336,18 @@ CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), PressHelpBubbleDefaultButton())), - // Step 2: Status area. - InAnyContext(WaitForHelpBubble()), - InSameContext( - Steps(CheckHelpBubbleAnchor(ash::kUnifiedSystemTrayElementId), - CheckHelpBubbleBodyText(l10n_util::GetStringUTF16( - IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT)), - CheckHelpBubbleDefaultButtonFocus(true), - CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), - PressHelpBubbleDefaultButton())), + // Step 2 in V1: Status area. + If([&] { return !ash::features::IsWelcomeTourV3Enabled(); }, + InAnyContext( + Steps(WaitForHelpBubble(), + CheckHelpBubbleAnchor(ash::kUnifiedSystemTrayElementId), + CheckHelpBubbleBodyText(l10n_util::GetStringUTF16( + IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT)), + CheckHelpBubbleDefaultButtonFocus(true), + CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), + PressHelpBubbleDefaultButton()))), - // Step 3: Home button. + // Step 3 in V1 and step 2 in V3: Home button. InAnyContext(WaitForHelpBubble()), InSameContext(Steps( CheckHelpBubbleAnchor(ash::kHomeButtonElementId), @@ -364,7 +360,7 @@ CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), PressHelpBubbleDefaultButton())), - // Step 4: Search box. + // Step 4 in V1 and step 3 in V3: Search box. InAnyContext(WaitForHelpBubble()), InSameContext(Steps( CheckAppListBubbleVisibility(true), @@ -375,8 +371,8 @@ CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), PressHelpBubbleDefaultButton())), - // Step 5 in V2: Files app. - If([&] { return ash::features::IsWelcomeTourV2Enabled(); }, + // Step 4 in V3: Files app. + If([&] { return ash::features::IsWelcomeTourV3Enabled(); }, InAnyContext( Steps(WaitForHelpBubble(), CheckAppListBubbleVisibility(true), CheckHelpBubbleAnchor(ash::kFilesAppElementId), @@ -386,7 +382,7 @@ CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), PressHelpBubbleDefaultButton()))), - // Step 5 in V1 and step 6 in V2: Settings app. + // Step 5: Settings app. InAnyContext(WaitForHelpBubble()), InSameContext( Steps(CheckAppListBubbleVisibility(true), @@ -398,7 +394,7 @@ CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), PressHelpBubbleDefaultButton())), - // Step 6 in V1 and step 7 in V2: Explore app. + // Step 6: Explore app. InAnyContext(WaitForHelpBubble()), InSameContext(Steps( CheckAppListBubbleVisibility(true), @@ -410,7 +406,7 @@ IDS_ASH_WELCOME_TOUR_COMPLETE_BUTTON_TEXT), PressHelpBubbleDefaultButton())), - // Step 7 in V1 and step 8 in V2: Explore app window. + // Step 7: Explore app window. InAnyContext(WaitForBrowser()), InSameContext(Steps(WaitForAppListBubbleToHide(), CheckBrowserIsForWebApp(ash::kHelpAppId))));
diff --git a/chrome/browser/ui/chromeos/magic_boost/magic_boost_card_controller.cc b/chrome/browser/ui/chromeos/magic_boost/magic_boost_card_controller.cc index 6e2c18d..d14310b2 100644 --- a/chrome/browser/ui/chromeos/magic_boost/magic_boost_card_controller.cc +++ b/chrome/browser/ui/chromeos/magic_boost/magic_boost_card_controller.cc
@@ -110,7 +110,9 @@ void MagicBoostCardController::ShowOptInUi( const gfx::Rect& anchor_view_bounds) { - CHECK(!opt_in_widget_); + if (opt_in_widget_) { + opt_in_widget_.reset(); + } // If the disclaimer view is showing, close it. CloseDisclaimerUi();
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h index 8ddd88b8..dff71d0 100644 --- a/chrome/browser/ui/color/chrome_color_id.h +++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -789,6 +789,7 @@ E_CPONLY(kColorTaskManagerBackground) \ E_CPONLY(kColorTaskManagerSearchBarBackground) \ E_CPONLY(kColorTaskManagerSearchBarTransparent) \ + E_CPONLY(kColorTaskManagerSearchBarPlaceholderText) \ /* Thumbnail tab colors. */ \ E_CPONLY(kColorThumbnailTabBackground) \ E_CPONLY(kColorThumbnailTabForeground) \
diff --git a/chrome/browser/ui/color/chrome_color_mixer.cc b/chrome/browser/ui/color/chrome_color_mixer.cc index 48ab546f..806c7b7 100644 --- a/chrome/browser/ui/color/chrome_color_mixer.cc +++ b/chrome/browser/ui/color/chrome_color_mixer.cc
@@ -651,6 +651,8 @@ mixer[kColorTaskManagerSearchBarBackground] = { ui::kColorSysBaseContainerElevated}; mixer[kColorTaskManagerSearchBarTransparent] = {SK_ColorTRANSPARENT}; + mixer[kColorTaskManagerSearchBarPlaceholderText] = { + ui::kColorTextfieldForeground}; } #endif // BUILDFLAG(IS_ANDROID) mixer[kColorThumbnailTabBackground] =
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 6e28cc6..4f59270 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -83,6 +83,7 @@ #include "chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h" #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h" #include "chrome/browser/tab_contents/navigation_metrics_recorder.h" +#include "chrome/browser/task_manager/web_contents_tags.h" #include "chrome/browser/tpcd/heuristics/opener_heuristic_tab_helper.h" #include "chrome/browser/tpcd/heuristics/redirect_heuristic_tab_helper.h" #include "chrome/browser/tpcd/http_error_observer/http_error_tab_helper.h" @@ -608,6 +609,7 @@ } PolicyAuditorBridge::CreateForWebContents(web_contents); PluginObserverAndroid::CreateForWebContents(web_contents); + task_manager::WebContentsTags::CreateForTabContents(web_contents); if (base::FeatureList::IsEnabled(payments::facilitated::kEnablePixPayments) || base::FeatureList::IsEnabled(blink::features::kPaymentLinkDetection)) {
diff --git a/chrome/browser/ui/tabs/public/tab_interface.h b/chrome/browser/ui/tabs/public/tab_interface.h index 7ff1ca7..9eda44ab 100644 --- a/chrome/browser/ui/tabs/public/tab_interface.h +++ b/chrome/browser/ui/tabs/public/tab_interface.h
@@ -129,6 +129,11 @@ virtual bool CanShowModalUI() const = 0; virtual std::unique_ptr<ScopedTabModalUI> ShowModalUI() = 0; + // Register for this callback to detect when a modal is shown or hidden. + using TabInterfaceCallback = base::RepeatingCallback<void(TabInterface*)>; + virtual base::CallbackListSubscription RegisterModalUIChanged( + TabInterfaceCallback callback) = 0; + // A normal browser window has a tab strip and an omnibox. The returned value // never changes. virtual bool IsInNormalWindow() const = 0;
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/DEPS b/chrome/browser/ui/tabs/saved_tab_groups/DEPS index 76561bc1..ea95eba 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/DEPS +++ b/chrome/browser/ui/tabs/saved_tab_groups/DEPS
@@ -2,4 +2,5 @@ "+components/saved_tab_groups", "+components/saved_tab_groups/delegate", "+components/saved_tab_groups/public", + "+components/data_sharing", ]
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer_browsertest.cc b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer_browsertest.cc index 6e17af7..c31b425 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer_browsertest.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer_browsertest.cc
@@ -148,6 +148,10 @@ // CHIP messages set the message in TabFeatures auto tab2_id = browser()->tab_strip_model()->GetTabAtIndex(2)->GetHandle().raw_value(); + + // Prevent network request. + GetTabDataAtIndex(browser(), 2)->set_mocked_avatar_for_testing(gfx::Image()); + auto chip_message = CreateMessage("User", "URL", CollaborationEvent::TAB_ADDED, PersistentNotificationType::CHIP, tab2_id, group_id); @@ -207,6 +211,10 @@ // CHIP messages set the message in TabFeatures auto tab2_id = browser()->tab_strip_model()->GetTabAtIndex(2)->GetHandle().raw_value(); + + // Prevent network request. + GetTabDataAtIndex(browser(), 2)->set_mocked_avatar_for_testing(gfx::Image()); + auto chip_message = CreateMessage("User", "URL", CollaborationEvent::TAB_ADDED, PersistentNotificationType::CHIP, tab2_id, group_id);
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc index fbd420c3..7506b21 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.cc
@@ -4,15 +4,41 @@ #include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h" +#include "chrome/browser/data_sharing/data_sharing_service_factory.h" +#include "chrome/browser/image_fetcher/image_fetcher_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_key.h" +#include "chrome/browser/ui/layout_constants.h" #include "components/collaboration/public/messaging/message.h" +#include "components/data_sharing/public/data_sharing_service.h" +#include "components/image_fetcher/core/image_fetcher_service.h" #include "content/public/browser/web_contents_observer.h" -#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_util.h" using collaboration::messaging::PersistentMessage; namespace tab_groups { +namespace { -CollaborationMessagingTabData::CollaborationMessagingTabData() = default; +int GetHoverCardImageSize() { + return GetLayoutConstant(TAB_ALERT_INDICATOR_ICON_WIDTH); +} + +int GetPageActionImageSize() { + return GetLayoutConstant(LOCATION_BAR_TRAILING_ICON_SIZE); +} + +gfx::Image ResizeForHoverCard(const gfx::Image& image) { + auto image_size = GetHoverCardImageSize(); + auto size = gfx::Size(image_size, image_size); + return gfx::ResizedImage(image, size); +} + +} // namespace + +CollaborationMessagingTabData::CollaborationMessagingTabData(Profile* profile) + : profile_(profile) {} CollaborationMessagingTabData::~CollaborationMessagingTabData() = default; void CollaborationMessagingTabData::SetMessage(PersistentMessage message) { @@ -26,12 +52,35 @@ CHECK(message.collaboration_event == CollaborationEvent::TAB_ADDED || message.collaboration_event == CollaborationEvent::TAB_UPDATED); - message_ = message; - NotifyMessageChanged(); + // Chip messages must contain a triggering user. + CHECK(message.attribution.triggering_user.has_value()); + + // Cache this message to prevent committing stale data when the + // image request resolves. + message_to_commit_ = message; + + if (mock_avatar_for_testing_.has_value()) { + // Testing path only. + // Commit the message outright without triggering a network request. + CommitMessage(message, mock_avatar_for_testing_.value()); + } else { + // Initiate the request to fetch the avatar image. Rather than setting + // the message data directly, the data will be set once the image request + // is resolved. This prevents UI flicker in the user's avatar. + FetchAvatar(message); + } } void CollaborationMessagingTabData::ClearMessage(PersistentMessage message) { - message_ = std::nullopt; + // Reject committing data from any in-flight requests. + message_to_commit_ = std::nullopt; + + // Clear out all data, i.e. set HasMessage() to return false. + given_name_ = std::u16string(); + page_action_avatar_ = ui::ImageModel(); + hover_card_avatar_ = ui::ImageModel(); + collaboration_event_ = CollaborationEvent::UNDEFINED; + NotifyMessageChanged(); } @@ -45,4 +94,73 @@ message_changed_callback_list_.Notify(); } +void CollaborationMessagingTabData::FetchAvatar(PersistentMessage message) { + // Safe to unwrap member because it was previously CHECKed. + auto avatar_url = message.attribution.triggering_user->avatar_url; + + image_fetcher::ImageFetcherService* image_fetcher_service = + ImageFetcherServiceFactory::GetForKey(profile_->GetProfileKey()); + if (!image_fetcher_service) { + // Commit message immediately without an image. + return CommitMessage(message, gfx::Image()); + } + + data_sharing::DataSharingService* const data_sharing_service = + data_sharing::DataSharingServiceFactory::GetForProfile(profile_); + if (!data_sharing_service) { + // Commit message immediately without an image. + return CommitMessage(message, gfx::Image()); + } + + // Perform the request using disk caching. The page action icon size + // is used to request the larger of the 2 images needed. The sizes are + // similar enough that the larger image is resized to accommodate the + // smaller hover card image. + data_sharing_service->GetAvatarImageForURL( + avatar_url, GetPageActionImageSize(), + base::BindOnce(&CollaborationMessagingTabData::CommitMessage, + base::Unretained(this), message), + image_fetcher_service->GetImageFetcher( + image_fetcher::ImageFetcherConfig::kDiskCacheOnly)); +} + +void CollaborationMessagingTabData::CommitMessage( + PersistentMessage requested_message, + const gfx::Image& avatar) { + if (!message_to_commit_.has_value()) { + // If the message to commit has been cleared, do nothing. + return; + } + + // Only commit message data if the requested avatar has not changed + // since last requested. + if (message_to_commit_->attribution.triggering_user->avatar_url != + requested_message.attribution.triggering_user->avatar_url) { + return; + } + + // Since it is possible for the message to have changed while the avatar + // stayed the same (i.e. the same user performed another action on + // this tab), this will use the collaboration_event from the most recent + // message_to_commit_ and subsequently reset it. + given_name_ = base::UTF8ToUTF16( + message_to_commit_->attribution.triggering_user->given_name); + collaboration_event_ = message_to_commit_->collaboration_event; + + // In rare cases such as null services or no response data, there + // may not be an avatar to display. Downstream UIs will be responsible + // for deciding what to show instead. + if (avatar.IsEmpty()) { + page_action_avatar_ = ui::ImageModel(); + hover_card_avatar_ = ui::ImageModel(); + } else { + page_action_avatar_ = ui::ImageModel::FromImage(avatar); + hover_card_avatar_ = ui::ImageModel::FromImage(ResizeForHoverCard(avatar)); + } + + // Message has been committed. + message_to_commit_ = std::nullopt; + NotifyMessageChanged(); +} + } // namespace tab_groups
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h index 3086d8ea..e8809cc79 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h
@@ -8,6 +8,9 @@ #include "base/callback_list.h" #include "base/strings/utf_string_conversions.h" #include "components/collaboration/public/messaging/message.h" +#include "ui/base/models/image_model.h" + +class Profile; namespace tab_groups { @@ -18,7 +21,7 @@ public: using CallbackList = base::RepeatingCallbackList<void()>; - CollaborationMessagingTabData(); + explicit CollaborationMessagingTabData(Profile* profile); CollaborationMessagingTabData(CollaborationMessagingTabData& other) = delete; CollaborationMessagingTabData& operator=( CollaborationMessagingTabData& other) = delete; @@ -29,33 +32,40 @@ void SetMessage(PersistentMessage message); void ClearMessage(PersistentMessage message); - bool HasMessage() { return message_.has_value(); } + bool HasMessage() { + return !given_name_.empty() && + collaboration_event_ != CollaborationEvent::UNDEFINED; + } + // Testing only. Method for setting the avatar image fetch result. + // Calling SetMessage after this avoids a network request and commits + // the message data synchronously. + void set_mocked_avatar_for_testing(std::optional<gfx::Image> mock_avatar) { + mock_avatar_for_testing_ = mock_avatar; + } + + // Register a callback to be notified when the message changes. base::CallbackListSubscription RegisterMessageChangedCallback( CallbackList::CallbackType cb); - void NotifyMessageChanged(); std::u16string given_name() { CHECK(HasMessage()); - - auto member = message_->attribution.triggering_user; - CHECK(member.has_value()); - - return base::UTF8ToUTF16(member->given_name); + return given_name_; } - GURL avatar_url() { + ui::ImageModel hover_card_avatar() { CHECK(HasMessage()); + return hover_card_avatar_; + } - auto member = message_->attribution.triggering_user; - CHECK(member.has_value()); - - return member->avatar_url; + ui::ImageModel page_action_avatar() { + CHECK(HasMessage()); + return page_action_avatar_; } CollaborationEvent collaboration_event() { CHECK(HasMessage()); - return message_->collaboration_event; + return collaboration_event_; } base::WeakPtr<CollaborationMessagingTabData> GetWeakPtr() { @@ -63,7 +73,42 @@ } private: - std::optional<PersistentMessage> message_ = std::nullopt; + FRIEND_TEST_ALL_PREFIXES(CollaborationMessagingTabDataTest, + IgnoresRequestsWhenMessageIsCleared); + FRIEND_TEST_ALL_PREFIXES(CollaborationMessagingTabDataTest, + IgnoresRequestsWhenMessageIsChanged); + + // Notify callback list that a new message has been committed. + void NotifyMessageChanged(); + + // Fetch the avatar image and commit the result, if possible. + void FetchAvatar(PersistentMessage message); + + // Set the message data to be displayed and notify the callback list. + void CommitMessage(PersistentMessage message, const gfx::Image& avatar); + + raw_ptr<Profile> profile_; + + // The cached message while a request is in flight. This is used to + // verify that the message has not changed while the image was being + // requested. + std::optional<PersistentMessage> message_to_commit_ = std::nullopt; + + // Contains the given name of the user who triggered the event. + std::u16string given_name_; + + // Contains the type of event this message describes. + CollaborationEvent collaboration_event_ = CollaborationEvent::UNDEFINED; + + // Contains the avatar image sized for display in the tab Hovercard. + ui::ImageModel hover_card_avatar_; + + // Contains the avatar image sized for display in the PageAction. + ui::ImageModel page_action_avatar_; + + // Testing purposes only. Contains a mock image to use in lieu of making + // a network request for the avatar. + std::optional<gfx::Image> mock_avatar_for_testing_ = std::nullopt; // Listeners to notify when the message for this tab changes. CallbackList message_changed_callback_list_;
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc index 8622a149..8dfabb5f 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc
@@ -4,9 +4,14 @@ #include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h" -#include "base/test/mock_callback.h" +#include "chrome/browser/data_sharing/data_sharing_service_factory.h" +#include "chrome/browser/favicon/favicon_utils.h" +#include "chrome/test/base/testing_profile.h" #include "components/collaboration/public/messaging/message.h" +#include "components/data_sharing/public/data_sharing_service.h" #include "components/data_sharing/public/group_data.h" +#include "components/data_sharing/test_support/mock_data_sharing_service.h" +#include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" namespace tab_groups { @@ -16,82 +21,200 @@ using collaboration::messaging::PersistentMessage; using collaboration::messaging::PersistentNotificationType; using data_sharing::GroupMember; +using testing::_; + +namespace { +PersistentMessage CreateMessage(std::string given_name, + std::string avatar_url, + CollaborationEvent event) { + GroupMember member; + member.given_name = given_name; + member.avatar_url = GURL(avatar_url); + + MessageAttribution attribution; + attribution.triggering_user = member; + + PersistentMessage message; + message.type = PersistentNotificationType::CHIP; + message.attribution = attribution; + message.collaboration_event = event; + + return message; +} + +} // namespace class CollaborationMessagingTabDataTest : public testing::Test { protected: void SetUp() override { - tab_data_ = std::make_unique<CollaborationMessagingTabData>(); + TestingProfile::Builder builder; + + auto sharing_service = + std::make_unique<data_sharing::MockDataSharingService>(); + sharing_service_ = sharing_service.get(); + + builder.AddTestingFactory( + data_sharing::DataSharingServiceFactory::GetInstance(), + base::BindOnce( + [](std::unique_ptr<data_sharing::MockDataSharingService> + sharing_service, + content::BrowserContext* context) + -> std::unique_ptr<KeyedService> { return sharing_service; }, + std::move(sharing_service))); + + testing_profile_ = builder.Build(); + tab_data_ = std::make_unique<CollaborationMessagingTabData>(profile()); } + TestingProfile* profile() { return testing_profile_.get(); } CollaborationMessagingTabData& tab_data() { return *tab_data_; } - - PersistentMessage CreateMessage(std::string given_name, - std::string avatar_url, - CollaborationEvent event) { - GroupMember member; - member.given_name = given_name; - member.avatar_url = GURL(avatar_url); - - MessageAttribution attribution; - attribution.triggering_user = member; - - PersistentMessage message; - message.type = PersistentNotificationType::CHIP; - message.attribution = attribution; - message.collaboration_event = event; - - return message; + data_sharing::MockDataSharingService* sharing_service() { + return sharing_service_; } + protected: + content::BrowserTaskEnvironment task_environment_; + private: + std::unique_ptr<TestingProfile> testing_profile_; std::unique_ptr<CollaborationMessagingTabData> tab_data_; + raw_ptr<data_sharing::MockDataSharingService> sharing_service_; }; TEST_F(CollaborationMessagingTabDataTest, CanSetAndClearData) { EXPECT_FALSE(tab_data().HasMessage()); std::string given_name = "User"; - std::string avatar_url = "URL"; + std::string avatar_url = "https://google.com/chrome/1"; auto message = CreateMessage(given_name, avatar_url, CollaborationEvent::TAB_ADDED); - tab_data().SetMessage(message); + + // Run loop to trigger network request callback. + { + base::RunLoop run_loop; + auto quit_closure = run_loop.QuitClosure(); + + EXPECT_CALL(*sharing_service(), GetAvatarImageForURL) + .WillOnce([&](GURL url, int size, auto load_callback, auto fetcher) { + EXPECT_EQ(url, GURL(message.attribution.triggering_user->avatar_url)); + EXPECT_EQ(size, 20); + + // Trigger callback with a mock avatar. + std::move(load_callback).Run(favicon::GetDefaultFavicon()); + + quit_closure.Run(); + }); + + tab_data().SetMessage(message); + run_loop.Run(); + } + + // Data will be set. EXPECT_TRUE(tab_data().HasMessage()); EXPECT_EQ(tab_data().given_name(), base::UTF8ToUTF16(given_name)); - EXPECT_EQ(tab_data().avatar_url(), GURL(avatar_url)); EXPECT_EQ(tab_data().collaboration_event(), CollaborationEvent::TAB_ADDED); + EXPECT_FALSE(tab_data().page_action_avatar().IsEmpty()); // Overwrite with a new message. std::string given_name2 = "User2"; - std::string avatar_url2 = "URL2"; + std::string avatar_url2 = "https://google.com/chrome/2"; auto message2 = CreateMessage(given_name2, avatar_url2, CollaborationEvent::TAB_UPDATED); - tab_data().SetMessage(message2); + + // Run loop to trigger network request callback. + { + base::RunLoop run_loop; + auto quit_closure = run_loop.QuitClosure(); + + EXPECT_CALL(*sharing_service(), GetAvatarImageForURL) + .WillOnce([&](GURL url, int size, auto load_callback, auto fetcher) { + EXPECT_EQ(url, + GURL(message2.attribution.triggering_user->avatar_url)); + EXPECT_EQ(size, 20); + + // Trigger callback with empty image. + std::move(load_callback).Run(gfx::Image()); + + quit_closure.Run(); + }); + + tab_data().SetMessage(message2); + run_loop.Run(); + } + EXPECT_TRUE(tab_data().HasMessage()); EXPECT_EQ(tab_data().given_name(), base::UTF8ToUTF16(given_name2)); - EXPECT_EQ(tab_data().avatar_url(), GURL(avatar_url2)); EXPECT_EQ(tab_data().collaboration_event(), CollaborationEvent::TAB_UPDATED); + EXPECT_TRUE(tab_data().page_action_avatar().IsEmpty()); tab_data().ClearMessage(message2); EXPECT_FALSE(tab_data().HasMessage()); } -TEST_F(CollaborationMessagingTabDataTest, NotifiesListeners) { +TEST_F(CollaborationMessagingTabDataTest, IgnoresRequestsWhenMessageIsCleared) { EXPECT_FALSE(tab_data().HasMessage()); - auto message = CreateMessage("User", "URL", CollaborationEvent::TAB_ADDED); + std::string given_name = "User"; + std::string avatar_url = "https://google.com/chrome/1"; + auto message = + CreateMessage(given_name, avatar_url, CollaborationEvent::TAB_ADDED); - base::MockCallback<CollaborationMessagingTabData::CallbackList::CallbackType> - cb; - auto subscription = tab_data().RegisterMessageChangedCallback(cb.Get()); + // Service will be triggered to request the image. + EXPECT_CALL(*sharing_service(), + GetAvatarImageForURL(GURL(avatar_url), 20, _, _)) + .Times(1); - // Callback is called when message is set. - EXPECT_CALL(cb, Run); + // Set the message. This will trigger the avatar request, but will not + // set data since the fetcher is mocked. tab_data().SetMessage(message); - EXPECT_TRUE(tab_data().HasMessage()); - // Callback is called again when message is cleared. - EXPECT_CALL(cb, Run); + // Clear the message. This will cause the following Commit to be rejected. tab_data().ClearMessage(message); + + // Mock resolution of the avatar image request by directly + // triggering the callback. + tab_data().CommitMessage(message, gfx::Image()); + + // Data will not be set. + EXPECT_FALSE(tab_data().HasMessage()); +} + +TEST_F(CollaborationMessagingTabDataTest, IgnoresRequestsWhenMessageIsChanged) { + EXPECT_FALSE(tab_data().HasMessage()); + + std::string given_name = "User"; + std::string avatar_url = "https://google.com/chrome/1"; + auto message = + CreateMessage(given_name, avatar_url, CollaborationEvent::TAB_ADDED); + + // Service will be triggered to request the image. + EXPECT_CALL(*sharing_service(), + GetAvatarImageForURL(GURL(avatar_url), 20, _, _)) + .Times(1); + + // Set the message. This will trigger the avatar request, but will not + // set data since the fetcher is mocked. + tab_data().SetMessage(message); + + std::string given_name2 = "User2"; + std::string avatar_url2 = "https://google.com/chrome/2"; + auto message2 = + CreateMessage(given_name2, avatar_url2, CollaborationEvent::TAB_UPDATED); + + // Service will be triggered to request the image. + EXPECT_CALL(*sharing_service(), + GetAvatarImageForURL(GURL(avatar_url2), 20, _, _)) + .Times(1); + + // Set a new message. This will cause the following Commit to be rejected. + tab_data().SetMessage(message2); + + // Attempt to commit the first message. This will be rejected. + // Mock resolution of the avatar image request by directly + // triggering the callback. + tab_data().CommitMessage(message, gfx::Image()); + + // Data will not be set. EXPECT_FALSE(tab_data().HasMessage()); }
diff --git a/chrome/browser/ui/tabs/tab_features.cc b/chrome/browser/ui/tabs/tab_features.cc index 0e93ee5..f8f9f2a4 100644 --- a/chrome/browser/ui/tabs/tab_features.cc +++ b/chrome/browser/ui/tabs/tab_features.cc
@@ -156,7 +156,7 @@ if (tab_groups::SavedTabGroupUtils::SupportsSharedTabGroups()) { collaboration_messaging_tab_data_ = - std::make_unique<tab_groups::CollaborationMessagingTabData>(); + std::make_unique<tab_groups::CollaborationMessagingTabData>(profile); } embedder_tab_observer_ =
diff --git a/chrome/browser/ui/tabs/tab_model.cc b/chrome/browser/ui/tabs/tab_model.cc index d6bbb3d..45e65f9 100644 --- a/chrome/browser/ui/tabs/tab_model.cc +++ b/chrome/browser/ui/tabs/tab_model.cc
@@ -208,6 +208,11 @@ return std::make_unique<ScopedTabModalUIImpl>(this); } +base::CallbackListSubscription TabModel::RegisterModalUIChanged( + TabInterface::TabInterfaceCallback callback) { + return modal_ui_changed_callback_list_.Add(std::move(callback)); +} + bool TabModel::IsInNormalWindow() const { return GetModelForTabInterface()->delegate()->IsNormalWindow(); } @@ -257,13 +262,17 @@ } TabModel::ScopedTabModalUIImpl::ScopedTabModalUIImpl(TabModel* tab) - : tab_(tab) { + : tab_(tab->weak_factory_.GetWeakPtr()) { CHECK(!tab_->showing_modal_ui_); tab_->showing_modal_ui_ = true; + tab_->modal_ui_changed_callback_list_.Notify(tab_.get()); } TabModel::ScopedTabModalUIImpl::~ScopedTabModalUIImpl() { - tab_->showing_modal_ui_ = false; + if (tab_) { + tab_->showing_modal_ui_ = false; + tab_->modal_ui_changed_callback_list_.Notify(tab_.get()); + } } void TabModel::WriteIntoTrace(perfetto::TracedValue context) const {
diff --git a/chrome/browser/ui/tabs/tab_model.h b/chrome/browser/ui/tabs/tab_model.h index 0a6f375d..bfab7b3 100644 --- a/chrome/browser/ui/tabs/tab_model.h +++ b/chrome/browser/ui/tabs/tab_model.h
@@ -10,6 +10,7 @@ #include "base/callback_list.h" #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/ui/tabs/public/tab_interface.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "components/tab_groups/tab_group_id.h" @@ -128,6 +129,9 @@ bool CanShowModalUI() const override; std::unique_ptr<ScopedTabModalUI> ShowModalUI() override; + base::CallbackListSubscription RegisterModalUIChanged( + TabInterfaceCallback callback) override; + bool IsInNormalWindow() const override; BrowserWindowInterface* GetBrowserWindowInterface() override; tabs::TabFeatures* GetTabFeatures() override; @@ -154,8 +158,10 @@ ~ScopedTabModalUIImpl() override; private: - // Owns this. - raw_ptr<TabModel> tab_; + // Owns this. Some consumers may hold this beyond the lifetime of the tab. + // This is because legacy code often clears state in WebContentsDestroyed(), + // which occurs during or after TabModel destruction. + base::WeakPtr<TabModel> tab_; }; // This must always be the first member so that it is destroyed last. This is @@ -207,11 +213,17 @@ void(TabInterface*, std::optional<tab_groups::TabGroupId> new_group)>; GroupChangedCallbackList group_changed_callback_list_; + using TabInterfaceCallbackList = + base::RepeatingCallbackList<void(TabInterface*)>; + TabInterfaceCallbackList modal_ui_changed_callback_list_; + // Tracks whether a modal UI is showing. bool showing_modal_ui_ = false; // Features that are per-tab will be owned by this class. std::unique_ptr<TabFeatures> tab_features_; + + base::WeakPtrFactory<TabModel> weak_factory_{this}; }; } // namespace tabs
diff --git a/chrome/browser/ui/tabs/test/mock_tab_interface.h b/chrome/browser/ui/tabs/test/mock_tab_interface.h index 27d772a8..f933b8e0 100644 --- a/chrome/browser/ui/tabs/test/mock_tab_interface.h +++ b/chrome/browser/ui/tabs/test/mock_tab_interface.h
@@ -50,6 +50,10 @@ (override)); MOCK_METHOD(bool, CanShowModalUI, (), (const, override)); MOCK_METHOD(std::unique_ptr<ScopedTabModalUI>, ShowModalUI, (), (override)); + MOCK_METHOD(base::CallbackListSubscription, + RegisterModalUIChanged, + (TabInterfaceCallback), + (override)); MOCK_METHOD(bool, IsInNormalWindow, (), (const override)); MOCK_METHOD(BrowserWindowInterface*, GetBrowserWindowInterface,
diff --git a/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc b/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc index 88de158..f1015c3 100644 --- a/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc +++ b/chrome/browser/ui/user_education/show_promo_in_page_browsertest.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" +#include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "chrome/test/interaction/interactive_browser_test.h" @@ -28,7 +29,6 @@ namespace { -constexpr char kPageWithAnchorURL[] = "chrome://internals/user-education"; constexpr char kPageWithoutAnchorURL[] = "chrome://settings"; constexpr char16_t kBubbleBodyText[] = u"bubble body"; @@ -56,7 +56,7 @@ base::MockCallback<ShowPromoInPage::Callback> bubble_shown; auto params = GetDefaultParams(); - params.target_url = GURL(kPageWithAnchorURL); + params.target_url = GURL(chrome::kChromeUIUserEducationInternalsURL); params.callback = bubble_shown.Get(); base::WeakPtr<ShowPromoInPage> handle; @@ -92,7 +92,7 @@ base::MockCallback<ShowPromoInPage::Callback> bubble_shown; auto params = GetDefaultParams(); - params.target_url = GURL(kPageWithAnchorURL); + params.target_url = GURL(chrome::kChromeUIUserEducationInternalsURL); params.callback = bubble_shown.Get(); params.overwrite_active_tab = true; @@ -126,8 +126,8 @@ } IN_PROC_BROWSER_TEST_F(ShowPromoInPageBrowserTest, ShowPromoInSamePage) { - ASSERT_TRUE( - ui_test_utils::NavigateToURL(browser(), GURL(kPageWithAnchorURL))); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), GURL(chrome::kChromeUIUserEducationInternalsURL))); base::MockCallback<ShowPromoInPage::Callback> bubble_shown; @@ -229,7 +229,7 @@ IN_PROC_BROWSER_TEST_F(ShowPromoInPageBrowserTest, HelpBubbleParamsCanConfigureCloseButtonAltText) { auto params = GetDefaultParams(); - params.target_url = GURL(kPageWithAnchorURL); + params.target_url = GURL(chrome::kChromeUIUserEducationInternalsURL); params.overwrite_active_tab = true; // Set the alt text here and then check that aria-label matches. params.close_button_alt_text_id = IDS_CLOSE_PROMO; @@ -247,11 +247,12 @@ bubble_is_visible.event = kBubbleIsVisible; bubble_is_visible.where = kPathToHelpBubbleCloseButton; bubble_is_visible.type = StateChange::Type::kExists; - RunTestSequence( - InstrumentTab(kTabId), Do(std::move(help_bubble_start_callback)), - WaitForWebContentsNavigation(kTabId, GURL(kPageWithAnchorURL)), - WaitForStateChange(kTabId, bubble_is_visible), - CheckJsResultAt(kTabId, kPathToHelpBubbleCloseButton, - "(el) => el.getAttribute('aria-label')", - l10n_util::GetStringUTF8(IDS_CLOSE_PROMO))); + RunTestSequence(InstrumentTab(kTabId), + Do(std::move(help_bubble_start_callback)), + WaitForWebContentsNavigation( + kTabId, GURL(chrome::kChromeUIUserEducationInternalsURL)), + WaitForStateChange(kTabId, bubble_is_visible), + CheckJsResultAt(kTabId, kPathToHelpBubbleCloseButton, + "(el) => el.getAttribute('aria-label')", + l10n_util::GetStringUTF8(IDS_CLOSE_PROMO))); }
diff --git a/chrome/browser/ui/user_education/show_promo_in_page_interactive_uitest.cc b/chrome/browser/ui/user_education/show_promo_in_page_interactive_uitest.cc index 0057761..fe3f1637 100644 --- a/chrome/browser/ui/user_education/show_promo_in_page_interactive_uitest.cc +++ b/chrome/browser/ui/user_education/show_promo_in_page_interactive_uitest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/user_education/show_promo_in_page.h" +#include "chrome/common/webui_url_constants.h" #include "chrome/test/interaction/interactive_browser_test.h" #include "components/strings/grit/components_strings.h" #include "components/user_education/common/help_bubble/help_bubble_params.h" @@ -20,7 +21,6 @@ namespace { -constexpr char kPageWithAnchorURL[] = "chrome://internals/user-education"; constexpr char16_t kBubbleBodyText[] = u"bubble body"; // Gets a partially-filled params block with default values. You will still @@ -67,7 +67,7 @@ IN_PROC_BROWSER_TEST_F(ShowPromoInPageBrowserTest, FocusesBrowserTabAndAnchor) { auto params = GetDefaultParams(); - params.target_url = GURL(kPageWithAnchorURL); + params.target_url = GURL(chrome::kChromeUIUserEducationInternalsURL); params.overwrite_active_tab = true; // Set the alt text here and then check that aria-label matches. params.close_button_alt_text_id = IDS_CLOSE_PROMO; @@ -91,7 +91,8 @@ InstrumentTab(kTabId), Do([this]() { browser()->window()->SetFocusToLocationBar(true); }), Do(std::move(help_bubble_start_callback)), - WaitForWebContentsNavigation(kTabId, GURL(kPageWithAnchorURL)), + WaitForWebContentsNavigation( + kTabId, GURL(chrome::kChromeUIUserEducationInternalsURL)), WaitForStateChange(kTabId, bubble_is_visible), Log("If the CheckViewProperty() step below fails intermittently, then " "there is a race condition and we should change it to a "
diff --git a/chrome/browser/ui/views/tabs/fade_footer_view.cc b/chrome/browser/ui/views/tabs/fade_footer_view.cc index ef70f2e..047cc24 100644 --- a/chrome/browser/ui/views/tabs/fade_footer_view.cc +++ b/chrome/browser/ui/views/tabs/fade_footer_view.cc
@@ -192,9 +192,9 @@ return; } - if (data_.avatar.has_value()) { + if (!data_.avatar.IsEmpty()) { // Use avatar, if supplied. - SetContent(*data_.avatar, data_.text); + SetContent(data_.avatar, data_.text); return; }
diff --git a/chrome/browser/ui/views/tabs/fade_footer_view.h b/chrome/browser/ui/views/tabs/fade_footer_view.h index bede8528..2df0381 100644 --- a/chrome/browser/ui/views/tabs/fade_footer_view.h +++ b/chrome/browser/ui/views/tabs/fade_footer_view.h
@@ -30,7 +30,7 @@ struct CollaborationMessagingRowData { bool should_show_collaboration_messaging = false; std::u16string text; - std::optional<ui::ImageModel> avatar = std::nullopt; + ui::ImageModel avatar; CollaborationMessagingRowData(); ~CollaborationMessagingRowData();
diff --git a/chrome/browser/ui/views/tabs/glic_button.cc b/chrome/browser/ui/views/tabs/glic_button.cc index 682217d..0f6a411 100644 --- a/chrome/browser/ui/views/tabs/glic_button.cc +++ b/chrome/browser/ui/views/tabs/glic_button.cc
@@ -4,13 +4,13 @@ #include "chrome/browser/ui/views/tabs/glic_button.h" +#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/tabs/tab_strip_control_button.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/common/buildflags.h" #include "chrome/grit/generated_resources.h" -#include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/views/accessibility/view_accessibility.h" @@ -26,7 +26,7 @@ GlicButton::GlicButton(TabStripController* tab_strip_controller) : TabStripControlButton(tab_strip_controller, PressedCallback(), - vector_icons::kErrorOutlineIcon) { + kGlicButtonIcon) { tab_strip_controller_ = tab_strip_controller; SetProperty(views::kElementIdentifierKey, kGlicButtonElementId);
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index 615f39ad..b09c5b6e 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -502,6 +502,7 @@ default: NOTREACHED(); } + collaboration_messaging_data.avatar = data->hover_card_avatar(); collaboration_messaging_data.should_show_collaboration_messaging = true; return collaboration_messaging_data;
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc index ba01ee9..ac79f0f 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_controller_interactive_uitest.cc
@@ -817,13 +817,16 @@ // Clear alert state. Alerts take precedence over all other footers. tab_renderer_data.alert_state = {}; - tab_groups::CollaborationMessagingTabData data; + tab_groups::CollaborationMessagingTabData data(browser()->profile()); tab_renderer_data.collaboration_messaging = data.GetWeakPtr(); + // Do not make a network request for the user's avatar. + data.set_mocked_avatar_for_testing(gfx::Image()); + // Create a mock PersistentMessage // Show collaboration messaging status with TAB_ADDED event. std::string given_name = "User"; - std::string avatar_url = "URL"; + std::string avatar_url = "https://google.com/chrome/1"; data.SetMessage( CreateMessage(given_name, avatar_url, collaboration::messaging::CollaborationEvent::TAB_ADDED)); @@ -851,7 +854,7 @@ // Change username and action to show collaboration messaging with TAB_UPDATED // event. std::string given_name2 = "Another User"; - std::string avatar_url2 = "URL2"; + std::string avatar_url2 = "https://google.com/chrome/2"; data.SetMessage( CreateMessage(given_name2, avatar_url2, collaboration::messaging::CollaborationEvent::TAB_UPDATED));
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc index 65676013..11f55c6 100644 --- a/chrome/browser/ui/views/tabs/tab_style_views.cc +++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/ui/views/tabs/tab_group_underline.h" #include "chrome/browser/ui/views/tabs/tab_slot_controller.h" #include "chrome/browser/ui/views/tabs/tab_slot_view.h" +#include "chrome/common/chrome_features.h" #include "chrome/grit/theme_resources.h" #include "components/tab_groups/tab_group_visual_data.h" #include "third_party/skia/include/core/SkRRect.h" @@ -748,11 +749,15 @@ } // If there isn't an adjacent tab, the tab is at the beginning or end of the - // tab strip. for the first tab, we shouldn't not show the leading separator, - // for the last tab, we should show the separator between the new tab button - // and the tab strip IF the tab isn't selected, hovered, or active. + // tab strip. For the first tab, we shouldn't show the leading separator, for + // the last tab, we should show the separator between the new tab button and + // the tab strip IF the tab isn't selected, hovered, or active. If there is a + // combo button with a non-transparent background in place of the new tab + // button, we should not show the trailing separator. if (!adjacent_tab) { - return leading ? 0.0f : shown_separator_opacity; + return (leading || features::HasTabstripComboButtonWithBackground()) + ? 0.0f + : shown_separator_opacity; } // Do not show when the adjacent tab is displaying a visible shape.
diff --git a/chrome/browser/ui/views/task_manager_search_bar_view.cc b/chrome/browser/ui/views/task_manager_search_bar_view.cc index 217962e..05787c1e 100644 --- a/chrome/browser/ui/views/task_manager_search_bar_view.cc +++ b/chrome/browser/ui/views/task_manager_search_bar_view.cc
@@ -14,6 +14,7 @@ #include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/color/color_id.h" #include "ui/views/animation/ink_drop.h" #include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/highlight_path_generator.h" @@ -24,7 +25,11 @@ namespace task_manager { TaskManagerSearchBarView::TaskManagerSearchBarView( const std::u16string& placeholder, - const gfx::Insets& margins) { + const gfx::Insets& margins) +#if BUILDFLAG(IS_LINUX) + : textfield_placeholder_color_id_(kColorTaskManagerSearchBarPlaceholderText) +#endif +{ auto* layout_provider = ChromeLayoutProvider::Get(); auto search_bar_layout = std::make_unique<views::BoxLayout>(); @@ -95,6 +100,11 @@ TaskManagerSearchBarView::~TaskManagerSearchBarView() = default; +void TaskManagerSearchBarView::OnThemeChanged() { + views::View::OnThemeChanged(); + UpdateTextfield(); +} + bool TaskManagerSearchBarView::HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) { if (key_event.type() == ui::EventType::kKeyPressed && @@ -125,6 +135,14 @@ return clear_->GetBoundsInScreen().CenterPoint(); } +void TaskManagerSearchBarView::UpdateTextfield() { + if (const auto* const color_provider = GetColorProvider(); color_provider) { + input_->set_placeholder_text_color( + color_provider->GetColor(textfield_placeholder_color_id_.value_or( + ui::kColorTextfieldForegroundPlaceholder))); + } +} + BEGIN_METADATA(TaskManagerSearchBarView) END_METADATA
diff --git a/chrome/browser/ui/views/task_manager_search_bar_view.h b/chrome/browser/ui/views/task_manager_search_bar_view.h index 319a949c..bb0907a 100644 --- a/chrome/browser/ui/views/task_manager_search_bar_view.h +++ b/chrome/browser/ui/views/task_manager_search_bar_view.h
@@ -33,6 +33,9 @@ TaskManagerSearchBarView& operator=(const TaskManagerSearchBarView&) = delete; ~TaskManagerSearchBarView() override; + // views::View + void OnThemeChanged() override; + // views::TextfieldController: bool HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) override; @@ -43,9 +46,15 @@ void SetInputTextForTesting(const std::u16string& text); gfx::Point GetClearButtonScreenCenterPointForTesting() const; + // Updates related fields on the Textfield. + void UpdateTextfield(); + private: void OnClearPressed(); + // Textfield placeholder color. + std::optional<ui::ColorId> textfield_placeholder_color_id_; + raw_ptr<views::Textfield> input_ = nullptr; raw_ptr<views::Button> clear_ = nullptr; };
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service_interactive_uitest.cc b/chrome/browser/ui/views/user_education/browser_user_education_service_interactive_uitest.cc index e550729..762d4138 100644 --- a/chrome/browser/ui/views/user_education/browser_user_education_service_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/browser_user_education_service_interactive_uitest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/browser/user_education/user_education_service.h" #include "chrome/browser/user_education/user_education_service_factory.h" +#include "chrome/common/webui_url_constants.h" #include "chrome/test/user_education/interactive_feature_promo_test.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/user_education/common/feature_promo/feature_promo_result.h" @@ -43,16 +44,17 @@ } auto DoSetup() { - return Steps(InstrumentTab(kMainContentsElementId), - NavigateWebContents(kMainContentsElementId, - GURL("chrome://internals/user-education")), - NameDescendantViewByType<ToolbarView>(kTopContainerElementId, - kToolbarName), - NameViewRelative(kBrowserViewElementId, kContentsPaneName, - [](BrowserView* browser_view) { - return browser_view->contents_web_view(); - }), - InAnyContext(WaitForShow(kWebUIIPHDemoElementIdentifier))); + return Steps( + InstrumentTab(kMainContentsElementId), + NavigateWebContents(kMainContentsElementId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), + NameDescendantViewByType<ToolbarView>(kTopContainerElementId, + kToolbarName), + NameViewRelative(kBrowserViewElementId, kContentsPaneName, + [](BrowserView* browser_view) { + return browser_view->contents_web_view(); + }), + InAnyContext(WaitForShow(kWebUIIPHDemoElementIdentifier))); } auto EnsureFocus(ElementSpecifier spec, bool focused) {
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc index de12f84..13bf69f 100644 --- a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
@@ -236,7 +236,7 @@ RunTestSequence( InstrumentTab(kBrowserTabId), NavigateWebContents(kBrowserTabId, - GURL("chrome://internals/user-education")), + GURL(chrome::kChromeUIUserEducationInternalsURL)), ShowHelpBubble(kWebUIIPHDemoElementIdentifier), // Verify that the handler believes that the anchor has a help bubble. @@ -268,7 +268,7 @@ RunTestSequence( InstrumentTab(kBrowserTabId), NavigateWebContents(kBrowserTabId, - GURL("chrome://internals/user-education")), + GURL(chrome::kChromeUIUserEducationInternalsURL)), ShowHelpBubble(kWebUIIPHDemoElementIdentifier), ExecuteJsAt(kBrowserTabId, kPathToHelpBubbleCloseButton,
diff --git a/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc index 31e3d4b..a11d765 100644 --- a/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc
@@ -23,8 +23,6 @@ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kBrowserTabId); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kBrowserTabId2); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kReadLaterWebContentsElementId); -constexpr char kUserEducationInternalsUrl[] = - "chrome://internals/user-education"; } // namespace class HelpBubbleHandlerInteractiveUiTest : public InteractiveBrowserTest { @@ -75,7 +73,8 @@ ElementBecomesVisibleOnPageLoad) { RunTestSequence( InstrumentTab(kBrowserTabId), - NavigateWebContents(kBrowserTabId, GURL(kUserEducationInternalsUrl)), + NavigateWebContents(kBrowserTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), InAnyContext(WaitForShow(kWebUIIPHDemoElementIdentifier))); } @@ -83,7 +82,8 @@ ElementBecomesHiddenOnTabBackgrounded) { RunTestSequence( InstrumentTab(kBrowserTabId), - NavigateWebContents(kBrowserTabId, GURL(kUserEducationInternalsUrl)), + NavigateWebContents(kBrowserTabId, + GURL(chrome::kChromeUIUserEducationInternalsURL)), InAnyContext(WaitForShow(kWebUIIPHDemoElementIdentifier)), // This will add the new tab in the foreground. AddInstrumentedTab(kBrowserTabId2, GURL(chrome::kChromeUIBookmarksURL)),
diff --git a/chrome/browser/ui/views/webid/account_selection_modal_view.cc b/chrome/browser/ui/views/webid/account_selection_modal_view.cc index d21e3a2a..0f6c320 100644 --- a/chrome/browser/ui/views/webid/account_selection_modal_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_modal_view.cc
@@ -330,11 +330,9 @@ auto scroll_view = std::make_unique<views::ScrollView>(); scroll_view->SetHorizontalScrollBarMode( views::ScrollView::ScrollBarMode::kDisabled); - constexpr int kMultipleAccountsVerticalPadding = 2; views::View* const content = scroll_view->SetContents(CreateAccountRows( accounts, /*should_hover=*/true, /*show_separator=*/true, - /*is_single_account_chooser=*/true, - /*additional_row_vertical_padding=*/kMultipleAccountsVerticalPadding)); + /*is_request_permission_dialog=*/false)); constexpr float kMaxAccountsToShow = 3.5f; const int per_account_size = @@ -348,13 +346,12 @@ const std::vector<IdentityRequestAccountPtr>& accounts, bool should_hover, bool show_separator, - bool is_single_account_chooser, - int additional_row_vertical_padding) { + bool is_request_permission_dialog) { auto content = std::make_unique<views::View>(); content->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical, gfx::Insets::VH( - /*vertical=*/is_single_account_chooser ? 0 : kVerticalPadding, + /*vertical=*/is_request_permission_dialog ? 0 : kVerticalPadding, /*horizontal=*/kDialogMargin))); if (show_separator) { @@ -363,6 +360,7 @@ } int num_rows = 0; + constexpr int kAccountRowVerticalPadding = 2; for (const auto& account : accounts) { content->AddChildView(CreateAccountRow( account, @@ -370,7 +368,8 @@ should_hover ? std::make_optional<int>(num_rows++) : std::nullopt, /*should_include_idp=*/false, /*is_modal_dialog=*/true, - /*additional_vertical_padding=*/additional_row_vertical_padding)); + /*additional_vertical_padding=*/ + is_request_permission_dialog ? 0 : kAccountRowVerticalPadding)); if (show_separator) { // Add separator after each account row. content->AddChildView(std::make_unique<views::Separator>()); @@ -416,12 +415,11 @@ if (is_single_account_chooser) { CHECK_EQ(accounts.size(), 1u); - account_chooser_ = AddChildView(CreateAccountRows( - accounts, - /*should_hover=*/true, - /*show_separator=*/true, - /*is_single_account_chooser=*/true, - /*additional_row_vertical_padding=*/kVerticalPadding)); + account_chooser_ = + AddChildView(CreateAccountRows(accounts, + /*should_hover=*/true, + /*show_separator=*/true, + /*is_request_permission_dialog=*/false)); } else { account_chooser_ = AddChildView(CreateMultipleAccountChooser(accounts)); } @@ -630,8 +628,7 @@ AddChildView(CreateAccountRows(accounts, /*should_hover=*/false, /*show_separator=*/false, - /*is_single_account_chooser=*/true, - /*additional_row_vertical_padding=*/0)); + /*is_request_permission_dialog=*/true)); if (account->login_state == Account::LoginState::kSignUp) { // Add disclosure label. std::unique_ptr<views::StyledLabel> disclosure_label =
diff --git a/chrome/browser/ui/views/webid/account_selection_modal_view.h b/chrome/browser/ui/views/webid/account_selection_modal_view.h index d649d93a..1500591 100644 --- a/chrome/browser/ui/views/webid/account_selection_modal_view.h +++ b/chrome/browser/ui/views/webid/account_selection_modal_view.h
@@ -103,8 +103,7 @@ const std::vector<IdentityRequestAccountPtr>& accounts, bool should_hover, bool show_separator, - bool is_single_account_chooser, - int additional_row_vertical_padding); + bool is_request_permission_dialog); // Returns a View for an account row that acts as a placeholder. std::unique_ptr<views::View> CreatePlaceholderAccountRow();
diff --git a/chrome/browser/ui/views/webid/account_selection_view_base.cc b/chrome/browser/ui/views/webid/account_selection_view_base.cc index acebd571..12b9942 100644 --- a/chrome/browser/ui/views/webid/account_selection_view_base.cc +++ b/chrome/browser/ui/views/webid/account_selection_view_base.cc
@@ -662,6 +662,8 @@ CHECK(!account->is_filtered_out); account_image_view->SetAccountImage(*account, *image_fetcher_, avatar_size); auto row = std::make_unique<views::View>(); + row->SetProperty(views::kElementIdentifierKey, + kFedCmAccountChooserDialogAccountElementId); row->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets::VH(
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc index 90e511c6..6bb040b 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -70,6 +70,9 @@ weak_ptr_factory_.GetWeakPtr()))); tab_subscriptions_.push_back(tab_->RegisterWillDetach(base::BindRepeating( &FedCmAccountSelectionView::WillDetach, weak_ptr_factory_.GetWeakPtr()))); + tab_subscriptions_.push_back(tab_->RegisterModalUIChanged( + base::BindRepeating(&FedCmAccountSelectionView::ModalUIChanged, + weak_ptr_factory_.GetWeakPtr()))); } FedCmAccountSelectionView::~FedCmAccountSelectionView() { @@ -858,6 +861,10 @@ Close(/*notify_delegate=*/true); } +void FedCmAccountSelectionView::ModalUIChanged(tabs::TabInterface* tab) { + UpdateDialogVisibilityAndPosition(); +} + void FedCmAccountSelectionView::WillDetach( tabs::TabInterface* tab, tabs::TabInterface::DetachReason reason) { @@ -1065,6 +1072,10 @@ void FedCmAccountSelectionView::TabWillEnterBackground( tabs::TabInterface* tab) { + // The reason this does not use UpdateDialogVisibilityAndPosition() is because + // the tab has not yet entered the background, and so tab->IsInForeground() + // returns true. If it's important to simplify this then we should add + // TabInterface::RegisterDidEnterBackground(). if (GetDialogWidget()) { HideDialogWidget(); } @@ -1214,6 +1225,11 @@ if (hide_dialog_widget_after_idp_login_popup_) { should_show_dialog = false; } + + // Or if a tab modal UI is showing (which means we can't show a new modal). + if (!tab_->CanShowModalUI()) { + should_show_dialog = false; + } } if (should_show_dialog) {
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h index b3cbf3cd..3ebb9ce 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
@@ -414,6 +414,9 @@ content::WebContents* old_contents, content::WebContents* new_contents); + // Called when the tab's modalUI is shown or hidden. + void ModalUIChanged(tabs::TabInterface* tab); + // Returns false if `this` got deleted. In that case, the caller must early // return. bool NotifyDelegateOfAccountSelection( @@ -471,6 +474,8 @@ // always updates the dialog position if the dialog should be visible. If the // dialog should be visible, and it is not, this method makes the dialog // visible and focuses the dialog. + // All control flows that want to show the dialog must go through this method. + // This ensures the complex logic to determine visibility is centralized. void UpdateDialogVisibilityAndPosition(); // Called when any of the Show*() methods is called.
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc index dd6f411..5d2d996 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc
@@ -188,6 +188,7 @@ content::WebContents* GetContents() const override { return contents_; } void SetIsInForeground(bool foreground) { is_in_foreground_ = foreground; } bool IsInForeground() const override { return is_in_foreground_; } + bool CanShowModalUI() const override { return true; } private: raw_ptr<content::WebContents> contents_;
diff --git a/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc b/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc index 33a13c2..f283a36 100644 --- a/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc +++ b/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc
@@ -6,6 +6,7 @@ // from webpages, and requires communication with multiple remote endpoints. // This test suite does not do any of that at the moment. +#include "build/build_config.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/views/webid/account_selection_view_test_base.h" #include "chrome/browser/ui/views/webid/fake_delegate.h" @@ -23,7 +24,7 @@ auto OpenAccounts(blink::mojom::RpMode mode) { return Do([this, mode]() { delegate_ = std::make_unique<FakeDelegate>( - browser()->tab_strip_model()->GetActiveWebContents()); + browser()->GetActiveTabInterface()->GetContents()); account_selection_view_ = std::make_unique<FedCmAccountSelectionView>( delegate_.get(), browser()->GetActiveTabInterface()); idps_ = {base::MakeRefCounted<content::IdentityProviderData>( @@ -48,11 +49,26 @@ return OpenAccounts(blink::mojom::RpMode::kActive); } + // Opens the bubble version of the account chooser. + auto OpenAccountsBubble() { + return OpenAccounts(blink::mojom::RpMode::kPassive); + } + + auto ShowTabModalUI() { + return Do([this]() { + tab_modal_ui_ = browser()->GetActiveTabInterface()->ShowModalUI(); + }); + } + auto HideTabModalUI() { + return Do([this]() { tab_modal_ui_.reset(); }); + } + protected: std::unique_ptr<FakeDelegate> delegate_; std::vector<IdentityProviderDataPtr> idps_; std::vector<IdentityRequestAccountPtr> accounts_; std::unique_ptr<FedCmAccountSelectionView> account_selection_view_; + std::unique_ptr<tabs::ScopedTabModalUI> tab_modal_ui_; }; // Shows the account picker. Selects an account. @@ -62,4 +78,20 @@ PressButton(kFedCmAccountChooserDialogAccountElementId), ); } +// TODO(https://crbug.com/382867817): Fix this on windows. +#if BUILDFLAG(IS_WIN) +#define MAYBE_BubbleHidesWhenModalUIShown DISABLED_BubbleHidesWhenModalUIShown +#else +#define MAYBE_BubbleHidesWhenModalUIShown BubbleHidesWhenModalUIShown +#endif +// Shows the bubble account picker. It should hide when a modal UI is shown. It +// should re-show when the modal UI goes away. +IN_PROC_BROWSER_TEST_F(FedCmCUJTest, MAYBE_BubbleHidesWhenModalUIShown) { + RunTestSequence( + OpenAccountsBubble(), + WaitForShow(kFedCmAccountChooserDialogAccountElementId), ShowTabModalUI(), + WaitForHide(kFedCmAccountChooserDialogAccountElementId), HideTabModalUI(), + WaitForShow(kFedCmAccountChooserDialogAccountElementId), ); +} + } // namespace
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc index b574c92..e6e89439 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -762,6 +762,11 @@ CHECK(source_browser); CHECK(web_contents); CHECK(target_browser); + CHECK(AreWebAppsEnabled(target_browser->profile(), + /*exclude_original_profile=*/true)); + CHECK(AreWebAppsEnabled(source_browser->profile(), + /*exclude_original_profile=*/true)); + CHECK_EQ(source_browser->profile(), target_browser->profile()); // In a reparent, the owning session service needs to be told it's tab // has been removed, otherwise it will reopen the tab on restoration.
diff --git a/chrome/browser/ui/webui/about/about_ui.cc b/chrome/browser/ui/webui/about/about_ui.cc index d8205f0..ca7c302 100644 --- a/chrome/browser/ui/webui/about/about_ui.cc +++ b/chrome/browser/ui/webui/about/about_ui.cc
@@ -474,21 +474,16 @@ : base::StrCat({"<li>", url, "</li>\n"}); } - html += - "</ul><a id=\"internals\"><h2>List of chrome://internals " - "pages</h2></a>\n<ul>\n"; - const base::span<const base::cstring_view> internals_paths = - chrome::ChromeInternalsURLPaths(); - std::vector<std::string_view> sorted_internals_paths = base::ToVector( - internals_paths, - [](base::cstring_view v) -> std::string_view { return v; }); - std::ranges::sort(sorted_internals_paths); - for (const std::string_view path : sorted_internals_paths) { - html += base::StrCat({"<li><a href='chrome://internals/", path, - "'>chrome://internals/", path, "</a></li>\n"}); - } } +#if BUILDFLAG(ENABLE_SESSION_SERVICE) + // Add the session service internals page to the end. + html += base::StrCat( + {"<li><a href='chrome://internals/", + chrome::kChromeUISessionServiceInternalsPath, "'>chrome://internals/", + chrome::kChromeUISessionServiceInternalsPath, "</a></li>\n"}); +#endif // BUILDFLAG(ENABLE_SESSION_SERVICE) + html += "</ul>\n<h2>For Debug</h2>\n" "<p>The following pages are for debugging purposes only. Because they " "crash or hang the renderer, they're not linked directly; you can type "
diff --git a/chrome/browser/ui/webui/ash/config/BUILD.gn b/chrome/browser/ui/webui/ash/config/BUILD.gn index 9cd345ab..27cb98e 100644 --- a/chrome/browser/ui/webui/ash/config/BUILD.gn +++ b/chrome/browser/ui/webui/ash/config/BUILD.gn
@@ -32,6 +32,7 @@ "//ash/webui/print_management", "//ash/webui/print_preview_cros", "//ash/webui/sanitize_ui", + "//ash/webui/scanner_feedback_ui", "//ash/webui/scanning", "//ash/webui/shimless_rma", "//ash/webui/shortcut_customization_ui",
diff --git a/chrome/browser/ui/webui/ash/config/chrome_untrusted_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/ash/config/chrome_untrusted_web_ui_configs_chromeos.cc index 5dbd6592..7045f81 100644 --- a/chrome/browser/ui/webui/ash/config/chrome_untrusted_web_ui_configs_chromeos.cc +++ b/chrome/browser/ui/webui/ash/config/chrome_untrusted_web_ui_configs_chromeos.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/webui/ash/config/chrome_untrusted_web_ui_configs_chromeos.h" +#include <memory> + #include "ash/constants/ash_features.h" #include "ash/webui/demo_mode_app_ui/demo_mode_app_untrusted_ui.h" #include "ash/webui/eche_app_ui/untrusted_eche_app_ui.h" @@ -11,6 +13,7 @@ #include "ash/webui/focus_mode/focus_mode_untrusted_ui.h" #include "ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.h" #include "ash/webui/os_feedback_ui/os_feedback_untrusted_ui.h" +#include "ash/webui/scanner_feedback_ui/scanner_feedback_untrusted_ui.h" #include "base/functional/bind.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/ash/annotator/untrusted_annotator_ui_config.h" @@ -72,6 +75,8 @@ map.AddUntrustedWebUIConfig(std::make_unique<MakoUntrustedUIConfig>()); map.AddUntrustedWebUIConfig(std::make_unique<ScalableIphDebugUIConfig>()); map.AddUntrustedWebUIConfig(std::make_unique<FocusModeUntrustedUIConfig>()); + map.AddUntrustedWebUIConfig( + std::make_unique<ScannerFeedbackUntrustedUIConfig>()); #if !defined(OFFICIAL_BUILD) map.AddUntrustedWebUIConfig( std::make_unique<SampleSystemWebAppUntrustedUIConfig>());
diff --git a/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc b/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc index 1002654..68e9659 100644 --- a/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc +++ b/chrome/browser/ui/webui/ash/cryptohome/cryptohome_web_ui_handler.cc
@@ -136,6 +136,14 @@ return ss.empty() ? s : ss + " " + s; }); } + + std::string recovery_seed = "<empty>"; + if (reply.has_value() && + !reply->recovery_info_reply().recovery_seed().empty()) { + recovery_seed = reply->recovery_info_reply().recovery_seed(); + } + + SetCryptohomeProperty("recovery_seed", base::Value(recovery_seed)); SetCryptohomeProperty("recovery_ids", base::Value(recovery_ids)); }
diff --git a/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc b/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc index 8605520..eb478f2 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.cc
@@ -242,9 +242,6 @@ } void AddAppManagementStrings(content::WebUIDataSource* html_source) { - const bool kIsRevampEnabled = - ash::features::IsOsSettingsRevampWayfindingEnabled(); - webui::LocalizedString kLocalizedStrings[] = { {"appManagementAppDetailsTitle", IDS_APP_MANAGEMENT_APP_DETAILS_TITLE}, {"appManagementAppDetailsTooltipWebA11y", @@ -317,8 +314,7 @@ {"appManagementIntentSettingsTitle", IDS_APP_MANAGEMENT_INTENT_SETTINGS_TITLE}, {"appManagementIntentSharingOpenAppLabel", - kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_OPEN_IN_APP_TITLE - : IDS_APP_MANAGEMENT_INTENT_SHARING_APP_OPEN}, + IDS_OS_SETTINGS_OPEN_IN_APP_TITLE}, {"appManagementPermissionItemClickTogglePermission", IDS_OS_SETTINGS_PERMISSION_ITEM_CLICK_TOGGLE_PERMISSION}, {"appManagementIntentSharingOpenBrowserLabel", @@ -329,17 +325,16 @@ {"appManagementMicrophonePermissionLabel", IDS_APP_MANAGEMENT_MICROPHONE}, {"appManagementMorePermissionsLabel", IDS_APP_MANAGEMENT_MORE_SETTINGS}, {"appManagementMorePermissionsLabelAndroidApp", - IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_ANDROID}, + IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_ANDROID}, {"appManagementMorePermissionsLabelWebApp", - IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_WEB_APP}, + IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_WEB_APP}, {"appManagementMorePermissionsLabelChromeApp", - IDS_OS_SETTINGS_REVAMP_APP_PERMISSIONS_TITLE_CHROME_APP}, + IDS_OS_SETTINGS_APP_PERMISSIONS_TITLE_CHROME_APP}, {"appManagementNoAppsFound", IDS_APP_MANAGEMENT_NO_APPS_FOUND}, {"appManagementNoPermissions", IDS_APPLICATION_INFO_APP_NO_PERMISSIONS_TEXT}, {"appManagementNotificationsLabel", - kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_TITLE - : IDS_APP_MANAGEMENT_NOTIFICATIONS}, + IDS_OS_SETTINGS_APP_NOTIFICATIONS_TITLE}, {"appManagementParentAppPermissionExplanation", IDS_APP_MANAGEMENT_PARENT_APP_PERMISSION_EXPLANATION}, {"appManagementPermissionAllowed", IDS_APP_MANAGEMENT_PERMISSION_ALLOWED}, @@ -499,18 +494,10 @@ ArcAppListPrefs* arc_app_list_prefs, apps::AppServiceProxy* app_service_proxy) : OsSettingsSection(profile, search_tag_registry), - startup_subsection_( - !ash::features::IsOsSettingsRevampWayfindingEnabled() - ? std::make_optional<StartupSection>(profile, search_tag_registry) - : std::nullopt), pref_service_(pref_service), arc_app_list_prefs_(arc_app_list_prefs), app_service_proxy_(app_service_proxy), is_arc_allowed_(arc::IsArcAllowedForProfile(profile)) { - if (!ash::features::IsOsSettingsRevampWayfindingEnabled()) { - CHECK(startup_subsection_); - } - SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.AddSearchTags(GetAppsSearchConcepts()); @@ -562,9 +549,6 @@ } void AppsSection::AddLoadTimeData(content::WebUIDataSource* html_source) { - const bool kIsRevampEnabled = - ash::features::IsOsSettingsRevampWayfindingEnabled(); - webui::LocalizedString kLocalizedStrings[] = { {"appsPageTitle", IDS_SETTINGS_APPS_TITLE}, {"appsMenuItemDescription", IDS_OS_SETTINGS_APPS_MENU_ITEM_DESCRIPTION}, @@ -580,17 +564,15 @@ IDS_SETTINGS_MANAGE_ISOLATED_WEB_APPS_SUBPAGE_TITLE}, {"appNotificationsManagerLabel", - IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LABEL}, + IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LABEL}, {"appNotificationsManagerSublabel", - IDS_OS_SETTINGS_REVAMP_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION}, + IDS_OS_SETTINGS_NOTIFICATIONS_MANAGER_LINK_DESCRIPTION}, {"doNotDisturbToggleDescription", - kIsRevampEnabled - ? IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION - : IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION}, + IDS_OS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION}, {"appNotificationsLinkToBrowserSettingsDescription", IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TO_BROWSER_SETTINGS_DESCRIPTION}, {"appNotificationsRowSublabel", - IDS_OS_SETTINGS_REVAMP_APP_NOTIFICATIONS_LINK_DESCRIPTION}, + IDS_OS_SETTINGS_APP_NOTIFICATIONS_LINK_DESCRIPTION}, {"appNotificationsCountDescription", IDS_SETTINGS_APP_NOTIFICATIONS_SUBLABEL_TEXT}, {"appNotificationsDoNotDisturbEnabledDescription", @@ -671,11 +653,6 @@ AddPluginVmLoadTimeData(html_source); AddBorealisStrings(html_source); AddAppParentalControlsStrings(html_source); - - // Startup subsection exists only when OsSettingsRevampWayfinding is disabled. - if (startup_subsection_) { - startup_subsection_->AddLoadTimeData(html_source); - } } void AppsSection::AddHandlers(content::WebUI* web_ui) { @@ -784,7 +761,7 @@ mojom::kPluginVmUsbPreferencesSubpagePath); // Google Play Store. - generator->RegisterTopLevelSubpage(IDS_SETTINGS_ANDROID_APPS_LABEL, + generator->RegisterTopLevelSubpage(IDS_OS_SETTINGS_ANDROID_APPS_LABEL, mojom::Subpage::kGooglePlayStore, mojom::SearchResultIcon::kGooglePlay, mojom::SearchResultDefaultRank::kMedium, @@ -812,11 +789,6 @@ mojom::SearchResultIcon::kAppsParentalControls, mojom::SearchResultDefaultRank::kMedium, mojom::kAppParentalControlsSubpagePath); - - // Startup subsection exists only when OsSettingsRevampWayfinding is disabled. - if (startup_subsection_) { - startup_subsection_->RegisterHierarchy(generator); - } } void AppsSection::OnAppRegistered(const std::string& app_id, @@ -825,37 +797,23 @@ } void AppsSection::AddAndroidAppStrings(content::WebUIDataSource* html_source) { - const bool kIsRevampEnabled = - ash::features::IsOsSettingsRevampWayfindingEnabled(); - webui::LocalizedString kLocalizedStrings[] = { - {"androidAppsPageLabel", kIsRevampEnabled - ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_LABEL - : IDS_SETTINGS_ANDROID_APPS_LABEL}, + {"androidAppsPageLabel", IDS_OS_SETTINGS_ANDROID_APPS_LABEL}, {"androidAppsEnable", IDS_SETTINGS_TURN_ON}, - {"androidAppsManageApps", - kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_MANAGE_APPS - : IDS_SETTINGS_ANDROID_APPS_MANAGE_APPS}, - {"androidAppsRemove", kIsRevampEnabled - ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_REMOVE - : IDS_SETTINGS_ANDROID_APPS_REMOVE}, + {"androidAppsManageApps", IDS_OS_SETTINGS_ANDROID_APPS_MANAGE_APPS}, + {"androidAppsRemove", IDS_OS_SETTINGS_ANDROID_APPS_REMOVE}, {"androidAppsRemoveButton", IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON}, {"androidAppsDisableDialogTitle", - kIsRevampEnabled - ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_TITLE - : IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE}, + IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE}, {"androidAppsDisableDialogMessage", - kIsRevampEnabled - ? IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_DISABLE_DIALOG_MESSAGE - : IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE}, + IDS_OS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE}, {"androidAppsDisableDialogRemove", - kIsRevampEnabled ? IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON - : IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE}, + IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON}, {"arcvmSharedUsbDevicesDescription", IDS_SETTINGS_APPS_ARC_VM_SHARED_USB_DEVICES_DESCRIPTION}, {"androidAppsEnableButtonRole", IDS_SETTINGS_ANDROID_APPS_ENABLE_BUTTON_ROLE}, - {"androidOpenGooglePlay", IDS_OS_SETTINGS_REVAMP_OPEN_GOOGLE_PLAY}, + {"androidOpenGooglePlay", IDS_OS_SETTINGS_OPEN_GOOGLE_PLAY}, {"appLanguageDeviceLanguageLabel", IDS_OS_SETTINGS_APP_LANGUAGE_DEVICE_LANGUAGE_LABEL}, {"appLanguageDialogTitle", IDS_OS_SETTINGS_APP_LANGUAGE_DIALOG_TITLE}, @@ -875,23 +833,12 @@ : IDS_SETTINGS_ANDROID_SETTINGS_TITLE); html_source->AddString( "androidAppsSubtext", - kIsRevampEnabled - ? l10n_util::GetStringFUTF16( - IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT, - GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL)) - : l10n_util::GetStringFUTF16( - IDS_SETTINGS_ANDROID_APPS_SUBTEXT, ui::GetChromeOSDeviceName(), - GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL))); - if (kIsRevampEnabled) { - html_source->AddLocalizedString( - "androidAppsSubtextDescription", - IDS_OS_SETTINGS_REVAMP_ANDROID_APPS_SUBTEXT_DESCRIPTION); - } else { - html_source->AddString("androidAppsSubtextDescription", - l10n_util::GetStringFUTF16( - IDS_SETTINGS_ANDROID_APPS_SUBTEXT_DESCRIPTION, - ui::GetChromeOSDeviceName())); - } + l10n_util::GetStringFUTF16( + IDS_OS_SETTINGS_ANDROID_APPS_SUBTEXT, + GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL))); + html_source->AddLocalizedString( + "androidAppsSubtextDescription", + IDS_OS_SETTINGS_ANDROID_APPS_SUBTEXT_DESCRIPTION); } void AppsSection::AddPluginVmLoadTimeData( @@ -948,22 +895,16 @@ } void AppsSection::OnQuietModeChanged(bool in_quiet_mode) { - const bool kIsRevampEnabled = - ash::features::IsOsSettingsRevampWayfindingEnabled(); SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.RemoveSearchTags(GetTurnOnAppNotificationSearchConcepts()); updater.RemoveSearchTags(GetTurnOffAppNotificationSearchConcepts()); updater.RemoveSearchTags(GetAppNotificationsSearchConcepts()); - if (kIsRevampEnabled) { - updater.RemoveSearchTags(GetAppNotificationsManagerSearchConcepts()); - } + updater.RemoveSearchTags(GetAppNotificationsManagerSearchConcepts()); updater.RemoveSearchTags(GetAppBadgingSearchConcepts()); updater.AddSearchTags(GetAppNotificationsSearchConcepts()); - if (kIsRevampEnabled) { - updater.AddSearchTags(GetAppNotificationsManagerSearchConcepts()); - } + updater.AddSearchTags(GetAppNotificationsManagerSearchConcepts()); updater.AddSearchTags(GetAppBadgingSearchConcepts()); if (!MessageCenterAsh::Get()->IsQuietMode()) {
diff --git a/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.h b/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.h index e5a2c973..4a90e0b6 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.h +++ b/chrome/browser/ui/webui/ash/settings/pages/apps/apps_section.h
@@ -60,7 +60,6 @@ void UpdateAndroidSearchTags(); - std::optional<StartupSection> startup_subsection_; raw_ptr<PrefService> pref_service_; raw_ptr<ArcAppListPrefs> arc_app_list_prefs_; raw_ptr<apps::AppServiceProxy> app_service_proxy_;
diff --git a/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.cc b/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.cc index 861ee38..22485d1 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h" #include "chrome/browser/ui/webui/ash/settings/os_settings_features_util.h" -#include "chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.h" #include "chrome/browser/ui/webui/ash/settings/search/search_tag_registry.h" #include "chrome/browser/ui/webui/settings/languages_handler.h" #include "chrome/browser/ui/webui/webui_util.h" @@ -169,18 +168,7 @@ LanguagesSection::LanguagesSection(Profile* profile, SearchTagRegistry* search_tag_registry, PrefService* pref_service) - : OsSettingsSection(profile, search_tag_registry), - inputs_subsection_( - !ash::features::IsOsSettingsRevampWayfindingEnabled() - ? std::make_optional<InputsSection>( - profile, - search_tag_registry, - pref_service, - chromeos::features::IsOrcaEnabled() - ? input_method::EditorMediatorFactory::GetInstance() - ->GetForProfile(profile) - : nullptr) - : std::nullopt) { + : OsSettingsSection(profile, search_tag_registry) { SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.AddSearchTags(GetLanguagesPageSearchConceptsV2()); if (IsPerAppLanguageEnabled(profile)) { @@ -209,13 +197,6 @@ IsPerAppLanguageEnabled(profile())); AddLanguagesPageStringsV2(html_source); - - // Inputs subsection exists only when the OsSettingsRevampWayfinding feature - // is disabled. It is part of the Device section when the feature is enabled. - if (!ash::features::IsOsSettingsRevampWayfindingEnabled()) { - CHECK(inputs_subsection_); - inputs_subsection_->AddLoadTimeData(html_source); - } } void LanguagesSection::AddHandlers(content::WebUI* web_ui) { @@ -228,9 +209,7 @@ } mojom::Section LanguagesSection::GetSection() const { - return ash::features::IsOsSettingsRevampWayfindingEnabled() - ? mojom::Section::kSystemPreferences - : mojom::Section::kLanguagesAndInput; + return mojom::Section::kSystemPreferences; } mojom::SearchResultIcon LanguagesSection::GetSectionIcon() const { @@ -238,9 +217,7 @@ } const char* LanguagesSection::GetSectionPath() const { - return ash::features::IsOsSettingsRevampWayfindingEnabled() - ? mojom::kSystemPreferencesSectionPath - : mojom::kLanguagesAndInputSectionPath; + return mojom::kSystemPreferencesSectionPath; } bool LanguagesSection::LogMetric(mojom::Setting setting, @@ -278,13 +255,6 @@ mojom::SearchResultDefaultRank::kMedium, mojom::kAppLanguagesSubpagePath); } - - // Inputs subsection exists only when the OsSettingsRevampWayfinding feature - // is disabled. It is part of the Device section when the feature is enabled. - if (!ash::features::IsOsSettingsRevampWayfindingEnabled()) { - CHECK(inputs_subsection_); - inputs_subsection_->RegisterHierarchy(generator); - } } } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.h b/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.h index 06351d4..c75409357 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.h +++ b/chrome/browser/ui/webui/ash/settings/pages/languages/languages_section.h
@@ -5,13 +5,12 @@ #ifndef CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_PAGES_LANGUAGES_LANGUAGES_SECTION_H_ #define CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_PAGES_LANGUAGES_LANGUAGES_SECTION_H_ -#include <optional> - #include "base/memory/raw_ptr.h" #include "base/values.h" -#include "chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.h" #include "chrome/browser/ui/webui/ash/settings/pages/os_settings_section.h" +class PrefService; + namespace content { class WebUIDataSource; } // namespace content @@ -38,9 +37,6 @@ bool LogMetric(chromeos::settings::mojom::Setting setting, base::Value& value) const override; void RegisterHierarchy(HierarchyGenerator* generator) const override; - - private: - std::optional<InputsSection> inputs_subsection_; }; } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc index ac89f41..95d3af5 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc
@@ -427,21 +427,14 @@ } void AddUsersStrings(content::WebUIDataSource* html_source) { - const bool kIsRevampEnabled = - ash::features::IsOsSettingsRevampWayfindingEnabled(); - webui::LocalizedString kLocalizedStrings[] = { {"usersModifiedByOwnerLabel", IDS_SETTINGS_USERS_MODIFIED_BY_OWNER_LABEL}, - {"guestBrowsingLabel", - kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_USERS_GUEST_BROWSING_LABEL - : IDS_SETTINGS_USERS_GUEST_BROWSING_LABEL}, + {"guestBrowsingLabel", IDS_OS_SETTINGS_USERS_GUEST_BROWSING_LABEL}, {"settingsManagedLabel", IDS_SETTINGS_USERS_MANAGED_LABEL}, {"showOnSigninLabel", IDS_SETTINGS_USERS_SHOW_ON_SIGNIN_LABEL}, - {"restrictSigninLabel", - kIsRevampEnabled ? IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_LABEL - : IDS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL}, + {"restrictSigninLabel", IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL}, {"restrictSigninDescription", - IDS_OS_SETTINGS_REVAMP_USERS_RESTRICT_SIGNIN_DESCRIPTION}, + IDS_OS_SETTINGS_USERS_RESTRICT_SIGNIN_DESCRIPTION}, {"deviceOwnerLabel", IDS_SETTINGS_USERS_DEVICE_OWNER_LABEL}, {"removeUserTooltip", IDS_SETTINGS_USERS_REMOVE_USER_TOOLTIP}, {"userRemovedMessage", IDS_SETTINGS_USERS_USER_REMOVED_MESSAGE}, @@ -508,10 +501,6 @@ signin::IdentityManager* identity_manager, PrefService* pref_service) : OsSettingsSection(profile, search_tag_registry), - sync_subsection_( - !ash::features::IsOsSettingsRevampWayfindingEnabled() - ? std::make_optional<SyncSection>(profile, search_tag_registry) - : std::nullopt), identity_manager_(identity_manager), pref_service_(pref_service), auth_performer_(UserDataAuthClient::Get()), @@ -522,10 +511,6 @@ return; } - if (!ash::features::IsOsSettingsRevampWayfindingEnabled()) { - CHECK(sync_subsection_); - } - SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.AddSearchTags(GetPeopleSearchConcepts()); @@ -611,12 +596,6 @@ AddGraduationStrings(html_source, profile()); ::settings::AddPasswordPromptDialogStrings(html_source); - - // `sync_subsection_` is initialized only if the feature revamp wayfinding is - // disabled. - if (sync_subsection_) { - sync_subsection_->AddLoadTimeData(html_source); - } } void PeopleSection::AddHandlers(content::WebUI* web_ui) { @@ -641,12 +620,6 @@ web_ui->AddMessageHandler( std::make_unique<ParentalControlsHandler>(profile())); } - - // `sync_subsection_` is initialized only if the feature revamp wayfinding is - // disabled. - if (sync_subsection_) { - sync_subsection_->AddHandlers(web_ui); - } } int PeopleSection::GetSectionNameMessageId() const { @@ -679,38 +652,21 @@ } void PeopleSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kAddAccount); + generator->RegisterTopLevelSetting(mojom::Setting::kRemoveAccount); generator->RegisterTopLevelSetting(mojom::Setting::kSetUpParentalControls); generator->RegisterTopLevelSetting(mojom::Setting::kGraduation); + // TODO(crbug.com/370837151) Remove this obsolete subpage Mojom constant and + // the respective route redirect. generator->RegisterTopLevelSubpage( IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE, mojom::Subpage::kMyAccounts, mojom::SearchResultIcon::kAvatar, mojom::SearchResultDefaultRank::kMedium, mojom::kMyAccountsSubpagePath); - // My accounts. - if (ash::features::IsOsSettingsRevampWayfindingEnabled()) { - // Accounts settings are up-leveled to the top level page if the revamp - // wayfind is enabled. - generator->RegisterTopLevelSetting(mojom::Setting::kAddAccount); - generator->RegisterTopLevelSetting(mojom::Setting::kRemoveAccount); - } else { - static constexpr mojom::Setting kMyAccountsSettings[] = { - mojom::Setting::kAddAccount, - mojom::Setting::kRemoveAccount, - }; - RegisterNestedSettingBulk(mojom::Subpage::kMyAccounts, kMyAccountsSettings, - generator); - } - // Smart Lock -- main setting is on multidevice page, but is mirrored here generator->RegisterNestedAltSetting(mojom::Setting::kSmartLockOnOff, mojom::Subpage::kSecurityAndSignInV2); - - // `sync_subsection_` is initialized only if the feature revamp wayfinding is - // disabled. - if (sync_subsection_) { - sync_subsection_->RegisterHierarchy(generator); - } } void PeopleSection::FetchAccounts() {
diff --git a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.h b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.h index b257b6f..61f08237 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.h +++ b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.h
@@ -5,15 +5,12 @@ #ifndef CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_PAGES_PEOPLE_PEOPLE_SECTION_H_ #define CHROME_BROWSER_UI_WEBUI_ASH_SETTINGS_PAGES_PEOPLE_PEOPLE_SECTION_H_ -#include <optional> - #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/values.h" #include "chrome/browser/ash/auth/legacy_fingerprint_engine.h" #include "chrome/browser/ui/webui/ash/settings/pages/os_settings_section.h" -#include "chrome/browser/ui/webui/ash/settings/pages/privacy/sync_section.h" #include "chromeos/ash/components/login/auth/auth_performer.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" @@ -77,7 +74,6 @@ void UpdateAccountManagerSearchTags( const std::vector<::account_manager::Account>& accounts); - std::optional<SyncSection> sync_subsection_; raw_ptr<account_manager::AccountManager> account_manager_ = nullptr; raw_ptr<account_manager::AccountManagerFacade> account_manager_facade_ =
diff --git a/chrome/browser/ui/webui/ash/settings/pages/search/BUILD.gn b/chrome/browser/ui/webui/ash/settings/pages/search/BUILD.gn index ec3831a..87d964c 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/search/BUILD.gn +++ b/chrome/browser/ui/webui/ash/settings/pages/search/BUILD.gn
@@ -80,6 +80,7 @@ "//chrome/test:test_support", "//chrome/test:test_support_unit", "//chromeos/components/magic_boost/test:fake_magic_boost_state", + "//chromeos/components/quick_answers:test_support", "//content/test:test_support", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/browser/ui/webui/ash/settings/pages/search/search_section.cc b/chrome/browser/ui/webui/ash/settings/pages/search/search_section.cc index 633cebd0..67d2a9a 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/search/search_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/search/search_section.cc
@@ -592,6 +592,10 @@ UpdateQuickAnswersSearchTags(); } +void SearchSection::OnFeatureTypeChanged() { + UpdateQuickAnswersSearchTags(); +} + void SearchSection::OnMagicBoostEnabledUpdated(bool enabled) { // This is triggered on magic boost prefs value changes, which means magic // boost must be available.
diff --git a/chrome/browser/ui/webui/ash/settings/pages/search/search_section.h b/chrome/browser/ui/webui/ash/settings/pages/search/search_section.h index f771684..50ee221a 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/search/search_section.h +++ b/chrome/browser/ui/webui/ash/settings/pages/search/search_section.h
@@ -51,6 +51,7 @@ // QuickAnswersStateObserver: void OnSettingsEnabled(bool enabled) override; void OnEligibilityChanged(bool eligible) override; + void OnFeatureTypeChanged() override; // chromeos::MagicBoostState::Observer: void OnMagicBoostEnabledUpdated(bool enabled) override;
diff --git a/chrome/browser/ui/webui/ash/settings/pages/search/search_section_unittest.cc b/chrome/browser/ui/webui/ash/settings/pages/search/search_section_unittest.cc index 641ff16..74c39833 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/search/search_section_unittest.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/search/search_section_unittest.cc
@@ -8,15 +8,21 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" +#include "ash/webui/settings/public/constants/setting.mojom-shared.h" #include "base/auto_reset.h" #include "base/memory/raw_ptr.h" +#include "base/strings/strcat.h" +#include "base/strings/to_string.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/ash/settings/search/search_tag_registry.h" +#include "chrome/grit/generated_resources.h" #include "chrome/test/base/chrome_ash_test_base.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/components/magic_boost/test/fake_magic_boost_state.h" +#include "chromeos/components/quick_answers/public/cpp/quick_answers_state.h" +#include "chromeos/components/quick_answers/test/fake_quick_answers_state.h" #include "content/public/test/test_web_ui_data_source.h" #include "testing/gtest/include/gtest/gtest.h" @@ -120,4 +126,44 @@ .value()); } +// MagicBoost availability check requires an async operation. There is a short +// period where `MagicBoostState` returns false for its availability even if a +// user/device is eligible. +TEST_F(SearchSectionTest, + QuickAnswersSearchConceptsRemovedIfItBecomesUnavailable) { + const std::string quick_answers_result_id = base::StrCat( + {base::ToString(chromeos::settings::mojom::Setting::kQuickAnswersOnOff), + ",", base::ToString(IDS_OS_SETTINGS_TAG_QUICK_ANSWERS)}); + + chromeos::test::FakeMagicBoostState magic_boost_state; + magic_boost_state.SetMagicBoostAvailability(false); + FakeQuickAnswersState quick_answers_state; + quick_answers_state.SetApplicationLocale("en"); + ASSERT_EQ(QuickAnswersState::FeatureType::kQuickAnswers, + QuickAnswersState::GetFeatureType()) + << "Current feature type is set to kQuickAnswers. This is simulating the " + "case where MagicBoost availability check async opearation is not " + "completed."; + + search_section_ = + std::make_unique<SearchSection>(profile(), search_tag_registry()); + + EXPECT_NE(nullptr, + search_tag_registry()->GetTagMetadata(quick_answers_result_id)) + << "QuickAnswers tag should be registered as the current feature is set " + "to kQuickAnswers"; + + // Simulate that MagicBoost availability check async operation has been + // completed and a user has went through MagicBoost consent flow. + magic_boost_state.SetMagicBoostAvailability(true); + magic_boost_state.SetMagicBoostEnabled(true); + ASSERT_EQ(QuickAnswersState::FeatureType::kHmr, + QuickAnswersState::GetFeatureType()); + + EXPECT_EQ(nullptr, + search_tag_registry()->GetTagMetadata(quick_answers_result_id)) + << "Quick Answers tag should not be found as the current feature type is " + "set to kHmr"; +} + } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.cc b/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.cc index c347421..be7f64f 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.cc
@@ -81,8 +81,7 @@ crostini_size_calculator_(profile), other_users_size_calculator_(), profile_(profile), - source_name_(html_source->GetSource()), - special_volume_path_pattern_("[a-z]+://.*") {} + source_name_(html_source->GetSource()) {} StorageHandler::~StorageHandler() { StopObservingEvents(); @@ -226,7 +225,7 @@ base::Value::List devices; for (const auto& mount_point : DiskMountManager::GetInstance()->mount_points()) { - if (!IsEligibleForAndroidStorage(mount_point.source_path)) { + if (!IsEligibleForAndroidStorage(mount_point)) { continue; } @@ -261,12 +260,12 @@ void StorageHandler::OnMountEvent( DiskMountManager::MountEvent event, MountError error_code, - const DiskMountManager::MountPoint& mount_info) { + const DiskMountManager::MountPoint& mount_point) { if (error_code != MountError::kSuccess) { return; } - if (!IsEligibleForAndroidStorage(mount_info.source_path)) { + if (!IsEligibleForAndroidStorage(mount_point)) { return; } @@ -442,11 +441,13 @@ base::Value(message)); } -bool StorageHandler::IsEligibleForAndroidStorage(std::string source_path) { - // Android's StorageManager volume concept relies on assumption that it is - // local filesystem. Hence, special volumes like DriveFS should not be - // listed on the Settings. - return !RE2::FullMatch(source_path, special_volume_path_pattern_); +bool StorageHandler::IsEligibleForAndroidStorage( + const MountPoint& mount_point) { + // Android's StorageManager volume concept relies on the assumption that it is + // a local filesystem. Hence, special volumes like DriveFS and mounted + // archives should not be listed on the "External storage preferences" + // settings page. + return mount_point.mount_type == MountType::kDevice; } } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.h b/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.h index dac3fea..b2e53dd 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.h +++ b/chrome/browser/ui/webui/ash/settings/pages/storage/device_storage_handler.h
@@ -14,8 +14,8 @@ #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h" #include "chrome/browser/ui/webui/ash/settings/calculator/size_calculator.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h" #include "chromeos/ash/components/disks/disk_mount_manager.h" -#include "third_party/re2/src/re2/re2.h" class Profile; @@ -99,9 +99,9 @@ // Updates list of external storages. void UpdateExternalStorages(); - // Returns true if the volume from |source_path| can be used as Android + // Returns true if the volume from |mount_point| can be used as Android // storage. - bool IsEligibleForAndroidStorage(std::string source_path); + bool IsEligibleForAndroidStorage(const MountPoint& mount_point); // Update encryption type whenever it is fetched. void OnGetVaultProperties( @@ -130,7 +130,6 @@ base::ScopedObservation<arc::ArcSessionManager, arc::ArcSessionManagerObserver> arc_observation_{this}; - const re2::RE2 special_volume_path_pattern_; base::WeakPtrFactory<StorageHandler> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 47e594b..4e9aa10c 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -344,9 +344,7 @@ "chrome://identity-internals", "chrome://indexeddb-internals", "chrome://inspect", - "chrome://internals", "chrome://internals/session-service", - "chrome://internals/user-education", "chrome://interstitials/ssl", "chrome://local-state", "chrome://management", @@ -397,6 +395,7 @@ "chrome://ukm", "chrome://usb-internals", "chrome://user-actions", + "chrome://user-education-internals", "chrome://version", "chrome://web-app-internals", "chrome://webrtc-internals",
diff --git a/chrome/browser/ui/webui/chrome_web_ui_configs.cc b/chrome/browser/ui/webui/chrome_web_ui_configs.cc index a2719d7..c3648143 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_configs.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_configs.cc
@@ -84,7 +84,9 @@ #include "chrome/browser/ui/webui/history/history_ui.h" #include "chrome/browser/ui/webui/identity_internals_ui.h" #include "chrome/browser/ui/webui/inspect_ui.h" +#if BUILDFLAG(ENABLE_SESSION_SERVICE) #include "chrome/browser/ui/webui/internals/internals_ui.h" +#endif // BUILDFLAG(ENABLE_SESSION_SERVICE) #include "chrome/browser/ui/webui/management/management_ui.h" #include "chrome/browser/ui/webui/media_router/media_router_internals_ui.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" @@ -106,6 +108,7 @@ #include "chrome/browser/ui/webui/support_tool/support_tool_ui.h" #include "chrome/browser/ui/webui/system/system_info_ui.h" #include "chrome/browser/ui/webui/tab_search/tab_search_ui.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.h" #include "chrome/browser/ui/webui/web_app_internals/web_app_internals_ui.h" #include "chrome/browser/ui/webui/webui_gallery/webui_gallery_ui.h" #include "chrome/browser/ui/webui/webui_js_error/webui_js_error_ui.h" @@ -292,7 +295,9 @@ map.AddWebUIConfig(std::make_unique<HistoryClustersSidePanelUIConfig>()); map.AddWebUIConfig(std::make_unique<IdentityInternalsUIConfig>()); map.AddWebUIConfig(std::make_unique<InspectUIConfig>()); +#if BUILDFLAG(ENABLE_SESSION_SERVICE) map.AddWebUIConfig(std::make_unique<InternalsUIConfig>()); +#endif // BUILDFLAG(ENABLE_SESSION_SERVICE) map.AddWebUIConfig(std::make_unique<ManagementUIConfig>()); map.AddWebUIConfig( std::make_unique<media_router::MediaRouterInternalsUIConfig>()); @@ -316,6 +321,7 @@ map.AddWebUIConfig(std::make_unique<SystemInfoUIConfig>()); map.AddWebUIConfig(std::make_unique<TabSearchUIConfig>()); map.AddWebUIConfig(std::make_unique<TermsUIConfig>()); + map.AddWebUIConfig(std::make_unique<UserEducationInternalsUIConfig>()); map.AddWebUIConfig(std::make_unique<WebAppInternalsUIConfig>()); map.AddWebUIConfig(std::make_unique<WebuiGalleryUIConfig>()); map.AddWebUIConfig(std::make_unique<WebUIJsErrorUIConfig>());
diff --git a/chrome/browser/ui/webui/internals/internals_ui.cc b/chrome/browser/ui/webui/internals/internals_ui.cc index a420b40..569bfe07 100644 --- a/chrome/browser/ui/webui/internals/internals_ui.cc +++ b/chrome/browser/ui/webui/internals/internals_ui.cc
@@ -9,22 +9,15 @@ #include "build/build_config.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" -#include "chrome/grit/dev_ui_browser_resources.h" -#include "chrome/grit/internals_resources.h" -#include "chrome/grit/internals_resources_map.h" -#include "components/user_education/common/user_education_features.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_data_source.h" #include "chrome/browser/ui/browser_element_identifiers.h" -#include "chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "ui/base/interaction/element_identifier.h" -#if BUILDFLAG(ENABLE_SESSION_SERVICE) #include "chrome/browser/ui/webui/internals/sessions/session_service_internals_handler.h" -#endif InternalsUIConfig::InternalsUIConfig() : DefaultWebUIConfig(content::kChromeUIScheme, @@ -56,58 +49,17 @@ } // namespace InternalsUI::InternalsUI(content::WebUI* web_ui) - : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true), - help_bubble_handler_factory_receiver_(this) { + : content::WebUIController(web_ui) { profile_ = Profile::FromWebUI(web_ui); source_ = content::WebUIDataSource::CreateAndAdd( profile_, chrome::kChromeUIInternalsHost); - webui::SetupWebUIDataSource(source_, kInternalsResources, - IDR_INTERNALS_INTERNALS_HTML); - source_->AddResourcePath("user-education", - IDR_USER_EDUCATION_INTERNALS_INDEX_HTML); - // chrome://internals/session-service source_->SetRequestFilter( base::BindRepeating(&ShouldHandleWebUIRequestCallback), base::BindRepeating(&HandleWebUIRequestCallback, profile_)); - - source_->AddBoolean("isWhatsNewV2", user_education::features::IsWhatsNewV2()); } InternalsUI::~InternalsUI() = default; -void InternalsUI::BindInterface( - mojo::PendingReceiver< - mojom::user_education_internals::UserEducationInternalsPageHandler> - receiver) { - user_education_handler_ = - std::make_unique<UserEducationInternalsPageHandlerImpl>( - web_ui(), profile_, std::move(receiver)); -} - -void InternalsUI::BindInterface( - mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandlerFactory> - pending_receiver) { - if (help_bubble_handler_factory_receiver_.is_bound()) - help_bubble_handler_factory_receiver_.reset(); - help_bubble_handler_factory_receiver_.Bind(std::move(pending_receiver)); -} - -void InternalsUI::CreateHelpBubbleHandler( - mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> pending_client, - mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler> - pending_handler) { - help_bubble_handler_ = std::make_unique<user_education::HelpBubbleHandler>( - std::move(pending_handler), std::move(pending_client), this, - std::vector<ui::ElementIdentifier>{kWebUIIPHDemoElementIdentifier}); -} - -void InternalsUI::BindInterface( - mojo::PendingReceiver<color_change_listener::mojom::PageHandler> - pending_receiver) { - color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>( - web_ui()->GetWebContents(), std::move(pending_receiver)); -} - WEB_UI_CONTROLLER_TYPE_IMPL(InternalsUI)
diff --git a/chrome/browser/ui/webui/internals/internals_ui.h b/chrome/browser/ui/webui/internals/internals_ui.h index dd61afb..564b5eb4 100644 --- a/chrome/browser/ui/webui/internals/internals_ui.h +++ b/chrome/browser/ui/webui/internals/internals_ui.h
@@ -8,13 +8,9 @@ #include "base/memory/raw_ptr.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom.h" -#include "components/user_education/webui/help_bubble_handler.h" +#include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/webui_config.h" -#include "ui/webui/color_change_listener/color_change_handler.h" -#include "ui/webui/mojo_web_ui_controller.h" -#include "ui/webui/resources/cr_components/help_bubble/help_bubble.mojom.h" namespace content { class WebUI; @@ -27,50 +23,16 @@ InternalsUIConfig(); }; -// Client could put debug WebUI as sub-URL under chrome://internals/. -// e.g. chrome://internals/your-feature. -class InternalsUI : public ui::MojoWebUIController, - public help_bubble::mojom::HelpBubbleHandlerFactory { +class InternalsUI : public content::WebUIController { public: explicit InternalsUI(content::WebUI* web_ui); ~InternalsUI() override; - void BindInterface( - mojo::PendingReceiver< - mojom::user_education_internals::UserEducationInternalsPageHandler> - receiver); - - // The HelpBubbleHandlerFactory provides support for help bubbles in this - // WebUI. Also see CreateHelpBubbleHandler() below. - void BindInterface( - mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandlerFactory> - pending_receiver); - - // help_bubble::mojom::HelpBubbleHandlerFactory: - void CreateHelpBubbleHandler( - mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> pending_client, - mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler> - pending_handler) override; - - void BindInterface( - mojo::PendingReceiver<color_change_listener::mojom::PageHandler> - pending_receiver); - private: WEB_UI_CONTROLLER_TYPE_DECL(); raw_ptr<Profile> profile_; raw_ptr<content::WebUIDataSource> source_; - - std::unique_ptr< - mojom::user_education_internals::UserEducationInternalsPageHandler> - user_education_handler_; - - std::unique_ptr<user_education::HelpBubbleHandler> help_bubble_handler_; - mojo::Receiver<help_bubble::mojom::HelpBubbleHandlerFactory> - help_bubble_handler_factory_receiver_; - - std::unique_ptr<ui::ColorChangeHandler> color_provider_handler_; }; #endif // CHROME_BROWSER_UI_WEBUI_INTERNALS_INTERNALS_UI_H_
diff --git a/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc b/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc index 83046911..c494c02 100644 --- a/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc +++ b/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc
@@ -104,7 +104,7 @@ // discard it as in https://crbug.com/1094088. IN_PROC_BROWSER_TEST_F(WebUiNtpBrowserTest, SpareRenderer) { // Capture current spare renderer. - std::vector<int> spare_ids_before_navigation = + std::vector<content::ChildProcessId> spare_ids_before_navigation = content::SpareRenderProcessHostManager::Get().GetSpareIds(); ASSERT_FALSE(spare_ids_before_navigation.empty()); @@ -119,9 +119,9 @@ ExpectIsWebUiNtp(ntp); // Check spare was taken. - EXPECT_TRUE(base::Contains( - spare_ids_before_navigation, - ntp->GetPrimaryMainFrame()->GetProcess()->GetDeprecatedID())); + EXPECT_TRUE( + base::Contains(spare_ids_before_navigation, + ntp->GetPrimaryMainFrame()->GetProcess()->GetID())); // No processes should be unnecessarily terminated. const std::set<int> ending_rph_ids = LiveRenderProcessHostIds();
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom index ede28f8a..b194730 100644 --- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom +++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page.mojom
@@ -8,6 +8,7 @@ import "mojo/public/mojom/base/file_path.mojom"; import "mojo/public/mojom/base/time.mojom"; import "services/on_device_model/public/mojom/on_device_model.mojom"; +import "services/on_device_model/public/mojom/on_device_model_service.mojom"; import "skia/public/mojom/bitmap.mojom"; // Struct containing data to be displayed on on-device-internals page. @@ -43,6 +44,7 @@ // Binds a new OnDeviceModel interface if possible using model assets loaded // from within `model_path`. LoadModel(mojo_base.mojom.FilePath model_path, + on_device_model.mojom.ModelPerformanceHint performance_hint, pending_receiver<on_device_model.mojom.OnDeviceModel> model) => (on_device_model.mojom.LoadModelResult result);
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.cc b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.cc index ee69491..5b5c9599 100644 --- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.cc +++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.cc
@@ -5,10 +5,12 @@ #include "chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.h" #include "base/files/file_util.h" +#include "base/strings/string_number_conversions.h" #include "base/task/thread_pool.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h" #include "components/optimization_guide/core/model_execution/on_device_model_component.h" #include "components/optimization_guide/core/optimization_guide_constants.h" +#include "components/optimization_guide/core/optimization_guide_features.h" #include "components/optimization_guide/core/prediction_manager.h" #include "content/public/browser/service_process_host.h" #include "mojo/public/cpp/bindings/callback_helpers.h" @@ -61,6 +63,7 @@ void OnDeviceInternalsPageHandler::LoadModel( const base::FilePath& model_path, + ml::ModelPerformanceHint performance_hint, mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model, LoadModelCallback callback) { #if BUILDFLAG(USE_CHROMEOS_MODEL_SERVICE) @@ -81,7 +84,7 @@ base::BindOnce(&LoadModelAssets, model_path), base::BindOnce(&OnDeviceInternalsPageHandler::OnModelAssetsLoaded, weak_ptr_factory_.GetWeakPtr(), std::move(model), - std::move(callback))); + std::move(callback), performance_hint)); #endif } @@ -109,10 +112,12 @@ void OnDeviceInternalsPageHandler::OnModelAssetsLoaded( mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model, LoadModelCallback callback, + ml::ModelPerformanceHint performance_hint, on_device_model::ModelAssets assets) { auto params = on_device_model::mojom::LoadModelParams::New(); params->assets = std::move(assets); params->max_tokens = 4096; + params->performance_hint = performance_hint; GetService().LoadModel(std::move(params), std::move(model), std::move(callback)); } @@ -183,21 +188,32 @@ auto* criteria = component_manager->GetRegistrationCriteria(); base::flat_map<std::string, std::string> mojom_criteria; if (criteria != nullptr) { - mojom_criteria["disk_space_available"] = - bool_strings[criteria->disk_space_available]; - mojom_criteria["device_capable"] = bool_strings[criteria->device_capable]; - mojom_criteria["on_device_feature_recently_used"] = + mojom_criteria["device capable"] = bool_strings[criteria->device_capable]; + mojom_criteria["on device feature recently used"] = bool_strings[criteria->on_device_feature_recently_used]; - mojom_criteria["enabled_by_feature"] = + mojom_criteria["enabled by feature"] = bool_strings[criteria->enabled_by_feature]; - mojom_criteria["enabled_by_enterprise_policy"] = + mojom_criteria["enabled by enterprise policy"] = bool_strings[criteria->enabled_by_enterprise_policy]; - mojom_criteria["running_out_of_disk_space"] = - bool_strings[criteria->running_out_of_disk_space]; - mojom_criteria["out_of_retention"] = + mojom_criteria["out of retention"] = bool_strings[criteria->out_of_retention]; - mojom_criteria["is_already_installing"] = + mojom_criteria["is already installing"] = bool_strings[criteria->is_already_installing]; + + // Disk criteria, needs to show what's available vs. required when not met. + std::string disk_space_string = + bool_strings[criteria->disk_space_available]; + if (!criteria->disk_space_available) { + int disk_space_required_mb = optimization_guide::features:: + GetDiskSpaceRequiredInMbForOnDeviceModelInstall(); + int disk_space_available_mb = + component_manager->GetDiskBytesAvailableForModel() / (1024 * 1024); + disk_space_string += + " (" + base::NumberToString(disk_space_available_mb) + + " MiB available, " + base::NumberToString(disk_space_required_mb) + + " MiB required)"; + } + mojom_criteria["disk space available"] = disk_space_string; } data->registration_criteria = mojom_criteria;
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.h b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.h index a42e203a..98dd1c41 100644 --- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.h +++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_page_handler.h
@@ -43,12 +43,14 @@ void OnModelAssetsLoaded( mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model, LoadModelCallback callback, + ml::ModelPerformanceHint performance_hint, on_device_model::ModelAssets assets); #endif // mojom::OnDeviceInternalsPageHandler: void LoadModel( const base::FilePath& model_path, + ml::ModelPerformanceHint performance_hint, mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model, LoadModelCallback callback) override; void GetEstimatedPerformanceClass(
diff --git a/chrome/browser/ui/webui/sandbox/sandbox_handler.cc b/chrome/browser/ui/webui/sandbox/sandbox_handler.cc index ea9960f..792443e 100644 --- a/chrome/browser/ui/webui/sandbox/sandbox_handler.cc +++ b/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
@@ -91,6 +91,8 @@ FeatureToValue(sandbox::policy::features::kWinSboxNoFakeGdiInit)); features.Append(FeatureToValue( sandbox::policy::features::kWinSboxRestrictCoreSharingOnRenderer)); + features.Append( + FeatureToValue(sandbox::policy::features::kEnableCsrssLockdown)); return features; }
diff --git a/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc b/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc index 014f66f..0292098 100644 --- a/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc +++ b/chrome/browser/ui/webui/top_chrome/webui_contents_preload_manager.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/ui/webui/top_chrome/top_chrome_webui_config.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" +#include "components/crash/core/common/crash_key.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents_delegate.h" @@ -570,6 +571,17 @@ if (web_contents == preloaded_web_contents_.get()) { content::RenderWidgetHostView* render_widget_host_view = web_contents->GetRenderWidgetHostView(); + + // TODO(crbug.com/383937390): TopChromeWebUIConfig::From() returns nullptr. + // This crash key is to investigate if the visible URL is empty. + static crash_reporter::CrashKeyString<1024> visible_url( + "webui-preload-visible-url"); + visible_url.Set(web_contents->GetVisibleURL().possibly_invalid_spec()); + static crash_reporter::CrashKeyString<1024> site_instance_url( + "webui-preload-site-instance-url"); + site_instance_url.Set( + web_contents->GetSiteInstance()->GetSiteURL().possibly_invalid_spec()); + const bool should_auto_reisze_host = TopChromeWebUIConfig::From(web_contents->GetBrowserContext(), web_contents->GetVisibleURL())
diff --git a/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.cc b/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.cc index ce6a3d6..97ff054 100644 --- a/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.cc +++ b/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.cc
@@ -70,10 +70,9 @@ CHECK(pre_condition_) << "You must call BeforeContentsCreation()"; CHECK(web_contents); - if (base::Contains(pre_condition_->spare_process_ids, - web_contents->GetPrimaryMainFrame() - ->GetProcess() - ->GetDeprecatedID())) { + if (base::Contains( + pre_condition_->spare_process_ids, + web_contents->GetPrimaryMainFrame()->GetProcess()->GetID())) { level_ = WebUIContentsWarmupLevel::kSpareRenderer; return; }
diff --git a/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.h b/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.h index 349ee84..6ea0187 100644 --- a/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.h +++ b/chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level_recorder.h
@@ -13,6 +13,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/webui/top_chrome/webui_contents_warmup_level.h" +#include "content/public/browser/child_process_id.h" namespace content { @@ -30,7 +31,7 @@ // The IDs of the spare processes before the contents is created. This can be // empty when the memory pressure is high or a spare process creation is // delayed. - std::vector<int> spare_process_ids; + std::vector<content::ChildProcessId> spare_process_ids; // Use WeakPtr because the preloaded contents could be destroyed, e.g. after // a request of contents under a different browser context.
diff --git a/chrome/browser/ui/webui/internals/user_education/BUILD.gn b/chrome/browser/ui/webui/user_education_internals/BUILD.gn similarity index 78% rename from chrome/browser/ui/webui/internals/user_education/BUILD.gn rename to chrome/browser/ui/webui/user_education_internals/BUILD.gn index 932e4829..dcd4b5f4 100644 --- a/chrome/browser/ui/webui/internals/user_education/BUILD.gn +++ b/chrome/browser/ui/webui/user_education_internals/BUILD.gn
@@ -6,5 +6,5 @@ mojom("mojo_bindings") { sources = [ "user_education_internals.mojom" ] - webui_module_path = "/chrome/browser/ui/webui/internals/user_education" + webui_module_path = "/" }
diff --git a/chrome/browser/ui/webui/internals/user_education/DIR_METADATA b/chrome/browser/ui/webui/user_education_internals/DIR_METADATA similarity index 100% rename from chrome/browser/ui/webui/internals/user_education/DIR_METADATA rename to chrome/browser/ui/webui/user_education_internals/DIR_METADATA
diff --git a/chrome/browser/ui/webui/internals/user_education/OWNERS b/chrome/browser/ui/webui/user_education_internals/OWNERS similarity index 100% rename from chrome/browser/ui/webui/internals/user_education/OWNERS rename to chrome/browser/ui/webui/user_education_internals/OWNERS
diff --git a/chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom b/chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom similarity index 98% rename from chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom rename to chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom index d3115a8..153ad4d 100644 --- a/chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom +++ b/chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom
@@ -68,7 +68,7 @@ }; // Provides access to browser-side user education data for -// chrome://internals/user-education +// chrome://user-education-internals interface UserEducationInternalsPageHandler { // Get the list of all available tutorials. Only needs to be called once // since the browser-side list is static and does not change.
diff --git a/chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.cc b/chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.cc similarity index 99% rename from chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.cc rename to chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.cc index 2b2324e..a7bf88c 100644 --- a/chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.cc +++ b/chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.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 "chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.h" #include <stdint.h> @@ -25,7 +25,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/user_education/browser_user_education_interface.h" -#include "chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom-forward.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom-forward.h" #include "chrome/browser/user_education/user_education_service.h" #include "chrome/browser/user_education/user_education_service_factory.h" #include "components/feature_engagement/public/tracker.h"
diff --git a/chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.h b/chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.h similarity index 91% rename from chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.h rename to chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.h index 5015681..ab0a64c 100644 --- a/chrome/browser/ui/webui/internals/user_education/user_education_internals_page_handler_impl.h +++ b/chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_INTERNALS_USER_EDUCATION_USER_EDUCATION_INTERNALS_PAGE_HANDLER_IMPL_H_ -#define CHROME_BROWSER_UI_WEBUI_INTERNALS_USER_EDUCATION_USER_EDUCATION_INTERNALS_PAGE_HANDLER_IMPL_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_USER_EDUCATION_INTERNALS_USER_EDUCATION_INTERNALS_PAGE_HANDLER_IMPL_H_ +#define CHROME_BROWSER_UI_WEBUI_USER_EDUCATION_INTERNALS_USER_EDUCATION_INTERNALS_PAGE_HANDLER_IMPL_H_ #include "base/feature_list.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/internals/user_education/user_education_internals.mojom.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom.h" #include "components/user_education/common/feature_promo/feature_promo_result.h" #include "components/user_education/common/tutorial/tutorial_service.h" #include "content/public/browser/web_ui_data_source.h" @@ -72,4 +72,4 @@ this}; }; -#endif // CHROME_BROWSER_UI_WEBUI_INTERNALS_USER_EDUCATION_USER_EDUCATION_INTERNALS_PAGE_HANDLER_IMPL_H_ +#endif // CHROME_BROWSER_UI_WEBUI_USER_EDUCATION_INTERNALS_USER_EDUCATION_INTERNALS_PAGE_HANDLER_IMPL_H_
diff --git a/chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.cc b/chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.cc new file mode 100644 index 0000000..7f0e4d0 --- /dev/null +++ b/chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.cc
@@ -0,0 +1,77 @@ +// Copyright 2024 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/webui/user_education_internals/user_education_internals_ui.h" + +#include <vector> + +#include "build/build_config.h" +#include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals_page_handler_impl.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/dev_ui_browser_resources.h" +#include "chrome/grit/user_education_internals_resources.h" +#include "chrome/grit/user_education_internals_resources_map.h" +#include "components/user_education/common/user_education_features.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/browser/web_ui_data_source.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "ui/base/interaction/element_identifier.h" + +UserEducationInternalsUIConfig::UserEducationInternalsUIConfig() + : DefaultWebUIConfig(content::kChromeUIScheme, + chrome::kChromeUIUserEducationInternalsHost) {} + +UserEducationInternalsUI::UserEducationInternalsUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true), + help_bubble_handler_factory_receiver_(this) { + profile_ = Profile::FromWebUI(web_ui); + source_ = content::WebUIDataSource::CreateAndAdd( + profile_, chrome::kChromeUIUserEducationInternalsHost); + + webui::SetupWebUIDataSource(source_, kUserEducationInternalsResources, + IDR_USER_EDUCATION_INTERNALS_INDEX_HTML); + + source_->AddBoolean("isWhatsNewV2", user_education::features::IsWhatsNewV2()); +} + +UserEducationInternalsUI::~UserEducationInternalsUI() = default; + +void UserEducationInternalsUI::BindInterface( + mojo::PendingReceiver< + mojom::user_education_internals::UserEducationInternalsPageHandler> + receiver) { + user_education_handler_ = + std::make_unique<UserEducationInternalsPageHandlerImpl>( + web_ui(), profile_, std::move(receiver)); +} + +void UserEducationInternalsUI::BindInterface( + mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandlerFactory> + pending_receiver) { + if (help_bubble_handler_factory_receiver_.is_bound()) { + help_bubble_handler_factory_receiver_.reset(); + } + help_bubble_handler_factory_receiver_.Bind(std::move(pending_receiver)); +} + +void UserEducationInternalsUI::CreateHelpBubbleHandler( + mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> pending_client, + mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler> + pending_handler) { + help_bubble_handler_ = std::make_unique<user_education::HelpBubbleHandler>( + std::move(pending_handler), std::move(pending_client), this, + std::vector<ui::ElementIdentifier>{kWebUIIPHDemoElementIdentifier}); +} + +void UserEducationInternalsUI::BindInterface( + mojo::PendingReceiver<color_change_listener::mojom::PageHandler> + pending_receiver) { + color_provider_handler_ = std::make_unique<ui::ColorChangeHandler>( + web_ui()->GetWebContents(), std::move(pending_receiver)); +} + +WEB_UI_CONTROLLER_TYPE_IMPL(UserEducationInternalsUI)
diff --git a/chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.h b/chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.h new file mode 100644 index 0000000..0782362e --- /dev/null +++ b/chrome/browser/ui/webui/user_education_internals/user_education_internals_ui.h
@@ -0,0 +1,78 @@ +// Copyright 2024 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_WEBUI_USER_EDUCATION_INTERNALS_USER_EDUCATION_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_USER_EDUCATION_INTERNALS_USER_EDUCATION_INTERNALS_UI_H_ + +#include "base/memory/raw_ptr.h" +#include "build/build_config.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/user_education_internals/user_education_internals.mojom.h" +#include "components/user_education/webui/help_bubble_handler.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/browser/webui_config.h" +#include "ui/webui/color_change_listener/color_change_handler.h" +#include "ui/webui/mojo_web_ui_controller.h" +#include "ui/webui/resources/cr_components/help_bubble/help_bubble.mojom.h" + +namespace content { +class WebUI; +} // namespace content + +class UserEducationInternalsUI; + +class UserEducationInternalsUIConfig + : public content::DefaultWebUIConfig<UserEducationInternalsUI> { + public: + UserEducationInternalsUIConfig(); +}; + +// Client could put debug WebUI as sub-URL under chrome://internals/. +// e.g. chrome://internals/your-feature. +class UserEducationInternalsUI + : public ui::MojoWebUIController, + public help_bubble::mojom::HelpBubbleHandlerFactory { + public: + explicit UserEducationInternalsUI(content::WebUI* web_ui); + ~UserEducationInternalsUI() override; + + void BindInterface( + mojo::PendingReceiver< + mojom::user_education_internals::UserEducationInternalsPageHandler> + receiver); + + // The HelpBubbleHandlerFactory provides support for help bubbles in this + // WebUI. Also see CreateHelpBubbleHandler() below. + void BindInterface( + mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandlerFactory> + pending_receiver); + + // help_bubble::mojom::HelpBubbleHandlerFactory: + void CreateHelpBubbleHandler( + mojo::PendingRemote<help_bubble::mojom::HelpBubbleClient> pending_client, + mojo::PendingReceiver<help_bubble::mojom::HelpBubbleHandler> + pending_handler) override; + + void BindInterface( + mojo::PendingReceiver<color_change_listener::mojom::PageHandler> + pending_receiver); + + private: + WEB_UI_CONTROLLER_TYPE_DECL(); + + raw_ptr<Profile> profile_; + raw_ptr<content::WebUIDataSource> source_; + + std::unique_ptr< + mojom::user_education_internals::UserEducationInternalsPageHandler> + user_education_handler_; + + std::unique_ptr<user_education::HelpBubbleHandler> help_bubble_handler_; + mojo::Receiver<help_bubble::mojom::HelpBubbleHandlerFactory> + help_bubble_handler_factory_receiver_; + + std::unique_ptr<ui::ColorChangeHandler> color_provider_handler_; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_USER_EDUCATION_INTERNALS_USER_EDUCATION_INTERNALS_UI_H_
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc index 7a426ee..ece5a2f0 100644 --- a/chrome/browser/web_applications/web_app_utils.cc +++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -274,15 +274,21 @@ constexpr base::FilePath::CharType kTempDirectoryName[] = FILE_PATH_LITERAL("Temp"); -bool AreWebAppsEnabled(Profile* profile) { +bool AreWebAppsEnabled(Profile* profile, bool exclude_original_profile) { if (!profile || profile->IsSystemProfile()) { return false; } +#if !BUILDFLAG(IS_CHROMEOS) + if (exclude_original_profile) { + return !profile->IsOffTheRecord(); + } + DCHECK(!profile->GetOriginalProfile()->IsOffTheRecord()); + return true; +#else const Profile* original_profile = profile->GetOriginalProfile(); DCHECK(!original_profile->IsOffTheRecord()); -#if BUILDFLAG(IS_CHROMEOS) // Web Apps should not be installed to the ChromeOS system profiles except the // lock screen app profile. if (!ash::ProfileHelper::IsUserProfile(original_profile) && @@ -298,9 +304,9 @@ return false; } } -#endif // BUILDFLAG(IS_CHROMEOS) return true; +#endif // BUILDFLAG(IS_CHROMEOS) } bool AreWebAppsUserInstallable(Profile* profile) {
diff --git a/chrome/browser/web_applications/web_app_utils.h b/chrome/browser/web_applications/web_app_utils.h index c55d76a8..6770f7ca 100644 --- a/chrome/browser/web_applications/web_app_utils.h +++ b/chrome/browser/web_applications/web_app_utils.h
@@ -58,7 +58,10 @@ // Returns false if |profile| is nullptr. // // Is main WebApp System allowed (WebAppProvider exists): -bool AreWebAppsEnabled(Profile* profile); +// TODO(crbug.com/382108359): Remove exclude_original_profile argument when +// incognito profiles return 'false'. +bool AreWebAppsEnabled(Profile* profile, bool exclude_original_profile = false); + // Is user allowed to install web apps from UI: bool AreWebAppsUserInstallable(Profile* profile);
diff --git a/chrome/browser_exposed_mojom_targets.gni b/chrome/browser_exposed_mojom_targets.gni index 00825c72..b1c9cb37 100644 --- a/chrome/browser_exposed_mojom_targets.gni +++ b/chrome/browser_exposed_mojom_targets.gni
@@ -30,7 +30,7 @@ "//chrome/browser/ui/webui/discards:mojo_bindings", "//chrome/browser/ui/webui/downloads:mojo_bindings", "//chrome/browser/ui/webui/glic:mojo_bindings", - "//chrome/browser/ui/webui/internals/user_education:mojo_bindings", + "//chrome/browser/ui/webui/user_education_internals:mojo_bindings", "//chrome/browser/ui/webui/location_internals:mojo_bindings", "//chrome/browser/ui/webui/new_tab_page_third_party:mojo_bindings", "//chrome/browser/ui/webui/new_tab_page:mojo_bindings",
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 1768477..c246442 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1734026255-e81bfb68d272a4debca7b5cca9f4dd653f757fa0-82984e12716aed4036e1542f3ce1980289edeb1b.profdata +chrome-android32-main-1734069544-658b72d24c7c2d65904226af854ae04bd4393867-5d6ee3e7c7a5cbdf378dfc89e3427de9c5105112.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index d2a968c..9d94f51 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1734026255-8c21802c37164307059207d485f56ef7860e7e37-82984e12716aed4036e1542f3ce1980289edeb1b.profdata +chrome-android64-main-1734078027-8470d1fbb43ee4a277c7f8964afacc6becc4296a-22e7858719f029d720173fedb1016907621c3363.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index c563298..c50a188 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1734004756-ab5ebede46a6a82239e2af65a3e7522bad07480f-3ef735a78d1ee8ef1ce5264304f7c56f2ac55993.profdata +chrome-linux-main-1734069544-f541a2b96020455680e6955a28766f6703b25807-5d6ee3e7c7a5cbdf378dfc89e3427de9c5105112.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 8486fa73..c803cb8 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1734026255-12f4344fb16e9f386e1679f6e58feacafbc7764c-82984e12716aed4036e1542f3ce1980289edeb1b.profdata +chrome-mac-arm-main-1734076763-805fbf1fe01263c030e588648ccf6c5e101cb37b-1fb34e0e96800a2869e7039d59d767d5e452c63a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index e4491d4..037853e 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1734004756-78e4be568a90c88429d46779f60283a86cd7aade-3ef735a78d1ee8ef1ce5264304f7c56f2ac55993.profdata +chrome-mac-main-1734069544-b81e1110432ea8a0cf984aba0c60e38ee0e5530b-5d6ee3e7c7a5cbdf378dfc89e3427de9c5105112.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 00e898b..396beff 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1734026255-706744c94a4b09e9470990b42a986f98f1d30165-82984e12716aed4036e1542f3ce1980289edeb1b.profdata +chrome-win-arm64-main-1734069544-488557563c0b8864aa1cfdf73b57544a324f260b-5d6ee3e7c7a5cbdf378dfc89e3427de9c5105112.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 9003326..5f8b1661 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1734004756-7adf9694b3f474569741afa86946056c521de58a-3ef735a78d1ee8ef1ce5264304f7c56f2ac55993.profdata +chrome-win32-main-1734047822-df0bfe8d2a129b89a86921de4df4153a96832b72-765b58c316c93a52d804145915b7d4581d16a83b.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index b1c393c3..fc890cf90 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1734004756-41146fa1e0c741279dd35498fdb537001e1ffb7f-3ef735a78d1ee8ef1ce5264304f7c56f2ac55993.profdata +chrome-win64-main-1734058527-b39cc71fe553e68e211b3091b45c4341a077287e-3bac9545e0f52e071132434d228d0fb4a5f2760b.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 97ea12b..96fd2a3f 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -268,6 +268,7 @@ "$root_gen_dir/ash/webui/ash_projector_app_untrusted_resources.pak", "$root_gen_dir/ash/webui/ash_projector_common_resources.pak", "$root_gen_dir/ash/webui/ash_sanitize_app_resources.pak", + "$root_gen_dir/ash/webui/ash_scanner_feedback_ui_resources.pak", "$root_gen_dir/ash/webui/ash_scanning_app_resources.pak", "$root_gen_dir/ash/webui/ash_shimless_rma_resources.pak", "$root_gen_dir/ash/webui/ash_shortcut_customization_app_resources.pak", @@ -376,6 +377,7 @@ "//ash/webui/resources:projector_app_untrusted_resources", "//ash/webui/resources:projector_common_resources", "//ash/webui/sanitize_ui/resources:resources", + "//ash/webui/scanner_feedback_ui/resources", "//ash/webui/scanning/resources:resources", "//ash/webui/shimless_rma/resources:resources", "//ash/webui/shortcut_customization_ui/resources:resources",
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index b04b8dc..cf266775 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -230,22 +230,6 @@ return base::span(kChromeURLHosts); } -// Add chrome://internals/* subpages here to be included in chrome://chrome-urls -// (about:about). -base::span<const base::cstring_view> ChromeInternalsURLPaths() { - static constexpr auto kChromeInternalsURLPaths = - std::to_array<base::cstring_view>({ -#if BUILDFLAG(IS_ANDROID) - kChromeUIInternalsQueryTilesPath, -#endif // BUILDFLAG(IS_ANDROID) -#if BUILDFLAG(ENABLE_SESSION_SERVICE) - kChromeUISessionServiceInternalsPath, -#endif - }); - - return base::span(kChromeInternalsURLPaths); -} - base::span<const base::cstring_view> ChromeDebugURLs() { // TODO(crbug.com/40253037): make this list comprehensive static constexpr auto kChromeDebugURLs = std::to_array<base::cstring_view>(
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 3462658..9347ac7a 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -278,6 +278,10 @@ "chrome-untrusted://theme/"; inline constexpr char kChromeUIUsbInternalsHost[] = "usb-internals"; inline constexpr char kChromeUIUserActionsHost[] = "user-actions"; +inline constexpr char kChromeUIUserEducationInternalsHost[] = + "user-education-internals"; +inline constexpr char kChromeUIUserEducationInternalsURL[] = + "chrome://user-education-internals"; inline constexpr char kChromeUIVersionHost[] = "version"; inline constexpr char kChromeUIVersionURL[] = "chrome://version/"; inline constexpr char16_t kChromeUIVersionURL16[] = u"chrome://version/"; @@ -285,7 +289,6 @@ inline constexpr char kChromeUIWebuiGalleryHost[] = "webui-gallery"; #if BUILDFLAG(IS_ANDROID) -inline constexpr char kChromeUIInternalsQueryTilesPath[] = "query-tiles"; inline constexpr char kChromeUIJavaCrashURL[] = "chrome://java-crash/"; inline constexpr char kChromeUINativeBookmarksURL[] = "chrome-native://bookmarks/"; @@ -648,10 +651,6 @@ // Gets the hosts/domains that are shown in chrome://chrome-urls. base::span<const base::cstring_view> ChromeURLHosts(); -// Gets the path strings of chrome://internals URLs that are shown in -// chrome://chrome-urls. -base::span<const base::cstring_view> ChromeInternalsURLPaths(); - // Gets the URL strings of "debug" pages which are dangerous and not for general // consumption. base::span<const base::cstring_view> ChromeDebugURLs();
diff --git a/chrome/elevation_service/elevator.cc b/chrome/elevation_service/elevator.cc index 14f3692..1eff2df 100644 --- a/chrome/elevation_service/elevator.cc +++ b/chrome/elevation_service/elevator.cc
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" @@ -187,12 +188,17 @@ } else { return impersonate.result(); } + bool should_reencrypt = false; #if BUILDFLAG(GOOGLE_CHROME_BRANDING) - auto post_process_result = PostProcessData(plaintext_str); + InternalFlags flags; + auto post_process_result = PostProcessData(plaintext_str, &flags); if (!post_process_result.has_value()) { return post_process_result.error(); } plaintext_str.swap(*post_process_result); + if (flags.post_process_should_reencrypt) { + should_reencrypt = true; + } #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) *plaintext = @@ -201,7 +207,11 @@ if (!*plaintext) return E_OUTOFMEMORY; - return S_OK; + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kFakeReencryptForTestingSwitch)) { + should_reencrypt = true; + } + return should_reencrypt ? kSuccessShouldReencrypt : S_OK; } // static
diff --git a/chrome/elevation_service/elevator.h b/chrome/elevation_service/elevator.h index 860985cc..4e8f8d0 100644 --- a/chrome/elevation_service/elevator.h +++ b/chrome/elevation_service/elevator.h
@@ -25,6 +25,8 @@ namespace switches { constexpr char kElevatorClsIdForTestingSwitch[] = "elevator-clsid-for-testing"; +constexpr char kFakeReencryptForTestingSwitch[] = + "elevator-fake-reencrypt-for-testing"; } // namespace switches class Elevator @@ -37,6 +39,7 @@ IElevatorChromeDev, IElevatorChromeCanary> { public: + // Failure codes. static constexpr HRESULT kErrorCouldNotObtainCallingProcess = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA001); static constexpr HRESULT kErrorCouldNotGenerateValidationData = @@ -58,6 +61,10 @@ static constexpr HRESULT kErrorUnsupportedProtectionLevel = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0xA00A); + // Success codes. + static constexpr HRESULT kSuccessShouldReencrypt = + MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0xA001); + Elevator() = default; Elevator(const Elevator&) = delete;
diff --git a/chrome/enterprise_companion/BUILD.gn b/chrome/enterprise_companion/BUILD.gn index a896f2c..38595fd 100644 --- a/chrome/enterprise_companion/BUILD.gn +++ b/chrome/enterprise_companion/BUILD.gn
@@ -70,6 +70,8 @@ "enterprise_companion_service.h", "enterprise_companion_service_stub.cc", "enterprise_companion_service_stub.h", + "enterprise_companion_status.cc", + "enterprise_companion_status.h", "event_logger.cc", "event_logger.h", "global_constants.h", @@ -301,16 +303,14 @@ static_library("client") { sources = [ + "constants.h", "enterprise_companion_client.cc", "enterprise_companion_client.h", - "enterprise_companion_status.cc", - "enterprise_companion_status.h", ] deps = [ ":branding_header", ":installer_paths", "//components/named_mojo_ipc_server", - "//components/policy/core/common", "//components/policy/core/common:common_constants", "//mojo/public/cpp/platform", ]
diff --git a/chrome/enterprise_companion/constants.h b/chrome/enterprise_companion/constants.h new file mode 100644 index 0000000..a575f82 --- /dev/null +++ b/chrome/enterprise_companion/constants.h
@@ -0,0 +1,36 @@ +// Copyright 2024 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_ENTERPRISE_COMPANION_CONSTANTS_H_ +#define CHROME_ENTERPRISE_COMPANION_CONSTANTS_H_ + +namespace enterprise_companion { + +// Errors defined by the enterprise companion app. Ordinals are transmitted +// across IPC and network boundaries. Entries must not be removed or reordered. +enum class ApplicationError { + // An action failed due to the client not being registered. + kRegistrationPreconditionFailed, + // DMStorage reports that it is not capable of persisting policies. + kPolicyPersistenceImpossible, + // DMStorage failed to persist the policies. + kPolicyPersistenceFailed, + // The global singleton lock could not be acquired. + kCannotAcquireLock, + // An IPC connection could not be established. + kMojoConnectionFailed, + // Installation or uninstallation failed. + kInstallationFailed, + // The IPC caller is not allowed to perform the requested action. + kIpcCallerNotAllowed, + // Failed to initialize COM on Windows. + kCOMInitializationFailed, +}; + +inline constexpr int kStatusOk = 0; +inline constexpr int kStatusApplicationError = 3; + +} // namespace enterprise_companion + +#endif // CHROME_ENTERPRISE_COMPANION_CONSTANTS_H_
diff --git a/chrome/enterprise_companion/enterprise_companion_status.h b/chrome/enterprise_companion/enterprise_companion_status.h index 1c11e501..c4843f4 100644 --- a/chrome/enterprise_companion/enterprise_companion_status.h +++ b/chrome/enterprise_companion/enterprise_companion_status.h
@@ -12,33 +12,13 @@ #include <variant> #include "base/functional/overloaded.h" +#include "chrome/enterprise_companion/constants.h" #include "chrome/enterprise_companion/mojom/enterprise_companion.mojom.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_validator.h" namespace enterprise_companion { -// Errors defined by the enterprise companion app. Ordinals are transmitted -// across IPC and network boundaries. Entries must not be removed or reordered. -enum class ApplicationError { - // An action failed due to the client not being registered. - kRegistrationPreconditionFailed, - // DMStorage reports that it is not capable of persisting policies. - kPolicyPersistenceImpossible, - // DMStorage failed to persist the policies. - kPolicyPersistenceFailed, - // The global singleton lock could not be acquired. - kCannotAcquireLock, - // An IPC connection could not be established. - kMojoConnectionFailed, - // Installation or uninstallation failed. - kInstallationFailed, - // The IPC caller is not allowed to perform the requested action. - kIpcCallerNotAllowed, - // Failed to initialize COM on Windows. - kCOMInitializationFailed, -}; - // Represents an error which was deserialized from an external source (e.g. // across an IPC or network boundary). The error may not be known to this // version of the application.
diff --git a/chrome/enterprise_companion/enterprise_companion_status_unittest.cc b/chrome/enterprise_companion/enterprise_companion_status_unittest.cc index bc0b84f2..8d371eea 100644 --- a/chrome/enterprise_companion/enterprise_companion_status_unittest.cc +++ b/chrome/enterprise_companion/enterprise_companion_status_unittest.cc
@@ -197,4 +197,11 @@ EXPECT_NE(success, error2); } +TEST(EnterpriseCompanionStatusTest, ConstantsCorrect) { + EXPECT_EQ(EnterpriseCompanionStatus::Success().space(), kStatusOk); + EXPECT_EQ( + EnterpriseCompanionStatus(ApplicationError::kInstallationFailed).space(), + kStatusApplicationError); +} + } // namespace enterprise_companion
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 7525665..162b3f6 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -7741,6 +7741,7 @@ "//chrome/browser/ui/webui/settings", "//chrome/browser/ui/webui/signin:unit_tests", "//components/autofill_ai/core/browser:browser", + "//components/data_sharing:test_support", ] if (is_chrome_branded) {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_freeform_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_freeform_element_test.ts index 3427d211..a2bd8f8e 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/sea_pen_freeform_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/sea_pen_freeform_element_test.ts
@@ -12,7 +12,7 @@ import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; -import {baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js'; +import {baseSetup, dispatchKeydown, getActiveElement, initElement, teardownElement} from './personalization_app_test_utils.js'; import {TestPersonalizationStore} from './test_personalization_store.js'; import {TestSeaPenProvider} from './test_sea_pen_interface_provider.js'; @@ -61,9 +61,9 @@ !!freeformElement.shadowRoot!.querySelector(SeaPenSamplesElement.is), 'sample prompts element shown on freeform page'); - assertFalse( - !!freeformElement.shadowRoot!.querySelector('#tabContainer'), - 'tab container is not shown'); + const tabContainer = freeformElement.shadowRoot!.querySelector( + '#tabContainer') as HTMLElement; + assertTrue(!!tabContainer.hidden, 'tab container is not shown'); assertTrue( !!freeformElement.shadowRoot!.querySelector('#promptingGuide'), 'Prompting guide is shown'); @@ -109,21 +109,21 @@ freeformElement = initElement(SeaPenFreeformElement); await waitAfterNextRender(freeformElement); - const tabContainer = - freeformElement.shadowRoot!.querySelector('#tabContainer'); + const tabContainer = freeformElement.shadowRoot!.querySelector( + '#tabContainer:not([hidden])'); assertTrue(!!tabContainer, 'tab container displays'); // Sample prompts tab should be present and but not pressed. const samplePromptsTabButton = tabContainer!.querySelector<CrButtonElement>('#samplePromptsTab'); assertTrue(!!samplePromptsTabButton, 'sample prompts tab displays'); - assertEquals(samplePromptsTabButton.getAttribute('aria-pressed'), 'false'); + assertEquals(samplePromptsTabButton.getAttribute('aria-selected'), 'false'); // Results tab should be present and pressed. const resultsTabButton = tabContainer!.querySelector<CrButtonElement>('#resultsTab'); assertTrue(!!resultsTabButton, 'results tab display'); - assertEquals(resultsTabButton.getAttribute('aria-pressed'), 'true'); + assertEquals(resultsTabButton.getAttribute('aria-selected'), 'true'); assertFalse( !!freeformElement.shadowRoot!.querySelector(SeaPenSamplesElement.is), @@ -154,8 +154,8 @@ freeformElement = initElement(SeaPenFreeformElement); await waitAfterNextRender(freeformElement); - const tabContainer = - freeformElement.shadowRoot!.querySelector('#tabContainer'); + const tabContainer = freeformElement.shadowRoot!.querySelector( + '#tabContainer:not([hidden])'); assertTrue(!!tabContainer, 'tab container displays'); // Switch to Sample Prompts tab @@ -247,18 +247,41 @@ await waitAfterNextRender(freeformElement); // Results tab should be present and pressed. - const tabContainer = - freeformElement.shadowRoot!.querySelector('#tabContainer'); - assertTrue(!!tabContainer, 'tab container should exist'); + const tabContainer = freeformElement.shadowRoot!.querySelector( + '#tabContainer:not([hidden])'); + assertTrue(!!tabContainer, 'tab container should be shown'); const resultsTabButton = tabContainer!.querySelector<CrButtonElement>('#resultsTab'); assertTrue(!!resultsTabButton, 'results tab displays'); assertEquals( - 'true', resultsTabButton.getAttribute('aria-pressed'), - 'results tab is pressed'); + 'true', resultsTabButton.getAttribute('aria-selected'), + 'results tab is selected'); assertTrue( !!freeformElement.shadowRoot!.querySelector<HTMLElement>( SeaPenImagesElement.is), 'sea-pen-images is shown'); }); + + test('keypress moves focus', async () => { + personalizationStore.data.wallpaper.seaPen.currentSeaPenQuery = + seaPenProvider.seaPenFreeformQuery; + freeformElement = initElement(SeaPenFreeformElement); + await waitAfterNextRender(freeformElement); + const tabContainer = freeformElement.shadowRoot!.querySelector<HTMLElement>( + '#tabContainer:not([hidden])'); + const samplePromptsTabButton = + tabContainer!.querySelector<CrButtonElement>('#samplePromptsTab'); + const resultsTabButton = + tabContainer!.querySelector<CrButtonElement>('#resultsTab'); + resultsTabButton?.focus(); + + dispatchKeydown(tabContainer!, 'ArrowLeft'); + + assertEquals( + samplePromptsTabButton, getActiveElement(freeformElement), + 'sample prompts tab should be focused'); + assertEquals( + 'true', resultsTabButton?.ariaSelected, + 'The results tab should still be selected'); + }); });
diff --git a/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_actions_card_test.ts b/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_actions_card_test.ts index eef7597a..32468d8 100644 --- a/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_actions_card_test.ts +++ b/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_actions_card_test.ts
@@ -149,8 +149,8 @@ test('actions enabled button syncs to pref', async () => { await initPage(); - assertTrue(faceGazeActionsCard.prefs.settings.a11y.face_gaze.actions_enabled - .value); + assertTrue(faceGazeActionsCard.prefs.settings.a11y.face_gaze + .actions_enabled_sentinel.value); const button = faceGazeActionsCard.shadowRoot! .querySelector<SettingsToggleButtonElement>( @@ -164,7 +164,7 @@ assertFalse(button.checked); assertFalse(faceGazeActionsCard.prefs.settings.a11y.face_gaze - .actions_enabled.value); + .actions_enabled_sentinel.value); }); test('actions disables controls if feature is disabled', async () => {
diff --git a/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_cursor_card_test.ts b/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_cursor_card_test.ts index 098dc82..da01e0b2 100644 --- a/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_cursor_card_test.ts +++ b/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_cursor_card_test.ts
@@ -77,7 +77,7 @@ const prefs = faceGazeCursorCard.prefs.settings.a11y.face_gaze; - assertTrue(prefs.cursor_control_enabled.value); + assertTrue(prefs.cursor_control_enabled_sentinel.value); const button = faceGazeCursorCard.shadowRoot! .querySelector<SettingsToggleButtonElement>( @@ -90,7 +90,7 @@ flush(); assertFalse(button.checked); - assertFalse(prefs.cursor_control_enabled.value); + assertFalse(prefs.cursor_control_enabled_sentinel.value); }); test(
diff --git a/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_subpage_test.ts b/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_subpage_test.ts index e906406..1d11459 100644 --- a/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_subpage_test.ts +++ b/chrome/test/data/webui/chromeos/settings/os_a11y_page/facegaze_subpage_test.ts
@@ -71,10 +71,12 @@ test('toggle button reflects pref value', async () => { await initPage(); - faceGazeSubpage.set('prefs.settings.a11y.face_gaze.enabled.value', true); + faceGazeSubpage.set( + 'prefs.settings.a11y.face_gaze.enabled_sentinel.value', true); await flushTasks(); - assertTrue(faceGazeSubpage.prefs.settings.a11y.face_gaze.enabled.value); + assertTrue( + faceGazeSubpage.prefs.settings.a11y.face_gaze.enabled_sentinel.value); const toggle = getToggleButton(); assertTrue(!!toggle); @@ -86,7 +88,8 @@ test('clicking toggle button updates pref value', async () => { await initPage(); - assertFalse(faceGazeSubpage.prefs.settings.a11y.face_gaze.enabled.value); + assertFalse( + faceGazeSubpage.prefs.settings.a11y.face_gaze.enabled_sentinel.value); const toggle = getToggleButton(); assertTrue(!!toggle); @@ -98,7 +101,8 @@ await flushTasks(); assertTrue(toggle.checked); - assertTrue(faceGazeSubpage.prefs.settings.a11y.face_gaze.enabled.value); + assertTrue( + faceGazeSubpage.prefs.settings.a11y.face_gaze.enabled_sentinel.value); assertEquals('On', toggle.label); }); });
diff --git a/chrome/test/data/webui/chromeos/settings/os_languages_page/language_settings_card_test.ts b/chrome/test/data/webui/chromeos/settings/os_languages_page/language_settings_card_test.ts index ab006444..5bbd207 100644 --- a/chrome/test/data/webui/chromeos/settings/os_languages_page/language_settings_card_test.ts +++ b/chrome/test/data/webui/chromeos/settings/os_languages_page/language_settings_card_test.ts
@@ -8,15 +8,12 @@ import {Route, Router, routes} from 'chrome://os-settings/os_settings.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; suite('<language-settings-card>', () => { - const isRevampWayfindingEnabled = - loadTimeData.getBoolean('isRevampWayfindingEnabled'); - const defaultRoute = isRevampWayfindingEnabled ? routes.SYSTEM_PREFERENCES : - routes.OS_LANGUAGES; + const defaultRoute = routes.SYSTEM_PREFERENCES; let languageSettingsCard: LanguageSettingsCardElement; function createLanguagesCard(): void { @@ -70,28 +67,4 @@ await assertSubpageTriggerFocused( '#languagesRow', routes.OS_LANGUAGES_LANGUAGES); }); - - if (isRevampWayfindingEnabled) { - test('Input row is not visible', () => { - createLanguagesCard(); - const inputRow = - languageSettingsCard.shadowRoot!.querySelector<HTMLElement>( - '#inputRow'); - assertFalse(isVisible(inputRow)); - }); - } else { - test('Input row is visible', () => { - createLanguagesCard(); - const inputRow = - languageSettingsCard.shadowRoot!.querySelector<HTMLElement>( - '#inputRow'); - assertTrue(isVisible(inputRow)); - }); - - test('Input row is focused when returning from subpage', async () => { - Router.getInstance().navigateTo(defaultRoute); - createLanguagesCard(); - await assertSubpageTriggerFocused('#inputRow', routes.OS_LANGUAGES_INPUT); - }); - } });
diff --git a/chrome/test/data/webui/cr_elements/cr_ripple_test.ts b/chrome/test/data/webui/cr_elements/cr_ripple_test.ts index e2ae5b1..2ca173bd 100644 --- a/chrome/test/data/webui/cr_elements/cr_ripple_test.ts +++ b/chrome/test/data/webui/cr_elements/cr_ripple_test.ts
@@ -5,35 +5,15 @@ import 'chrome://resources/cr_elements/cr_ripple/cr_ripple.js'; import type {CrRippleElement} from 'chrome://resources/cr_elements/cr_ripple/cr_ripple.js'; -import {assertArrayEquals, assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; suite('CrRipple', function() { let ripple: CrRippleElement; - let setPointerCaptureCalls: number[]; - let releasePointerCaptureCalls: number[]; - setup(function() { document.body.innerHTML = window.trustedTypes!.emptyHTML; ripple = document.createElement('cr-ripple'); document.body.appendChild(ripple); - - setPointerCaptureCalls = []; - releasePointerCaptureCalls = []; - - // Overriding setPointerCapture, releasePointerCapture, to verify they are - // called as expected during tests. - ripple.setPointerCapture = function(id: number) { - setPointerCaptureCalls.push(id); - }; - - ripple.releasePointerCapture = function(id: number) { - releasePointerCaptureCalls.push(id); - }; - - ripple.hasPointerCapture = function(id: number): boolean { - return setPointerCaptureCalls.includes(id); - }; }); function pointerdown() { @@ -41,19 +21,14 @@ new PointerEvent('pointerdown', {pointerId: 1})); } - function pointermove() { - ripple.parentElement!.dispatchEvent( - new PointerEvent('pointermove', {pointerId: 1})); - } - function pointerup() { ripple.parentElement!.dispatchEvent( new PointerEvent('pointerup', {pointerId: 1})); } - function pointercancel() { + function pointerout() { ripple.parentElement!.dispatchEvent( - new PointerEvent('pointercancel', {pointerId: 1})); + new PointerEvent('pointerout', {pointerId: 1})); } function keydown(key: string) { @@ -136,47 +111,17 @@ }); }); - test('RippleShown_PointerDownUp', function() { + test('RippleShown_PointerEvents', function() { return assertRipplesShown(1, () => { pointerdown(); pointerup(); - - assertArrayEquals([], setPointerCaptureCalls); - assertArrayEquals([], releasePointerCaptureCalls); }); }); - test('RippleShown_PointerDownMoveUp', function() { + test('RippleShown_PointerDownOut', function() { return assertRipplesShown(1, () => { pointerdown(); - pointermove(); - pointermove(); - pointerup(); - - assertArrayEquals([1], setPointerCaptureCalls); - assertArrayEquals([1], releasePointerCaptureCalls); - }); - }); - - test('RippleShown_PointerDownCancel', function() { - return assertRipplesShown(1, () => { - pointerdown(); - pointercancel(); - - assertArrayEquals([], setPointerCaptureCalls); - assertArrayEquals([], releasePointerCaptureCalls); - }); - }); - - test('RippleShown_PointerDownMoveCancel', function() { - return assertRipplesShown(1, () => { - pointerdown(); - pointermove(); - pointermove(); - pointercancel(); - - assertArrayEquals([1], setPointerCaptureCalls); - assertArrayEquals([1], releasePointerCaptureCalls); + pointerout(); }); });
diff --git a/chrome/test/data/webui/lens/lens_overlay_webui_browsertest.cc b/chrome/test/data/webui/lens/lens_overlay_webui_browsertest.cc index 902f9a9..c0506ef0 100644 --- a/chrome/test/data/webui/lens/lens_overlay_webui_browsertest.cc +++ b/chrome/test/data/webui/lens/lens_overlay_webui_browsertest.cc
@@ -157,9 +157,46 @@ RunOverlayTest("lens/overlay/object_selection_test.js", "mocha.run()"); } -// TODO(crbug.com/358172758): Test is failing on Linux bot. -IN_PROC_BROWSER_TEST_F(LensOverlayTest, DISABLED_SelectionOverlay) { - RunOverlayTest("lens/overlay/selection_overlay_test.js", "mocha.run()"); +IN_PROC_BROWSER_TEST_F(LensOverlayTest, + SelectionOverlayWithoutWordsOrObjects) { + RunOverlayTest( + "lens/overlay/selection_overlay_test.js", + "runMochaSuite('SelectionOverlay WithoutWordsOrObjects')"); +} + +IN_PROC_BROWSER_TEST_F(LensOverlayTest, + SelectionOverlayWithWords) { + RunOverlayTest( + "lens/overlay/selection_overlay_test.js", + "runMochaSuite('SelectionOverlay WithWords')"); +} + +IN_PROC_BROWSER_TEST_F(LensOverlayTest, + SelectionOverlayWithObjects) { + RunOverlayTest( + "lens/overlay/selection_overlay_test.js", + "runMochaSuite('SelectionOverlay WithObjects')"); +} + +IN_PROC_BROWSER_TEST_F(LensOverlayTest, + SelectionOverlayWithTranslatedWords) { + RunOverlayTest( + "lens/overlay/selection_overlay_test.js", + "runMochaSuite('SelectionOverlay WithTranslatedWords')"); +} + +IN_PROC_BROWSER_TEST_F(LensOverlayTest, + SelectionOverlayWithObjectsAndWords) { + RunOverlayTest( + "lens/overlay/selection_overlay_test.js", + "runMochaSuite('SelectionOverlay WithObjectsAndWords')"); +} + +IN_PROC_BROWSER_TEST_F(LensOverlayTest, + SelectionOverlayInvocationSourceContextMenuImage) { + RunOverlayTest( + "lens/overlay/selection_overlay_test.js", + "runMochaSuite('SelectionOverlay InvocationSourceContextMenuImage')"); } IN_PROC_BROWSER_TEST_F(LensOverlayTest, PostSelectionRenderer) {
diff --git a/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts b/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts index ddcd70c..f161812 100644 --- a/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts +++ b/chrome/test/data/webui/lens/overlay/selection_overlay_test.ts
@@ -105,6 +105,8 @@ ]), ]); callbackRouterRemote.textReceived(text); + await flushTasks(); + const semanticEventArgs = await testBrowserProxy.handler.getArgs( 'recordLensOverlaySemanticEvent'); const semanticEvent = semanticEventArgs[semanticEventArgs.length - 1]; @@ -112,52 +114,7 @@ await waitAfterNextRender(selectionOverlayElement); } - function addWordsWithTranslations() { - const text = createText([ - createParagraph( - [ - createLine([ - createWord( - 'hello', - normalizedBox({x: 20, y: 20, width: 30, height: 10})), - createWord( - 'there', - normalizedBox({x: 50, y: 20, width: 50, height: 10})), - createWord( - 'test', normalizedBox({x: 35, y: 20, width: 30, height: 10})), - ]), - ], - createTranslatedParagraph([createTranslatedLine( - [ - createWord('wow'), - createWord('a'), - createWord('translation'), - ], - /*translation=*/ 'wow a translation', - /*textHexColor=*/ '#ffffff', - /*backgroundHexColor=*/ '#000000', - /*lineBoundingBox=*/ normalizedBox({ - x: 80, - y: 20, - width: 100, - height: 30, - }))])), - // Words without translations should still be selectable. - createParagraph([ - createLine([ - createWord( - 'no', normalizedBox({x: 70, y: 20, width: 10, height: 10})), - createWord( - 'translation', - normalizedBox({x: 100, y: 20, width: 30, height: 10})), - ]), - ]), - ]); - callbackRouterRemote.textReceived(text); - return flushTasks(); - } - - function addObjects() { + async function addObjects() { objects = [ {x: 80, y: 20, width: 25, height: 10}, @@ -188,1189 +145,1232 @@ await waitAfterNextRender(selectionOverlayElement); } - test( - 'verify that adding words twice sends a end text view event.', - async () => { - await addWords(); - await addWords(); + suite('WithoutWordsOrObjects', function() { + test( + 'verify region search canvas resizes when selection overlay resizes', + async () => { + selectionOverlayElement.style.display = 'block'; + selectionOverlayElement.style.width = '50px'; + selectionOverlayElement.style.height = '50px'; + // Resize observer does not trigger with flushTasks(), so we need to + // use waitAfterNextRender() instead. + await waitForScreenshotResize(); + assertEquals( + 50, + selectionOverlayElement.$.regionSelectionLayer.$ + .regionSelectionCanvas.width); + assertEquals( + 50, + selectionOverlayElement.$.regionSelectionLayer.$ + .regionSelectionCanvas.height); - const semanticEventArgs = await testBrowserProxy.handler.getArgs( - 'recordLensOverlaySemanticEvent'); - const penultimateSemanticEvent = - semanticEventArgs[semanticEventArgs.length - 2]; - assertEquals( - SemanticEvent.kTextGleamsViewEnd, penultimateSemanticEvent); - }); - - // <if expr="not chromeos_lacros"> - test( - 'verify that starting a drag on a word does not trigger region search', - async () => { - await addWords(); - - // Drag that starts on a word but finishes on empty space. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting()[0]!; - await simulateDrag( - selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left + 15, - y: wordEl.getBoundingClientRect().top + 5, - }, - {x: 0, y: 0}); - - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('hello', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); - // </if> - - test( - `verify that starting a drag off a word and continuing onto a word triggers region search`, - async () => { - await addWords(); - - // Drag that starts off a word but finishes on a word. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting()[0]!; - const dragEnd = { - x: wordEl.getBoundingClientRect().left + 5, - y: wordEl.getBoundingClientRect().top + 5, - }; - await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, dragEnd); - - const expectedRect: CenterRotatedBox = { - box: normalizedBox({ - x: dragEnd.x / 2, - y: dragEnd.y / 2, - width: dragEnd.x, - height: dragEnd.y, - }), - rotation: 0, - coordinateType: CenterRotatedBox_CoordinateType.kNormalized, - }; - verifyRegionRequest(expectedRect, /*expectedIsClick=*/ false); - assertEquals( - 0, - testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); - }); - - test( - 'verify region search canvas resizes when selection overlay resizes', - async () => { - selectionOverlayElement.style.display = 'block'; - selectionOverlayElement.style.width = '50px'; - selectionOverlayElement.style.height = '50px'; - // Resize observer does not trigger with flushTasks(), so we need to use - // waitAfterNextRender() instead. - await waitForScreenshotResize(); - assertEquals( - 50, - selectionOverlayElement.$.regionSelectionLayer.$ - .regionSelectionCanvas.width); - assertEquals( - 50, - selectionOverlayElement.$.regionSelectionLayer.$ - .regionSelectionCanvas.height); - - selectionOverlayElement.style.width = '200px'; - selectionOverlayElement.style.height = '200px'; - await waitForScreenshotResize(); - assertEquals( - 200, - selectionOverlayElement.$.regionSelectionLayer.$ - .regionSelectionCanvas.width); - assertEquals( - 200, - selectionOverlayElement.$.regionSelectionLayer.$ - .regionSelectionCanvas.height); - }); + selectionOverlayElement.style.width = '200px'; + selectionOverlayElement.style.height = '200px'; + await waitForScreenshotResize(); + assertEquals( + 200, + selectionOverlayElement.$.regionSelectionLayer.$ + .regionSelectionCanvas.width); + assertEquals( + 200, + selectionOverlayElement.$.regionSelectionLayer.$ + .regionSelectionCanvas.height); + }); test( - 'verify object selection canvas resizes when selection overlay resizes', - async () => { - selectionOverlayElement.style.display = 'block'; - selectionOverlayElement.style.width = '50px'; - selectionOverlayElement.style.height = '50px'; - // Resize observer does not trigger with flushTasks(), so we need to use - // waitAfterNextRender() instead. - await waitForScreenshotResize(); - assertEquals( - 50, - selectionOverlayElement.$.objectSelectionLayer.$ - .objectSelectionCanvas.width); - assertEquals( - 50, - selectionOverlayElement.$.objectSelectionLayer.$ - .objectSelectionCanvas.height); + 'verify object selection canvas resizes when selection overlay resizes', + async () => { + selectionOverlayElement.style.display = 'block'; + selectionOverlayElement.style.width = '50px'; + selectionOverlayElement.style.height = '50px'; + // Resize observer does not trigger with flushTasks(), so we need to + // use waitAfterNextRender() instead. + await waitForScreenshotResize(); + assertEquals( + 50, + selectionOverlayElement.$.objectSelectionLayer.$ + .objectSelectionCanvas.width); + assertEquals( + 50, + selectionOverlayElement.$.objectSelectionLayer.$ + .objectSelectionCanvas.height); - selectionOverlayElement.style.width = '200px'; - selectionOverlayElement.style.height = '200px'; - await waitForScreenshotResize(); - assertEquals( - 200, - selectionOverlayElement.$.objectSelectionLayer.$ - .objectSelectionCanvas.width); - assertEquals( - 200, - selectionOverlayElement.$.objectSelectionLayer.$ - .objectSelectionCanvas.height); - }); + selectionOverlayElement.style.width = '200px'; + selectionOverlayElement.style.height = '200px'; + await waitForScreenshotResize(); + assertEquals( + 200, + selectionOverlayElement.$.objectSelectionLayer.$ + .objectSelectionCanvas.width); + assertEquals( + 200, + selectionOverlayElement.$.objectSelectionLayer.$ + .objectSelectionCanvas.height); + }); + + + test('verify that region search triggers post selection', async () => { + await simulateDrag( + selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); + + const postSelectionStyles = + selectionOverlayElement.$.postSelectionRenderer.style; + const parentBoundingRect = + selectionOverlayElement.getBoundingClientRect(); + const expectedHeight = 175 / parentBoundingRect.height * 100; + const expectedWidth = 250 / parentBoundingRect.width * 100; + const expectedTop = 25 / parentBoundingRect.height * 100; + const expectedLeft = 50 / parentBoundingRect.width * 100; + + // Only look at first 5 digits to account for rounding errors. + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-height'), + expectedHeight.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-width'), + expectedWidth.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-top'), + expectedTop.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-left'), + expectedLeft.toString().substring(0, 6)); + }); test( - `verify that text respond to taps, even when an object is underneath`, - async () => { - await Promise.all([addWords(), addObjects()]); + 'verify that region search triggers selected region context menu', + async () => { + await addEmptyText(); - await simulateClick(selectionOverlayElement, {x: 80, y: 20}); + await simulateDrag( + selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); + await waitAfterNextRender(selectionOverlayElement); - const textQuery = - await testBrowserProxy.handler.whenCalled('issueTextSelectionRequest'); - assertDeepEquals('test', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); - - test( - `verify that dragging performs region search, even when an object overlaps`, - async () => { - await addObjects(); - - // Drag that starts and ends inside the bounding box of an object. - const objectEl = selectionOverlayElement.$.objectSelectionLayer - .getObjectNodesForTesting()[1]!; - const objectElBoundingBox = objectEl.getBoundingClientRect(); - const dragStart = { - x: objectElBoundingBox.left + 1, - y: objectElBoundingBox.top + 1, - }; - const dragEnd = { - x: objectElBoundingBox.right - 1, - y: objectElBoundingBox.bottom - 1, - }; - await simulateDrag(selectionOverlayElement, dragStart, dragEnd); - - const expectedRect: CenterRotatedBox = { - box: normalizedBox({ - x: (dragStart.x + dragEnd.x) / 2, - y: (dragStart.y + dragEnd.y) / 2, - width: dragEnd.x - dragStart.x, - height: dragEnd.y - dragStart.y, - }), - rotation: 0, - coordinateType: CenterRotatedBox_CoordinateType.kNormalized, - }; - verifyRegionRequest(expectedRect, /*expectedIsClick=*/ false); - }); - - // <if expr="not chromeos_lacros"> - test( - 'verify that region search over text triggers detected text options', - async () => { - await addWords(); - - await simulateDrag( - selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); - await waitAfterNextRender(selectionOverlayElement); - - assertEquals( - 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 0, - testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertTrue(selectionOverlayElement - .getShowDetectedTextContextMenuOptionsForTesting()); - - testBrowserProxy.handler.reset(); - selectionOverlayElement.handleSelectTextForTesting(); - - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('hello there test', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); - - test( - `verify that adding text after region selection triggers detected text ` + - `options`, - async () => { - callbackRouterRemote.setPostRegionSelection({ - box: normalizedBox({x: 65, y: 25, width: 30, height: 30}), - rotation: 0.0, - coordinateType: 1, + assertTrue(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + assertFalse(selectionOverlayElement + .getShowDetectedTextContextMenuOptionsForTesting()); }); - await addWords(); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 0, - testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertTrue(selectionOverlayElement - .getShowDetectedTextContextMenuOptionsForTesting()); + test('verify that resizing renders image with padding', async () => { + // Resize to be the same size as screenshot. + selectionOverlayElement.style.display = 'block'; + selectionOverlayElement.style.width = '100px'; + selectionOverlayElement.style.height = '100px'; - testBrowserProxy.handler.reset(); - selectionOverlayElement.handleSelectTextForTesting(); + // ScreenshotBitmapBrowserProxy assumes only one screenshot will be sent. + // We need to reset it to allow a new screenshot to be fetched. + ScreenshotBitmapBrowserProxyImpl.setInstance( + new ScreenshotBitmapBrowserProxyImpl()); + selectionOverlayElement.fetchNewScreenshotForTesting(); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('there test', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); + // Send a fake screenshot of size 100x100. + testBrowserProxy.page.screenshotDataReceived( + fakeScreenshotBitmap(100, 100)); + await waitForScreenshotRendered(selectionOverlayElement); + await waitForScreenshotResize(); - test('verify that select text in detected text options works', async () => { - await addWords(); + // Resize to smaller than the screenshot and verify margins. + selectionOverlayElement.style.width = '90px'; + selectionOverlayElement.style.height = '90px'; + await waitForScreenshotResize(); - await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); - selectionOverlayElement.handleSelectTextForTesting(); + // Size should now be 90px - 48px margin. + let imageSize = selectionOverlayElement.$.backgroundImageCanvas + .getBoundingClientRect(); + assertEquals(42, imageSize.width); + assertEquals(42, imageSize.height); - const textQuery = - await testBrowserProxy.handler.whenCalled('issueTextSelectionRequest'); - assertDeepEquals('hello there test', textQuery); - assertEquals( - 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertFalse( - selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); - }); + // Resize back to same size as screenshot and verify no margins. + selectionOverlayElement.style.width = '100px'; + selectionOverlayElement.style.height = '100px'; + await waitForScreenshotResize(); - test('verify that translate in detected text options works', async () => { - await addWords(); + // Size should now be back to fullscreen. + imageSize = selectionOverlayElement.$.backgroundImageCanvas + .getBoundingClientRect(); + assertEquals(100, imageSize.width); + assertEquals(100, imageSize.height); - await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); - selectionOverlayElement.handleTranslateDetectedTextForTesting(); + // Increase the device pixel ratio and resize. Since 100 (screenshot size) + // / 1.5 is 66.666667, this will also test rounding errors in our + // calculations. + selectionOverlayElement.style.width = '67px'; + selectionOverlayElement.style.height = '67px'; + window.devicePixelRatio = 1.5; + await waitForScreenshotResize(); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTranslateSelectionRequest'); - assertDeepEquals('hello there test', textQuery); - assertEquals( - 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertFalse( - selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); - assertFalse( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - }); - - test( - 'verify that copy as image in selected region context menu works', - async () => { - await addWords(); - - await simulateDrag( - selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); - selectionOverlayElement.handleCopyAsImageForTesting(); - - await testBrowserProxy.handler.whenCalled('copyImage'); - - // Verify context menu hides when an option is selected. - assertFalse(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - - // Verify context menu is restored when selection region is - // right-clicked. - await simulateClick( - selectionOverlayElement, { - x: 40, - y: 20, - }, - /* button = */ 2); - - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - }); - - test( - 'verify that save as image in selected region context menu works', - async () => { - await addWords(); - - await simulateDrag( - selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); - selectionOverlayElement.handleSaveAsImageForTesting(); - - await testBrowserProxy.handler.whenCalled('saveAsImage'); - - // Verify context menu hides when an option is selected. - assertFalse(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - - // Verify context menu is restored when selection region is - // right-clicked. - await simulateClick( - selectionOverlayElement, { - x: 40, - y: 20, - }, - /* button = */ 2); - - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - }); - // </if> - - test('verify that region search triggers post selection', async () => { - await simulateDrag( - selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); - - const postSelectionStyles = - selectionOverlayElement.$.postSelectionRenderer.style; - const parentBoundingRect = selectionOverlayElement.getBoundingClientRect(); - const expectedHeight = 175 / parentBoundingRect.height * 100; - const expectedWidth = 250 / parentBoundingRect.width * 100; - const expectedTop = 25 / parentBoundingRect.height * 100; - const expectedLeft = 50 / parentBoundingRect.width * 100; - - // Only look at first 5 digits to account for rounding errors. - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-height'), - expectedHeight.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-width'), - expectedWidth.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-top'), - expectedTop.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-left'), - expectedLeft.toString().substring(0, 6)); - }); - - test( - 'verify that region search triggers selected region context menu', - async () => { - await addEmptyText(); - - await simulateDrag( - selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); - await waitAfterNextRender(selectionOverlayElement); - - assertTrue(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertFalse(selectionOverlayElement - .getShowDetectedTextContextMenuOptionsForTesting()); - }); - - test('verify that tapping an object triggers post selection', async () => { - await addObjects(); - const objectEl = selectionOverlayElement.$.objectSelectionLayer - .getObjectNodesForTesting()[1]!; - const objectBoundingBox = objectEl.getBoundingClientRect(); - - await simulateClick( - selectionOverlayElement, - {x: objectBoundingBox.left + 2, y: objectBoundingBox.top + 2}); - - const postSelectionStyles = - selectionOverlayElement.$.postSelectionRenderer.style; - const parentBoundingRect = selectionOverlayElement.getBoundingClientRect(); - - // Based on box coordinates of {x: 70, y: 35, width: 20, height: 10}, - const expectedHeight = 10 / parentBoundingRect.height * 100; - const expectedWidth = 20 / parentBoundingRect.width * 100; - const expectedTop = 30 / parentBoundingRect.height * 100; - const expectedLeft = 60 / parentBoundingRect.width * 100; - - // Only look at first 5 digits to account for rounding errors. - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-height'), - expectedHeight.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-width'), - expectedWidth.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-top'), - expectedTop.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-left'), - expectedLeft.toString().substring(0, 6)); - }); - - test('verify that resizing renders image with padding', async () => { - // Resize to be the same size as screenshot. - selectionOverlayElement.style.display = 'block'; - selectionOverlayElement.style.width = '100px'; - selectionOverlayElement.style.height = '100px'; - - // ScreenshotBitmapBrowserProxy assumes only one screenshot will be sent. We - // need to reset it to allow a new screenshot to be fetched. - ScreenshotBitmapBrowserProxyImpl.setInstance( - new ScreenshotBitmapBrowserProxyImpl()); - selectionOverlayElement.fetchNewScreenshotForTesting(); - - // Send a fake screenshot of size 100x100. - testBrowserProxy.page.screenshotDataReceived( - fakeScreenshotBitmap(100, 100)); - await waitForScreenshotRendered(selectionOverlayElement); - await waitForScreenshotResize(); - - // Resize to smaller than the screenshot and verify margins. - selectionOverlayElement.style.width = '90px'; - selectionOverlayElement.style.height = '90px'; - await waitForScreenshotResize(); - - // Size should now be 90px - 48px margin. - let imageSize = - selectionOverlayElement.$.backgroundImageCanvas.getBoundingClientRect(); - assertEquals(42, imageSize.width); - assertEquals(42, imageSize.height); - - // Resize back to same size as screenshot and verify no margins. - selectionOverlayElement.style.width = '100px'; - selectionOverlayElement.style.height = '100px'; - await waitForScreenshotResize(); - - // Size should now be back to fullscreen. - imageSize = - selectionOverlayElement.$.backgroundImageCanvas.getBoundingClientRect(); - assertEquals(100, imageSize.width); - assertEquals(100, imageSize.height); - - // Increase the device pixel ratio and resize. Since 100 (screenshot size) / - // 1.5 is 66.666667, this will also test rounding errors in our - // calculations. - selectionOverlayElement.style.width = '67px'; - selectionOverlayElement.style.height = '67px'; - window.devicePixelRatio = 1.5; - await waitForScreenshotResize(); - - // Size should now be back to fullscreen. - imageSize = - selectionOverlayElement.$.backgroundImageCanvas.getBoundingClientRect(); - assertEquals(67, imageSize.width); - assertEquals(67, imageSize.height); - }); - - test('verify that you can drag text over post selection', async () => { - // Add the words - await addWords(); - // Add the post selection over the words. - await simulateDrag(selectionOverlayElement, {x: 150, y: 150}, {x: 5, y: 5}); - testBrowserProxy.handler.reset(); - - // Drag that starts on a word and post selection. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting()[1]!; - const wordElBoundingBox = wordEl.getBoundingClientRect(); - await simulateDrag( - selectionOverlayElement, { - x: wordElBoundingBox.left + (wordElBoundingBox.width / 3), - y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), - }, - { - x: wordElBoundingBox.right, - y: wordElBoundingBox.bottom, - }); - - const textQuery = - await testBrowserProxy.handler.whenCalled('issueTextSelectionRequest'); - assertDeepEquals('there test', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); - - test('verify that copy in selected text context menu works', async () => { - // Add the words - await addWords(); - testBrowserProxy.handler.reset(); - - // Drag that starts on a word. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting()[1]!; - const wordElBoundingBox = wordEl.getBoundingClientRect(); - await simulateDrag( - selectionOverlayElement, { - x: wordElBoundingBox.left + (wordElBoundingBox.width / 3), - y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), - }, - { - x: wordElBoundingBox.right, - y: wordElBoundingBox.bottom, - }); - - assertFalse( - selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); - assertTrue( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - - selectionOverlayElement.handleCopyForTesting(); - const textQuery = await testBrowserProxy.handler.whenCalled('copyText'); - // Copied text should include newlines. - assertDeepEquals('there\r\ntest', textQuery); - - // Verify context menu hides when an option is selected. - assertFalse( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - - // Verify context menu is restored when a selected word is right-clicked. - await simulateClick( - selectionOverlayElement, { - x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), - y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), - }, - /* button = */ 2); - - assertTrue( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - }); - - test( - 'verify that translate in selected text context menu works', async () => { - // Add the words - await addWords(); - testBrowserProxy.handler.reset(); - - // Drag that starts on a word. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting()[1]!; - const wordElBoundingBox = wordEl.getBoundingClientRect(); - await simulateDrag( - selectionOverlayElement, { - x: wordElBoundingBox.left + (wordElBoundingBox.width / 3), - y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), - }, - { - x: wordElBoundingBox.right, - y: wordElBoundingBox.bottom, - }); - - assertFalse(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertTrue( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - - selectionOverlayElement.handleTranslateForTesting(); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTranslateSelectionRequest'); - assertDeepEquals('there test', textQuery); - - // Verify context menu hides when an option is selected. - assertFalse( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - - // Verify context menu is restored when a selected word is - // right-clicked. - await simulateClick( - selectionOverlayElement, { - x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), - y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), - }, - /* button = */ 2); - - assertTrue( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - }); - - test( - 'verify that dragging on post selection over an object does not tap that object', - async () => { - // Add the objects - await addObjects(); - // Add the post selection over the words. - await simulateDrag( - selectionOverlayElement, {x: 150, y: 150}, {x: 5, y: 5}); - testBrowserProxy.handler.reset(); - - // Store the previous post seleciton dimensions. - let postSelectionStyles = - selectionOverlayElement.$.postSelectionRenderer.style; - const oldLeft = - parseInt(postSelectionStyles.getPropertyValue('--selection-top')); - const oldTop = - parseInt(postSelectionStyles.getPropertyValue('--selection-left')); - - // Drag that starts on an object - const objectEl = selectionOverlayElement.$.objectSelectionLayer - .getObjectNodesForTesting()[1]!; - const objectBoundingBox = objectEl.getBoundingClientRect(); - await simulateDrag( - selectionOverlayElement, { - x: objectBoundingBox.left + (objectBoundingBox.width / 2), - y: objectBoundingBox.top + (objectBoundingBox.height / 2), - }, - { - x: 100, - y: 100, - }); - // Should only be called once from post selection adjustment and not - // object tap. - assertEquals( - 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - - // Get most recent styles - postSelectionStyles = - selectionOverlayElement.$.postSelectionRenderer.style; - assertNotEquals( - oldLeft, - parseInt(postSelectionStyles.getPropertyValue('--selection-left'))); - assertNotEquals( - oldTop, - parseInt(postSelectionStyles.getPropertyValue('--selection-top'))); - }); - test( - `verify that only objects respond to taps, even when post selection overlaps`, - async () => { - // Add the objects - await addObjects(); - // Add the post selection over the words. - await simulateDrag( - selectionOverlayElement, {x: 150, y: 150}, {x: 5, y: 5}); - testBrowserProxy.handler.reset(); - - // Click on an object behind post selection - const objectEl = selectionOverlayElement.$.objectSelectionLayer - .getObjectNodesForTesting()[1]!; - const objectBoundingBox = objectEl.getBoundingClientRect(); - await simulateClick(selectionOverlayElement, { - x: objectBoundingBox.left + (objectBoundingBox.width / 2), - y: objectBoundingBox.top + (objectBoundingBox.height / 2), - }); - - // Should only be called once from post selection adjustment and not - // object tap. - assertEquals( - 1, testBrowserProxy.handler.getCallCount('issueLensObjectRequest')); - - // Verify tap triggered new post selection - const postSelectionStyles = - selectionOverlayElement.$.postSelectionRenderer.style; - const parentBoundingRect = - selectionOverlayElement.getBoundingClientRect(); - - // Based on box coordinates of {x: 70, y: 35, width: 20, height: 10}, - const expectedHeight = 10 / parentBoundingRect.height * 100; - const expectedWidth = 20 / parentBoundingRect.width * 100; - const expectedTop = 30 / parentBoundingRect.height * 100; - const expectedLeft = 60 / parentBoundingRect.width * 100; - - // Only look at first 5 digits to account for rounding errors. - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-height'), - expectedHeight.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-width'), - expectedWidth.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-top'), - expectedTop.toString().substring(0, 6)); - assertStringContains( - postSelectionStyles.getPropertyValue('--selection-left'), - expectedLeft.toString().substring(0, 6)); - }); - - test( - `verify that post selection corners are draggable over text and objects`, - async () => { - await Promise.all([addWords(), addObjects()]); - // Add the post selection to have top left corner overlap with text - // and objects - await simulateDrag( - selectionOverlayElement, {x: 10, y: 150}, {x: 80, y: 20}); - testBrowserProxy.handler.reset(); - - // Start drag on word corner over word and object - await simulateDrag( - selectionOverlayElement, {x: 85, y: 25}, {x: 100, y: 50}); - - // No text request was triggered - assertEquals( - 0, - testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); - // Lens request for the new region - const expectedRect: CenterRotatedBox = { - box: normalizedBox({ - x: 55, - y: 100, - width: 90, - height: 100, - }), - rotation: 0, - coordinateType: CenterRotatedBox_CoordinateType.kNormalized, - }; - verifyRegionRequest(expectedRect, /*expectedIsClick=*/ false); - }); - test( - 'verify that completing a drag calls closePreselectionBubble', - async () => { - const imageBounds = getImageBoundingRect(selectionOverlayElement); - const startPointInsideOverlay = { - x: imageBounds.left + 10, - y: imageBounds.top + 10, - }; - const endPointAboveOverlay = { - x: imageBounds.left + 100, - y: imageBounds.top - 30, - }; - - await simulateDrag( - selectionOverlayElement, startPointInsideOverlay, - endPointAboveOverlay); - - await testBrowserProxy.handler.whenCalled('closePreselectionBubble'); - assertEquals( - 1, - testBrowserProxy.handler.getCallCount('closePreselectionBubble')); - }); - test(`verify that a tap calls closePreselectionBubble`, async () => { - const imageBounds = getImageBoundingRect(selectionOverlayElement); - await simulateClick( - selectionOverlayElement, - {x: imageBounds.left + 10, y: imageBounds.top + 10}); - - await testBrowserProxy.handler.whenCalled('closePreselectionBubble'); - assertEquals( - 1, testBrowserProxy.handler.getCallCount('closePreselectionBubble')); - }); - - test( - `verify that translate text is selected from anywhere on the overlay`, - async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - // Drag at the top corner, above any actual words. - await simulateDrag( - selectionOverlayElement, { - x: 1, - y: 1, - }, - { - x: 2, - y: 2, - }); - - // Despite not clicking on a word to start the text selection, - // there should be selected text and no selected region. - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('wow', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); - }); - - test( - `verify that object selection is disabled when translate mode is on`, - async () => { - await addObjects(); - await addWordsWithTranslations(); - const objectEl = selectionOverlayElement.$.objectSelectionLayer - .getObjectNodesForTesting()[1]!; - const objectBoundingBox = objectEl.getBoundingClientRect(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - await simulateClick( - selectionOverlayElement, - {x: objectBoundingBox.left + 2, y: objectBoundingBox.top + 2}); - - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensObjectRequest')); - }); - - test( - `verify that translate text does not render if translate mode disabled`, - async () => { - await addWordsWithTranslations(); - - // Make sure only non-translated word divs are present and visible. - const wordElements = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting(); - assertTrue(wordElements.length > 0); - for (const word of wordElements) { - assertTrue(isVisible(word)); - } - - const translatedWordElements = - selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting(); - assertTrue(translatedWordElements.length > 0); - for (const word of translatedWordElements) { - assertFalse(isVisible(word)); - } - }); - - test( - `verify that translate text does render if translate mode enabled`, - async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - const translatedWordElements = - selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting(); - assertTrue(translatedWordElements.length > 0); - for (const word of translatedWordElements) { - assertTrue(isVisible(word)); - } - }); - - test( - `verify that clicking a translated word issues a text request`, - async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting()[0]!; - await simulateClick(selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, - }); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('wow', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); - }); - - test( - `verify that dragging a translated word and finishing drag off the word - issues a text request`, - async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - // Drag that starts on a word but finishes on empty space. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting()[0]!; - await simulateDrag( - selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, - }, - {x: 0, y: 0}); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('wow', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); - }); - - test( - `verify that clicking a detected word without a translation in translate - mode issues a text request`, - async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - await simulateClick(selectionOverlayElement, { - x: 100, - y: 20, - }); - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('translation', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); - }); - - test( - `verify that dragging over translated and detected text sends a request - with both`, - async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting()[0]!; - await simulateDrag( - selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, - }, - {x: 80, y: 40}); - - const textQuery = await testBrowserProxy.handler.whenCalled( - 'issueTextSelectionRequest'); - assertDeepEquals('wow a translation no', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertFalse(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); - }); - - test( - `verify that copy in selected text context menu works for translated - text`, - async () => { - // Add the words - await addWordsWithTranslations(); - testBrowserProxy.handler.reset(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - // Drag that starts on a word. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting()[0]!; - await simulateDrag( - selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, - }, - {x: 80, y: 40}); - - await waitAfterNextRender(selectionOverlayElement); - assertFalse(selectionOverlayElement - .getShowSelectedRegionContextMenuForTesting()); - assertTrue( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - - selectionOverlayElement.handleCopyForTesting(); - const textQuery = await testBrowserProxy.handler.whenCalled('copyText'); - // Copied translated text should include newlines. - assertDeepEquals('wow a translation\r\nno', textQuery); - - // Verify context menu hides when an option is selected. - await waitAfterNextRender(selectionOverlayElement); - assertFalse( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - - // Verify context menu is restored when a selected word is - // right-clicked. - await simulateClick( - selectionOverlayElement, { - x: 80, - y: 20, - }, - /* button = */ 2); - - assertTrue( - selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); - }); - - test('SearchboxDisablesTaps', async () => { - await Promise.all([addWords(), addObjects()]); - - // Emulate the searchbox having focus. - selectionOverlayElement.setSearchboxFocusForTesting(true); - - // Verify tapping on text does nothing. - await simulateClick(selectionOverlayElement, {x: 80, y: 20}); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); - - // Verify tapping on object does nothing. - const objectEl = selectionOverlayElement.$.objectSelectionLayer - .getObjectNodesForTesting()[1]!; - const objectBoundingBox = objectEl.getBoundingClientRect(); - - await simulateClick( - selectionOverlayElement, - {x: objectBoundingBox.left + 2, y: objectBoundingBox.top + 2}); - - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - - // Verify tapping for default region does nothing. - await simulateClick(selectionOverlayElement, {x: 1, y: 1}); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - }); - - test('SearchboxAllowsDrags', async () => { - // Emulate the searchbox having focus. - selectionOverlayElement.setSearchboxFocusForTesting(true); - await addWords(); - - // Verify that dragging on text works. - // Drag that starts on a word but finishes on empty space. - const wordEl = selectionOverlayElement.$.textSelectionLayer - .getWordNodesForTesting()[0]!; - await simulateDrag( - selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left + 15, - y: wordEl.getBoundingClientRect().top + 5, - }, - {x: 0, y: 0}); - - // Text query should have been sent. - const textQuery = - await testBrowserProxy.handler.whenCalled('issueTextSelectionRequest'); - assertDeepEquals('hello', textQuery); - - // Verify that dragging region works. - await simulateDrag( - selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); - - const postSelectionRenderer = - selectionOverlayElement.$.postSelectionRenderer; - isVisible(postSelectionRenderer.$.postSelection); - - // Verify dragging post selection corners works. - const postSelectionBounds = - postSelectionRenderer.$.postSelection.getBoundingClientRect(); - await simulateDrag( - selectionOverlayElement, - {x: postSelectionBounds.left, y: postSelectionBounds.top}, - {x: postSelectionBounds.left + 10, y: postSelectionBounds.top + 10}); - - const newPostSelectionBounds = - postSelectionRenderer.$.postSelection.getBoundingClientRect(); - assertNotEquals(postSelectionBounds.x, newPostSelectionBounds.x); - assertNotEquals(postSelectionBounds.y, newPostSelectionBounds.y); - }); - - test('NoTextSelectionIfLanguagePickersOpen', async () => { - await addWordsWithTranslations(); - - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - - selectionOverlayElement.setLanguagePickersOpenForTesting(true); - let wordEl = selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting()[0]!; - await simulateClick(selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, + // Size should now be back to fullscreen. + imageSize = selectionOverlayElement.$.backgroundImageCanvas + .getBoundingClientRect(); + assertEquals(67, imageSize.width); + assertEquals(67, imageSize.height); }); - assertEquals( - 0, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 0, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); - selectionOverlayElement.setLanguagePickersOpenForTesting(false); - wordEl = selectionOverlayElement.$.textSelectionLayer - .getTranslatedWordNodesForTesting()[0]!; - await simulateClick(selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, + test( + 'verify that completing a drag calls closePreselectionBubble', + async () => { + const imageBounds = getImageBoundingRect(selectionOverlayElement); + const startPointInsideOverlay = { + x: imageBounds.left + 10, + y: imageBounds.top + 10, + }; + const endPointAboveOverlay = { + x: imageBounds.left + 100, + y: imageBounds.top - 30, + }; + + await simulateDrag( + selectionOverlayElement, startPointInsideOverlay, + endPointAboveOverlay); + + await testBrowserProxy.handler.whenCalled('closePreselectionBubble'); + assertEquals( + 1, + testBrowserProxy.handler.getCallCount('closePreselectionBubble')); + }); + + test(`verify that a tap calls closePreselectionBubble`, async () => { + const imageBounds = getImageBoundingRect(selectionOverlayElement); + await simulateClick( + selectionOverlayElement, + {x: imageBounds.left + 10, y: imageBounds.top + 10}); + + await testBrowserProxy.handler.whenCalled('closePreselectionBubble'); + assertEquals( + 1, testBrowserProxy.handler.getCallCount('closePreselectionBubble')); }); - const textQuery = - await testBrowserProxy.handler.whenCalled('issueTextSelectionRequest'); - assertDeepEquals('wow', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); }); - test('TextSelectionDragIfLanguagePickersOpen', async () => { - await addWordsWithTranslations(); + suite('WithWords', function() { + setup(async function() { + return addWords(); + }); - dispatchTranslateStateEvent( - selectionOverlayElement.$.textSelectionLayer, true, 'es'); - await waitAfterNextRender(selectionOverlayElement); - selectionOverlayElement.setLanguagePickersOpenForTesting(true); + test( + 'verify that adding words twice sends a end text view event.', + async () => { + await addWords(); - const wordEl = selectionOverlayElement.$.textSelectionLayer + const semanticEventArgs = await testBrowserProxy.handler.getArgs( + 'recordLensOverlaySemanticEvent'); + const penultimateSemanticEvent = + semanticEventArgs[semanticEventArgs.length - 2]; + assertEquals( + SemanticEvent.kTextGleamsViewEnd, penultimateSemanticEvent); + }); + + test( + 'verify that starting a drag on a word does not trigger region search', + async () => { + // Drag that starts on a word but finishes on empty space. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[0]!; + await simulateDrag( + selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left + 15, + y: wordEl.getBoundingClientRect().top + 5, + }, + {x: 0, y: 0}); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('hello', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); + + test( + `verify that starting a drag off a word and continuing onto a word triggers region search`, + async () => { + // Drag that starts off a word but finishes on a word. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[0]!; + const dragEnd = { + x: wordEl.getBoundingClientRect().left + 5, + y: wordEl.getBoundingClientRect().top + 5, + }; + await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, dragEnd); + + const expectedRect: CenterRotatedBox = { + box: normalizedBox({ + x: dragEnd.x / 2, + y: dragEnd.y / 2, + width: dragEnd.x, + height: dragEnd.y, + }), + rotation: 0, + coordinateType: CenterRotatedBox_CoordinateType.kNormalized, + }; + verifyRegionRequest(expectedRect, /*expectedIsClick=*/ false); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount( + 'issueTextSelectionRequest')); + }); + + test( + 'verify that region search over text triggers detected text options', + async () => { + await simulateDrag( + selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + await waitAfterNextRender(selectionOverlayElement); + + assertEquals( + 1, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount( + 'issueTextSelectionRequest')); + assertTrue(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + assertTrue(selectionOverlayElement + .getShowDetectedTextContextMenuOptionsForTesting()); + + testBrowserProxy.handler.reset(); + selectionOverlayElement.handleSelectTextForTesting(); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('hello there test', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); + + test( + `verify that adding text after region selection triggers detected text ` + + `options`, + async () => { + callbackRouterRemote.setPostRegionSelection({ + box: normalizedBox({x: 65, y: 25, width: 30, height: 30}), + rotation: 0.0, + coordinateType: 1, + }); + await addWords(); + + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount( + 'issueTextSelectionRequest')); + assertTrue(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + assertTrue(selectionOverlayElement + .getShowDetectedTextContextMenuOptionsForTesting()); + + testBrowserProxy.handler.reset(); + selectionOverlayElement.handleSelectTextForTesting(); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('there test', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); + + test('verify that select text in detected text options works', async () => { + await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + selectionOverlayElement.handleSelectTextForTesting(); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('hello there test', textQuery); + assertEquals( + 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertFalse( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + }); + + test('verify that translate in detected text options works', async () => { + await simulateDrag(selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + selectionOverlayElement.handleTranslateDetectedTextForTesting(); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTranslateSelectionRequest'); + assertDeepEquals('hello there test', textQuery); + assertEquals( + 1, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertFalse( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + assertFalse( + selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); + }); + + test( + 'verify that copy as image in selected region context menu works', + async () => { + await simulateDrag( + selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + selectionOverlayElement.handleCopyAsImageForTesting(); + + await testBrowserProxy.handler.whenCalled('copyImage'); + + // Verify context menu hides when an option is selected. + assertFalse(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + + // Verify context menu is restored when selection region is + // right-clicked. + await simulateClick( + selectionOverlayElement, { + x: 40, + y: 20, + }, + /* button = */ 2); + + assertTrue(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + }); + + test( + 'verify that save as image in selected region context menu works', + async () => { + await simulateDrag( + selectionOverlayElement, {x: 0, y: 0}, {x: 80, y: 40}); + selectionOverlayElement.handleSaveAsImageForTesting(); + + await testBrowserProxy.handler.whenCalled('saveAsImage'); + + // Verify context menu hides when an option is selected. + assertFalse(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + + // Verify context menu is restored when selection region is + // right-clicked. + await simulateClick( + selectionOverlayElement, { + x: 40, + y: 20, + }, + /* button = */ 2); + + assertTrue(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + }); + + test('verify that you can drag text over post selection', async () => { + // Add the post selection over the words. + await simulateDrag( + selectionOverlayElement, {x: 150, y: 150}, {x: 5, y: 5}); + testBrowserProxy.handler.reset(); + + // Drag that starts on a word and post selection. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[1]!; + const wordElBoundingBox = wordEl.getBoundingClientRect(); + await simulateDrag( + selectionOverlayElement, { + x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), + y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), + }, + { + x: wordElBoundingBox.right, + y: wordElBoundingBox.bottom, + }); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('there test', textQuery); + assertEquals( + 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); + + test('verify that copy in selected text context menu works', async () => { + testBrowserProxy.handler.reset(); + + // Drag that starts on a word. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[1]!; + const wordElBoundingBox = wordEl.getBoundingClientRect(); + await simulateDrag( + selectionOverlayElement, { + x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), + y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), + }, + { + x: wordElBoundingBox.right, + y: wordElBoundingBox.bottom, + }); + + assertFalse( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + assertTrue( + selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); + + selectionOverlayElement.handleCopyForTesting(); + const textQuery = await testBrowserProxy.handler.whenCalled('copyText'); + // Copied text should include newlines. + assertDeepEquals('there\r\ntest', textQuery); + + // Verify context menu hides when an option is selected. + assertFalse( + selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); + + // Verify context menu is restored when a selected word is right-clicked. + await simulateClick( + selectionOverlayElement, { + x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), + y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), + }, + /* button = */ 2); + + assertTrue( + selectionOverlayElement.getShowSelectedTextContextMenuForTesting()); + }); + + test( + 'verify that translate in selected text context menu works', + async () => { + testBrowserProxy.handler.reset(); + + // Drag that starts on a word. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[1]!; + const wordElBoundingBox = wordEl.getBoundingClientRect(); + await simulateDrag( + selectionOverlayElement, { + x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), + y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), + }, + { + x: wordElBoundingBox.right, + y: wordElBoundingBox.bottom, + }); + + assertFalse(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + assertTrue(selectionOverlayElement + .getShowSelectedTextContextMenuForTesting()); + + selectionOverlayElement.handleTranslateForTesting(); + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTranslateSelectionRequest'); + assertDeepEquals('there test', textQuery); + + // Verify context menu hides when an option is selected. + assertFalse(selectionOverlayElement + .getShowSelectedTextContextMenuForTesting()); + + // Verify context menu is restored when a selected word is + // right-clicked. + await simulateClick( + selectionOverlayElement, { + x: wordElBoundingBox.left + (wordElBoundingBox.width / 2), + y: wordElBoundingBox.top + (wordElBoundingBox.height / 2), + }, + /* button = */ 2); + + assertTrue(selectionOverlayElement + .getShowSelectedTextContextMenuForTesting()); + }); + + test('SearchboxAllowsDrags', async () => { + // Emulate the searchbox having focus. + selectionOverlayElement.setSearchboxFocusForTesting(true); + + // Verify that dragging on text works. + // Drag that starts on a word but finishes on empty space. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting()[0]!; + await simulateDrag( + selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left + 15, + y: wordEl.getBoundingClientRect().top + 5, + }, + {x: 0, y: 0}); + + // Text query should have been sent. + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('hello', textQuery); + + // Verify that dragging region works. + await simulateDrag( + selectionOverlayElement, {x: 50, y: 25}, {x: 300, y: 200}); + + const postSelectionRenderer = + selectionOverlayElement.$.postSelectionRenderer; + isVisible(postSelectionRenderer.$.postSelection); + + // Verify dragging post selection corners works. + const postSelectionBounds = + postSelectionRenderer.$.postSelection.getBoundingClientRect(); + await simulateDrag( + selectionOverlayElement, + {x: postSelectionBounds.left, y: postSelectionBounds.top}, + {x: postSelectionBounds.left + 10, y: postSelectionBounds.top + 10}); + + const newPostSelectionBounds = + postSelectionRenderer.$.postSelection.getBoundingClientRect(); + assertNotEquals(postSelectionBounds.x, newPostSelectionBounds.x); + assertNotEquals(postSelectionBounds.y, newPostSelectionBounds.y); + }); + }); + + suite('WithObjects', function() { + setup(async function() { + return addObjects(); + }); + + test( + `verify that dragging performs region search, even when an object overlaps`, + async () => { + // Drag that starts and ends inside the bounding box of an object. + const objectEl = selectionOverlayElement.$.objectSelectionLayer + .getObjectNodesForTesting()[1]!; + const objectElBoundingBox = objectEl.getBoundingClientRect(); + const dragStart = { + x: objectElBoundingBox.left + 1, + y: objectElBoundingBox.top + 1, + }; + const dragEnd = { + x: objectElBoundingBox.right - 1, + y: objectElBoundingBox.bottom - 1, + }; + await simulateDrag(selectionOverlayElement, dragStart, dragEnd); + + const expectedRect: CenterRotatedBox = { + box: normalizedBox({ + x: (dragStart.x + dragEnd.x) / 2, + y: (dragStart.y + dragEnd.y) / 2, + width: dragEnd.x - dragStart.x, + height: dragEnd.y - dragStart.y, + }), + rotation: 0, + coordinateType: CenterRotatedBox_CoordinateType.kNormalized, + }; + verifyRegionRequest(expectedRect, /*expectedIsClick=*/ false); + }); + + test('verify that tapping an object triggers post selection', async () => { + const objectEl = selectionOverlayElement.$.objectSelectionLayer + .getObjectNodesForTesting()[1]!; + const objectBoundingBox = objectEl.getBoundingClientRect(); + + await simulateClick( + selectionOverlayElement, + {x: objectBoundingBox.left + 2, y: objectBoundingBox.top + 2}); + + const postSelectionStyles = + selectionOverlayElement.$.postSelectionRenderer.style; + const parentBoundingRect = + selectionOverlayElement.getBoundingClientRect(); + + // Based on box coordinates of {x: 70, y: 35, width: 20, height: 10}, + const expectedHeight = 10 / parentBoundingRect.height * 100; + const expectedWidth = 20 / parentBoundingRect.width * 100; + const expectedTop = 30 / parentBoundingRect.height * 100; + const expectedLeft = 60 / parentBoundingRect.width * 100; + + // Only look at first 5 digits to account for rounding errors. + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-height'), + expectedHeight.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-width'), + expectedWidth.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-top'), + expectedTop.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-left'), + expectedLeft.toString().substring(0, 6)); + }); + + test( + 'verify that dragging on post selection over an object does not tap that object', + async () => { + // Add the post selection over the words. + await simulateDrag( + selectionOverlayElement, {x: 150, y: 150}, {x: 5, y: 5}); + testBrowserProxy.handler.reset(); + + // Store the previous post seleciton dimensions. + let postSelectionStyles = + selectionOverlayElement.$.postSelectionRenderer.style; + const oldLeft = + parseInt(postSelectionStyles.getPropertyValue('--selection-top')); + const oldTop = parseInt( + postSelectionStyles.getPropertyValue('--selection-left')); + + // Drag that starts on an object + const objectEl = selectionOverlayElement.$.objectSelectionLayer + .getObjectNodesForTesting()[1]!; + const objectBoundingBox = objectEl.getBoundingClientRect(); + await simulateDrag( + selectionOverlayElement, { + x: objectBoundingBox.left + (objectBoundingBox.width / 2), + y: objectBoundingBox.top + (objectBoundingBox.height / 2), + }, + { + x: 100, + y: 100, + }); + // Should only be called once from post selection adjustment and not + // object tap. + assertEquals( + 1, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + + // Get most recent styles + postSelectionStyles = + selectionOverlayElement.$.postSelectionRenderer.style; + assertNotEquals( + oldLeft, + parseInt( + postSelectionStyles.getPropertyValue('--selection-left'))); + assertNotEquals( + oldTop, + parseInt( + postSelectionStyles.getPropertyValue('--selection-top'))); + }); + test( + `verify that only objects respond to taps, even when post selection overlaps`, + async () => { + // Add the post selection over the words. + await simulateDrag( + selectionOverlayElement, {x: 150, y: 150}, {x: 5, y: 5}); + testBrowserProxy.handler.reset(); + + // Click on an object behind post selection + const objectEl = selectionOverlayElement.$.objectSelectionLayer + .getObjectNodesForTesting()[1]!; + const objectBoundingBox = objectEl.getBoundingClientRect(); + await simulateClick(selectionOverlayElement, { + x: objectBoundingBox.left + (objectBoundingBox.width / 2), + y: objectBoundingBox.top + (objectBoundingBox.height / 2), + }); + + // Should only be called once from post selection adjustment and not + // object tap. + assertEquals( + 1, + testBrowserProxy.handler.getCallCount('issueLensObjectRequest')); + + // Verify tap triggered new post selection + const postSelectionStyles = + selectionOverlayElement.$.postSelectionRenderer.style; + const parentBoundingRect = + selectionOverlayElement.getBoundingClientRect(); + + // Based on box coordinates of {x: 70, y: 35, width: 20, height: 10}, + const expectedHeight = 10 / parentBoundingRect.height * 100; + const expectedWidth = 20 / parentBoundingRect.width * 100; + const expectedTop = 30 / parentBoundingRect.height * 100; + const expectedLeft = 60 / parentBoundingRect.width * 100; + + // Only look at first 5 digits to account for rounding errors. + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-height'), + expectedHeight.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-width'), + expectedWidth.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-top'), + expectedTop.toString().substring(0, 6)); + assertStringContains( + postSelectionStyles.getPropertyValue('--selection-left'), + expectedLeft.toString().substring(0, 6)); + }); + }); + + suite('WithTranslatedWords', function() { + setup(async function() { + return addWordsWithTranslations(); + }); + + async function addWordsWithTranslations() { + const text = createText([ + createParagraph( + [ + createLine([ + createWord( + 'hello', + normalizedBox({x: 20, y: 20, width: 30, height: 10})), + createWord( + 'there', + normalizedBox({x: 50, y: 20, width: 50, height: 10})), + createWord( + 'test', + normalizedBox({x: 35, y: 20, width: 30, height: 10})), + ]), + ], + createTranslatedParagraph([createTranslatedLine( + [ + createWord('wow'), + createWord('a'), + createWord('translation'), + ], + /*translation=*/ 'wow a translation', + /*textHexColor=*/ '#ffffff', + /*backgroundHexColor=*/ '#000000', + /*lineBoundingBox=*/ normalizedBox({ + x: 80, + y: 20, + width: 100, + height: 30, + }))])), + // Words without translations should still be selectable. + createParagraph([ + createLine([ + createWord( + 'no', normalizedBox({x: 70, y: 20, width: 10, height: 10})), + createWord( + 'translation', + normalizedBox({x: 100, y: 20, width: 30, height: 10})), + ]), + ]), + ]); + callbackRouterRemote.textReceived(text); + return flushTasks(); + } + + test( + `verify that translate text is selected from anywhere on the overlay`, + async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + // Drag at the top corner, above any actual words. + await simulateDrag( + selectionOverlayElement, { + x: 1, + y: 1, + }, + { + x: 2, + y: 2, + }); + + // Despite not clicking on a word to start the text selection, + // there should be selected text and no selected region. + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('wow', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + + test( + `verify that object selection is disabled when translate mode is on`, + async () => { + await addObjects(); + const objectEl = selectionOverlayElement.$.objectSelectionLayer + .getObjectNodesForTesting()[1]!; + const objectBoundingBox = objectEl.getBoundingClientRect(); + + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + await simulateClick( + selectionOverlayElement, + {x: objectBoundingBox.left + 2, y: objectBoundingBox.top + 2}); + + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensObjectRequest')); + }); + + test( + `verify that translate text does not render if translate mode disabled`, + async () => { + // Make sure only non-translated word divs are present and visible. + const wordElements = selectionOverlayElement.$.textSelectionLayer + .getWordNodesForTesting(); + assertTrue(wordElements.length > 0); + for (const word of wordElements) { + assertTrue(isVisible(word)); + } + + const translatedWordElements = + selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting(); + assertTrue(translatedWordElements.length > 0); + for (const word of translatedWordElements) { + assertFalse(isVisible(word)); + } + }); + + test( + `verify that translate text does render if translate mode enabled`, + async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + const translatedWordElements = + selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting(); + assertTrue(translatedWordElements.length > 0); + for (const word of translatedWordElements) { + assertTrue(isVisible(word)); + } + }); + + test( + `verify that clicking a translated word issues a text request`, + async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting()[0]!; + await simulateClick(selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }); + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('wow', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + + test( + `verify that dragging a translated word and finishing drag off the word + issues a text request`, + async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + // Drag that starts on a word but finishes on empty space. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting()[0]!; + await simulateDrag( + selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }, + {x: 0, y: 0}); + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('wow', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + + test( + `verify that clicking a detected word without a translation in translate + mode issues a text request`, + async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + await simulateClick(selectionOverlayElement, { + x: 100, + y: 20, + }); + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('translation', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + + test( + `verify that dragging over translated and detected text sends a request + with both`, + async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting()[0]!; + await simulateDrag( + selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }, + {x: 80, y: 40}); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('wow a translation no', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertFalse(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + + test( + `verify that copy in selected text context menu works for translated + text`, + async () => { + testBrowserProxy.handler.reset(); + + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + // Drag that starts on a word. + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting()[0]!; + await simulateDrag( + selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }, + {x: 80, y: 40}); + + await waitAfterNextRender(selectionOverlayElement); + assertFalse(selectionOverlayElement + .getShowSelectedRegionContextMenuForTesting()); + assertTrue(selectionOverlayElement + .getShowSelectedTextContextMenuForTesting()); + + selectionOverlayElement.handleCopyForTesting(); + const textQuery = + await testBrowserProxy.handler.whenCalled('copyText'); + // Copied translated text should include newlines. + assertDeepEquals('wow a translation\r\nno', textQuery); + + // Verify context menu hides when an option is selected. + await waitAfterNextRender(selectionOverlayElement); + assertFalse(selectionOverlayElement + .getShowSelectedTextContextMenuForTesting()); + + // Verify context menu is restored when a selected word is + // right-clicked. + await simulateClick( + selectionOverlayElement, { + x: 80, + y: 20, + }, + /* button = */ 2); + + assertTrue(selectionOverlayElement + .getShowSelectedTextContextMenuForTesting()); + }); + + test('NoTextSelectionIfLanguagePickersOpen', async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + + selectionOverlayElement.setLanguagePickersOpenForTesting(true); + let wordEl = selectionOverlayElement.$.textSelectionLayer .getTranslatedWordNodesForTesting()[0]!; - await simulateDrag( - selectionOverlayElement, { - x: wordEl.getBoundingClientRect().left, - y: wordEl.getBoundingClientRect().top, - }, - {x: 80, y: 40}); + await simulateClick(selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }); + assertEquals( + 0, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 0, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); - const textQuery = - await testBrowserProxy.handler.whenCalled('issueTextSelectionRequest'); - assertDeepEquals('wow a translation no', textQuery); - assertEquals( - 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); - assertFalse( - selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.UserAction', - UserAction.kTranslateTextSelection)); - assertEquals( - 1, - metrics.count( - 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', - UserAction.kTranslateTextSelection)); + selectionOverlayElement.setLanguagePickersOpenForTesting(false); + wordEl = selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting()[0]!; + await simulateClick(selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }); + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('wow', textQuery); + assertEquals( + 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + + test('TextSelectionDragIfLanguagePickersOpen', async () => { + dispatchTranslateStateEvent( + selectionOverlayElement.$.textSelectionLayer, true, 'es'); + await waitAfterNextRender(selectionOverlayElement); + selectionOverlayElement.setLanguagePickersOpenForTesting(true); + + const wordEl = selectionOverlayElement.$.textSelectionLayer + .getTranslatedWordNodesForTesting()[0]!; + await simulateDrag( + selectionOverlayElement, { + x: wordEl.getBoundingClientRect().left, + y: wordEl.getBoundingClientRect().top, + }, + {x: 80, y: 40}); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('wow a translation no', textQuery); + assertEquals( + 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + assertFalse( + selectionOverlayElement.getShowSelectedRegionContextMenuForTesting()); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.UserAction', + UserAction.kTranslateTextSelection)); + assertEquals( + 1, + metrics.count( + 'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction', + UserAction.kTranslateTextSelection)); + }); + }); + + suite('WithObjectsAndWords', function() { + setup(async function() { + return Promise.all([addWords(), addObjects()]); + }); + + test( + `verify that text respond to taps, even when an object is underneath`, + async () => { + await simulateClick(selectionOverlayElement, {x: 80, y: 20}); + + const textQuery = await testBrowserProxy.handler.whenCalled( + 'issueTextSelectionRequest'); + assertDeepEquals('test', textQuery); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); + + test( + `verify that post selection corners are draggable over text and + objects`, + async () => { + // Add the post selection to have top left corner overlap with text + // and objects + await simulateDrag( + selectionOverlayElement, {x: 10, y: 150}, {x: 80, y: 20}); + testBrowserProxy.handler.reset(); + + // Start drag on word corner over word and object + await simulateDrag( + selectionOverlayElement, {x: 85, y: 25}, {x: 100, y: 50}); + + // No text request was triggered + assertEquals( + 0, + testBrowserProxy.handler.getCallCount( + 'issueTextSelectionRequest')); + // Lens request for the new region + const expectedRect: CenterRotatedBox = { + box: normalizedBox({ + x: 55, + y: 100, + width: 90, + height: 100, + }), + rotation: 0, + coordinateType: CenterRotatedBox_CoordinateType.kNormalized, + }; + verifyRegionRequest(expectedRect, /*expectedIsClick=*/ false); + }); + + test('SearchboxDisablesTaps', async () => { + // Emulate the searchbox having focus. + selectionOverlayElement.setSearchboxFocusForTesting(true); + + // Verify tapping on text does nothing. + await simulateClick(selectionOverlayElement, {x: 80, y: 20}); + assertEquals( + 0, + testBrowserProxy.handler.getCallCount('issueTextSelectionRequest')); + + // Verify tapping on object does nothing. + const objectEl = selectionOverlayElement.$.objectSelectionLayer + .getObjectNodesForTesting()[1]!; + const objectBoundingBox = objectEl.getBoundingClientRect(); + + await simulateClick( + selectionOverlayElement, + {x: objectBoundingBox.left + 2, y: objectBoundingBox.top + 2}); + + assertEquals( + 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + + // Verify tapping for default region does nothing. + await simulateClick(selectionOverlayElement, {x: 1, y: 1}); + assertEquals( + 0, testBrowserProxy.handler.getCallCount('issueLensRegionRequest')); + }); }); suite('InvocationSourceContextMenuImage', function() {
diff --git a/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.ts b/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.ts index d3eb2b5..0ab31d0 100644 --- a/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.ts +++ b/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.ts
@@ -12,7 +12,9 @@ import {PageCallbackRouter, PageHandlerRemote} from 'chrome://new-tab-page/new_tab_page.mojom-webui.js'; import {Command, CommandHandlerRemote} from 'chrome://resources/js/browser_command.mojom-webui.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; +import {isMac} from 'chrome://resources/js/platform.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {keyDownOn} from 'chrome://webui-test/keyboard_mock_interactions.js'; import type {MetricsTracker} from 'chrome://webui-test/metrics_test_support.js'; import {fakeMetricsPrivate} from 'chrome://webui-test/metrics_test_support.js'; import type {TestMock} from 'chrome://webui-test/test_mock.js'; @@ -233,21 +235,24 @@ }); test('clicking undo button restores promo', async () => { + // Dismiss middle slot promo. const canShowPromo = true; const middleSlotPromo = await createMiddleSlotPromo(canShowPromo); - assertHasContent(canShowPromo, middleSlotPromo); const parts = middleSlotPromo.$.promoAndDismissContainer.children; assertEquals(2, parts.length); - const dismissPromoButton = parts[1] as HTMLElement; dismissPromoButton.click(); + assertEquals(0, newTabPageHandler.getCallCount('undoBlocklistPromo')); assertFalse(isVisible(middleSlotPromo.$.promoAndDismissContainer)); assertEquals( - 1, + 0, metrics.count( - 'NewTabPage.Promos.DismissAction', PromoDismissAction.DISMISS)); + 'NewTabPage.Promos.DismissAction', PromoDismissAction.RESTORE)); + // Undo dismissal via toast. middleSlotPromo.$.undoDismissPromoButton.click(); + + assertEquals(1, newTabPageHandler.getCallCount('undoBlocklistPromo')); assertTrue(isVisible(middleSlotPromo.$.promoAndDismissContainer)); assertEquals( 1, @@ -255,12 +260,49 @@ 'NewTabPage.Promos.DismissAction', PromoDismissAction.RESTORE)); }); + test('restores promo if undo command is fired via keyboard', async () => { + // Dismiss middle slot promo. + const canShowPromo = true; + const middleSlotPromo = await createMiddleSlotPromo(canShowPromo); + const parts = middleSlotPromo.$.promoAndDismissContainer.children; + assertEquals(2, parts.length); + const dismissPromoButton = parts[1] as HTMLElement; + dismissPromoButton.click(); + assertEquals(0, newTabPageHandler.getCallCount('undoBlocklistPromo')); + assertFalse(isVisible(middleSlotPromo.$.promoAndDismissContainer)); + assertEquals( + 0, + metrics.count( + 'NewTabPage.Promos.DismissAction', PromoDismissAction.RESTORE)); + + // Simulate 'ctrl+z' key combo (or meta+z for Mac). + keyDownOn(document.documentElement, 0, isMac ? 'meta' : 'ctrl', 'z'); + + assertEquals(1, newTabPageHandler.getCallCount('undoBlocklistPromo')); + assertTrue(isVisible(middleSlotPromo.$.promoAndDismissContainer)); + assertEquals( + 1, + metrics.count( + 'NewTabPage.Promos.DismissAction', PromoDismissAction.RESTORE)); + }); + + test('ignores undo command if no promo was blocklisted', async () => { + const canShowPromo = true; + await createMiddleSlotPromo(canShowPromo); + + // Simulate 'ctrl+z' key combo (or meta+z for Mac). + keyDownOn(document.documentElement, 0, isMac ? 'meta' : 'ctrl', 'z'); + + assertEquals(0, newTabPageHandler.getCallCount('undoBlocklistPromo')); + assertEquals( + 0, + metrics.count( + 'NewTabPage.Promos.DismissAction', PromoDismissAction.RESTORE)); + }); + test('setting promo data resurfaces promo after dismissal', async () => { const canShowPromo = true; const middleSlotPromo = await createMiddleSlotPromo(canShowPromo); - assertHasContent(canShowPromo, middleSlotPromo); - const parts = middleSlotPromo.$.promoAndDismissContainer.children; - assertEquals(2, parts.length); callbackRouterRemote.setPromo(null); await callbackRouterRemote.$.flushForTesting();
diff --git a/chrome/test/data/webui/new_tab_page/mobile_promo_test.ts b/chrome/test/data/webui/new_tab_page/mobile_promo_test.ts index 763584d4..58d8b52 100644 --- a/chrome/test/data/webui/new_tab_page/mobile_promo_test.ts +++ b/chrome/test/data/webui/new_tab_page/mobile_promo_test.ts
@@ -8,7 +8,9 @@ import type {CrAutoImgElement} from 'chrome://new-tab-page/new_tab_page.js'; import {$$, NewTabPageProxy} from 'chrome://new-tab-page/new_tab_page.js'; import {PageCallbackRouter, PageHandlerRemote} from 'chrome://new-tab-page/new_tab_page.mojom-webui.js'; +import {isMac} from 'chrome://resources/js/platform.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {keyDownOn} from 'chrome://webui-test/keyboard_mock_interactions.js'; import type {TestMock} from 'chrome://webui-test/test_mock.js'; import {eventToPromise, isVisible, microtasksFinished} from 'chrome://webui-test/test_util.js'; @@ -116,4 +118,36 @@ assertFalse(mobilePromo.$.dismissPromoButtonToast.open); assertEquals(1, newTabPageHandler.getCallCount('onUndoDismissMobilePromo')); }); + + test('restores promo if undo command is fired via keyboard', async () => { + newTabPageHandler.setResultFor( + 'getMobilePromoQrCode', Promise.resolve({qrCode: 'abc'})); + const mobilePromo = await (createMobilePromo(true)); + + const parts = mobilePromo.$.titleAndDismissContainer.children; + assertEquals(2, parts.length); + const dismissPromoButton = parts[1] as HTMLElement; + dismissPromoButton.click(); + await microtasksFinished(); + + assertEquals(0, newTabPageHandler.getCallCount('onUndoDismissMobilePromo')); + // Simulate 'ctrl+z' key combo (or meta+z for Mac). + keyDownOn(document.documentElement, 0, isMac ? 'meta' : 'ctrl', 'z'); + await microtasksFinished(); + + assertTrue(isVisible(mobilePromo.$.promoContainer)); + assertFalse(mobilePromo.$.dismissPromoButtonToast.open); + assertEquals(1, newTabPageHandler.getCallCount('onUndoDismissMobilePromo')); + }); + + test('ignores undo command if no promo was blocklisted', async () => { + newTabPageHandler.setResultFor( + 'getMobilePromoQrCode', Promise.resolve({qrCode: 'abc'})); + await (createMobilePromo(true)); + + // Simulate 'ctrl+z' key combo (or meta+z for Mac). + keyDownOn(document.documentElement, 0, isMac ? 'meta' : 'ctrl', 'z'); + + assertEquals(0, newTabPageHandler.getCallCount('onUndoDismissMobilePromo')); + }); });
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index 8ddcd68..237bfd8 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -35,6 +35,12 @@ "//chrome/updater/tools", ] } + + # These packages have problematic license files that we need to avoid for + # updater redistribution. + if (!is_component_build) { + assert_no_deps = [ "//third_party/libaom" ] + } } group("all") {
diff --git a/chrome/updater/policy/policy_fetcher.cc b/chrome/updater/policy/policy_fetcher.cc index c7e47e6d..a51833a7 100644 --- a/chrome/updater/policy/policy_fetcher.cc +++ b/chrome/updater/policy/policy_fetcher.cc
@@ -19,9 +19,9 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/time/default_clock.h" +#include "chrome/enterprise_companion/constants.h" #include "chrome/enterprise_companion/device_management_storage/dm_storage.h" #include "chrome/enterprise_companion/enterprise_companion_client.h" -#include "chrome/enterprise_companion/enterprise_companion_status.h" #include "chrome/enterprise_companion/global_constants.h" #include "chrome/enterprise_companion/mojom/enterprise_companion.mojom.h" #include "chrome/updater/configurator.h" @@ -307,10 +307,7 @@ VLOG(1) << "Policy fetch status: " << mojom_status->code << ", space: " << mojom_status->space << ", description: " << mojom_status->description; - enterprise_companion::EnterpriseCompanionStatus status = - enterprise_companion::EnterpriseCompanionStatus::FromMojomStatus( - std::move(mojom_status)); - if (status.ok()) { + if (mojom_status->space == enterprise_companion::kStatusOk) { base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::WithBaseSyncPrimitives()}, base::BindOnce( @@ -326,8 +323,10 @@ std::move(fetch_complete_callback_))); } else { int result = kErrorPolicyFetchFailed; - if (status.EqualsApplicationError(enterprise_companion::ApplicationError:: - kRegistrationPreconditionFailed)) { + if (mojom_status->space == enterprise_companion::kStatusApplicationError && + mojom_status->code == + static_cast<int>(enterprise_companion::ApplicationError:: + kRegistrationPreconditionFailed)) { scoped_refptr<device_management_storage::DMStorage> dm_storage = device_management_storage::GetDefaultDMStorage(); result = (dm_storage && dm_storage->IsEnrollmentMandatory())
diff --git a/chromeos/ash/components/disks/disk_mount_manager.cc b/chromeos/ash/components/disks/disk_mount_manager.cc index caaeb06..372feeb 100644 --- a/chromeos/ash/components/disks/disk_mount_manager.cc +++ b/chromeos/ash/components/disks/disk_mount_manager.cc
@@ -632,21 +632,24 @@ } } - if (const MountPoints::const_iterator mount_point = - mount_points_.find(mount_path); - mount_point != mount_points_.end()) { - NotifyMountStatusUpdate(UNMOUNTING, error, *mount_point); - + if (const MountPoints::const_iterator it = mount_points_.find(mount_path); + it != mount_points_.end()) { if (error == MountError::kSuccess) { + const MountPoints::node_type n = mount_points_.extract(it); + DCHECK(n); + const MountPoint& mount_point = n.value(); + if (const Disks::const_iterator disk = - disks_.find(mount_point->source_path); + disks_.find(mount_point.source_path); disk != disks_.end()) { DCHECK(*disk); (*disk)->clear_mount_path(); (*disk)->set_mounted(false); } - mount_points_.erase(mount_point); + NotifyMountStatusUpdate(UNMOUNTING, error, mount_point); + } else { + NotifyMountStatusUpdate(UNMOUNTING, error, *it); } }
diff --git a/chromeos/ash/services/ime/input_method_user_data_service_impl.cc b/chromeos/ash/services/ime/input_method_user_data_service_impl.cc index ac69472..f74e445 100644 --- a/chromeos/ash/services/ime/input_method_user_data_service_impl.cc +++ b/chromeos/ash/services/ime/input_method_user_data_service_impl.cc
@@ -215,6 +215,27 @@ std::move(user_data_response.export_japanese_dictionary())); } +void InputMethodUserDataServiceImpl::ImportJapaneseDictionary( + uint64_t dict_id, + const std::string& tsv_data, + ImportJapaneseDictionaryCallback callback) { + chromeos_input::UserDataRequest user_data_request; + user_data_request.mutable_import_japanese_dictionary()->set_dictionary_id( + dict_id); + user_data_request.mutable_import_japanese_dictionary()->set_tsv_data( + tsv_data); + + chromeos_input::UserDataResponse user_data_response = + c_api_->ProcessUserDataRequest(user_data_request); + + mojom::StatusPtr response = mojom::Status::New(); + response->success = user_data_response.status().success(); + if (user_data_response.status().has_reason()) { + response->reason = user_data_response.status().reason(); + } + std::move(callback).Run(std::move(response)); +} + void InputMethodUserDataServiceImpl::AddReceiver( mojo::PendingReceiver<mojom::InputMethodUserDataService> receiver) { receiver_set_.Add(this, std::move(receiver));
diff --git a/chromeos/ash/services/ime/input_method_user_data_service_impl.h b/chromeos/ash/services/ime/input_method_user_data_service_impl.h index 4ce09a38..e419609 100644 --- a/chromeos/ash/services/ime/input_method_user_data_service_impl.h +++ b/chromeos/ash/services/ime/input_method_user_data_service_impl.h
@@ -62,6 +62,11 @@ uint64_t dict_id, ExportJapaneseDictionaryCallback callback) override; + void ImportJapaneseDictionary( + uint64_t dict_id, + const std::string& tsv_data, + ImportJapaneseDictionaryCallback callback) override; + void AddReceiver( mojo::PendingReceiver<mojom::InputMethodUserDataService> receiver);
diff --git a/chromeos/ash/services/ime/public/mojom/input_method_user_data.mojom b/chromeos/ash/services/ime/public/mojom/input_method_user_data.mojom index b32666a..38dc64c5 100644 --- a/chromeos/ash/services/ime/public/mojom/input_method_user_data.mojom +++ b/chromeos/ash/services/ime/public/mojom/input_method_user_data.mojom
@@ -60,4 +60,10 @@ // Get tab separated values that represent the dictionary. ExportJapaneseDictionary(uint64 dict_id) => (mojo_base.mojom.BigString result); + + // Import tab separated entries into the dictionary. + // The tsv_data is a user provided dictionary that would be loaded from a file + // and then sent directly to the sandboxed IMEService. + ImportJapaneseDictionary( + uint64 dict_id, mojo_base.mojom.BigString tsv_data) => (Status status); };
diff --git a/chromeos/components/magic_boost/test/fake_magic_boost_state.cc b/chromeos/components/magic_boost/test/fake_magic_boost_state.cc index ac0cbd8..a42dbca5 100644 --- a/chromeos/components/magic_boost/test/fake_magic_boost_state.cc +++ b/chromeos/components/magic_boost/test/fake_magic_boost_state.cc
@@ -10,7 +10,7 @@ namespace test { bool FakeMagicBoostState::IsMagicBoostAvailable() { - return true; + return is_magic_boost_available_; } bool FakeMagicBoostState::CanShowNoticeBannerForHMR() { @@ -30,5 +30,13 @@ UpdateHMREnabled(enabled); } +void FakeMagicBoostState::SetMagicBoostAvailability(bool available) { + is_magic_boost_available_ = available; +} + +void FakeMagicBoostState::SetMagicBoostEnabled(bool enabled) { + UpdateMagicBoostEnabled(enabled); +} + } // namespace test } // namespace chromeos
diff --git a/chromeos/components/magic_boost/test/fake_magic_boost_state.h b/chromeos/components/magic_boost/test/fake_magic_boost_state.h index 116a24b..67ca4ac 100644 --- a/chromeos/components/magic_boost/test/fake_magic_boost_state.h +++ b/chromeos/components/magic_boost/test/fake_magic_boost_state.h
@@ -19,6 +19,12 @@ chromeos::HMRConsentStatus consent_status) override; void AsyncWriteHMREnabled(bool enabled) override; void DisableOrcaFeature() override {} + + void SetMagicBoostAvailability(bool available); + void SetMagicBoostEnabled(bool enabled); + + private: + bool is_magic_boost_available_ = true; }; } // namespace test
diff --git a/chromeos/components/quick_answers/public/cpp/quick_answers_state.cc b/chromeos/components/quick_answers/public/cpp/quick_answers_state.cc index 9d74d44..a36563c 100644 --- a/chromeos/components/quick_answers/public/cpp/quick_answers_state.cc +++ b/chromeos/components/quick_answers/public/cpp/quick_answers_state.cc
@@ -161,12 +161,15 @@ CHECK(!g_quick_answers_state); g_quick_answers_state = this; - if (GetFeatureType() == FeatureType::kHmr) { chromeos::MagicBoostState* magic_boost_state = chromeos::MagicBoostState::Get(); - CHECK(magic_boost_state) << "QuickAnswersState depends on MagicBoostState."; - magic_boost_state_observation_.Observe(magic_boost_state); - } + if (magic_boost_state) { + magic_boost_state_observation_.Observe(magic_boost_state); + } + + // Inovke `MaybeNotifyFeatureTypeChanged` to set initial last notified + // value. + MaybeNotifyFeatureTypeChanged(); } QuickAnswersState::~QuickAnswersState() { @@ -183,6 +186,18 @@ observers_.RemoveObserver(observer); } +void QuickAnswersState::OnMagicBoostEnabledUpdated(bool enabled) { + // MagicBoost's availability check includes an async operation. It can return + // false for a short period even if a user/device is eligible. + // `MagicBoostState` does not have an interface to allow clients to listen + // availability change. As a workaround, we are currently using + // `OnMagicBoostEnabled` as a signal. See + // `SearchSection::OnMagicBoostEnabledUpdated` as an example. + // TODO(b/383612536): allow clients to observe MagicBoostState availability + // change + MaybeNotifyFeatureTypeChanged(); +} + void QuickAnswersState::OnHMREnabledUpdated(bool enabled) { MaybeNotifyIsEnabledChanged(); } @@ -410,6 +425,12 @@ void QuickAnswersState::InitializeObserver( QuickAnswersStateObserver* observer) { + base::expected<QuickAnswersState::FeatureType, QuickAnswersState::Error> + maybe_feature_type = GetFeatureTypeExpected(); + if (maybe_feature_type.has_value()) { + observer->OnFeatureTypeChanged(); + } + if (prefs_initialized_) { observer->OnPrefsInitialized(); observer->OnApplicationLocaleReady(resolved_application_locale_); @@ -477,6 +498,31 @@ } } +void QuickAnswersState::MaybeNotifyFeatureTypeChanged() { + base::expected<QuickAnswersState::FeatureType, QuickAnswersState::Error> + feature_type = GetFeatureTypeExpected(); + + if (last_notified_feature_type_ == feature_type) { + return; + } + + last_notified_feature_type_ = feature_type; + + if (last_notified_feature_type_.has_value()) { + for (auto& observer : observers_) { + observer.OnFeatureTypeChanged(); + } + } + + // Trigger potential value change notifications. Note that this won't reset + // the last value with the previous feature type. e.g., if it's eligible with + // the previous feature type and it's still eligible with new feature type, it + // won't notify. + MaybeNotifyEligibilityChanged(); + MaybeNotifyIsEnabledChanged(); + MaybeNotifyConsentStatusChanged(); +} + void QuickAnswersState::MaybeNotifyConsentStatusChanged() { base::expected<quick_answers::prefs::ConsentStatus, Error> consent_status = GetConsentStatusExpected();
diff --git a/chromeos/components/quick_answers/public/cpp/quick_answers_state.h b/chromeos/components/quick_answers/public/cpp/quick_answers_state.h index 904675f..f43e1b90 100644 --- a/chromeos/components/quick_answers/public/cpp/quick_answers_state.h +++ b/chromeos/components/quick_answers/public/cpp/quick_answers_state.h
@@ -38,6 +38,7 @@ // A checked observer which receives Quick Answers state change. class QuickAnswersStateObserver : public base::CheckedObserver { public: + virtual void OnFeatureTypeChanged() {} virtual void OnSettingsEnabled(bool enabled) {} virtual void OnConsentStatusUpdated( quick_answers::prefs::ConsentStatus status) {} @@ -112,6 +113,7 @@ void RemoveObserver(QuickAnswersStateObserver* observer); // chromeos::MagicBoostState::Observer: + void OnMagicBoostEnabledUpdated(bool enabled) override; void OnHMREnabledUpdated(bool enabled) override; void OnHMRConsentStatusUpdated( chromeos::HMRConsentStatus consent_status) override; @@ -209,6 +211,7 @@ base::ObserverList<QuickAnswersStateObserver> observers_; private: + void MaybeNotifyFeatureTypeChanged(); void MaybeNotifyConsentStatusChanged(); // Holds consent status of Quick Answers capability as a Quick Answers @@ -256,6 +259,8 @@ FeatureType feature_type) const; // Last notified values in the current feature type. + base::expected<QuickAnswersState::FeatureType, Error> + last_notified_feature_type_ = base::unexpected(Error::kUninitialized); base::expected<bool, Error> last_notified_is_eligible_ = base::unexpected(Error::kUninitialized); base::expected<bool, Error> last_notified_is_enabled_ =
diff --git a/chromeos/components/quick_answers/public/cpp/quick_answers_state_unittest.cc b/chromeos/components/quick_answers/public/cpp/quick_answers_state_unittest.cc index eec356a9..3c72e956 100644 --- a/chromeos/components/quick_answers/public/cpp/quick_answers_state_unittest.cc +++ b/chromeos/components/quick_answers/public/cpp/quick_answers_state_unittest.cc
@@ -4,6 +4,7 @@ #include "chromeos/components/quick_answers/public/cpp/quick_answers_state.h" +#include <optional> #include <string_view> #include "base/functional/callback_forward.h" @@ -24,6 +25,9 @@ class FakeObserver : public QuickAnswersStateObserver { public: + void OnFeatureTypeChanged() override { + feature_type_ = QuickAnswersState::GetFeatureType(); + } void OnEligibilityChanged(bool eligible) override { is_eligible_ = eligible; } void OnSettingsEnabled(bool enabled) override { is_enabled_ = enabled; } void OnConsentStatusUpdated( @@ -31,6 +35,9 @@ consent_status_ = consent_status; } + std::optional<QuickAnswersState::FeatureType> feature_type() const { + return feature_type_; + } bool is_eligible() const { return is_eligible_; } bool is_enabled() const { return is_enabled_; } quick_answers::prefs::ConsentStatus consent_status() const { @@ -38,20 +45,25 @@ } private: + std::optional<QuickAnswersState::FeatureType> feature_type_; bool is_eligible_ = false; bool is_enabled_ = false; quick_answers::prefs::ConsentStatus consent_status_ = quick_answers::prefs::ConsentStatus::kUnknown; }; -std::unique_ptr<base::test::ScopedFeatureList> MaybeEnableMagicBoost() { -#if BUILDFLAG(IS_CHROMEOS_ASH) +std::unique_ptr<base::test::ScopedFeatureList> EnableMagicBoost() { // Note that `kMahi` is associated with the Magic Boost feature. auto feature_list = std::make_unique<base::test::ScopedFeatureList>(); feature_list->InitWithFeatures( {chromeos::features::kMahi, chromeos::features::kFeatureManagementMahi}, {}); return feature_list; +} + +std::unique_ptr<base::test::ScopedFeatureList> MaybeEnableMagicBoost() { +#if BUILDFLAG(IS_CHROMEOS) + return EnableMagicBoost(); #else // chromeos_components_unittests is expected to run only in Ash build for now. // @@ -135,6 +147,36 @@ EXPECT_FALSE(QuickAnswersState::IsEnabled()); } +// MagicBoost availability check requires an async operation. There is a short +// period where `MagicBoostState` returns false for its availability even if a +// user/device is eligible. +TEST(QuickAnswersStateTest, MagicBoostStateEligibilityChanged) { + std::unique_ptr<base::test::ScopedFeatureList> magic_boost_enabled = + EnableMagicBoost(); + + chromeos::test::FakeMagicBoostState magic_boost_state; + magic_boost_state.SetMagicBoostAvailability(false); + FakeQuickAnswersState quick_answers_state; + quick_answers_state.SetApplicationLocale("en"); + + FakeObserver observer; + quick_answers_state.AddObserver(&observer); + + EXPECT_EQ(QuickAnswersState::FeatureType::kQuickAnswers, + QuickAnswersState::GetFeatureType()); + EXPECT_EQ(QuickAnswersState::FeatureType::kQuickAnswers, + observer.feature_type()); + + // Simulate that MagicBoost availability check async operation is compalted + // and a user has went through MagicBoost consent flow. + magic_boost_state.SetMagicBoostAvailability(true); + magic_boost_state.SetMagicBoostEnabled(true); + + EXPECT_EQ(QuickAnswersState::FeatureType::kHmr, + QuickAnswersState::GetFeatureType()); + EXPECT_EQ(QuickAnswersState::FeatureType::kHmr, observer.feature_type()); +} + TEST(QuickAnswersStateTest, EnabledButKiosk) { user_manager::ScopedUserManager scoped_user_manager( std::make_unique<user_manager::FakeUserManager>());
diff --git a/clank b/clank index 2f52e8c..b5d98568 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 2f52e8c05d050394684c53b038ac105abf95f4d0 +Subproject commit b5d98568bc15a6db04d96b75da6adede917e67e4
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 0b546788..8226c5f 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -476,7 +476,6 @@ password_generation_agent_(std::move(password_generation_agent)) { render_frame->GetWebFrame()->SetAutofillClient(this); password_autofill_agent_->Init(this); - AddFormObserver(this); registry->AddInterface<mojom::AutofillAgent>(base::BindRepeating( &AutofillAgent::BindPendingReceiver, base::Unretained(this))); } @@ -484,9 +483,7 @@ // The destructor is not guaranteed to be called. Destruction happens (only) // through the OnDestruct() event, which posts a task to delete this object. // The process may be killed before this deletion can happen. -AutofillAgent::~AutofillAgent() { - RemoveFormObserver(this); -} +AutofillAgent::~AutofillAgent() = default; WebDocument AutofillAgent::GetDocument() const { return unsafe_render_frame() @@ -726,6 +723,11 @@ void AutofillAgent::FireHostSubmitEvents(const FormData& form_data, mojom::SubmissionSource source) { + if (source == mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL && + !base::FeatureList::IsEnabled( + features::kAutofillAcceptDomMutationAfterAutofillSubmission)) { + return; + } DenseSet<mojom::SubmissionSource>& sources = submitted_forms_[form_data.renderer_id()]; if (!sources.insert(source).second) { @@ -1853,7 +1855,7 @@ void AutofillAgent::OnProvisionallySaveForm( const WebFormElement& form_element, const WebFormControlElement& element, - SaveFormReason source) { + FormTracker::SaveFormReason source) { DCHECK(form_util::MaybeWasOwnedByFrame(form_element, unsafe_render_frame())); DCHECK(form_util::MaybeWasOwnedByFrame(element, unsafe_render_frame())); @@ -1885,7 +1887,7 @@ }; switch (source) { - case FormTracker::Observer::SaveFormReason::kWillSendSubmitEvent: + case FormTracker::SaveFormReason::kWillSendSubmitEvent: // TODO(crbug.com/40281981): Figure out if this is still needed, and // document the reason, otherwise remove. password_autofill_agent_->InformBrowserAboutUserInput( @@ -1899,94 +1901,60 @@ // Javascript's submit event handler could change it. We don't clear // submitted_forms_ because OnFormSubmitted will normally be invoked // afterwards and we don't want to fire the same event twice. - if (std::optional<FormData> form_data = GetSubmittedForm( - mojom::SubmissionSource::FORM_SUBMISSION, form_element)) { - FireHostSubmitEvents(*form_data, - mojom::SubmissionSource::FORM_SUBMISSION); - } + OnFormSubmission(mojom::SubmissionSource::FORM_SUBMISSION, form_element); break; - case FormTracker::Observer::SaveFormReason::kTextFieldChanged: + case FormTracker::SaveFormReason::kTextFieldChanged: update_submission_data_on_user_edit(); OnTextFieldDidChange(element); break; - case FormTracker::Observer::SaveFormReason::kSelectChanged: + case FormTracker::SaveFormReason::kSelectChanged: update_submission_data_on_user_edit(); OnSelectControlDidChange(element); break; } } -void AutofillAgent::OnProbablyFormSubmitted() { - if (std::optional<FormData> form_data = - GetSubmittedForm(mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED, - /*form_element=*/std::nullopt)) { - FireHostSubmitEvents(form_data.value(), - mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED); - } - if (!base::FeatureList::IsEnabled(features::kAutofillFixFormTracking)) { - ResetLastInteractedElements(); - } - OnFormNoLongerSubmittable(); -} - -void AutofillAgent::OnFormSubmitted(const WebFormElement& form_element) { - DCHECK(form_util::MaybeWasOwnedByFrame(form_element, unsafe_render_frame())); - // Fire the submission event here because WILL_SEND_SUBMIT_EVENT is skipped - // if javascript calls submit() directly. - if (std::optional<FormData> form_data = GetSubmittedForm( - mojom::SubmissionSource::FORM_SUBMISSION, form_element)) { - FireHostSubmitEvents(*form_data, mojom::SubmissionSource::FORM_SUBMISSION); - } -} - -void AutofillAgent::OnInferredFormSubmission(mojom::SubmissionSource source) { +void AutofillAgent::OnFormSubmission( + mojom::SubmissionSource source, + std::optional<blink::WebFormElement> submitted_form_element) { if (!unsafe_render_frame()) { return; } + if (source == mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL) { + // TODO(crbug.com/40281981): Investigate removing this and relying on the + // call conditioned on the submitted form. + password_autofill_agent_->FireHostSubmitEvent(FormRendererId(), source); + } + if (std::optional<FormData> form_data = + GetSubmittedForm(source, submitted_form_element)) { + FireHostSubmitEvents(*form_data, source); + } switch (source) { - // This source is only used as a default value to variables. - case mojom::SubmissionSource::NONE: - // This source is handled by `AutofillAgent::OnFormSubmitted`. case mojom::SubmissionSource::FORM_SUBMISSION: - // This source is handled by `AutofillAgent::OnProbablyFormSubmitted`. - case mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED: - NOTREACHED(); case mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL: - password_autofill_agent_->FireHostSubmitEvent(FormRendererId(), source); - if (std::optional<FormData> form_data = - GetSubmittedForm(source, /*form_element=*/std::nullopt); - form_data && - base::FeatureList::IsEnabled( - features::kAutofillAcceptDomMutationAfterAutofillSubmission)) { - FireHostSubmitEvents(*form_data, source); + break; + case mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED: + if (!base::FeatureList::IsEnabled(features::kAutofillFixFormTracking)) { + // TODO(crbug.com/40281981): Figure out if this is still needed, and + // document the reason, otherwise remove. + ResetLastInteractedElements(); } - // `BrowserAutofillManager` ignores submissions with - // DOM_MUTATION_AFTER_AUTOFILL as a source, therefore we early return in - // this case as to not call `AutofillAgent::ResetLastInteractedElements()` - // which could cause us to miss a submission that BAM actually cares - // about. - return; - // This event occurs only when either this frame or a same process parent - // frame of it gets detached. + // TODO(crbug.com/40281981): Figure out if this is still needed, and + // document the reason, otherwise remove. + OnFormNoLongerSubmittable(); + break; case mojom::SubmissionSource::FRAME_DETACHED: case mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION: case mojom::SubmissionSource::XHR_SUCCEEDED: - if (std::optional<FormData> form_data = - GetSubmittedForm(source, /*form_element=*/std::nullopt)) { - FireHostSubmitEvents(*form_data, source); - } + // TODO(crbug.com/40281981): Figure out if those two lines are still + // needed, and document the reason, otherwise remove. + ResetLastInteractedElements(); + OnFormNoLongerSubmittable(); break; + // This source is only used as a default value to variables. + case mojom::SubmissionSource::NONE: + NOTREACHED(); } - ResetLastInteractedElements(); - OnFormNoLongerSubmittable(); -} - -void AutofillAgent::AddFormObserver(Observer* observer) { - form_tracker_->AddObserver(observer); -} - -void AutofillAgent::RemoveFormObserver(Observer* observer) { - form_tracker_->RemoveObserver(observer); } void AutofillAgent::TrackAutofilledElement( @@ -2010,7 +1978,7 @@ std::optional<FormData> AutofillAgent::GetSubmittedForm( mojom::SubmissionSource source, - std::optional<WebFormElement> form_element) const { + std::optional<WebFormElement> submitted_form_element) const { // Behavior when `AutofillReplaceFormElementObserver` is enabled: // - Never try to extract and unconditionally look at the provisionally saved // form. The reason is that some form extraction could happen during style @@ -2044,22 +2012,19 @@ // `last_interacted_form()` or `form_element` if provided). if (base::FeatureList::IsEnabled( features::kAutofillPreferSavedFormAsSubmittedForm)) { - if (!form_tracker_->IsTracking() && !form_element.has_value()) { - LogSubmittedFormMetric(source, SubmittedFormType::kNull); - return std::nullopt; - } if (std::optional<FormData> form = provisionally_saved_form(); - form && - (!form_element.has_value() || - form->renderer_id() == form_util::GetFormRendererId(*form_element))) { + form && (!submitted_form_element.has_value() || + form->renderer_id() == + form_util::GetFormRendererId(*submitted_form_element))) { LogSubmittedFormMetric(source, SubmittedFormType::kCached); return form; } if (WebDocument document = GetDocument()) { if (std::optional<FormData> form = form_util::ExtractFormData( document, - form_element.has_value() ? *form_element - : last_interacted_form().GetForm(), + submitted_form_element.has_value() + ? *submitted_form_element + : last_interacted_form().GetForm(), field_data_manager(), GetCallTimerState(kGetSubmittedForm))) { LogSubmittedFormMetric(source, SubmittedFormType::kExtracted); return form; @@ -2075,18 +2040,18 @@ // - Primarily try to extract the form represented by `form_element`. // - In case of failure, fallback to the provisionally saved form, only if it // has the same FormRendererId as `form_element`. - if (form_element.has_value() && + if (submitted_form_element.has_value() && base::FeatureList::IsEnabled( features::kAutofillUseSubmittedFormInHtmlSubmission)) { if (std::optional<FormData> form = form_util::ExtractFormData( - form_element->GetDocument(), *form_element, field_data_manager(), - GetCallTimerState(kGetSubmittedForm))) { + submitted_form_element->GetDocument(), *submitted_form_element, + field_data_manager(), GetCallTimerState(kGetSubmittedForm))) { LogSubmittedFormMetric(source, SubmittedFormType::kExtracted); return form; } if (std::optional<FormData> form = provisionally_saved_form(); - form && - form->renderer_id() == form_util::GetFormRendererId(*form_element)) { + form && form->renderer_id() == + form_util::GetFormRendererId(*submitted_form_element)) { LogSubmittedFormMetric(source, SubmittedFormType::kCached); return form; } @@ -2099,10 +2064,10 @@ if (source == mojom::SubmissionSource::FORM_SUBMISSION && !base::FeatureList::IsEnabled( features::kAutofillUseSubmittedFormInHtmlSubmission)) { - CHECK(form_element); + CHECK(submitted_form_element); std::optional<FormData> form = form_util::ExtractFormData( - form_element->GetDocument(), *form_element, field_data_manager(), - GetCallTimerState(kGetSubmittedForm)); + submitted_form_element->GetDocument(), *submitted_form_element, + field_data_manager(), GetCallTimerState(kGetSubmittedForm)); LogSubmittedFormMetric(source, form ? SubmittedFormType::kExtracted : SubmittedFormType::kNull); return form;
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index c48cf3b..6282840 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -106,7 +106,6 @@ // - password form fill, referred to as Password Autofill, and // - entire form fill based on one field entry, referred to as Form Autofill. class AutofillAgent : public content::RenderFrameObserver, - public FormTracker::Observer, public blink::WebAutofillClient, public mojom::AutofillAgent { public: @@ -231,16 +230,17 @@ return weak_ptr_factory_.GetWeakPtr(); } - // FormTracker::Observer + // TODO(crbug.com/40147954): Find a better name for this method. + // Invoked when form needs to be saved because of `reason`, `element` is + // valid if the callback caused by a reason other than + // SaveFormReason::kWillSendSubmitEvent, |form| is valid for the callback + // caused by SaveFormReason::kWillSendSubmitEvent. void OnProvisionallySaveForm(const blink::WebFormElement& form, const blink::WebFormControlElement& element, - SaveFormReason source) override; - void OnProbablyFormSubmitted() override; - void OnFormSubmitted(const blink::WebFormElement& form_element) override; - void OnInferredFormSubmission(mojom::SubmissionSource source) override; - - void AddFormObserver(Observer* observer); - void RemoveFormObserver(Observer* observer); + FormTracker::SaveFormReason reason); + void OnFormSubmission( + mojom::SubmissionSource source, + std::optional<blink::WebFormElement> submitted_form_element); // Instructs `form_tracker_` to track the autofilled `element`. void TrackAutofilledElement(const blink::WebFormControlElement& element); @@ -426,15 +426,15 @@ // been removed afterwards). // - `last_interacted_form_`'s current `FormData`, because this corresponds to // the last form element the user interacted with. - // - `known_submitted_form_element`'s current `FormData`, because the caller + // - `submitted_form_element`'s current `FormData`, because the caller // specified that this is the form element that was submitted, regardless // of autofill's tracking. - // When `known_submitted_form_element` is provided the function makes sure + // When `submitted_form_element` is provided the function makes sure // that the returned form corresponds to that DOM element. // `source` is the type of submission requesting the submitted form. std::optional<FormData> GetSubmittedForm( mojom::SubmissionSource source, - std::optional<blink::WebFormElement> known_submitted_form_element) const; + std::optional<blink::WebFormElement> submitted_form_element) const; void ResetLastInteractedElements(); // A form_id means that the user last interacted with a FormElement.
diff --git a/components/autofill/content/renderer/autofill_agent_browsertest.cc b/components/autofill/content/renderer/autofill_agent_browsertest.cc index 0ce7183..53d1ed7e 100644 --- a/components/autofill/content/renderer/autofill_agent_browsertest.cc +++ b/components/autofill/content/renderer/autofill_agent_browsertest.cc
@@ -8,6 +8,7 @@ #include <algorithm> #include <memory> +#include <optional> #include <string> #include <string_view> #include <utility> @@ -157,12 +158,10 @@ public: void SetUp() override { test::AutofillRendererTest::SetUp(); - std::unique_ptr<MockFormTracker> form_tracker = - std::make_unique<MockFormTracker>( + test_api(autofill_agent()) + .set_form_tracker(std::make_unique<MockFormTracker>( GetMainRenderFrame(), FormTracker::UserGestureRequired(true), - autofill_agent()); - form_tracker->AddObserver(&autofill_agent()); - test_api(autofill_agent()).set_form_tracker(std::move(form_tracker)); + autofill_agent())); } FormRendererId GetFormRendererIdById(std::string_view id) { @@ -1030,8 +1029,8 @@ // removed after an AJAX call. ExecuteJavaScriptForTests( R"(document.getElementById('shipping').innerHTML = '')"); - autofill_agent().OnInferredFormSubmission( - mojom::SubmissionSource::XHR_SUCCEEDED); + autofill_agent().OnFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED, + /*submitted_form_element=*/std::nullopt); } // Tests that an inferred form submission as a result of a page deleting ALL of @@ -1061,8 +1060,8 @@ // Simulate inferred form submission as a result the focused field being // removed after an AJAX call. ExecuteJavaScriptForTests(R"(document.getElementById('shipping').remove();)"); - autofill_agent().OnInferredFormSubmission( - mojom::SubmissionSource::XHR_SUCCEEDED); + autofill_agent().OnFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED, + /*submitted_form_element=*/std::nullopt); } // Test scenario WHERE: @@ -1100,7 +1099,9 @@ // Remove element that the user did not interact with last. ExecuteJavaScriptForTests(R"(document.getElementById('name').remove();)"); // Simulate page navigation. - autofill_agent().OnProbablyFormSubmitted(); + autofill_agent().OnFormSubmission( + mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED, + /*submitted_form_element=*/std::nullopt); } // Test that in the scenario that: @@ -1159,8 +1160,8 @@ FieldsAre(HasValue(u"input2 autofilled"))), _)); ExecuteJavaScriptForTests(R"(document.getElementById('form').remove();)"); - autofill_agent().OnInferredFormSubmission( - mojom::SubmissionSource::XHR_SUCCEEDED); + autofill_agent().OnFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED, + /*submitted_form_element=*/std::nullopt); } class AutofillAgentTestNavigationReset : public AutofillAgentTest {
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 86ab769..f70a422 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -2154,10 +2154,10 @@ } } - base::UmaHistogramCounts100(!form_element - ? "Autofill.ExtractFormUnowned.FieldCount" - : "Autofill.ExtractFormOwned.FieldCount", - fields.size()); + base::UmaHistogramCounts1000(!form_element + ? "Autofill.ExtractFormUnowned.FieldCount2" + : "Autofill.ExtractFormOwned.FieldCount2", + fields.size()); FormData form; if (!form_element) { DCHECK(form.renderer_id().is_null());
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc index 40f8ddc7..af8f84b 100644 --- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc +++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -2153,10 +2153,10 @@ Property(&FormFieldData::name, u"check_input"), Property(&FormFieldData::name, u"number_input"), Property(&FormFieldData::name, u"select_input"))))); - histogram_tester.ExpectTotalCount("Autofill.ExtractFormUnowned.FieldCount", + histogram_tester.ExpectTotalCount("Autofill.ExtractFormUnowned.FieldCount2", 0); - histogram_tester.ExpectUniqueSample("Autofill.ExtractFormOwned.FieldCount", 4, - 1); + histogram_tester.ExpectUniqueSample("Autofill.ExtractFormOwned.FieldCount2", + 4, 1); } TEST_F(FormAutofillUtilsTest, ExtractFormData_UnownedForm) { @@ -2181,8 +2181,8 @@ Property(&FormFieldData::name, u"check_input"), Property(&FormFieldData::name, u"number_input"), Property(&FormFieldData::name, u"select_input"))))); - histogram_tester.ExpectTotalCount("Autofill.ExtractFormOwned.FieldCount", 0); - histogram_tester.ExpectUniqueSample("Autofill.ExtractFormUnowned.FieldCount", + histogram_tester.ExpectTotalCount("Autofill.ExtractFormOwned.FieldCount2", 0); + histogram_tester.ExpectUniqueSample("Autofill.ExtractFormUnowned.FieldCount2", 4, 1); }
diff --git a/components/autofill/content/renderer/form_tracker.cc b/components/autofill/content/renderer/form_tracker.cc index 9b3ca2c..e09f4d6 100644 --- a/components/autofill/content/renderer/form_tracker.cc +++ b/components/autofill/content/renderer/form_tracker.cc
@@ -4,10 +4,13 @@ #include "components/autofill/content/renderer/form_tracker.h" +#include <optional> + #include "base/check.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" +#include "base/notreached.h" #include "base/observer_list.h" #include "components/autofill/content/renderer/autofill_agent.h" #include "components/autofill/content/renderer/form_autofill_util.h" @@ -124,18 +127,6 @@ ResetLastInteractedElements(); } -void FormTracker::AddObserver(Observer* observer) { - DCHECK(observer); - DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_); - observers_.AddObserver(observer); -} - -void FormTracker::RemoveObserver(Observer* observer) { - DCHECK(observer); - DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_); - observers_.RemoveObserver(observer); -} - void FormTracker::AjaxSucceeded() { DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_); submission_triggering_events_.xhr_succeeded = true; @@ -170,11 +161,11 @@ unsafe_render_frame() ->GetWebFrame() ->GetTaskRunner(blink::TaskType::kInternalUserInteraction) - ->PostTask(FROM_HERE, base::BindRepeating( - &FormTracker::FormControlDidChangeImpl, - weak_ptr_factory_.GetWeakPtr(), - form_util::GetFieldRendererId(element), - Observer::SaveFormReason::kTextFieldChanged)); + ->PostTask(FROM_HERE, + base::BindRepeating(&FormTracker::FormControlDidChangeImpl, + weak_ptr_factory_.GetWeakPtr(), + form_util::GetFieldRendererId(element), + SaveFormReason::kTextFieldChanged)); } void FormTracker::SelectControlDidChange(const WebFormControlElement& element) { @@ -191,7 +182,7 @@ base::BindRepeating(&FormTracker::FormControlDidChangeImpl, weak_ptr_factory_.GetWeakPtr(), form_util::GetFieldRendererId(element), - Observer::SaveFormReason::kSelectChanged)); + SaveFormReason::kSelectChanged)); } void FormTracker::ElementDisappeared(const blink::WebElement& element) { @@ -218,17 +209,18 @@ return; } if (submission_triggering_events_.xhr_succeeded) { - FireInferredFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED); + FireFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED, + /*submitted_form_element=*/std::nullopt); return; } if (submission_triggering_events_.finished_same_document_navigation) { - FireInferredFormSubmission( - mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION); + FireFormSubmission(mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION, + /*submitted_form_element=*/std::nullopt); return; } if (submission_triggering_events_.tracked_element_autofilled) { - FireInferredFormSubmission( - mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL); + FireFormSubmission(mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL, + /*submitted_form_element=*/std::nullopt); return; } submission_triggering_events_.tracked_element_disappeared = true; @@ -250,9 +242,8 @@ TrackElement(mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL); } -void FormTracker::FormControlDidChangeImpl( - FieldRendererId element_id, - Observer::SaveFormReason change_source) { +void FormTracker::FormControlDidChangeImpl(FieldRendererId element_id, + SaveFormReason change_source) { DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_); WebFormControlElement element = form_util::GetFormControlByRendererId(element_id); @@ -268,9 +259,7 @@ } else { UpdateLastInteractedElement(form_util::GetFieldRendererId(element)); } - for (auto& observer : observers_) { - observer.OnProvisionallySaveForm(form_element, element, change_source); - } + agent_->OnProvisionallySaveForm(form_element, element, change_source); } void FormTracker::DidCommitProvisionalLoad(ui::PageTransition transition) { @@ -302,7 +291,8 @@ // and are discarded here. if (navigation_type.has_value() && navigation_type.value() != blink::kWebNavigationTypeLinkClicked) { - FireProbablyFormSubmitted(); + FireFormSubmission(mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED, + /*submitted_form_element=*/std::nullopt); } } @@ -312,13 +302,13 @@ return; } if (detach_reason == blink::DetachReason::kFrameDeletion && - !unsafe_render_frame()->GetWebFrame()->IsOutermostMainFrame() && - IsTracking()) { + !unsafe_render_frame()->GetWebFrame()->IsOutermostMainFrame()) { // Exclude cases where the previous RenderFrame gets deleted only to be // replaced by a new RenderFrame, which happens on navigations. This is so // that we only trigger inferred form submission if the actual frame // (<iframe> element etc) gets detached. - FireInferredFormSubmission(SubmissionSource::FRAME_DETACHED); + FireFormSubmission(SubmissionSource::FRAME_DETACHED, + /*submitted_form_element=*/std::nullopt); } // TODO(crbug.com/40281981): Figure out if this is still needed, and // document the reason, otherwise remove. @@ -333,11 +323,8 @@ // document the reason, otherwise remove. UpdateLastInteractedElement(form_util::GetFormRendererId(form)); } - for (auto& observer : observers_) { - observer.OnProvisionallySaveForm( - form, blink::WebFormControlElement(), - Observer::SaveFormReason::kWillSendSubmitEvent); - } + agent_->OnProvisionallySaveForm(form, blink::WebFormControlElement(), + SaveFormReason::kWillSendSubmitEvent); } void FormTracker::WillSubmitForm(const WebFormElement& form) { @@ -352,7 +339,7 @@ !form_util::IsOwnedByFrame(form, unsafe_render_frame())) { return; } - FireFormSubmitted(form); + FireFormSubmission(mojom::SubmissionSource::FORM_SUBMISSION, form); } void FormTracker::OnDestruct() { @@ -360,35 +347,38 @@ ResetLastInteractedElements(); } -void FormTracker::FireFormSubmitted(const blink::WebFormElement& form) { - base::UmaHistogramEnumeration(kSubmissionSourceHistogram, - SubmissionSource::FORM_SUBMISSION); - for (auto& observer : observers_) - observer.OnFormSubmitted(form); - if (!base::FeatureList::IsEnabled(features::kAutofillFixFormTracking)) { - ResetLastInteractedElements(); - } -} - -void FormTracker::FireProbablyFormSubmitted() { - base::UmaHistogramEnumeration(kSubmissionSourceHistogram, - SubmissionSource::PROBABLY_FORM_SUBMITTED); - for (auto& observer : observers_) - observer.OnProbablyFormSubmitted(); - if (!base::FeatureList::IsEnabled(features::kAutofillFixFormTracking)) { - ResetLastInteractedElements(); - } -} - -void FormTracker::FireInferredFormSubmission(SubmissionSource source) { +void FormTracker::FireFormSubmission( + SubmissionSource source, + std::optional<WebFormElement> submitted_form_element) { DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_); + if (!IsTracking() && source != mojom::SubmissionSource::FORM_SUBMISSION) { + // If no form is being tracked, there's no need to inform the agent of + // submission since no submitted form will be fetched. The only source + // that's an exception for this is SubmissionSource::FORM_SUBMISSION since + // it provides the submitted form element and therefore no tracking is + // needed. + return; + } base::UmaHistogramEnumeration(kSubmissionSourceHistogram, source); - for (auto& observer : observers_) - observer.OnInferredFormSubmission(source); - if (source != SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL || - !base::FeatureList::IsEnabled( - features::kAutofillAcceptDomMutationAfterAutofillSubmission)) { - ResetLastInteractedElements(); + agent_->OnFormSubmission(source, submitted_form_element); + switch (source) { + case mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED: + case mojom::SubmissionSource::FORM_SUBMISSION: + if (!base::FeatureList::IsEnabled(features::kAutofillFixFormTracking)) { + ResetLastInteractedElements(); + } + break; + case mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION: + case mojom::SubmissionSource::XHR_SUCCEEDED: + case mojom::SubmissionSource::FRAME_DETACHED: + // TODO(crbug.com/40281981): Figure out if this is still needed, and + // document the reason, otherwise remove. + ResetLastInteractedElements(); + break; + case mojom::SubmissionSource::DOM_MUTATION_AFTER_AUTOFILL: + break; + case mojom::SubmissionSource::NONE: + NOTREACHED(); } } @@ -397,7 +387,7 @@ (submission_triggering_events_.tracked_element_disappeared && base::FeatureList::IsEnabled( features::kAutofillReplaceFormElementObserver))) { - FireInferredFormSubmission(source); + FireFormSubmission(source, /*submitted_form_element=*/std::nullopt); return; } TrackElement(source); @@ -486,7 +476,7 @@ } void FormTracker::ElementWasHiddenOrRemoved(mojom::SubmissionSource source) { - FireInferredFormSubmission(source); + FireFormSubmission(source, /*submitted_form_element=*/std::nullopt); } } // namespace autofill
diff --git a/components/autofill/content/renderer/form_tracker.h b/components/autofill/content/renderer/form_tracker.h index 141a30d..d981359 100644 --- a/components/autofill/content/renderer/form_tracker.h +++ b/components/autofill/content/renderer/form_tracker.h
@@ -5,6 +5,8 @@ #ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_TRACKER_H_ #define COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_TRACKER_H_ +#include <optional> + #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" @@ -70,44 +72,12 @@ class FormTracker : public content::RenderFrameObserver, public blink::WebLocalFrameObserver { public: - // The interface implemented by observer to get notification of form's change - // and submission. - class Observer { - public: - enum class SaveFormReason { - kTextFieldChanged, - // TODO(crbug.com/40281981): Remove after launching the feature - // kAutofillPreferSavedFormAsSubmittedForm. - kWillSendSubmitEvent, - kSelectChanged, - }; - - // TODO(crbug.com/40147954): Find a better name for this method. - // Invoked when form needs to be saved because of |source|, |element| is - // valid if the callback caused by source other than - // WILL_SEND_SUBMIT_EVENT, |form| is valid for the callback caused by - // WILL_SEND_SUBMIT_EVENT. - virtual void OnProvisionallySaveForm( - const blink::WebFormElement& form, - const blink::WebFormControlElement& element, - SaveFormReason source) = 0; - - // Invoked when the form is probably submitted, the submitted form could be - // the one saved in OnProvisionallySaveForm() or others in the page. - virtual void OnProbablyFormSubmitted() = 0; - - // Invoked when |form| is submitted. The submission might not be successful, - // observer needs to check whether the form exists in new page. - virtual void OnFormSubmitted(const blink::WebFormElement& form) = 0; - - // Invoked when tracker infers the last form or element saved in - // OnProvisionallySaveForm() is submitted from the |source|, the tracker - // infers submission from the disappearance of form or element, observer - // might not need to check it again. - virtual void OnInferredFormSubmission(mojom::SubmissionSource source) = 0; - - protected: - virtual ~Observer() = default; + enum class SaveFormReason { + kTextFieldChanged, + // TODO(crbug.com/40281981): Remove after launching the feature + // kAutofillPreferSavedFormAsSubmittedForm. + kWillSendSubmitEvent, + kSelectChanged, }; using UserGestureRequired = @@ -121,9 +91,6 @@ ~FormTracker() override; - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - // Same methods as those in blink::WebAutofillClient, but invoked by // AutofillAgent. void AjaxSucceeded(); @@ -187,10 +154,11 @@ // http://bugs.webkit.org/show_bug.cgi?id=16976 , we also don't want to // process element while it is changing. void FormControlDidChangeImpl(FieldRendererId element_id, - Observer::SaveFormReason change_source); - void FireProbablyFormSubmitted(); - void FireFormSubmitted(const blink::WebFormElement& form); - void FireInferredFormSubmission(mojom::SubmissionSource source); + SaveFormReason change_source); + // Virtual for testing. + virtual void FireFormSubmission( + mojom::SubmissionSource source, + std::optional<blink::WebFormElement> submitted_form_element); void FireSubmissionIfFormDisappear(mojom::SubmissionSource source); bool CanInferFormSubmitted(); @@ -209,7 +177,6 @@ // Whether a user gesture is required to pass on text field change events. const UserGestureRequired user_gesture_required_; - base::ObserverList<Observer>::Unchecked observers_; struct { FormRef form; FieldRef formless_element;
diff --git a/components/autofill/content/renderer/form_tracker_browsertest.cc b/components/autofill/content/renderer/form_tracker_browsertest.cc index a5459c3e5..4aedc26c 100644 --- a/components/autofill/content/renderer/form_tracker_browsertest.cc +++ b/components/autofill/content/renderer/form_tracker_browsertest.cc
@@ -4,10 +4,13 @@ #include "components/autofill/content/renderer/form_tracker.h" +#include <optional> + #include "base/test/scoped_feature_list.h" #include "components/autofill/content/renderer/autofill_agent_test_api.h" #include "components/autofill/content/renderer/autofill_renderer_test.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" @@ -17,16 +20,15 @@ namespace autofill { namespace { -class MockFormTrackerObserver : public FormTracker::Observer { - public: - // Not a mock method so that gmock ignores calls to this method. - void OnProvisionallySaveForm(const blink::WebFormElement&, - const blink::WebFormControlElement&, - SaveFormReason) override {} +using ::testing::_; - MOCK_METHOD0(OnProbablyFormSubmitted, void()); - MOCK_METHOD1(OnFormSubmitted, void(const blink::WebFormElement&)); - MOCK_METHOD1(OnInferredFormSubmission, void(mojom::SubmissionSource)); +class MockFormTracker : public FormTracker { + public: + using FormTracker::FormTracker; + MOCK_METHOD((void), + FireFormSubmission, + (mojom::SubmissionSource, std::optional<blink::WebFormElement>), + (override)); }; class FormTrackerTest : public test::AutofillRendererTest, @@ -47,6 +49,20 @@ features.begin() + GetParam(), features.end()); scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); } + + void SetUp() override { + test::AutofillRendererTest::SetUp(); + test_api(autofill_agent()) + .set_form_tracker(std::make_unique<MockFormTracker>( + GetMainRenderFrame(), FormTracker::UserGestureRequired(true), + autofill_agent())); + } + + MockFormTracker& form_tracker() { + return static_cast<MockFormTracker&>( + test_api(autofill_agent()).form_tracker()); + } + blink::WebFormControlElement GetFormControlById(const std::string& id) { return GetMainFrame() ->GetDocument() @@ -71,23 +87,22 @@ blink::WebFormControlElement input1 = GetFormControlById("input1"); - testing::StrictMock<MockFormTrackerObserver> observer; - test_api(autofill_agent()).form_tracker().AddObserver(&observer); - GetMainFrame()->NotifyUserActivation( blink::mojom::UserActivationNotificationType::kTest); ExecuteJavaScriptForTests("document.getElementById('input1').focus();"); - test_api(autofill_agent()).form_tracker().TextFieldDidChange(input1); + form_tracker().TextFieldDidChange(input1); task_environment_.RunUntilIdle(); - test_api(autofill_agent()).form_tracker().AjaxSucceeded(); + form_tracker().AjaxSucceeded(); task_environment_.RunUntilIdle(); // FormTracker should not think there is a submission because the <input>s are // still visible. // FormTracker should detect a submission after the <input>s are hidden. - EXPECT_CALL(observer, OnInferredFormSubmission).Times(1); + EXPECT_CALL(form_tracker(), + FireFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED, _)) + .Times(1); ExecuteJavaScriptForTests( R"(document.getElementById('input1').style.display = 'none'; document.getElementById('input2').style.display = 'none';)"); @@ -103,13 +118,10 @@ blink::WebFormControlElement input1 = GetFormControlById("input1"); - testing::StrictMock<MockFormTrackerObserver> observer; - test_api(autofill_agent()).form_tracker().AddObserver(&observer); - GetMainFrame()->NotifyUserActivation( blink::mojom::UserActivationNotificationType::kTest); ExecuteJavaScriptForTests("document.getElementById('input1').focus();"); - test_api(autofill_agent()).form_tracker().TextFieldDidChange(input1); + form_tracker().TextFieldDidChange(input1); task_environment_.RunUntilIdle(); ExecuteJavaScriptForTests( @@ -121,8 +133,10 @@ // done any XHRs. // FormTracker should detect a submission when the XHR succeeds. - EXPECT_CALL(observer, OnInferredFormSubmission).Times(1); - test_api(autofill_agent()).form_tracker().AjaxSucceeded(); + EXPECT_CALL(form_tracker(), + FireFormSubmission(mojom::SubmissionSource::XHR_SUCCEEDED, _)) + .Times(1); + form_tracker().AjaxSucceeded(); task_environment_.RunUntilIdle(); }
diff --git a/components/autofill/content/renderer/form_tracker_test_api.h b/components/autofill/content/renderer/form_tracker_test_api.h index 74f9709..747ab4b 100644 --- a/components/autofill/content/renderer/form_tracker_test_api.h +++ b/components/autofill/content/renderer/form_tracker_test_api.h
@@ -5,8 +5,11 @@ #ifndef COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_TRACKER_TEST_API_H_ #define COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_TRACKER_TEST_API_H_ +#include <optional> + #include "base/memory/raw_ref.h" #include "components/autofill/content/renderer/form_tracker.h" +#include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" namespace autofill { @@ -19,7 +22,8 @@ } void FireProbablyFormSubmitted() { - form_tracker_->FireProbablyFormSubmitted(); + form_tracker_->FireFormSubmission( + mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED, std::nullopt); } private:
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index f12bc6d..a4ad863a 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -1073,6 +1073,29 @@ return payment_instrument; } +sync_pb::PaymentInstrument CreatePaymentInstrumentWithLinkedBnplIssuer( + int64_t instrument_id, + std::string issuer_id, + std::string currency, + uint64_t min_price_in_micros, + uint64_t max_price_in_micros) { + sync_pb::PaymentInstrument payment_instrument; + payment_instrument.set_instrument_id(instrument_id); + payment_instrument.add_supported_rails( + sync_pb::PaymentInstrument::SupportedRail:: + PaymentInstrument_SupportedRail_CARD_NUMBER); + + sync_pb::BnplIssuerDetails* bnpl_issuer_details = + payment_instrument.mutable_bnpl_issuer_details(); + bnpl_issuer_details->set_issuer_id(std::move(issuer_id)); + sync_pb::EligiblePriceRange* eligible_price_range = + bnpl_issuer_details->add_eligible_price_range(); + eligible_price_range->set_min_price_in_micros(min_price_in_micros); + eligible_price_range->set_max_price_in_micros(max_price_in_micros); + eligible_price_range->set_currency(std::move(currency)); + return payment_instrument; +} + BnplIssuer GetTestBnplIssuer() { std::vector<BnplIssuer::EligiblePriceRange> eligible_price_ranges; // Currency: USD, price lower bound: $50, price upper bound: $200.
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h index ae3be72..6095474 100644 --- a/components/autofill/core/browser/autofill_test_utils.h +++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -402,6 +402,15 @@ sync_pb::PaymentInstrument CreatePaymentInstrumentWithEwalletAccount( int64_t instrument_id); +// Returns a payment instrument with a linked BNPL issuer based on the data +// provided. +sync_pb::PaymentInstrument CreatePaymentInstrumentWithLinkedBnplIssuer( + int64_t instrument_id, + std::string issuer_id, + std::string currency, + uint64_t min_price_in_micros, + uint64_t max_price_in_micros); + // Returns a BNPL issuer with fake data. BnplIssuer GetTestBnplIssuer();
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc index f87ac93..b80e0a7 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
@@ -15,6 +15,7 @@ #include "components/autofill/core/browser/payments/credit_card_access_manager.h" #include "components/autofill/core/browser/payments/credit_card_access_manager_test_api.h" #include "components/autofill/core/browser/payments/credit_card_cvc_authenticator.h" +#include "components/autofill/core/browser/payments/credit_card_risk_based_authenticator.h" #include "components/autofill/core/browser/payments/iban_save_manager.h" #include "components/autofill/core/browser/payments/payments_autofill_client.h" #include "components/autofill/core/browser/payments/test_payments_autofill_client.h" @@ -165,6 +166,22 @@ payments::PaymentsAutofillClient::PaymentsRpcResult result, const std::string& real_pan, bool is_virtual_card) { + // FPAN risk-based authentication is implemented in some platforms. If + // risk-based authentication is available, simulate a CVC authentication + // challenge is required. + if (autofill_manager() + .GetCreditCardAccessManager() + .IsMaskedServerCardRiskBasedAuthAvailable()) { + autofill_manager() + .GetCreditCardAccessManager() + .OnRiskBasedAuthenticationResponseReceived( + CreditCardRiskBasedAuthenticator::RiskBasedAuthenticationResponse() + .with_result(CreditCardRiskBasedAuthenticator:: + RiskBasedAuthenticationResponse::Result:: + kAuthenticationRequired) + .with_context_token("fake context token")); + } + payments::FullCardRequest* full_card_request = autofill_manager() .client()
diff --git a/components/autofill/core/browser/payments_data_manager.cc b/components/autofill/core/browser/payments_data_manager.cc index 41997b3..dec884d 100644 --- a/components/autofill/core/browser/payments_data_manager.cc +++ b/components/autofill/core/browser/payments_data_manager.cc
@@ -21,6 +21,7 @@ #include "components/autofill/core/browser/data_model/bnpl_issuer.h" #include "components/autofill/core/browser/data_model/credit_card_art_image.h" #include "components/autofill/core/browser/data_model/ewallet.h" +#include "components/autofill/core/browser/data_model/payment_instrument.h" #include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/metrics/autofill_settings_metrics.h" #include "components/autofill/core/browser/metrics/payments/card_metadata_metrics.h" @@ -424,9 +425,11 @@ &pending_payment_instruments_query_, &payment_instruments); ewallet_accounts_.clear(); + linked_bnpl_issuers_.clear(); for (sync_pb::PaymentInstrument& payment_instrument : payment_instruments) { CacheIfEwalletPaymentInstrument(payment_instrument); + CacheIfLinkedBnplPaymentInstrument(payment_instrument); } OnPaymentInstrumentsRefreshed(payment_instruments); break; @@ -793,6 +796,13 @@ return !masked_bank_accounts_.empty(); } +base::span<const BnplIssuer> PaymentsDataManager::GetLinkedBnplIssuers() const { + if (!IsAutofillPaymentMethodsEnabled()) { + return {}; + } + return linked_bnpl_issuers_; +} + bool PaymentsDataManager::HasEwalletAccounts() const { if (!IsAutofillPaymentMethodsEnabled()) { return false; @@ -2020,9 +2030,9 @@ } bool PaymentsDataManager::ArePaymentInstrumentsSupported() const { - // Currently only eWallet accounts are using generic payment instrument proto - // for read from table. - return AreEwalletAccountsSupported(); + // Currently only eWallet accounts and linked BNPL issuers are using generic + // payment instrument proto for read from table. + return AreEwalletAccountsSupported() || AreBnplIssuersSupported(); } bool PaymentsDataManager::ArePaymentInstrumentCreationOptionsSupported() const { @@ -2151,6 +2161,37 @@ } } +void PaymentsDataManager::CacheIfLinkedBnplPaymentInstrument( + sync_pb::PaymentInstrument& payment_instrument) { + if (!payment_instrument.has_bnpl_issuer_details()) { + return; + } + + sync_pb::BnplIssuerDetails bnpl_issuer_details = + payment_instrument.bnpl_issuer_details(); + + std::vector<BnplIssuer::EligiblePriceRange> eligible_price_ranges; + eligible_price_ranges.reserve( + bnpl_issuer_details.eligible_price_range_size()); + for (const auto& eligible_price_range : + bnpl_issuer_details.eligible_price_range()) { + eligible_price_ranges.emplace_back( + eligible_price_range.currency(), + eligible_price_range.min_price_in_micros(), + eligible_price_range.max_price_in_micros()); + } + + // A linked BNPL issuer is only valid if there is at least one eligible price + // range. + if (eligible_price_ranges.empty()) { + return; + } + + linked_bnpl_issuers_.emplace_back(payment_instrument.instrument_id(), + bnpl_issuer_details.issuer_id(), + std::move(eligible_price_ranges)); +} + void PaymentsDataManager::CacheIfEwalletPaymentInstrument( sync_pb::PaymentInstrument& payment_instrument) { if (!payment_instrument.has_ewallet_details()) {
diff --git a/components/autofill/core/browser/payments_data_manager.h b/components/autofill/core/browser/payments_data_manager.h index a8e6965..e4db52f 100644 --- a/components/autofill/core/browser/payments_data_manager.h +++ b/components/autofill/core/browser/payments_data_manager.h
@@ -20,6 +20,7 @@ #include "components/autofill/core/browser/country_type.h" #include "components/autofill/core/browser/data_model/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/autofill_wallet_usage_data.h" +#include "components/autofill/core/browser/data_model/bnpl_issuer.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_benefit.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" @@ -207,6 +208,11 @@ // Returns the masked bank accounts that can be suggested to the user. base::span<const BankAccount> GetMaskedBankAccounts() const; + // Returns the linked BNPL issuers that can be shown to the user. If the "Save + // and fill payment methods" toggle is off, this will return no BNPL issuers + // automatically. + base::span<const BnplIssuer> GetLinkedBnplIssuers() const; + // Returns true if the user has at least 1 eWallet account. bool HasEwalletAccounts() const; // Returns the eWallet accounts that can be suggested to the user. @@ -576,6 +582,9 @@ // Cached versions of the masked bank accounts. std::vector<BankAccount> masked_bank_accounts_; + // Cached versions of the linked BNPL issuers. + std::vector<BnplIssuer> linked_bnpl_issuers_; + // Cached versions of the eWallet accounts. std::vector<Ewallet> ewallet_accounts_; @@ -689,6 +698,11 @@ void OnPaymentInstrumentsRefreshed( const std::vector<sync_pb::PaymentInstrument>& payment_instruments); + // If a payment instrument contains linked BNPL issuer details, caches the + // relevant information in `linked_bnpl_issuers_`. + void CacheIfLinkedBnplPaymentInstrument( + sync_pb::PaymentInstrument& payment_instrument); + // Checks whether a payment instrument contains eWallet details. If yes, // caches relevant information in `ewallet_accounts_`. void CacheIfEwalletPaymentInstrument(
diff --git a/components/autofill/core/browser/payments_data_manager_unittest.cc b/components/autofill/core/browser/payments_data_manager_unittest.cc index 704ec29..47de721f 100644 --- a/components/autofill/core/browser/payments_data_manager_unittest.cc +++ b/components/autofill/core/browser/payments_data_manager_unittest.cc
@@ -32,6 +32,7 @@ #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/data_model/bank_account.h" +#include "components/autofill/core/browser/data_model/bnpl_issuer.h" #include "components/autofill/core/browser/data_model/credit_card_art_image.h" #include "components/autofill/core/browser/data_model/credit_card_benefit_test_api.h" #include "components/autofill/core/browser/data_model/ewallet.h" @@ -2307,6 +2308,147 @@ } #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ + BUILDFLAG(IS_CHROMEOS) +// Tests that no linked BNPL issuers are returned if the BNPL sync flag is off. +TEST_F(PaymentsDataManagerTest, GetLinkedBnplIssuers_FlagOff) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + features::kAutofillEnableBuyNowPayLaterSyncing); + sync_pb::PaymentInstrument payment_instrument = + test::CreatePaymentInstrumentWithLinkedBnplIssuer( + 1234L, /*issuer_id=*/"some_bnpl_issuer", "USD", + /*min_price_in_micros=*/0, + /*max_price_in_micros=*/35000000); + ASSERT_TRUE( + GetServerDataTable()->SetPaymentInstruments({payment_instrument})); + + base::span<const BnplIssuer> linked_bnpl_issuers = + payments_data_manager().GetLinkedBnplIssuers(); + // Since the PaymentsDataManager was initialized before adding the linked BNPL + // issuer payment instruments to the WebDatabase, `GetLinkedBnplIssuers()` is + // expected to return an empty list. + EXPECT_TRUE(linked_bnpl_issuers.empty()); + + // Refresh the PaymentsDataManager. Under normal circumstances with the flag + // on, this step would load the linked BNPL issuers from the WebDatabase. + payments_data_manager().Refresh(); + WaitForOnPaymentsDataChanged(); + + // Verify that no linked BNPL issuers are loaded into PaymentsDataManager + // because the experiment is turned off. + EXPECT_TRUE(payments_data_manager().GetLinkedBnplIssuers().empty()); +} + +// Tests that no linked BNPL issuers are returned if the "Save and fill payment +// methods" toggle is off. +TEST_F(PaymentsDataManagerTest, GetLinkedBnplIssuers_PaymentMethodsDisabled) { + base::test::ScopedFeatureList scoped_feature_list( + features::kAutofillEnableBuyNowPayLaterSyncing); + sync_pb::PaymentInstrument payment_instrument_1 = + test::CreatePaymentInstrumentWithLinkedBnplIssuer( + 1234L, /*issuer_id=*/"some_bnpl_issuer", "USD", + /*min_price_in_micros=*/0, + /*max_price_in_micros=*/35000000); + sync_pb::PaymentInstrument payment_instrument_2 = + test::CreatePaymentInstrumentWithLinkedBnplIssuer( + 2345L, /*issuer_id=*/"zip", "USD", /*min_price_in_micros=*/0, + /*max_price_in_micros=*/35000000); + ASSERT_TRUE(GetServerDataTable()->SetPaymentInstruments( + {payment_instrument_1, payment_instrument_2})); + + // `Refresh()` must be called to ensure that the linked BNPL issuer payment + // instruments are loaded again from the WebDatabase. + payments_data_manager().Refresh(); + WaitForOnPaymentsDataChanged(); + + // Disable payment methods prefs. + prefs::SetAutofillPaymentMethodsEnabled(prefs_.get(), false); + + // Verify that no linked BNPL issuers are loaded into PaymentsDataManager + // because the AutofillPaymentMethodsEnabled pref is set to false. + EXPECT_TRUE(payments_data_manager().GetLinkedBnplIssuers().empty()); +} + +// If the conditions are met to return a linked BNPL issuer, this test ensures +// it is returned and verifies that they had the expected values upon returning. +TEST_F(PaymentsDataManagerTest, GetLinkedBnplIssuers) { + base::test::ScopedFeatureList scoped_feature_list( + features::kAutofillEnableBuyNowPayLaterSyncing); + int64_t instrument_id = 1234L; + std::string issuer_id = "some_bnpl_issuer"; + std::string currency = "USD"; + uint64_t min_price_in_micros = 50000000; + uint64_t max_price_in_micros = 35000000; + sync_pb::PaymentInstrument payment_instrument = + test::CreatePaymentInstrumentWithLinkedBnplIssuer( + instrument_id, issuer_id, currency, min_price_in_micros, + max_price_in_micros); + ASSERT_TRUE( + GetServerDataTable()->SetPaymentInstruments({payment_instrument})); + + // Since the PaymentsDataManager was initialized before adding the linked BNPL + // issuer payment instruments to the WebDatabase, `GetLinkedBnplIssuers()` is + // expected to return an empty list. + base::span<const BnplIssuer> linked_bnpl_issuers = + payments_data_manager().GetLinkedBnplIssuers(); + EXPECT_TRUE(linked_bnpl_issuers.empty()); + + // `Refresh()` must be called to ensure that the linked BNPL issuer payment + // instruments are loaded again from the WebDatabase. + payments_data_manager().Refresh(); + WaitForOnPaymentsDataChanged(); + + linked_bnpl_issuers = payments_data_manager().GetLinkedBnplIssuers(); + + ASSERT_EQ(linked_bnpl_issuers.size(), 1U); + EXPECT_EQ(linked_bnpl_issuers[0], + BnplIssuer(instrument_id, issuer_id, + /*eligible_price_ranges=*/ + {BnplIssuer::EligiblePriceRange( + currency, /*price_lower_bound=*/min_price_in_micros, + /*price_upper_bound=*/max_price_in_micros)})); +} + +// If the conditions are met to return a linked BNPL issuer, but it does not +// have an eligible price range this test ensures it is not returned. +TEST_F(PaymentsDataManagerTest, GetLinkedBnplIssuers_NoEligiblePriceRange) { + base::test::ScopedFeatureList scoped_feature_list( + features::kAutofillEnableBuyNowPayLaterSyncing); + int64_t instrument_id = 1234L; + std::string issuer_id = "some_bnpl_issuer"; + std::string currency = "USD"; + uint64_t min_price_in_micros = 50000000; + uint64_t max_price_in_micros = 35000000; + sync_pb::PaymentInstrument payment_instrument = + test::CreatePaymentInstrumentWithLinkedBnplIssuer( + instrument_id, issuer_id, currency, min_price_in_micros, + max_price_in_micros); + sync_pb::BnplIssuerDetails* bnpl_issuer_details = + payment_instrument.mutable_bnpl_issuer_details(); + bnpl_issuer_details->clear_eligible_price_range(); + ASSERT_TRUE( + GetServerDataTable()->SetPaymentInstruments({payment_instrument})); + + // Since the PaymentsDataManager was initialized before adding the linked BNPL + // issuer payment instruments to the WebDatabase, `GetLinkedBnplIssuers()` is + // expected to return an empty list. + base::span<const BnplIssuer> linked_bnpl_issuers = + payments_data_manager().GetLinkedBnplIssuers(); + EXPECT_TRUE(linked_bnpl_issuers.empty()); + + // `Refresh()` must be called to ensure that the linked BNPL issuer payment + // instruments are loaded again from the WebDatabase. + payments_data_manager().Refresh(); + WaitForOnPaymentsDataChanged(); + + linked_bnpl_issuers = payments_data_manager().GetLinkedBnplIssuers(); + + EXPECT_TRUE(linked_bnpl_issuers.empty()); +} +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || + // BUILDFLAG(IS_CHROMEOS) + TEST_F(PaymentsDataManagerTest, OnBenefitsPrefChange_PrefIsOn_LoadsCardBenefits) { // Add the card benefits to the web database.
diff --git a/components/autofill/core/browser/webdata/payments/payments_sync_bridge_test_util.cc b/components/autofill/core/browser/webdata/payments/payments_sync_bridge_test_util.cc index 44e3eb0..367f560 100644 --- a/components/autofill/core/browser/webdata/payments/payments_sync_bridge_test_util.cc +++ b/components/autofill/core/browser/webdata/payments/payments_sync_bridge_test_util.cc
@@ -5,6 +5,7 @@ #include "components/autofill/core/browser/webdata/payments/payments_sync_bridge_test_util.h" #include "base/strings/string_number_conversions.h" +#include "components/autofill/core/browser/autofill_test_utils.h" namespace autofill { @@ -182,21 +183,10 @@ sync_pb::PaymentInstrument* payment_instrument_specifics = wallet_specifics.mutable_payment_instrument(); - - payment_instrument_specifics->set_instrument_id(instrument_id); - - sync_pb::BnplIssuerDetails* bnpl_issuer_details = - payment_instrument_specifics->mutable_bnpl_issuer_details(); - bnpl_issuer_details->set_issuer_id(std::move(issuer_id)); - sync_pb::EligiblePriceRange* eligible_price_range = - bnpl_issuer_details->add_eligible_price_range(); - eligible_price_range->set_currency(currency); - eligible_price_range->set_min_price_in_micros(price_lower_bound); - eligible_price_range->set_max_price_in_micros(price_upper_bound); - - payment_instrument_specifics->add_supported_rails( - sync_pb::PaymentInstrument_SupportedRail:: - PaymentInstrument_SupportedRail_CARD_NUMBER); + *payment_instrument_specifics = + test::CreatePaymentInstrumentWithLinkedBnplIssuer( + instrument_id, std::move(issuer_id), std::move(currency), + price_lower_bound, price_upper_bound); return wallet_specifics; }
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc index 74a582e..bbc8920 100644 --- a/components/autofill/core/common/autofill_payments_features.cc +++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -125,7 +125,11 @@ // instead of jumping straight to CVC or biometric auth. BASE_FEATURE(kAutofillEnableFpanRiskBasedAuthentication, "AutofillEnableFpanRiskBasedAuthentication", +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT); +#else base::FEATURE_DISABLED_BY_DEFAULT); +#endif // When enabled, the Virtual Card enrollment bottom sheet uses the Java // payments data manager and associated image fetcher to retrieve the cached
diff --git a/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.cc b/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.cc index 8a01c1e7..b9ff4fa7 100644 --- a/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.cc +++ b/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.cc
@@ -4,6 +4,7 @@ #include "components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.h" +#include <cmath> #include <optional> #include <vector> @@ -16,6 +17,8 @@ #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/unique_ids.h" #include "components/autofill_ai/core/browser/autofill_ai_features.h" +#include "components/optimization_guide/core/model_quality/model_execution_logging_wrappers.h" +#include "components/optimization_guide/core/model_quality/model_quality_logs_uploader_service.h" #include "components/optimization_guide/core/optimization_guide_proto_util.h" #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/proto/features/common_quality_data.pb.h" @@ -27,11 +30,15 @@ AutofillAiModelExecutorImpl::AutofillAiModelExecutorImpl( optimization_guide::OptimizationGuideModelExecutor* model_executor, + optimization_guide::ModelQualityLogsUploaderService* logs_uploader, user_annotations::UserAnnotationsService* user_annotations_service) : model_executor_(model_executor), user_annotations_service_(user_annotations_service) { CHECK(model_executor_); CHECK(user_annotations_service_); + if (logs_uploader) { + logs_uploader_ = logs_uploader->GetWeakPtr(); + } } AutofillAiModelExecutorImpl::~AutofillAiModelExecutorImpl() = default; @@ -83,22 +90,29 @@ std::make_move_iterator(user_annotations.end())}; SetLatestRequestForDebugging(request); - model_executor_->ExecuteModel( + optimization_guide::ModelExecutionCallbackWithLogging< + optimization_guide::proto::FormsPredictionsLoggingData> + wrapper_callback = + base::BindOnce(&AutofillAiModelExecutorImpl::OnModelExecuted, + weak_ptr_factory_.GetWeakPtr(), std::move(form_data), + std::move(callback)); + optimization_guide::ExecuteModelWithLogging( + model_executor_, optimization_guide::ModelBasedCapabilityKey::kFormsPredictions, request, - kExecutionTimeout.Get(), - base::BindOnce(&AutofillAiModelExecutorImpl::OnModelExecuted, - weak_ptr_factory_.GetWeakPtr(), std::move(form_data), - std::move(callback))); + kExecutionTimeout.Get(), std::move(wrapper_callback)); } void AutofillAiModelExecutorImpl::OnModelExecuted( autofill::FormData form_data, PredictionsReceivedCallback callback, optimization_guide::OptimizationGuideModelExecutionResult execution_result, - std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry) { + std::unique_ptr<optimization_guide::proto::FormsPredictionsLoggingData> + logging_data) { + CHECK(logging_data); + auto log_entry = std::make_unique<optimization_guide::ModelQualityLogEntry>( + logs_uploader_); const std::optional<std::string> execution_id = - log_entry ? log_entry->model_execution_id() - : std::optional<std::string>(); + logging_data->model_execution_info().execution_id(); if (!execution_result.response.has_value()) { std::move(callback).Run(base::unexpected(false), execution_id); return;
diff --git a/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.h b/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.h index 4ec5e3e..d8b79619 100644 --- a/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.h +++ b/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/types/expected.h" #include "components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor.h" +#include "components/optimization_guide/core/model_quality/model_quality_logs_uploader_service.h" #include "components/optimization_guide/core/optimization_guide_model_executor.h" #include "components/optimization_guide/proto/features/forms_predictions.pb.h" #include "components/user_annotations/user_annotations_types.h" @@ -35,6 +36,7 @@ public: AutofillAiModelExecutorImpl( optimization_guide::OptimizationGuideModelExecutor* model_executor, + optimization_guide::ModelQualityLogsUploaderService* logs_uploader, user_annotations::UserAnnotationsService* user_annotations_service); ~AutofillAiModelExecutorImpl() override; @@ -68,7 +70,8 @@ PredictionsReceivedCallback callback, optimization_guide::OptimizationGuideModelExecutionResult execution_result, - std::unique_ptr<optimization_guide::ModelQualityLogEntry> log_entry); + std::unique_ptr<optimization_guide::proto::FormsPredictionsLoggingData> + logging_data); static PredictionsByGlobalId ExtractPredictions( const autofill::FormData& form_data, @@ -96,6 +99,8 @@ raw_ptr<optimization_guide::OptimizationGuideModelExecutor> model_executor_ = nullptr; + base::WeakPtr<optimization_guide::ModelQualityLogsUploaderService> + logs_uploader_; raw_ptr<user_annotations::UserAnnotationsService> user_annotations_service_ = nullptr;
diff --git a/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl_unittest.cc b/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl_unittest.cc index d6e0367..470e5582 100644 --- a/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl_unittest.cc +++ b/components/autofill_ai/core/browser/suggestion/autofill_ai_model_executor_impl_unittest.cc
@@ -14,9 +14,11 @@ #include "components/autofill/core/common/form_data.h" #include "components/autofill_ai/core/browser/autofill_ai_test_utils.h" #include "components/optimization_guide/core/mock_optimization_guide_model_executor.h" +#include "components/optimization_guide/core/model_quality/test_model_quality_logs_uploader_service.h" #include "components/optimization_guide/core/optimization_guide_proto_util.h" #include "components/optimization_guide/proto/features/common_quality_data.pb.h" #include "components/optimization_guide/proto/features/forms_predictions.pb.h" +#include "components/prefs/testing_pref_service.h" #include "components/user_annotations/test_user_annotations_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -60,10 +62,19 @@ class AutofillAiModelExecutorImplTest : public testing::Test { public: void SetUp() override { + logs_uploader_ = std::make_unique< + optimization_guide::TestModelQualityLogsUploaderService>(&local_state_); user_annotations_service_ = std::make_unique<user_annotations::TestUserAnnotationsService>(); engine_ = std::make_unique<AutofillAiModelExecutorImpl>( - &model_executor_, user_annotations_service_.get()); + &model_executor_, logs_uploader_.get(), + user_annotations_service_.get()); + } + + void TearDown() override { + // Reset the logs uploader to avoid keeping a dangling pointer to the local + // state during destruction. + logs_uploader_ = nullptr; } AutofillAiModelExecutorImpl* engine() { return engine_.get(); } @@ -84,6 +95,9 @@ std::unique_ptr<user_annotations::TestUserAnnotationsService> user_annotations_service_; std::unique_ptr<AutofillAiModelExecutorImpl> engine_; + std::unique_ptr<optimization_guide::TestModelQualityLogsUploaderService> + logs_uploader_; + TestingPrefServiceSimple local_state_; }; TEST_F(AutofillAiModelExecutorImplTest, EndToEnd) {
diff --git a/components/collaboration/internal/BUILD.gn b/components/collaboration/internal/BUILD.gn index 5fddee3..107aba6 100644 --- a/components/collaboration/internal/BUILD.gn +++ b/components/collaboration/internal/BUILD.gn
@@ -165,6 +165,7 @@ ":messaging_internal", "//base", "//base/test:test_support", + "//components/collaboration/internal/messaging/storage/protocol", "//components/data_sharing:test_support", "//components/data_sharing/public", "//components/saved_tab_groups/public",
diff --git a/components/collaboration/internal/messaging/data_sharing_change_notifier.h b/components/collaboration/internal/messaging/data_sharing_change_notifier.h index be10aa29..7f7ae77f 100644 --- a/components/collaboration/internal/messaging/data_sharing_change_notifier.h +++ b/components/collaboration/internal/messaging/data_sharing_change_notifier.h
@@ -46,11 +46,11 @@ const base::Time& event_time) {} // Called when a new member has been added to the group. - virtual void OnGroupMemberAdded(const data_sharing::GroupData& group_id, + virtual void OnGroupMemberAdded(const data_sharing::GroupData& group_data, const GaiaId& member_gaia_id, const base::Time& event_time) {} // Called when a member has been removed from the group. - virtual void OnGroupMemberRemoved(const data_sharing::GroupData& group_id, + virtual void OnGroupMemberRemoved(const data_sharing::GroupData& group_data, const GaiaId& member_gaia_id, const base::Time& event_time) {} };
diff --git a/components/collaboration/internal/messaging/messaging_backend_service_impl.cc b/components/collaboration/internal/messaging/messaging_backend_service_impl.cc index f759608..60d5ba4 100644 --- a/components/collaboration/internal/messaging/messaging_backend_service_impl.cc +++ b/components/collaboration/internal/messaging/messaging_backend_service_impl.cc
@@ -12,13 +12,189 @@ #include "base/check.h" #include "base/functional/callback.h" +#include "base/strings/utf_string_conversions.h" #include "components/collaboration/internal/messaging/data_sharing_change_notifier_impl.h" +#include "components/collaboration/internal/messaging/storage/collaboration_message_util.h" #include "components/collaboration/internal/messaging/storage/messaging_backend_store.h" +#include "components/collaboration/internal/messaging/storage/protocol/message.pb.h" #include "components/collaboration/internal/messaging/tab_group_change_notifier.h" +#include "components/collaboration/public/messaging/activity_log.h" #include "components/collaboration/public/messaging/message.h" +#include "components/data_sharing/public/group_data.h" #include "components/saved_tab_groups/public/types.h" namespace collaboration::messaging { +namespace { +collaboration_pb::Message CreateMessage( + const data_sharing::GroupId& collaboration_group_id, + collaboration_pb::EventType event_type, + DirtyType dirty_type, + const base::Time& event_time) { + collaboration_pb::Message message; + message.set_uuid(base::Uuid::GenerateRandomV4().AsLowercaseString()); + message.set_collaboration_id(collaboration_group_id.value()); + message.set_event_type(event_type); + message.set_dirty(static_cast<int>(dirty_type)); + message.set_event_timestamp(event_time.ToTimeT()); + return message; +} + +collaboration_pb::Message CreateTabGroupMessage( + data_sharing::GroupId collaboration_group_id, + const tab_groups::SavedTabGroup& tab_group, + collaboration_pb::EventType event_type, + DirtyType dirty_type) { + collaboration_pb::Message message = + CreateMessage(collaboration_group_id, event_type, dirty_type, + tab_group.update_time_windows_epoch_micros()); + message.mutable_tab_group_data()->set_sync_tab_group_id( + tab_group.saved_guid().AsLowercaseString()); + switch (event_type) { + case collaboration_pb::TAB_GROUP_ADDED: + message.set_triggering_user_gaia_id( + tab_group.shared_attribution().created_by.ToString()); + break; + case collaboration_pb::TAB_GROUP_REMOVED: + case collaboration_pb::TAB_GROUP_NAME_UPDATED: + case collaboration_pb::TAB_GROUP_COLOR_UPDATED: + message.set_triggering_user_gaia_id( + tab_group.shared_attribution().updated_by.ToString()); + break; + default: + break; + } + return message; +} + +collaboration_pb::Message CreateTabMessage( + data_sharing::GroupId collaboration_group_id, + const tab_groups::SavedTabGroupTab& tab, + collaboration_pb::EventType event_type, + DirtyType dirty_type) { + collaboration_pb::Message message = + CreateMessage(collaboration_group_id, event_type, dirty_type, + event_type == collaboration_pb::TAB_ADDED + ? tab.creation_time_windows_epoch_micros() + : tab.update_time_windows_epoch_micros()); + message.mutable_tab_data()->set_sync_tab_id( + tab.saved_tab_guid().AsLowercaseString()); + message.mutable_tab_data()->set_sync_tab_group_id( + tab.saved_group_guid().AsLowercaseString()); + message.mutable_tab_data()->set_last_url(tab.url().spec()); + switch (event_type) { + case collaboration_pb::TAB_ADDED: + message.set_triggering_user_gaia_id( + tab.shared_attribution().created_by.ToString()); + break; + case collaboration_pb::TAB_UPDATED: + case collaboration_pb::TAB_REMOVED: + message.set_triggering_user_gaia_id( + tab.shared_attribution().updated_by.ToString()); + break; + default: + break; + } + return message; +} + +CollaborationEvent ToCollaborationEvent( + collaboration_pb::EventType event_type) { + switch (event_type) { + case collaboration_pb::TAB_ADDED: + return CollaborationEvent::TAB_ADDED; + case collaboration_pb::TAB_REMOVED: + return CollaborationEvent::TAB_REMOVED; + case collaboration_pb::TAB_UPDATED: + return CollaborationEvent::TAB_UPDATED; + case collaboration_pb::TAB_GROUP_ADDED: + return CollaborationEvent::TAB_GROUP_ADDED; + case collaboration_pb::TAB_GROUP_REMOVED: + return CollaborationEvent::TAB_GROUP_REMOVED; + case collaboration_pb::TAB_GROUP_NAME_UPDATED: + return CollaborationEvent::TAB_GROUP_NAME_UPDATED; + case collaboration_pb::TAB_GROUP_COLOR_UPDATED: + return CollaborationEvent::TAB_GROUP_COLOR_UPDATED; + case collaboration_pb::COLLABORATION_ADDED: + return CollaborationEvent::COLLABORATION_ADDED; + case collaboration_pb::COLLABORATION_REMOVED: + return CollaborationEvent::COLLABORATION_REMOVED; + case collaboration_pb::COLLABORATION_MEMBER_ADDED: + return CollaborationEvent::COLLABORATION_MEMBER_ADDED; + case collaboration_pb::COLLABORATION_MEMBER_REMOVED: + return CollaborationEvent::COLLABORATION_MEMBER_REMOVED; + default: + return CollaborationEvent::UNDEFINED; + } +} + +RecentActivityAction GetRecentActivityActionFromCollaborationEvent( + CollaborationEvent event) { + switch (event) { + case CollaborationEvent::TAB_ADDED: + case CollaborationEvent::TAB_UPDATED: + return RecentActivityAction::kFocusTab; + case CollaborationEvent::TAB_REMOVED: + return RecentActivityAction::kReopenTab; + case CollaborationEvent::TAB_GROUP_ADDED: + case CollaborationEvent::TAB_GROUP_REMOVED: + return RecentActivityAction::kNone; + case CollaborationEvent::TAB_GROUP_NAME_UPDATED: + case CollaborationEvent::TAB_GROUP_COLOR_UPDATED: + return RecentActivityAction::kOpenTabGroupEditDialog; + case CollaborationEvent::COLLABORATION_ADDED: + case CollaborationEvent::COLLABORATION_REMOVED: + return RecentActivityAction::kNone; + case CollaborationEvent::COLLABORATION_MEMBER_ADDED: + case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: + return RecentActivityAction::kManageSharing; + case CollaborationEvent::UNDEFINED: + return RecentActivityAction::kNone; + } +} + +std::optional<GaiaId> GetGaiaIdFromMessage( + const collaboration_pb::Message& message) { + switch (GetMessageCategory(message)) { + case MessageCategory::kTab: + case MessageCategory::kTabGroup: + if (message.triggering_user_gaia_id().empty()) { + return std::nullopt; + } + return GaiaId(message.triggering_user_gaia_id()); + case MessageCategory::kCollaboration: + if (message.affected_user_gaia_id().empty()) { + return std::nullopt; + } + return GaiaId(message.affected_user_gaia_id()); + default: + return std::nullopt; + } +} + +std::optional<data_sharing::GroupId> GroupIdForTabGroup( + const tab_groups::SavedTabGroup& tab_group) { + if (!tab_group.collaboration_id()) { + return std::nullopt; + } + return data_sharing::GroupId(tab_group.collaboration_id().value().value()); +} + +tab_groups::CollaborationId ToCollaborationId( + const data_sharing::GroupId& group_id) { + return tab_groups::CollaborationId(group_id.value()); +} + +TabGroupMessageMetadata CreateTabGroupMessageMetadata( + const tab_groups::SavedTabGroup& tab_group) { + TabGroupMessageMetadata metadata; + metadata.local_tab_group_id = tab_group.local_group_id(); + metadata.sync_tab_group_id = tab_group.saved_guid(); + metadata.last_known_title = base::UTF16ToUTF8(tab_group.title()); + metadata.last_known_color = tab_group.color(); + return metadata; +} + +} // namespace MessagingBackendServiceImpl::MessagingBackendServiceImpl( std::unique_ptr<TabGroupChangeNotifier> tab_group_change_notifier, @@ -84,9 +260,25 @@ std::vector<ActivityLogItem> MessagingBackendServiceImpl::GetActivityLog( const ActivityLogQueryParams& params) { - // TODO(345856704): Implement this and DCHECK(IsInitialized()) and update - // interface description. - return std::vector<ActivityLogItem>(); + std::vector<ActivityLogItem> result; + std::vector<collaboration_pb::Message> messages = + store_->GetRecentMessagesForGroup(params.collaboration_id); + int message_count = 0; + for (const auto& message : messages) { + std::optional<ActivityLogItem> activity_log_item = + ConvertMessageToActivityLogItem(message); + if (!activity_log_item) { + continue; + } + result.emplace_back(*activity_log_item); + if (params.result_length == 0) { + continue; + } + if (++message_count >= params.result_length) { + break; + } + } + return result; } void MessagingBackendServiceImpl::OnStoreInitialized(bool success) { @@ -114,27 +306,355 @@ } void MessagingBackendServiceImpl::OnTabGroupAdded( - const tab_groups::SavedTabGroup& added_group) {} + const tab_groups::SavedTabGroup& added_group) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GroupIdForTabGroup(added_group); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab group. + return; + } + + collaboration_pb::Message message = CreateTabGroupMessage( + *collaboration_group_id, added_group, collaboration_pb::TAB_GROUP_ADDED, + DirtyType::kNone); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabGroupRemoved( - tab_groups::SavedTabGroup removed_group) {} + tab_groups::SavedTabGroup removed_group) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GroupIdForTabGroup(removed_group); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab group. + return; + } + + collaboration_pb::Message message = CreateTabGroupMessage( + *collaboration_group_id, removed_group, + collaboration_pb::TAB_GROUP_REMOVED, DirtyType::kNone); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabGroupNameUpdated( - const tab_groups::SavedTabGroup& updated_group) {} + const tab_groups::SavedTabGroup& updated_group) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GroupIdForTabGroup(updated_group); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab group. + return; + } + + collaboration_pb::Message message = CreateTabGroupMessage( + *collaboration_group_id, updated_group, + collaboration_pb::TAB_GROUP_NAME_UPDATED, DirtyType::kNone); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabGroupColorUpdated( - const tab_groups::SavedTabGroup& updated_group) {} + const tab_groups::SavedTabGroup& updated_group) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GroupIdForTabGroup(updated_group); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab group. + return; + } + + collaboration_pb::Message message = CreateTabGroupMessage( + *collaboration_group_id, updated_group, + collaboration_pb::TAB_GROUP_COLOR_UPDATED, DirtyType::kNone); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabAdded( - const tab_groups::SavedTabGroupTab& added_tab) {} + const tab_groups::SavedTabGroupTab& added_tab) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GetCollaborationGroupIdForTab(added_tab); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab. + return; + } + + collaboration_pb::Message message = + CreateTabMessage(*collaboration_group_id, added_tab, + collaboration_pb::TAB_ADDED, DirtyType::kDotAndChip); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabRemoved( - tab_groups::SavedTabGroupTab removed_tab) {} + tab_groups::SavedTabGroupTab removed_tab) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GetCollaborationGroupIdForTab(removed_tab); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab. + return; + } + + collaboration_pb::Message message = + CreateTabMessage(*collaboration_group_id, removed_tab, + collaboration_pb::TAB_REMOVED, DirtyType::kNone); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabUpdated( - const tab_groups::SavedTabGroupTab& updated_tab) {} + const tab_groups::SavedTabGroupTab& updated_tab) { + std::optional<data_sharing::GroupId> collaboration_group_id = + GetCollaborationGroupIdForTab(updated_tab); + if (!collaboration_group_id) { + // Unable to find collaboration ID from tab. + return; + } + + collaboration_pb::Message message = + CreateTabMessage(*collaboration_group_id, updated_tab, + collaboration_pb::TAB_UPDATED, DirtyType::kDotAndChip); + store_->AddMessage(message); +} void MessagingBackendServiceImpl::OnTabSelected( std::optional<tab_groups::SavedTabGroupTab> selected_tab) {} +void MessagingBackendServiceImpl::OnGroupAdded( + const data_sharing::GroupId& group_id, + const std::optional<data_sharing::GroupData>& group_data, + const base::Time& event_time) { + collaboration_pb::Message message = + CreateMessage(group_id, collaboration_pb::COLLABORATION_ADDED, + DirtyType::kNone, event_time); + store_->AddMessage(message); +} + +void MessagingBackendServiceImpl::OnGroupRemoved( + const data_sharing::GroupId& group_id, + const std::optional<data_sharing::GroupData>& group_data, + const base::Time& event_time) { + collaboration_pb::Message message = + CreateMessage(group_id, collaboration_pb::COLLABORATION_REMOVED, + DirtyType::kMessageOnly, event_time); + store_->AddMessage(message); +} + +void MessagingBackendServiceImpl::OnGroupMemberAdded( + const data_sharing::GroupData& group_data, + const GaiaId& member_gaia_id, + const base::Time& event_time) { + collaboration_pb::Message message = + CreateMessage(group_data.group_token.group_id, + collaboration_pb::COLLABORATION_MEMBER_ADDED, + DirtyType::kMessageOnly, event_time); + message.set_affected_user_gaia_id(member_gaia_id.ToString()); + std::optional<std::string> user_display_name = + GetDisplayNameForUserInGroup(group_data.group_token.group_id, + member_gaia_id, group_data, std::nullopt); + if (user_display_name) { + message.mutable_collaboration_data()->set_affected_user_name( + *user_display_name); + } + store_->AddMessage(message); +} + +void MessagingBackendServiceImpl::OnGroupMemberRemoved( + const data_sharing::GroupData& group_data, + const GaiaId& member_gaia_id, + const base::Time& event_time) { + collaboration_pb::Message message = + CreateMessage(group_data.group_token.group_id, + collaboration_pb::COLLABORATION_MEMBER_REMOVED, + DirtyType::kNone, event_time); + message.set_affected_user_gaia_id(member_gaia_id.ToString()); + std::optional<std::string> user_display_name = + GetDisplayNameForUserInGroup(group_data.group_token.group_id, + member_gaia_id, group_data, std::nullopt); + if (user_display_name) { + message.mutable_collaboration_data()->set_affected_user_name( + *user_display_name); + } + store_->AddMessage(message); +} + +std::optional<std::string> +MessagingBackendServiceImpl::GetDisplayNameForUserInGroup( + const data_sharing::GroupId& group_id, + const GaiaId& gaia_id, + const std::optional<data_sharing::GroupData>& group_data, + const std::optional<collaboration_pb::Message>& db_message) { + std::optional<data_sharing::GroupMemberPartialData> group_member_data = + data_sharing_service_->GetPossiblyRemovedGroupMember(group_id, gaia_id); + // Try given name from live data first. + if (group_member_data && !group_member_data->given_name.empty()) { + return group_member_data->given_name; + } + + // Then try given name from provided data. + if (group_data) { + for (const data_sharing::GroupMember& member : group_data->members) { + if (member.gaia_id == gaia_id) { + if (member.given_name.empty()) { + break; + } + return member.given_name; + } + } + } + + // Then try given name from stored data. + if (db_message) { + if (db_message->affected_user_gaia_id() == gaia_id.ToString()) { + if (!db_message->collaboration_data().affected_user_name().empty()) { + return db_message->collaboration_data().affected_user_name(); + } + } + } + + // Then try display name from live data. + if (group_member_data && !group_member_data->display_name.empty()) { + return group_member_data->display_name; + } + + // Then try display name from provided data. + if (group_data) { + for (const data_sharing::GroupMember& member : group_data->members) { + if (member.gaia_id == gaia_id) { + if (member.display_name.empty()) { + break; + } + return member.display_name; + } + } + } + + return std::nullopt; +} + +std::optional<ActivityLogItem> +MessagingBackendServiceImpl::ConvertMessageToActivityLogItem( + const collaboration_pb::Message& message) { + switch (message.event_type()) { + case collaboration_pb::TAB_GROUP_ADDED: + case collaboration_pb::TAB_GROUP_REMOVED: + case collaboration_pb::COLLABORATION_ADDED: + case collaboration_pb::COLLABORATION_REMOVED: + return std::nullopt; + default: + break; + } + ActivityLogItem item; + item.collaboration_event = ToCollaborationEvent(message.event_type()); + data_sharing::GroupId collaboration_group_id(message.collaboration_id()); + + std::optional<GaiaId> gaia_id = GetGaiaIdFromMessage(message); + std::optional<data_sharing::GroupMember> group_member; + if (gaia_id) { + std::optional<std::string> user_name_for_display = + GetDisplayNameForUserInGroup(collaboration_group_id, *gaia_id, + std::nullopt, message); + if (user_name_for_display) { + item.user_display_name = *user_name_for_display; + } + std::optional<data_sharing::GroupMemberPartialData> group_member_data = + data_sharing_service_->GetPossiblyRemovedGroupMember( + collaboration_group_id, *gaia_id); + if (group_member_data) { + group_member = group_member_data->ToGroupMember(); + } + } + + // TODO(nyquist): Compare GaiaId with current user in this profile. + item.user_is_self = false; + + item.description = GetDescriptionTextForActivityLogItem(message); + item.time_delta = + base::Time::Now() - base::Time::FromTimeT(message.event_timestamp()); + item.action = + GetRecentActivityActionFromCollaborationEvent(item.collaboration_event); + + item.activity_metadata = MessageAttribution(); + item.activity_metadata.collaboration_id = collaboration_group_id; + + // The code below needs to fill in `activity_metadata`, and optionally + // `show_favicon` if it is true. + switch (GetMessageCategory(message)) { + case MessageCategory::kTab: + break; + case MessageCategory::kTabGroup: { + item.activity_metadata.triggering_user = group_member; + std::optional<tab_groups::SavedTabGroup> tab_group = + tab_group_sync_service_->GetGroup(base::Uuid::ParseLowercase( + message.tab_group_data().sync_tab_group_id())); + if (tab_group) { + item.activity_metadata.tab_group_metadata = + CreateTabGroupMessageMetadata(*tab_group); + } else { + item.activity_metadata.tab_group_metadata = TabGroupMessageMetadata(); + std::optional<std::u16string> previous_title = + tab_group_sync_service_ + ->GetTitleForPreviouslyExistingSharedTabGroup( + ToCollaborationId(collaboration_group_id)); + if (previous_title) { + item.activity_metadata.tab_group_metadata->last_known_title = + base::UTF16ToUTF8(*previous_title); + } + } + break; + } + case MessageCategory::kCollaboration: + item.activity_metadata.affected_user = group_member; + break; + default: + break; + } + return item; +} + +std::u16string +MessagingBackendServiceImpl::GetDescriptionTextForActivityLogItem( + const collaboration_pb::Message& message) { + std::optional<GaiaId> gaia_id = GetGaiaIdFromMessage(message); + std::optional<data_sharing::GroupMemberPartialData> group_member_data; + if (gaia_id) { + group_member_data = data_sharing_service_->GetPossiblyRemovedGroupMember( + data_sharing::GroupId(message.collaboration_id()), *gaia_id); + } + + switch (ToCollaborationEvent(message.event_type())) { + case CollaborationEvent::TAB_ADDED: + case CollaborationEvent::TAB_UPDATED: + case CollaborationEvent::TAB_REMOVED: + // TODO(nyquist): Update this to use real data. + return u""; // Current domain as eTLD+1 (format for security display). + case CollaborationEvent::TAB_GROUP_ADDED: + case CollaborationEvent::TAB_GROUP_REMOVED: + return u""; // Not defined. + case CollaborationEvent::TAB_GROUP_NAME_UPDATED: + // TODO(nyquist): Update this to use real data. + return u""; // Current tab group name. + case CollaborationEvent::TAB_GROUP_COLOR_UPDATED: + return u""; // Intentionally left blank. + case CollaborationEvent::COLLABORATION_ADDED: + case CollaborationEvent::COLLABORATION_REMOVED: + return u""; // Not defined. + case CollaborationEvent::COLLABORATION_MEMBER_ADDED: + case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: + // Should use the email of the added / removed user. + if (group_member_data) { + return base::UTF8ToUTF16(group_member_data->email); + } else { + return u""; + } + case CollaborationEvent::UNDEFINED: + return u""; // Not defined. + } +} + +std::optional<data_sharing::GroupId> +MessagingBackendServiceImpl::GetCollaborationGroupIdForTab( + const tab_groups::SavedTabGroupTab& tab) { + // Find tab group using the tab group ID and look up collaboration group ID. + std::optional<tab_groups::SavedTabGroup> tab_group = + tab_group_sync_service_->GetGroup(tab.saved_group_guid()); + if (!tab_group) { + return std::nullopt; + } + return GroupIdForTabGroup(*tab_group); +} + } // namespace collaboration::messaging
diff --git a/components/collaboration/internal/messaging/messaging_backend_service_impl.h b/components/collaboration/internal/messaging/messaging_backend_service_impl.h index 82b614d..37ac0dad 100644 --- a/components/collaboration/internal/messaging/messaging_backend_service_impl.h +++ b/components/collaboration/internal/messaging/messaging_backend_service_impl.h
@@ -17,6 +17,10 @@ #include "components/collaboration/public/messaging/messaging_backend_service.h" #include "components/saved_tab_groups/public/tab_group_sync_service.h" +namespace collaboration_pb { +class Message; +} // namespace collaboration_pb + namespace data_sharing { class DataSharingService; } // namespace data_sharing @@ -77,10 +81,46 @@ // DataSharingChangeNotifier::Observer. void OnDataSharingChangeNotifierInitialized() override; + void OnGroupAdded(const data_sharing::GroupId& group_id, + const std::optional<data_sharing::GroupData>& group_data, + const base::Time& event_time) override; + void OnGroupRemoved(const data_sharing::GroupId& group_id, + const std::optional<data_sharing::GroupData>& group_data, + const base::Time& event_time) override; + void OnGroupMemberAdded(const data_sharing::GroupData& group_data, + const GaiaId& member_gaia_id, + const base::Time& event_time) override; + void OnGroupMemberRemoved(const data_sharing::GroupData& group_data, + const GaiaId& member_gaia_id, + const base::Time& event_time) override; private: void OnStoreInitialized(bool success); + // Uses all available sources to try to retrieve a name that describes the + // given user. + std::optional<std::string> GetDisplayNameForUserInGroup( + const data_sharing::GroupId& group_id, + const GaiaId& gaia_id, + const std::optional<data_sharing::GroupData>& group_data, + const std::optional<collaboration_pb::Message>& db_message); + + // Converts a stored message to an ActivityLogItem for display. Some events + // should not be part of the activity log and for those std::nullopt is + // return. + std::optional<ActivityLogItem> ConvertMessageToActivityLogItem( + const collaboration_pb::Message& message); + + // Provides the user visible description for activity log items based on the + // type of event. + std::u16string GetDescriptionTextForActivityLogItem( + const collaboration_pb::Message& message); + + // Looks for the related collaboration GroupId for the given tab, using the + // information available in the tab group sync service. + std::optional<data_sharing::GroupId> GetCollaborationGroupIdForTab( + const tab_groups::SavedTabGroupTab& tab); + // Provides functionality to go from observing the TabGroupSyncService to // a delta based observer API. std::unique_ptr<TabGroupChangeNotifier> tab_group_change_notifier_;
diff --git a/components/collaboration/internal/messaging/messaging_backend_service_impl_unittest.cc b/components/collaboration/internal/messaging/messaging_backend_service_impl_unittest.cc index 61456c7..2378b47e 100644 --- a/components/collaboration/internal/messaging/messaging_backend_service_impl_unittest.cc +++ b/components/collaboration/internal/messaging/messaging_backend_service_impl_unittest.cc
@@ -4,28 +4,98 @@ #include "components/collaboration/internal/messaging/messaging_backend_service_impl.h" +#include <ctime> #include <memory> #include "base/functional/callback_forward.h" #include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" +#include "base/time/time.h" +#include "base/uuid.h" #include "components/collaboration/internal/messaging/data_sharing_change_notifier.h" #include "components/collaboration/internal/messaging/storage/messaging_backend_store.h" +#include "components/collaboration/internal/messaging/storage/protocol/message.pb.h" #include "components/collaboration/internal/messaging/tab_group_change_notifier.h" +#include "components/data_sharing/public/group_data.h" +#include "components/data_sharing/test_support/mock_data_sharing_service.h" +#include "components/saved_tab_groups/public/saved_tab_group_tab.h" #include "components/saved_tab_groups/public/tab_group_sync_service.h" #include "components/saved_tab_groups/test_support/mock_tab_group_sync_service.h" +#include "components/tab_groups/tab_group_color.h" +#include "google_apis/gaia/gaia_id.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using base::test::RunOnceClosure; using testing::_; +using testing::Eq; using testing::Return; using testing::SaveArg; using testing::Truly; namespace collaboration::messaging { +namespace { +data_sharing::GroupMemberPartialData CreatePartialGroupMember( + const GaiaId& gaia_id, + const std::string& display_name, + const std::string& given_name) { + data_sharing::GroupMemberPartialData member; + member.gaia_id = gaia_id; + member.display_name = display_name; + member.given_name = given_name; + return member; +} + +collaboration_pb::Message CreateStoredMessage( + const data_sharing::GroupId& collaboration_group_id, + collaboration_pb::EventType event_type, + DirtyType dirty_type, + const base::Time& event_time) { + collaboration_pb::Message message; + message.set_uuid(base::Uuid::GenerateRandomV4().AsLowercaseString()); + message.set_collaboration_id(collaboration_group_id.value()); + message.set_event_type(event_type); + message.set_dirty(static_cast<int>(dirty_type)); + message.set_event_timestamp(event_time.ToTimeT()); + return message; +} + +data_sharing::GroupMemberPartialData CreatePartialMember( + const GaiaId& gaia_id, + std::string email, + std::string display_name, + std::string given_name) { + data_sharing::GroupMemberPartialData member; + member.gaia_id = gaia_id; + member.email = email; + member.display_name = display_name; + member.given_name = given_name; + return member; +} + +tab_groups::SavedTabGroup CreateSharedTabGroup( + data_sharing::GroupId collaboration_group_id) { + base::Uuid tab_group_sync_id = base::Uuid::GenerateRandomV4(); + + std::vector<tab_groups::SavedTabGroupTab> tabs; + tab_groups::SavedTabGroupTab tab1(GURL("https://example.com/"), u"Tab 1", + tab_group_sync_id, std::nullopt); + tab_groups::SavedTabGroupTab tab2(GURL("https://example2.com/"), u"Tab 2", + tab_group_sync_id, std::nullopt); + tabs.emplace_back(tab1); + tabs.emplace_back(tab2); + + tab_groups::SavedTabGroup tab_group(u"Tab Group Title", + tab_groups::TabGroupColorId::kOrange, + tabs, std::nullopt, tab_group_sync_id); + tab_group.SetCollaborationId( + tab_groups::CollaborationId(collaboration_group_id.value())); + return tab_group; +} +} // namespace + class MockTabGroupChangeNotifier : public TabGroupChangeNotifier { public: MockTabGroupChangeNotifier() = default; @@ -115,6 +185,8 @@ void SetUp() override { mock_tab_group_sync_service_ = std::make_unique<tab_groups::MockTabGroupSyncService>(); + mock_data_sharing_service_ = + std::make_unique<data_sharing::MockDataSharingService>(); } void TearDown() override {} @@ -154,14 +226,27 @@ std::move(tab_group_change_notifier), std::move(data_sharing_change_notifier), std::move(mock_messaging_backend_store), - mock_tab_group_sync_service_.get(), - /*data_sharing_service=*/nullptr); + mock_tab_group_sync_service_.get(), mock_data_sharing_service_.get()); + } + + void InitializeService() { + std::move(on_store_initialized_callback_).Run(/*success=*/true); + ds_notifier_observer_->OnDataSharingChangeNotifierInitialized(); + tg_notifier_observer_->OnTabGroupChangeNotifierInitialized(); + } + + void CreateAndInitializeService() { + CreateService(); + InitializeService(); } protected: - base::test::SingleThreadTaskEnvironment task_environment; + base::test::SingleThreadTaskEnvironment task_environment{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; base::OnceCallback<void(bool)> on_store_initialized_callback_; + std::unique_ptr<data_sharing::MockDataSharingService> + mock_data_sharing_service_; std::unique_ptr<tab_groups::MockTabGroupSyncService> mock_tab_group_sync_service_; std::unique_ptr<MessagingBackendServiceImpl> service_; @@ -183,4 +268,462 @@ EXPECT_TRUE(service_->IsInitialized()); } +void VerifyGenericMessageData(const collaboration_pb::Message& message, + const std::string& collaboration_id, + collaboration_pb::EventType event_type, + DirtyType dirty_type, + time_t event_timestamp) { + EXPECT_NE("", message.uuid()); + EXPECT_EQ(message.event_timestamp(), message.event_timestamp()); + EXPECT_EQ(message.collaboration_id(), collaboration_id); + EXPECT_EQ(message.event_type(), event_type); + EXPECT_EQ(message.dirty(), static_cast<int>(dirty_type)); +} + +TEST_F(MessagingBackendServiceImplTest, TestStoringCollaborationEvents) { + CreateAndInitializeService(); + + data_sharing::GroupData group_data; + group_data.group_token.group_id = data_sharing::GroupId("my group id"); + data_sharing::GroupMember member; + member.gaia_id = GaiaId("abc"); + member.display_name = "First Last"; + member.given_name = "First"; + group_data.members.emplace_back(member); + + // Always refers to the latest message that has been added to storage. + collaboration_pb::Message message; + EXPECT_CALL(*unowned_messaging_backend_store_, AddMessage(_)) + .WillRepeatedly(SaveArg<0>(&message)); + + EXPECT_CALL(*mock_data_sharing_service_, GetPossiblyRemovedGroupMember(_, _)) + .WillRepeatedly(Return(std::nullopt)); + + base::Time time = base::Time::Now(); + ds_notifier_observer_->OnGroupAdded(group_data.group_token.group_id, + group_data, time); + VerifyGenericMessageData(message, "my group id", + collaboration_pb::COLLABORATION_ADDED, + DirtyType::kNone, time.ToTimeT()); + + // Move time forward so it is unique. + time += base::Seconds(1); + ds_notifier_observer_->OnGroupRemoved(group_data.group_token.group_id, + group_data, time); + VerifyGenericMessageData(message, "my group id", + collaboration_pb::COLLABORATION_REMOVED, + DirtyType::kMessageOnly, time.ToTimeT()); + + time += base::Seconds(1); + GaiaId gaia_id("abc"); + ds_notifier_observer_->OnGroupMemberAdded(group_data, gaia_id, time); + VerifyGenericMessageData(message, "my group id", + collaboration_pb::COLLABORATION_MEMBER_ADDED, + DirtyType::kMessageOnly, time.ToTimeT()); + EXPECT_EQ("abc", message.affected_user_gaia_id()); + EXPECT_EQ("First", message.collaboration_data().affected_user_name()); + + time += base::Seconds(1); + ds_notifier_observer_->OnGroupMemberRemoved(group_data, gaia_id, time); + VerifyGenericMessageData(message, "my group id", + collaboration_pb::COLLABORATION_MEMBER_REMOVED, + DirtyType::kNone, time.ToTimeT()); + EXPECT_EQ("abc", message.affected_user_gaia_id()); + EXPECT_EQ("First", message.collaboration_data().affected_user_name()); +} + +TEST_F(MessagingBackendServiceImplTest, + TestLookingUpMemberNameForCollaborationEventsForStorage) { + CreateAndInitializeService(); + + data_sharing::GroupData group_data; + data_sharing::GroupId group_id("my group id"); + group_data.group_token.group_id = group_id; + data_sharing::GroupMember member1; + member1.gaia_id = GaiaId("abc"); + member1.display_name = "Provided Diplay Name 1"; + member1.given_name = "Provided Given Name 1"; + group_data.members.emplace_back(member1); + + data_sharing::GroupMember member2; + member2.gaia_id = GaiaId("def"); + member2.display_name = "Provided Display Name 2"; + member2.given_name = ""; // No given name available. + group_data.members.emplace_back(member2); + + // Always refers to the latest message that has been added to storage. + collaboration_pb::Message message; + EXPECT_CALL(*unowned_messaging_backend_store_, AddMessage(_)) + .WillRepeatedly(SaveArg<0>(&message)); + + // Current given name should be first priority. + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(group_id), Eq(member1.gaia_id))) + .WillOnce(Return(std::make_optional(CreatePartialGroupMember( + member1.gaia_id, "Live Display Name 1", "Live Given Name 1")))); + base::Time time = base::Time::Now(); + ds_notifier_observer_->OnGroupMemberAdded(group_data, member1.gaia_id, time); + VerifyGenericMessageData(message, group_id.value(), + collaboration_pb::COLLABORATION_MEMBER_ADDED, + DirtyType::kMessageOnly, time.ToTimeT()); + EXPECT_EQ(member1.gaia_id, message.affected_user_gaia_id()); + EXPECT_EQ("Live Given Name 1", + message.collaboration_data().affected_user_name()); + + // Given name from provided data should be second priority. + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(group_id), Eq(member1.gaia_id))) + .WillOnce(Return(std::nullopt)); + time += base::Seconds(1); + ds_notifier_observer_->OnGroupMemberAdded(group_data, member1.gaia_id, time); + VerifyGenericMessageData(message, group_id.value(), + collaboration_pb::COLLABORATION_MEMBER_ADDED, + DirtyType::kMessageOnly, time.ToTimeT()); + EXPECT_EQ(member1.gaia_id, message.affected_user_gaia_id()); + EXPECT_EQ("Provided Given Name 1", + message.collaboration_data().affected_user_name()); + + // Current display name should be next. + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(group_id), Eq(member2.gaia_id))) + .WillOnce(Return(std::make_optional(CreatePartialGroupMember( + member2.gaia_id, "Live Display Name 2", /*given_name=*/"")))); + time += base::Seconds(1); + ds_notifier_observer_->OnGroupMemberAdded(group_data, member2.gaia_id, time); + VerifyGenericMessageData(message, group_id.value(), + collaboration_pb::COLLABORATION_MEMBER_ADDED, + DirtyType::kMessageOnly, time.ToTimeT()); + EXPECT_EQ(member2.gaia_id, message.affected_user_gaia_id()); + EXPECT_EQ("Live Display Name 2", + message.collaboration_data().affected_user_name()); + + // Provided display name should be next. + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(group_id), Eq(member2.gaia_id))) + .WillOnce(Return(std::nullopt)); + time += base::Seconds(1); + ds_notifier_observer_->OnGroupMemberAdded(group_data, member2.gaia_id, time); + VerifyGenericMessageData(message, group_id.value(), + collaboration_pb::COLLABORATION_MEMBER_ADDED, + DirtyType::kMessageOnly, time.ToTimeT()); + EXPECT_EQ(member2.gaia_id, message.affected_user_gaia_id()); + EXPECT_EQ("Provided Display Name 2", + message.collaboration_data().affected_user_name()); +} + +TEST_F(MessagingBackendServiceImplTest, TestActivityLogWithNoEvents) { + CreateAndInitializeService(); + + std::vector<collaboration_pb::Message> messages; + + EXPECT_CALL(*unowned_messaging_backend_store_, GetRecentMessagesForGroup(_)) + .WillOnce(Return(messages)); + + ActivityLogQueryParams params; + params.collaboration_id = data_sharing::GroupId("my group id"); + std::vector<ActivityLogItem> activity_log = service_->GetActivityLog(params); + EXPECT_EQ(0u, activity_log.size()); +} + +TEST_F(MessagingBackendServiceImplTest, TestActivityLogAcceptsMaxLength) { + CreateAndInitializeService(); + + data_sharing::GroupId collaboration_group_id = + data_sharing::GroupId("my group id"); + + base::Time now = base::Time::Now(); + std::vector<collaboration_pb::Message> messages; + collaboration_pb::Message message1 = CreateStoredMessage( + collaboration_group_id, + collaboration_pb::EventType::COLLABORATION_MEMBER_ADDED, DirtyType::kNone, + now + base::Seconds(4)); + messages.emplace_back(message1); + collaboration_pb::Message message2 = CreateStoredMessage( + collaboration_group_id, + collaboration_pb::EventType::COLLABORATION_MEMBER_REMOVED, + DirtyType::kNone, now + base::Seconds(3)); + messages.emplace_back(message2); + collaboration_pb::Message message3 = CreateStoredMessage( + collaboration_group_id, collaboration_pb::EventType::TAB_ADDED, + DirtyType::kNone, now + base::Seconds(2)); + messages.emplace_back(message3); + // COLLABORATION_ADDED should never be returned. + collaboration_pb::Message message4 = CreateStoredMessage( + collaboration_group_id, collaboration_pb::EventType::COLLABORATION_ADDED, + DirtyType::kNone, now + base::Seconds(1)); + messages.emplace_back(message4); + + EXPECT_CALL(*unowned_messaging_backend_store_, + GetRecentMessagesForGroup(Eq(collaboration_group_id))) + .WillRepeatedly(Return(messages)); + + ActivityLogQueryParams params; + params.collaboration_id = collaboration_group_id; + params.result_length = 2; // We only want max 2 items. + std::vector<ActivityLogItem> activity_log = service_->GetActivityLog(params); + ASSERT_EQ(2u, activity_log.size()); + EXPECT_EQ(CollaborationEvent::COLLABORATION_MEMBER_ADDED, + activity_log[0].collaboration_event); + EXPECT_EQ(CollaborationEvent::COLLABORATION_MEMBER_REMOVED, + activity_log[1].collaboration_event); + + // We want max 5 items, but the log has 3, it should still return what it has. + params.result_length = 5; + activity_log = service_->GetActivityLog(params); + ASSERT_EQ(3u, activity_log.size()); + EXPECT_EQ(CollaborationEvent::COLLABORATION_MEMBER_ADDED, + activity_log[0].collaboration_event); + EXPECT_EQ(CollaborationEvent::COLLABORATION_MEMBER_REMOVED, + activity_log[1].collaboration_event); + EXPECT_EQ(CollaborationEvent::TAB_ADDED, activity_log[2].collaboration_event); + + // Setting result length to 0 should return all items. + params.result_length = 0; + activity_log = service_->GetActivityLog(params); + ASSERT_EQ(3u, activity_log.size()); +} + +TEST_F(MessagingBackendServiceImplTest, TestActivityLogCollaborationEvents) { + CreateAndInitializeService(); + + data_sharing::GroupId collaboration_group_id = + data_sharing::GroupId("my group id"); + + base::Time now = base::Time::Now(); + std::vector<collaboration_pb::Message> messages; + collaboration_pb::Message message1 = CreateStoredMessage( + collaboration_group_id, + collaboration_pb::EventType::COLLABORATION_MEMBER_ADDED, DirtyType::kNone, + now); + message1.set_affected_user_gaia_id("gaia_1"); + message1.mutable_collaboration_data()->set_affected_user_name("gaia_1 name"); + messages.emplace_back(message1); + + collaboration_pb::Message message2 = CreateStoredMessage( + collaboration_group_id, + collaboration_pb::EventType::COLLABORATION_MEMBER_REMOVED, + DirtyType::kNone, now); + message2.set_affected_user_gaia_id("gaia_2"); + message2.mutable_collaboration_data()->set_affected_user_name("gaia_2 name"); + messages.emplace_back(message2); + + EXPECT_CALL(*unowned_messaging_backend_store_, + GetRecentMessagesForGroup(Eq(collaboration_group_id))) + .WillOnce(Return(messages)); + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(collaboration_group_id), + Eq(GaiaId("gaia_1")))) + .WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(collaboration_group_id), + Eq(GaiaId("gaia_2")))) + .WillRepeatedly( + Return(CreatePartialMember(GaiaId("gaia_2"), "gaia2@gmail.com", + "Display Name", "Given Name 2"))); + + ActivityLogQueryParams params; + params.collaboration_id = collaboration_group_id; + std::vector<ActivityLogItem> activity_log = service_->GetActivityLog(params); + ASSERT_EQ(2u, activity_log.size()); + EXPECT_EQ(CollaborationEvent::COLLABORATION_MEMBER_ADDED, + activity_log[0].collaboration_event); + EXPECT_EQ(CollaborationEvent::COLLABORATION_MEMBER_REMOVED, + activity_log[1].collaboration_event); + + // Use name from DB and no email. This is not intended to happen, because we + // should always have the member data, but this tests that we still work + // without it. + EXPECT_EQ("gaia_1 name", activity_log[0].user_display_name); + EXPECT_EQ(u"", activity_log[0].description); + // Use name and email from DataSharingService. + EXPECT_EQ("Given Name 2", activity_log[1].user_display_name); + EXPECT_EQ(u"gaia2@gmail.com", activity_log[1].description); + // We should also fill in the MessageAttribution. + EXPECT_EQ("gaia2@gmail.com", + activity_log[1].activity_metadata.affected_user->email); +} + +TEST_F(MessagingBackendServiceImplTest, TestStoringTabGroupEvents) { + CreateAndInitializeService(); + + data_sharing::GroupId collaboration_group_id = + data_sharing::GroupId("my group id"); + base::Time now = base::Time::Now(); + GaiaId gaia1("abc"); + GaiaId gaia2("def"); + + // Always refers to the latest message that has been added to storage. + collaboration_pb::Message message; + EXPECT_CALL(*unowned_messaging_backend_store_, AddMessage(_)) + .WillRepeatedly(SaveArg<0>(&message)); + + tab_groups::SavedTabGroup tab_group = + CreateSharedTabGroup(collaboration_group_id); + tab_group.SetCreatedByAttribution(gaia1); + tab_group.SetUpdatedByAttribution(gaia2); + + tg_notifier_observer_->OnTabGroupAdded(tab_group); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_GROUP_ADDED, DirtyType::kNone, + now.ToTimeT()); + EXPECT_EQ(gaia1, message.triggering_user_gaia_id()); + + tg_notifier_observer_->OnTabGroupRemoved(tab_group); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_GROUP_REMOVED, + DirtyType::kNone, now.ToTimeT()); + EXPECT_EQ(gaia2, message.triggering_user_gaia_id()); + + tg_notifier_observer_->OnTabGroupNameUpdated(tab_group); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_GROUP_NAME_UPDATED, + DirtyType::kNone, now.ToTimeT()); + EXPECT_EQ(gaia2, message.triggering_user_gaia_id()); + + tg_notifier_observer_->OnTabGroupColorUpdated(tab_group); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_GROUP_COLOR_UPDATED, + DirtyType::kNone, now.ToTimeT()); + EXPECT_EQ(gaia2, message.triggering_user_gaia_id()); +} + +TEST_F(MessagingBackendServiceImplTest, TestActivityLogTabGroupEvents) { + CreateAndInitializeService(); + + data_sharing::GroupId collaboration_group_id = + data_sharing::GroupId("my group id"); + + base::Time now = base::Time::Now(); + std::vector<collaboration_pb::Message> messages; + // Adding and removing tab groups should not be part of activity log. + collaboration_pb::Message message1 = CreateStoredMessage( + collaboration_group_id, collaboration_pb::EventType::TAB_GROUP_ADDED, + DirtyType::kNone, now); + message1.set_triggering_user_gaia_id("gaia_1"); + messages.emplace_back(message1); + + collaboration_pb::Message message2 = CreateStoredMessage( + collaboration_group_id, collaboration_pb::EventType::TAB_GROUP_REMOVED, + DirtyType::kNone, now); + message2.set_triggering_user_gaia_id("gaia_2"); + messages.emplace_back(message2); + + collaboration_pb::Message message3 = + CreateStoredMessage(collaboration_group_id, + collaboration_pb::EventType::TAB_GROUP_NAME_UPDATED, + DirtyType::kNone, now); + message3.set_triggering_user_gaia_id("gaia_2"); + messages.emplace_back(message3); + + collaboration_pb::Message message4 = + CreateStoredMessage(collaboration_group_id, + collaboration_pb::EventType::TAB_GROUP_COLOR_UPDATED, + DirtyType::kNone, now); + message4.set_triggering_user_gaia_id("gaia_2"); + messages.emplace_back(message4); + + // Add support for looking up GAIA IDs. + EXPECT_CALL(*unowned_messaging_backend_store_, + GetRecentMessagesForGroup(Eq(collaboration_group_id))) + .WillOnce(Return(messages)); + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(collaboration_group_id), + Eq(GaiaId("gaia_1")))) + .WillRepeatedly(Return(std::nullopt)); + EXPECT_CALL(*mock_data_sharing_service_, + GetPossiblyRemovedGroupMember(Eq(collaboration_group_id), + Eq(GaiaId("gaia_2")))) + .WillRepeatedly( + Return(CreatePartialMember(GaiaId("gaia_2"), "gaia2@gmail.com", + "Display Name", "Given Name 2"))); + + // Query for all itemms, which should only be name and color updates. + ActivityLogQueryParams params; + params.collaboration_id = collaboration_group_id; + std::vector<ActivityLogItem> activity_log = service_->GetActivityLog(params); + ASSERT_EQ(2u, activity_log.size()); + EXPECT_EQ(CollaborationEvent::TAB_GROUP_NAME_UPDATED, + activity_log[0].collaboration_event); + EXPECT_EQ(CollaborationEvent::TAB_GROUP_COLOR_UPDATED, + activity_log[1].collaboration_event); +} + +TEST_F(MessagingBackendServiceImplTest, TestStoringTabEvents) { + CreateAndInitializeService(); + + data_sharing::GroupId collaboration_group_id = + data_sharing::GroupId("my group id"); + base::Time now = base::Time::Now(); + GaiaId gaia1("abc"); + GaiaId gaia2("def"); + + // Always refers to the latest message that has been added to storage. + collaboration_pb::Message message; + EXPECT_CALL(*unowned_messaging_backend_store_, AddMessage(_)) + .WillRepeatedly(SaveArg<0>(&message)); + + tab_groups::SavedTabGroup tab_group = + CreateSharedTabGroup(collaboration_group_id); + base::Uuid tab1_sync_id = tab_group.saved_tabs().at(0).saved_tab_guid(); + tab_groups::SavedTabGroupTab* tab1 = tab_group.GetTab(tab1_sync_id); + // Make creation and update GaiaId unique. + tab1->SetCreatedByAttribution(gaia1); + tab1->SetUpdatedByAttribution(gaia2); + // Make creation and update time unique. + tab1->SetUpdateTimeWindowsEpochMicros(now + base::Seconds(1)); + + base::Uuid tab2_sync_id = tab_group.saved_tabs().at(1).saved_tab_guid(); + tab_groups::SavedTabGroupTab* tab2 = tab_group.GetTab(tab2_sync_id); + // Make creation and update GaiaId unique. + tab2->SetCreatedByAttribution(gaia1); + tab2->SetUpdatedByAttribution(gaia2); + // Make creation and update time unique. + tab2->SetUpdateTimeWindowsEpochMicros(now + base::Seconds(1)); + + EXPECT_CALL(*mock_tab_group_sync_service_, GetGroup(tab_group.saved_guid())) + .WillRepeatedly(Return(tab_group)); + + tg_notifier_observer_->OnTabAdded(*tab1); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_ADDED, DirtyType::kDotAndChip, + now.ToTimeT()); + EXPECT_EQ(gaia1, message.triggering_user_gaia_id()); + EXPECT_EQ(tab1->saved_tab_guid().AsLowercaseString(), + message.tab_data().sync_tab_id()); + EXPECT_EQ(tab1->saved_group_guid().AsLowercaseString(), + message.tab_data().sync_tab_group_id()); + EXPECT_EQ(tab_group.saved_guid().AsLowercaseString(), + message.tab_data().sync_tab_group_id()); + EXPECT_EQ(tab1->creation_time_windows_epoch_micros().ToTimeT(), + message.event_timestamp()); + + tg_notifier_observer_->OnTabUpdated(*tab2); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_UPDATED, + DirtyType::kDotAndChip, now.ToTimeT()); + EXPECT_EQ(gaia2, message.triggering_user_gaia_id()); + EXPECT_EQ(tab2->saved_tab_guid().AsLowercaseString(), + message.tab_data().sync_tab_id()); + EXPECT_EQ(tab2->saved_group_guid().AsLowercaseString(), + message.tab_data().sync_tab_group_id()); + EXPECT_EQ(tab_group.saved_guid().AsLowercaseString(), + message.tab_data().sync_tab_group_id()); + EXPECT_EQ(tab2->update_time_windows_epoch_micros().ToTimeT(), + message.event_timestamp()); + + tg_notifier_observer_->OnTabRemoved(*tab2); + VerifyGenericMessageData(message, collaboration_group_id.value(), + collaboration_pb::TAB_REMOVED, DirtyType::kNone, + now.ToTimeT()); + EXPECT_EQ(gaia2, message.triggering_user_gaia_id()); + EXPECT_EQ(tab2->saved_tab_guid().AsLowercaseString(), + message.tab_data().sync_tab_id()); + EXPECT_EQ(tab2->saved_group_guid().AsLowercaseString(), + message.tab_data().sync_tab_group_id()); + EXPECT_EQ(tab_group.saved_guid().AsLowercaseString(), + message.tab_data().sync_tab_group_id()); + EXPECT_EQ(tab2->update_time_windows_epoch_micros().ToTimeT(), + message.event_timestamp()); +} + } // namespace collaboration::messaging
diff --git a/components/collaboration/internal/messaging/storage/messaging_backend_store.h b/components/collaboration/internal/messaging/storage/messaging_backend_store.h index d3c64cc..46c43db 100644 --- a/components/collaboration/internal/messaging/storage/messaging_backend_store.h +++ b/components/collaboration/internal/messaging/storage/messaging_backend_store.h
@@ -66,7 +66,8 @@ // Set cutoff duration for recent message. virtual void SetRecentMessageCutoffDuration(base::TimeDelta time_delta) = 0; - // Get the recent messages for a group. + // Get the recent messages for a group. The newest message is first in the + // result. virtual std::vector<collaboration_pb::Message> GetRecentMessagesForGroup( const data_sharing::GroupId& collaboration_id) = 0;
diff --git a/components/collaboration/internal/messaging/storage/messaging_backend_store_impl.cc b/components/collaboration/internal/messaging/storage/messaging_backend_store_impl.cc index 6ac19032..692a396 100644 --- a/components/collaboration/internal/messaging/storage/messaging_backend_store_impl.cc +++ b/components/collaboration/internal/messaging/storage/messaging_backend_store_impl.cc
@@ -4,6 +4,8 @@ #include "components/collaboration/internal/messaging/storage/messaging_backend_store_impl.h" +#include <algorithm> + #include "base/containers/contains.h" #include "base/task/single_thread_task_runner.h" #include "components/collaboration/internal/messaging/storage/collaboration_message_util.h" @@ -193,6 +195,12 @@ }, &result, cutoff_time)); + std::sort(result.begin(), result.end(), + [](const collaboration_pb::Message& a, + const collaboration_pb::Message& b) { + return a.event_timestamp() > b.event_timestamp(); + }); + return result; }
diff --git a/components/collaboration/internal/messaging/storage/messaging_backend_store_impl_unittest.cc b/components/collaboration/internal/messaging/storage/messaging_backend_store_impl_unittest.cc index ee6dda2..8212fa2 100644 --- a/components/collaboration/internal/messaging/storage/messaging_backend_store_impl_unittest.cc +++ b/components/collaboration/internal/messaging/storage/messaging_backend_store_impl_unittest.cc
@@ -5,6 +5,7 @@ #include "components/collaboration/internal/messaging/storage/messaging_backend_store_impl.h" #include "components/collaboration/internal/messaging/storage/collaboration_message_util.h" +#include "components/collaboration/internal/messaging/storage/protocol/message.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace collaboration::messaging { @@ -239,4 +240,40 @@ EXPECT_EQ(message2.uuid(), messages[0].uuid()); } +TEST_F(MessagingBackendStoreTest, EnsureRecentActivityIsSorted) { + data_sharing::GroupId group_id("Group ID"); + base::Time now = base::Time::Now(); + // Create three messages stored in an arbitrary order, but timestamp wise, + // their order is: 3, 1, 4, 2, message 3 being the oldest. + // This test verifies that they are received in the opposite order of this, + // so 2, 4, 1, 3. + auto message1 = CreateMessage(collaboration_pb::TAB_ADDED, group_id.value()); + message1.set_event_timestamp((now + base::Seconds(2)).ToTimeT()); + + auto message2 = + CreateMessage(collaboration_pb::TAB_REMOVED, group_id.value()); + message2.set_event_timestamp((now + base::Seconds(4)).ToTimeT()); + + auto message3 = CreateMessage(collaboration_pb::COLLABORATION_MEMBER_ADDED, + group_id.value()); + message3.set_event_timestamp((now + base::Seconds(1)).ToTimeT()); + + auto message4 = CreateMessage(collaboration_pb::COLLABORATION_MEMBER_REMOVED, + group_id.value()); + message4.set_event_timestamp((now + base::Seconds(3)).ToTimeT()); + + store_->AddMessage(message1); + store_->AddMessage(message2); + store_->AddMessage(message3); + store_->AddMessage(message4); + auto messages = store_->GetRecentMessagesForGroup(group_id); + ASSERT_EQ(4u, messages.size()); + + // Verify newest message is first, etc. + EXPECT_EQ(message2.uuid(), messages[0].uuid()); + EXPECT_EQ(message4.uuid(), messages[1].uuid()); + EXPECT_EQ(message1.uuid(), messages[2].uuid()); + EXPECT_EQ(message3.uuid(), messages[3].uuid()); +} + } // namespace collaboration::messaging
diff --git a/components/collaboration/internal/messaging/storage/protocol/message.proto b/components/collaboration/internal/messaging/storage/protocol/message.proto index 5a1c1f7d..776a9cd 100644 --- a/components/collaboration/internal/messaging/storage/protocol/message.proto +++ b/components/collaboration/internal/messaging/storage/protocol/message.proto
@@ -48,12 +48,13 @@ } // Collaboration message related data. -// Only set for COLLABORATION_MEMBER_REMOVED event. message CollaborationData { // Store the triggering user name. optional string triggering_user_name = 1; // Store the affected user name. + // Only set for COLLABORATION_MEMBER_ADDED & COLLABORATION_MEMBER_REMOVED + // event. optional string affected_user_name = 2; }
diff --git a/components/data_sharing/public/group_data.cc b/components/data_sharing/public/group_data.cc index 7345641..d15dfe0 100644 --- a/components/data_sharing/public/group_data.cc +++ b/components/data_sharing/public/group_data.cc
@@ -45,6 +45,16 @@ GroupMemberPartialData::~GroupMemberPartialData() = default; +GroupMember GroupMemberPartialData::ToGroupMember() { + GroupMember member; + member.gaia_id = gaia_id; + member.display_name = display_name; + member.email = email; + member.avatar_url = avatar_url; + member.given_name = given_name; + return member; +} + GroupToken::GroupToken() = default; GroupToken::GroupToken(GroupId group_id, const std::string& access_token)
diff --git a/components/data_sharing/public/group_data.h b/components/data_sharing/public/group_data.h index 8d7119d0..57722a0 100644 --- a/components/data_sharing/public/group_data.h +++ b/components/data_sharing/public/group_data.h
@@ -54,6 +54,8 @@ ~GroupMemberPartialData(); + GroupMember ToGroupMember(); + GaiaId gaia_id; std::string display_name; std::string email;
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc b/components/facilitated_payments/core/browser/facilitated_payments_manager.cc index 89f7412..0345f6b5 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager.cc
@@ -10,6 +10,7 @@ #include "base/check.h" #include "base/check_deref.h" #include "base/functional/callback_helpers.h" +#include "base/time/time.h" #include "components/autofill/core/browser/data_model/bank_account.h" #include "components/autofill/core/browser/payments/payments_util.h" #include "components/autofill/core/browser/payments_data_manager.h" @@ -21,6 +22,11 @@ #include "components/facilitated_payments/core/utils/facilitated_payments_utils.h" namespace payments::facilitated { +namespace { + +static constexpr base::TimeDelta kProgressScreenDismissDelay = base::Seconds(1); + +} // namespace FacilitatedPaymentsManager::FacilitatedPaymentsManager( FacilitatedPaymentsDriver* driver, @@ -280,12 +286,19 @@ ShowErrorScreen(); return; } + LogInitiatePurchaseActionAttempt(); purchase_action_start_time_ = base::TimeTicks::Now(); GetApiClient()->InvokePurchaseAction( account_info.value(), response_details->action_token_, base::BindOnce(&FacilitatedPaymentsManager::OnPurchaseActionResult, weak_ptr_factory_.GetWeakPtr())); + + // Close the progress screen just after the platform screen appears. + ui_timer_.Start( + FROM_HERE, kProgressScreenDismissDelay, + base::BindOnce(&FacilitatedPaymentsManager::DismissProgressScreen, + weak_ptr_factory_.GetWeakPtr())); } void FacilitatedPaymentsManager::OnPurchaseActionResult( @@ -300,10 +313,9 @@ break; } // Logs the general histograms. - std::string result_string = GetInitiatePurchaseActionResultString(result); LogInitiatePurchaseActionResultAndLatency( - result_string, base::TimeTicks::Now() - purchase_action_start_time_); - LogInitiatePurchaseActionResultUkm(result_string, ukm_source_id_); + result, base::TimeTicks::Now() - purchase_action_start_time_); + LogInitiatePurchaseActionResultUkm(result, ukm_source_id_); } void FacilitatedPaymentsManager::OnUiEvent(UiEvent ui_event_type) { @@ -360,15 +372,9 @@ client_->ShowErrorScreen(); } -std::string FacilitatedPaymentsManager::GetInitiatePurchaseActionResultString( - PurchaseActionResult result) { - switch (result) { - case PurchaseActionResult::kResultOk: - return std::string("Succeeded"); - case PurchaseActionResult::kCouldNotInvoke: - return std::string("Failed"); - case PurchaseActionResult::kResultCanceled: - return std::string("Abandoned"); +void FacilitatedPaymentsManager::DismissProgressScreen() { + if (ui_state_ == UiState::kProgressScreen) { + DismissPrompt(); } }
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.h b/components/facilitated_payments/core/browser/facilitated_payments_manager.h index 42b27046..aab5d7a1e 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.h +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager.h
@@ -96,6 +96,9 @@ FRIEND_TEST_ALL_PREFIXES( FacilitatedPaymentsManagerTest, DOMSearch_CheckAllowlistResultUnknown_PixCodeDetectionNotTriggered); + FRIEND_TEST_ALL_PREFIXES( + FacilitatedPaymentsManagerTest, + ErrorScreenNotAutoDismissedAfterInvokingPurchaseAction); FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, HandlesFailureToLazilyInitializeApiClient); FRIEND_TEST_ALL_PREFIXES( @@ -171,6 +174,9 @@ PixFopSelectorShown_HistogramsLogged); FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, PixPrefTurnedOff_NoApiClientTriggered); + FRIEND_TEST_ALL_PREFIXES( + FacilitatedPaymentsManagerTest, + ProgressScreenAutoDismissedAfterInvokingPurchaseAction); FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, RegisterPixAllowlist); FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, @@ -305,9 +311,9 @@ // Sets the internal state and triggers showing the error screen. void ShowErrorScreen(); - // Converts the PurchaseActionResult to the string version. - std::string GetInitiatePurchaseActionResultString( - PurchaseActionResult result); + // Dismisses the FacilitatedPayments bottom sheet if the progress screen is + // being shown. + void DismissProgressScreen(); // Owner. const raw_ref<FacilitatedPaymentsDriver> driver_; @@ -346,6 +352,9 @@ // Measures the time take to complete the purchase action. base::TimeTicks purchase_action_start_time_; + // A timer to make UI changes. + base::OneShotTimer ui_timer_; + // Contains the details required for the `InitiatePayment` request to be sent // to the Payments server. Its ownership is transferred to // `FacilitatedPaymentsInitiatePaymentRequest` in
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc b/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc index e572162e..46f5a07c 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc
@@ -900,10 +900,21 @@ FastForwardBy(base::Seconds(2)); manager_->OnPurchaseActionResult(result); + std::string result_string; + switch (result) { + case PurchaseActionResult::kResultOk: + result_string = "Succeeded"; + break; + case PurchaseActionResult::kCouldNotInvoke: + result_string = "Failed"; + break; + case PurchaseActionResult::kResultCanceled: + result_string = "Abandoned"; + break; + } histogram_tester.ExpectBucketCount( base::StrCat({"FacilitatedPayments.Pix.InitiatePurchaseAction.", - manager_->GetInitiatePurchaseActionResultString(result), - ".Latency"}), + result_string, ".Latency"}), /*sample=*/2000, /*expected_count=*/1); auto ukm_entries = ukm_recorder_.GetEntries( @@ -1091,6 +1102,59 @@ EXPECT_EQ(ukm_entries[0].metrics.at("Shown"), true); } +TEST_F(FacilitatedPaymentsManagerTest, + ProgressScreenAutoDismissedAfterInvokingPurchaseAction) { + // When purchase action is invoked, the progress screen would be showing. + manager_->ShowProgressScreen(); + ON_CALL(*client_, GetCoreAccountInfo) + .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); + + EXPECT_CALL(GetApiClient(), InvokePurchaseAction); + + auto response_details = + std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); + response_details->action_token_ = + std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; + manager_->OnInitiatePaymentResponseReceived( + autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, + std::move(response_details)); + + // The progress screen is persisted for a short duration after invoking the + // purchase action for a smooth transition to the platform screen. + EXPECT_EQ(manager_->ui_state_, UiState::kProgressScreen); + + FastForwardBy(base::Seconds(1)); + + // The progress screen should be dismissed after a short delay. + EXPECT_EQ(manager_->ui_state_, UiState::kHidden); +} + +TEST_F(FacilitatedPaymentsManagerTest, + ErrorScreenNotAutoDismissedAfterInvokingPurchaseAction) { + // When purchase action is invoked, the progress screen would be showing. + manager_->ShowProgressScreen(); + ON_CALL(*client_, GetCoreAccountInfo) + .WillByDefault(testing::Return(CreateLoggedInAccountInfo())); + + EXPECT_CALL(GetApiClient(), InvokePurchaseAction); + + auto response_details = + std::make_unique<FacilitatedPaymentsInitiatePaymentResponseDetails>(); + response_details->action_token_ = + std::vector<uint8_t>{'t', 'o', 'k', 'e', 'n'}; + manager_->OnInitiatePaymentResponseReceived( + autofill::payments::PaymentsAutofillClient::PaymentsRpcResult::kSuccess, + std::move(response_details)); + + // If the purchase action could not be invoked, the `PurchaseActionResult` is + // returned immediately. The error screen is shown. + manager_->OnPurchaseActionResult(PurchaseActionResult::kCouldNotInvoke); + FastForwardBy(base::Seconds(1)); + + // The error screen shouldn't be auto-dismissed. + EXPECT_EQ(manager_->ui_state_, UiState::kErrorScreen); +} + class FacilitatedPaymentsManagerTestForUiScreens : public FacilitatedPaymentsManagerTest, public testing::WithParamInterface<UiState> {
diff --git a/components/facilitated_payments/core/metrics/facilitated_payments_metrics.cc b/components/facilitated_payments/core/metrics/facilitated_payments_metrics.cc index d5c4d94..9a7fa7e 100644 --- a/components/facilitated_payments/core/metrics/facilitated_payments_metrics.cc +++ b/components/facilitated_payments/core/metrics/facilitated_payments_metrics.cc
@@ -9,9 +9,25 @@ #include "base/strings/strcat.h" #include "base/time/time.h" #include "components/facilitated_payments/core/utils/facilitated_payments_ui_utils.h" +#include "components/facilitated_payments/core/utils/facilitated_payments_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" namespace payments::facilitated { +namespace { + +// Helper to convert `PurchaseActionResult` to a string for logging. +std::string GetInitiatePurchaseActionResultString(PurchaseActionResult result) { + switch (result) { + case PurchaseActionResult::kResultOk: + return "Succeeded"; + case PurchaseActionResult::kCouldNotInvoke: + return "Failed"; + case PurchaseActionResult::kResultCanceled: + return "Abandoned"; + } +} + +} // namespace void LogPixCodeCopied(ukm::SourceId ukm_source_id) { base::UmaHistogramBoolean("FacilitatedPayments.Pix.PixCodeCopied", @@ -118,37 +134,24 @@ /*sample=*/true); } -void LogInitiatePurchaseActionResultAndLatency(const std::string& result, +void LogInitiatePurchaseActionResultAndLatency(PurchaseActionResult result, base::TimeDelta duration) { // TODO(crbug.com/337929926): Remove hardcoding for Pix and use // FacilitatedPaymentsType enum. base::UmaHistogramLongTimes( - base::StrCat({"FacilitatedPayments.Pix.InitiatePurchaseAction.", result, - ".Latency"}), + base::StrCat({"FacilitatedPayments.Pix.InitiatePurchaseAction.", + GetInitiatePurchaseActionResultString(result), ".Latency"}), duration); } -void LogInitiatePurchaseActionResultUkm(const std::string& result, +void LogInitiatePurchaseActionResultUkm(PurchaseActionResult result, ukm::SourceId ukm_source_id) { ukm::builders::FacilitatedPayments_Pix_InitiatePurchaseActionResult( ukm_source_id) - .SetResult(ConvertPurchaseActionResultToEnumValue(result)) + .SetResult(static_cast<uint8_t>(result)) .Record(ukm::UkmRecorder::Get()); } -uint8_t ConvertPurchaseActionResultToEnumValue(const std::string& result) { - if (result == "Failed") { - return 0; // See the definition of the enum - // FacilitatedPayments.InitiatePurchaseActionResult. - } else if (result == "Succeeded") { - return 1; - } else if (result == "Abandoned") { - return 2; - } else { - NOTREACHED(); - } -} - void LogUiScreenShown(UiState ui_screen) { base::UmaHistogramEnumeration("FacilitatedPayments.Pix.UiScreenShown", ui_screen);
diff --git a/components/facilitated_payments/core/metrics/facilitated_payments_metrics.h b/components/facilitated_payments/core/metrics/facilitated_payments_metrics.h index 9b74a9e..07a02e35 100644 --- a/components/facilitated_payments/core/metrics/facilitated_payments_metrics.h +++ b/components/facilitated_payments/core/metrics/facilitated_payments_metrics.h
@@ -7,6 +7,7 @@ #include "base/types/expected.h" #include "components/facilitated_payments/core/utils/facilitated_payments_ui_utils.h" +#include "components/facilitated_payments/core/utils/facilitated_payments_utils.h" #include "services/metrics/public/cpp/ukm_source_id.h" namespace base { @@ -110,19 +111,13 @@ // Log the result and latency for the InitiatePurchaseAction call made to the // payments platform (client). -// TODO(crbug.com/379723883): Move the `PurchaseActionResult` and have this -// function take in an enum instead of a string. -void LogInitiatePurchaseActionResultAndLatency(const std::string& result, +void LogInitiatePurchaseActionResultAndLatency(PurchaseActionResult result, base::TimeDelta duration); // Log the UKM for the InitiatePurchaseAction result. -void LogInitiatePurchaseActionResultUkm(const std::string& result, +void LogInitiatePurchaseActionResultUkm(PurchaseActionResult result, ukm::SourceId ukm_source_id); -// TODO(crbug.com/379723883): If the above function takes in an enum instead of -// a string, remove this temporary conversion function. -uint8_t ConvertPurchaseActionResultToEnumValue(const std::string& result); - // Logs showing a new UI screen. void LogUiScreenShown(UiState ui_screen);
diff --git a/components/facilitated_payments/core/metrics/facilitated_payments_metrics_unittest.cc b/components/facilitated_payments/core/metrics/facilitated_payments_metrics_unittest.cc index 857be85..41165f1 100644 --- a/components/facilitated_payments/core/metrics/facilitated_payments_metrics_unittest.cc +++ b/components/facilitated_payments/core/metrics/facilitated_payments_metrics_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/task_environment.h" #include "base/types/expected.h" #include "components/facilitated_payments/core/utils/facilitated_payments_ui_utils.h" +#include "components/facilitated_payments/core/utils/facilitated_payments_utils.h" #include "components/ukm/test_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -157,14 +158,28 @@ TEST(FacilitatedPaymentsMetricsTest, LogInitiatePurchaseActionResultAndLatency) { - for (const std::string& result : {"Succeeded", "Failed", "Abandoned"}) { + for (PurchaseActionResult result : + {PurchaseActionResult::kResultOk, PurchaseActionResult::kCouldNotInvoke, + PurchaseActionResult::kResultCanceled}) { base::HistogramTester histogram_tester; LogInitiatePurchaseActionResultAndLatency(result, base::Milliseconds(10)); + std::string result_string; + switch (result) { + case PurchaseActionResult::kResultOk: + result_string = "Succeeded"; + break; + case PurchaseActionResult::kCouldNotInvoke: + result_string = "Failed"; + break; + case PurchaseActionResult::kResultCanceled: + result_string = "Abandoned"; + break; + } histogram_tester.ExpectBucketCount( - base::StrCat({"FacilitatedPayments.Pix.InitiatePurchaseAction.", result, - ".Latency"}), + base::StrCat({"FacilitatedPayments.Pix.InitiatePurchaseAction.", + result_string, ".Latency"}), /*sample=*/10, /*expected_count=*/1); } @@ -255,9 +270,11 @@ } } -TEST_F(FacilitatedPaymentsMetricsUkmTest, LogInitiatePurchaseActionResult) { +TEST_F(FacilitatedPaymentsMetricsUkmTest, LogInitiatePurchaseActionResultUkm) { size_t index = 0; - for (const std::string result : {"Succeeded", "Failed", "Abandoned"}) { + for (PurchaseActionResult result : + {PurchaseActionResult::kResultOk, PurchaseActionResult::kCouldNotInvoke, + PurchaseActionResult::kResultCanceled}) { LogInitiatePurchaseActionResultUkm(result, ukm::UkmRecorder::GetNewSourceID()); @@ -268,7 +285,7 @@ kResultName}); ASSERT_EQ(ukm_entries.size(), index + 1); EXPECT_EQ(ukm_entries[index++].metrics.at("Result"), - ConvertPurchaseActionResultToEnumValue(result)); + static_cast<uint8_t>(result)); } }
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc index b2af449..82a6f24 100644 --- a/components/lens/lens_features.cc +++ b/components/lens/lens_features.cc
@@ -289,7 +289,7 @@ constexpr base::FeatureParam<base::TimeDelta> kLensSearchboxAutocompleteTimeout{ &kLensOverlayContextualSearchbox, "lens-searchbox-autocomplete-timeout", - base::Milliseconds(3000)}; + base::Milliseconds(10000)}; constexpr base::FeatureParam<bool> kShowContextualSearchboxSearchSuggest{ &kLensOverlayContextualSearchbox,
diff --git a/components/metrics/content/content_stability_metrics_provider_unittest.cc b/components/metrics/content/content_stability_metrics_provider_unittest.cc index c65116b..67b09db4 100644 --- a/components/metrics/content/content_stability_metrics_provider_unittest.cc +++ b/components/metrics/content/content_stability_metrics_provider_unittest.cc
@@ -80,7 +80,8 @@ base::HistogramTester histogram_tester; metrics::ContentStabilityMetricsProvider provider(prefs(), nullptr); - content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY); + content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY, + content::ChildProcessId()); child_process_data.metrics_name = kTestUtilityProcessName; provider.BrowserChildProcessLaunchedAndConnected(child_process_data); @@ -113,7 +114,8 @@ base::HistogramTester histogram_tester; metrics::ContentStabilityMetricsProvider provider(prefs(), nullptr); - content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY); + content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY, + content::ChildProcessId()); child_process_data.metrics_name = kTestCdmServiceUtilityProcessName; child_process_data.sandbox_type = sandbox::mojom::Sandbox::kCdm; @@ -138,7 +140,8 @@ base::HistogramTester histogram_tester; metrics::ContentStabilityMetricsProvider provider(prefs(), nullptr); - content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY); + content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY, + content::ChildProcessId()); child_process_data.metrics_name = kTestCdmServiceUtilityProcessName; child_process_data.sandbox_type = sandbox::mojom::Sandbox::kCdm; @@ -170,7 +173,8 @@ base::HistogramTester histogram_tester; metrics::ContentStabilityMetricsProvider provider(prefs(), nullptr); - content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY); + content::ChildProcessData child_process_data(content::PROCESS_TYPE_UTILITY, + content::ChildProcessId()); child_process_data.metrics_name = kTestMediaFoundationServiceUtilityProcessName; child_process_data.sandbox_type =
diff --git a/components/mirroring/service/media_remoter_unittest.cc b/components/mirroring/service/media_remoter_unittest.cc index ef4c10bb..bb13e22 100644 --- a/components/mirroring/service/media_remoter_unittest.cc +++ b/components/mirroring/service/media_remoter_unittest.cc
@@ -28,7 +28,6 @@ #include "third_party/openscreen/src/platform/api/time.h" #include "third_party/openscreen/src/platform/base/trivial_clock_traits.h" -using media::cast::RtpPayloadType; using media::mojom::RemotingSinkMetadata; using media::mojom::RemotingStopReason; using mirroring::mojom::SessionType; @@ -220,10 +219,8 @@ media_remoter_->StartRpcMessaging( cast_environment, std::move(openscreen_test_senders_->audio_sender), std::move(openscreen_test_senders_->video_sender), - MirrorSettings::GetDefaultAudioConfig(RtpPayloadType::REMOTE_AUDIO, - media::AudioCodec::kUnknown), - MirrorSettings::GetDefaultVideoConfig(RtpPayloadType::REMOTE_VIDEO, - media::VideoCodec::kUnknown)); + MirrorSettings::GetDefaultAudioConfig(media::AudioCodec::kUnknown), + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kUnknown)); task_environment_.RunUntilIdle(); Mock::VerifyAndClear(&remoting_source_); }
diff --git a/components/mirroring/service/mirror_settings.cc b/components/mirroring/service/mirror_settings.cc index ee8aeb3..ca09a91 100644 --- a/components/mirroring/service/mirror_settings.cc +++ b/components/mirroring/service/mirror_settings.cc
@@ -20,7 +20,6 @@ using media::ResolutionChangePolicy; using media::cast::AudioCodecParams; using media::cast::FrameSenderConfig; -using media::cast::RtpPayloadType; using media::cast::VideoCodecParams; namespace mirroring { @@ -85,7 +84,6 @@ // static FrameSenderConfig MirrorSettings::GetDefaultAudioConfig( - RtpPayloadType payload_type, media::AudioCodec codec) { FrameSenderConfig config; config.sender_ssrc = 1; @@ -93,8 +91,7 @@ const base::TimeDelta playout_delay = GetPlayoutDelay(); config.min_playout_delay = playout_delay; config.max_playout_delay = playout_delay; - config.rtp_payload_type = payload_type; - config.rtp_timebase = (payload_type == RtpPayloadType::REMOTE_AUDIO) + config.rtp_timebase = (codec == media::AudioCodec::kUnknown) ? media::cast::kRemotingRtpTimebase : kAudioTimebase; config.channels = kAudioChannels; @@ -107,7 +104,6 @@ // static FrameSenderConfig MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType payload_type, media::VideoCodec codec) { FrameSenderConfig config; config.sender_ssrc = 11; @@ -115,8 +111,7 @@ const base::TimeDelta playout_delay = GetPlayoutDelay(); config.min_playout_delay = playout_delay; config.max_playout_delay = playout_delay; - config.rtp_payload_type = payload_type; - config.rtp_timebase = (payload_type == RtpPayloadType::REMOTE_VIDEO) + config.rtp_timebase = (codec == media::VideoCodec::kUnknown) ? media::cast::kRemotingRtpTimebase : kVideoTimebase; config.channels = 1;
diff --git a/components/mirroring/service/mirror_settings.h b/components/mirroring/service/mirror_settings.h index 5f28c43..eb2d9c97 100644 --- a/components/mirroring/service/mirror_settings.h +++ b/components/mirroring/service/mirror_settings.h
@@ -43,10 +43,8 @@ // Get the audio/video config with given codec. static media::cast::FrameSenderConfig GetDefaultAudioConfig( - media::cast::RtpPayloadType payload_type, media::AudioCodec codec); static media::cast::FrameSenderConfig GetDefaultVideoConfig( - media::cast::RtpPayloadType payload_type, media::VideoCodec codec); // Call to override the default resolution settings.
diff --git a/components/mirroring/service/openscreen_session_host.cc b/components/mirroring/service/openscreen_session_host.cc index 6dbb6dd1..07814f3 100644 --- a/components/mirroring/service/openscreen_session_host.cc +++ b/components/mirroring/service/openscreen_session_host.cc
@@ -69,7 +69,6 @@ using media::cast::OperationalStatus; using media::cast::Packet; using media::cast::PacketEvent; -using media::cast::RtpPayloadType; using media::mojom::RemotingSinkAudioCapability; using media::mojom::RemotingSinkVideoCapability; using mirroring::mojom::SessionError; @@ -1059,8 +1058,8 @@ std::vector<openscreen::cast::VideoCaptureConfig> video_configs; if (session_params_.type != SessionType::VIDEO_ONLY) { - last_offered_audio_config_ = MirrorSettings::GetDefaultAudioConfig( - RtpPayloadType::AUDIO_OPUS, media::AudioCodec::kOpus); + last_offered_audio_config_ = + MirrorSettings::GetDefaultAudioConfig(media::AudioCodec::kOpus); UpdateConfigUsingSessionParameters(session_params_, *last_offered_audio_config_); UpdateAudioConfigMaxBitrate(*last_offered_audio_config_); @@ -1080,8 +1079,8 @@ media::cast::encoding_support::IsHardwareEnabled( media::VideoCodec::kVP8, supported_profiles_); if (should_offer_hardware_vp9) { - FrameSenderConfig config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::VIDEO_VP9, media::VideoCodec::kVP9); + FrameSenderConfig config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kVP9); UpdateConfigUsingSessionParameters(session_params_, config); config.use_hardware_encoder = true; last_offered_video_configs_.push_back(config); @@ -1089,8 +1088,8 @@ } if (should_offer_hardware_h264) { - FrameSenderConfig config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::VIDEO_H264, media::VideoCodec::kH264); + FrameSenderConfig config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kH264); UpdateConfigUsingSessionParameters(session_params_, config); config.use_hardware_encoder = true; last_offered_video_configs_.push_back(config); @@ -1098,8 +1097,8 @@ } if (should_offer_hardware_vp8) { - FrameSenderConfig config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::VIDEO_VP8, media::VideoCodec::kVP8); + FrameSenderConfig config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kVP8); UpdateConfigUsingSessionParameters(session_params_, config); config.use_hardware_encoder = true; last_offered_video_configs_.push_back(config); @@ -1109,8 +1108,8 @@ // Then add software AV1 if enabled. if (media::cast::encoding_support::IsSoftwareEnabled( media::VideoCodec::kAV1)) { - FrameSenderConfig config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::VIDEO_AV1, media::VideoCodec::kAV1); + FrameSenderConfig config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kAV1); UpdateConfigUsingSessionParameters(session_params_, config); last_offered_video_configs_.push_back(config); video_configs.push_back(ToOpenscreenVideoConfig(config)); @@ -1121,8 +1120,8 @@ if (!should_offer_hardware_vp9 && media::cast::encoding_support::IsSoftwareEnabled( media::VideoCodec::kVP9)) { - FrameSenderConfig config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::VIDEO_VP9, media::VideoCodec::kVP9); + FrameSenderConfig config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kVP9); UpdateConfigUsingSessionParameters(session_params_, config); last_offered_video_configs_.push_back(config); video_configs.push_back(ToOpenscreenVideoConfig(config)); @@ -1132,8 +1131,8 @@ if (!should_offer_hardware_vp8 && media::cast::encoding_support::IsSoftwareEnabled( media::VideoCodec::kVP8)) { - FrameSenderConfig config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::VIDEO_VP8, media::VideoCodec::kVP8); + FrameSenderConfig config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kVP8); UpdateConfigUsingSessionParameters(session_params_, config); last_offered_video_configs_.push_back(config); video_configs.push_back(ToOpenscreenVideoConfig(config)); @@ -1149,13 +1148,13 @@ } void OpenscreenSessionHost::NegotiateRemoting() { - FrameSenderConfig audio_config = MirrorSettings::GetDefaultAudioConfig( - RtpPayloadType::REMOTE_AUDIO, media::AudioCodec::kUnknown); + FrameSenderConfig audio_config = + MirrorSettings::GetDefaultAudioConfig(media::AudioCodec::kUnknown); UpdateAudioConfigMaxBitrate(audio_config); UpdateConfigUsingSessionParameters(session_params_, audio_config); - FrameSenderConfig video_config = MirrorSettings::GetDefaultVideoConfig( - RtpPayloadType::REMOTE_VIDEO, media::VideoCodec::kUnknown); + FrameSenderConfig video_config = + MirrorSettings::GetDefaultVideoConfig(media::VideoCodec::kUnknown); UpdateConfigUsingSessionParameters(session_params_, video_config); last_offered_audio_config_ = audio_config;
diff --git a/components/mirroring/service/openscreen_session_host_unittest.cc b/components/mirroring/service/openscreen_session_host_unittest.cc index 980b6e7..b8ddd45 100644 --- a/components/mirroring/service/openscreen_session_host_unittest.cc +++ b/components/mirroring/service/openscreen_session_host_unittest.cc
@@ -913,7 +913,6 @@ // Oh no! The encoder had a problem. FrameSenderConfig config; config.use_hardware_encoder = true; - config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; config.video_codec_params = media::cast::VideoCodecParams{media::VideoCodec::kVP8}; PushEncoderStatusChange(
diff --git a/components/mirroring/service/remoting_sender.cc b/components/mirroring/service/remoting_sender.cc index 78835ba..e8ead46 100644 --- a/components/mirroring/service/remoting_sender.cc +++ b/components/mirroring/service/remoting_sender.cc
@@ -162,8 +162,7 @@ base::Unretained(this)), std::move(pipe))), stream_sender_(this, std::move(stream_sender)), - is_audio_(config.rtp_payload_type <= - media::cast::RtpPayloadType::REMOTE_AUDIO), + is_audio_(config.is_audio()), frame_factory_( std::make_unique<SenderEncodedFrameFactory>(config.rtp_timebase, *frame_sender_,
diff --git a/components/mirroring/service/rtp_stream.cc b/components/mirroring/service/rtp_stream.cc index 36f0925..8185cd5 100644 --- a/components/mirroring/service/rtp_stream.cc +++ b/components/mirroring/service/rtp_stream.cc
@@ -13,9 +13,6 @@ #include "media/cast/sender/audio_sender.h" #include "media/cast/sender/video_sender.h" -using media::cast::FrameSenderConfig; -using media::cast::RtpPayloadType; - namespace mirroring { VideoRtpStream::VideoRtpStream(
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 1aafb2ca..2bade5e 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
@@ -105,7 +105,7 @@ /** See {@link #shouldRetainOmniboxOnFocus()}. */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) public static final CachedFlag sRetainOmniboxOnFocus = - newFlag(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS, FeatureState.DISABLED); + newFlag(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS, FeatureState.ENABLED_IN_TEST); public static final CachedFlag sAndroidHubSearch = newFlag(OmniboxFeatureList.ANDROID_HUB_SEARCH, FeatureState.DISABLED);
diff --git a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java index 45d7f1d..7cafe57d 100644 --- a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java +++ b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java
@@ -78,12 +78,6 @@ @Test @SmallTest - public void testShouldRetainOmniboxOnFocus_withFeatureInDefaultState() { - testShouldRetainOmniboxOnFocus(/* expectFeatureEnabled= */ false); - } - - @Test - @SmallTest @DisableFeatures(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS) public void testShouldRetainOmniboxOnFocus_withFeatureExplicitlyDisabled() { testShouldRetainOmniboxOnFocus(/* expectFeatureEnabled= */ false);
diff --git a/components/optimization_guide/core/model_execution/on_device_model_component.cc b/components/optimization_guide/core/model_execution/on_device_model_component.cc index dfabf35..e44fe9f 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_component.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_component.cc
@@ -138,6 +138,18 @@ return registration_criteria_.get(); } +int64_t OnDeviceModelComponentStateManager::GetDiskBytesAvailableForModel() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return disk_space_available_; +} + +bool OnDeviceModelComponentStateManager::IsLowTierDevice() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return IsPerformanceClassCompatible( + features::kLowTierPerformanceClassListForOnDeviceModel.Get(), + PerformanceClassFromPref(*local_state_)); +} + void OnDeviceModelComponentStateManager::OnDeviceEligibleFeatureUsed( ModelBasedCapabilityKey feature) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -227,8 +239,9 @@ void OnDeviceModelComponentStateManager::CompleteUpdateRegistration( int64_t disk_space_free_bytes) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + disk_space_available_ = disk_space_free_bytes; RegistrationCriteria criteria = - GetRegistrationCriteria(disk_space_free_bytes); + ComputeRegistrationCriteria(disk_space_free_bytes); bool first_registration_attempt = !registration_criteria_; registration_criteria_ = std::make_unique<RegistrationCriteria>(criteria); @@ -273,7 +286,7 @@ } OnDeviceModelComponentStateManager::RegistrationCriteria -OnDeviceModelComponentStateManager::GetRegistrationCriteria( +OnDeviceModelComponentStateManager::ComputeRegistrationCriteria( int64_t disk_space_free_bytes) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); RegistrationCriteria result;
diff --git a/components/optimization_guide/core/model_execution/on_device_model_component.h b/components/optimization_guide/core/model_execution/on_device_model_component.h index 8dc5546c..edd3ba1 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_component.h +++ b/components/optimization_guide/core/model_execution/on_device_model_component.h
@@ -179,6 +179,13 @@ // registration has been computed yet. const RegistrationCriteria* GetRegistrationCriteria(); + // Return the most recently queried free disk space in bytes, which is used to + // determine eligibility for model install. + int64_t GetDiskBytesAvailableForModel(); + + // Returns true if this is determined to be a low tier device. + bool IsLowTierDevice() const; + base::WeakPtr<OnDeviceModelComponentStateManager> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } @@ -202,7 +209,8 @@ std::unique_ptr<Delegate> delegate); ~OnDeviceModelComponentStateManager(); - RegistrationCriteria GetRegistrationCriteria(int64_t disk_space_free_bytes); + RegistrationCriteria ComputeRegistrationCriteria( + int64_t disk_space_free_bytes); // Installs the component installer if it needs installed. void BeginUpdateRegistration(); @@ -226,6 +234,8 @@ // Null until first registration attempt. std::unique_ptr<RegistrationCriteria> registration_criteria_ GUARDED_BY_CONTEXT(sequence_checker_); + // Most recently queried disk space available for model install. + int64_t disk_space_available_ GUARDED_BY_CONTEXT(sequence_checker_) = 0; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/components/optimization_guide/core/model_execution/on_device_model_component_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_component_unittest.cc index c13e70f..4669994 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_component_unittest.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_component_unittest.cc
@@ -53,7 +53,8 @@ feature_list_.InitWithFeaturesAndParameters( {{features::kOptimizationGuideModelExecution, {}}, - {features::kOptimizationGuideOnDeviceModel, + {features::kOptimizationGuideOnDeviceModel, {}}, + {features::kOnDeviceModelPerformanceParams, {{"compatible_on_device_performance_classes", "3,4,5,6"}}}}, /*disabled_features=*/{}); }
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc index 370180e..42a2570d 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller.cc
@@ -279,6 +279,10 @@ // TODO(crbug.com/302402959): Choose max_tokens based on device. params->max_tokens = features::GetOnDeviceModelMaxTokens(); params->adaptation_ranks = features::GetOnDeviceModelAllowedAdaptationRanks(); + if (on_device_component_state_manager_ && + on_device_component_state_manager_->IsLowTierDevice()) { + params->performance_hint = ml::ModelPerformanceHint::kFastestInference; + } service_client_.Get()->LoadModel( std::move(params), std::move(model), base::DoNothingAs<void(on_device_model::mojom::LoadModelResult)>());
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc index f14b879f..c48dc1485 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
@@ -213,6 +213,9 @@ {"on_device_model_disable_crash_count", "3"}, {"on_device_model_crash_backoff_base_time", "1m"}, {"on_device_model_max_crash_backoff_time", "1h"}}}, + {features::kOnDeviceModelPerformanceParams, + {{"compatible_on_device_performance_classes", "*"}, + {"compatible_low_tier_on_device_performance_classes", "3"}}}, {features::kTextSafetyClassifier, {}}, {features::kOnDeviceModelValidation, {{"on_device_model_validation_delay", "0"}}}}, @@ -3851,4 +3854,17 @@ EXPECT_EQ(0u, test_uploader.uploaded_logs().size()); } +TEST_F(OnDeviceModelServiceControllerTest, SendsPerformanceHint) { + // Low performance class should use fastest inference. + pref_service_.SetInteger( + model_execution::prefs::localstate::kOnDevicePerformanceClass, + base::to_underlying(OnDeviceModelPerformanceClass::kLow)); + Initialize(standard_assets_); + auto session = CreateSession(); + session->ExecuteModel(PageUrlRequest("foo"), + response_.GetStreamingCallback()); + ASSERT_TRUE(response_.GetFinalStatus()); + EXPECT_EQ(*response_.value(), "Fastest inference\nInput: execute:foo\n"); +} + } // namespace optimization_guide
diff --git a/components/optimization_guide/core/model_util.cc b/components/optimization_guide/core/model_util.cc index 3f64cc93..b1d4311 100644 --- a/components/optimization_guide/core/model_util.cc +++ b/components/optimization_guide/core/model_util.cc
@@ -138,6 +138,8 @@ return "ModelExecutionFeatureHistoryQueryIntent"; case proto::OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_SCAM_DETECTION: return "ModelExecutionFeatureScamDetection"; + case proto::OPTIMIZATION_TARGET_EXPERIMENTAL_EMBEDDER: + return "ExperimentalEmbedder"; // Whenever a new value is added, make sure to add it to the OptTarget // variant list in // //tools/metrics/histograms/metadata/optimization/histograms.xml.
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index 0985a15..abacdc9 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -202,10 +202,19 @@ "AiSettingsPageEnterpriseDisabledUi", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kOnDeviceModelPerformanceParams, + "OnDeviceModelPerformanceParams", + base::FEATURE_ENABLED_BY_DEFAULT); + const base::FeatureParam<std::string> kPerformanceClassListForOnDeviceModel{ - &kOptimizationGuideOnDeviceModel, + &kOnDeviceModelPerformanceParams, "compatible_on_device_performance_classes", "5,6"}; +const base::FeatureParam<std::string> + kLowTierPerformanceClassListForOnDeviceModel{ + &kOnDeviceModelPerformanceParams, + "compatible_low_tier_on_device_performance_classes", ""}; + BASE_FEATURE(kOptimizationGuideIconView, "OptimizationGuideIconView", base::FEATURE_DISABLED_BY_DEFAULT); @@ -752,12 +761,16 @@ base::Days(30)); } +int GetDiskSpaceRequiredInMbForOnDeviceModelInstall() { + return base::GetFieldTrialParamByFeatureAsInt( + kOptimizationGuideOnDeviceModel, + "on_device_model_free_space_mb_required_to_install", 20 * 1024); +} + bool IsFreeDiskSpaceSufficientForOnDeviceModelInstall( int64_t free_disk_space_bytes) { - return base::GetFieldTrialParamByFeatureAsInt( - kOptimizationGuideOnDeviceModel, - "on_device_model_free_space_mb_required_to_install", - 20 * 1024) <= free_disk_space_bytes / (1024 * 1024); + return GetDiskSpaceRequiredInMbForOnDeviceModelInstall() <= + free_disk_space_bytes / (1024 * 1024); } bool IsFreeDiskSpaceTooLowForOnDeviceModelInstall(
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h index 0e94704..ff665d9 100644 --- a/components/optimization_guide/core/optimization_guide_features.h +++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -90,6 +90,11 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) extern const base::FeatureParam<bool> kShowAiSettingsForTesting; +// Allows setting feature params for model download configuration, such as +// minimum performance class for download. +COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) +BASE_DECLARE_FEATURE(kOnDeviceModelPerformanceParams); + // Comma-separated list of performance classes (e.g. "3,4,5") that should // download the base model. Use "*" if there is no performance class // requirement. @@ -97,6 +102,13 @@ extern const base::FeatureParam<std::string> kPerformanceClassListForOnDeviceModel; +// Comma-separated list of performance classes that should use a smaller model +// if available. This should be a subset of +// kPerformanceClassListForOnDeviceModel. +COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) +extern const base::FeatureParam<std::string> + kLowTierPerformanceClassListForOnDeviceModel; + COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kOptimizationGuideIconView); @@ -450,6 +462,10 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) base::TimeDelta GetOnDeviceModelRetentionTime(); +// Return the disk space (in MiB) required for on device model install. +COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) +int GetDiskSpaceRequiredInMbForOnDeviceModelInstall(); + // Whether there is enough free disk space to allow on-device model // installation. COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES)
diff --git a/components/optimization_guide/proto/features/product_specifications.proto b/components/optimization_guide/proto/features/product_specifications.proto index ebd0661..288372d 100644 --- a/components/optimization_guide/proto/features/product_specifications.proto +++ b/components/optimization_guide/proto/features/product_specifications.proto
@@ -29,7 +29,7 @@ } // Data logged for each Product Specifications table by client. -// Next ID: 4 +// Next ID: 5 message ProductSpecificationsQuality { // The identifiers of the products that user is requesting product // specifications for. @@ -41,6 +41,10 @@ // Whether the user thumbs upped or downed the Product Specifications table. UserFeedback user_feedback = 3; + + // ID of the product specifications table. This is generated by the client and + // is used to identify log entries from the same product specifications table. + string table_id = 4; } // Information needed to identify a product.
diff --git a/components/optimization_guide/proto/features/writing_assistance_api.proto b/components/optimization_guide/proto/features/writing_assistance_api.proto new file mode 100644 index 0000000..41cfeec --- /dev/null +++ b/components/optimization_guide/proto/features/writing_assistance_api.proto
@@ -0,0 +1,80 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto3"; + +package optimization_guide.proto; + +import "components/optimization_guide/proto/model_quality_metadata.proto"; + +option optimize_for = LITE_RUNTIME; +option java_package = "org.chromium.components.optimization_guide.features.proto"; + +option java_outer_classname = "WritingAssistanceApiProto"; + +// DO NOT EDIT THIS FILE DIRECTLY! +// +// This file is generated in g3 and then synced to Chrome. Instead, please +// refer to http://go/chrome-intelligence-feature-protos (Google-internal link), +// and then changes will be synced with Chrome automatically. + +message WritingAssistanceApiLoggingData { + WritingAssistanceApiRequest request = 1; + + WritingAssistanceApiResponse response = 2; + + ModelExecutionInfo model_execution_info = 3; +} + +message WritingAssistanceApiRequest { + string context = 1; + + WritingAssistanceApiOptions options = 2; + + string rewrite_text = 3; + + string shared_context = 4; +} + +message WritingAssistanceApiOptions { + WritingAssistanceApiOutputTone output_tone = 1; + + WritingAssistanceApiOutputFormat output_format = 2; + + WritingAssistanceApiOutputLength output_length = 3; + + string output_language = 4; // TODO(crbug.com/372099809): Should this be an enum? +} + +message WritingAssistanceApiResponse { + string output = 1; +} + +enum WritingAssistanceApiOutputTone { + WRITING_ASSISTANCE_API_OUTPUT_TONE_NOT_SPECIFIED = 0; + + WRITING_ASSISTANCE_API_OUTPUT_TONE_FORMAL = 1; + + WRITING_ASSISTANCE_API_OUTPUT_TONE_NEUTRAL = 2; + + WRITING_ASSISTANCE_API_OUTPUT_TONE_CASUAL = 3; +} + +enum WritingAssistanceApiOutputFormat { + WRITING_ASSISTANCE_API_OUTPUT_FORMAT_NOT_SPECIFIED = 0; + + WRITING_ASSISTANCE_API_OUTPUT_FORMAT_PLAIN_TEXT = 1; + + WRITING_ASSISTANCE_API_OUTPUT_FORMAT_MARKDOWN = 2; +} + +enum WritingAssistanceApiOutputLength { + WRITING_ASSISTANCE_API_OUTPUT_LENGTH_NOT_SPECIFIED = 0; + + WRITING_ASSISTANCE_API_OUTPUT_LENGTH_SHORT = 1; + + WRITING_ASSISTANCE_API_OUTPUT_LENGTH_MEDIUM = 2; + + WRITING_ASSISTANCE_API_OUTPUT_LENGTH_LONG = 3; +}
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto index b7493da..30f3a36 100644 --- a/components/optimization_guide/proto/models.proto +++ b/components/optimization_guide/proto/models.proto
@@ -122,7 +122,7 @@ // The scenarios for which the optimization guide has models for. enum OptimizationTarget { - reserved 14; + reserved 14, 56; OPTIMIZATION_TARGET_UNKNOWN = 0; // Should only be applied when the page load is predicted to be painful. @@ -238,6 +238,8 @@ OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_HISTORY_QUERY_INTENT = 54; // Target for scam detection feature config. OPTIMIZATION_TARGET_MODEL_EXECUTION_FEATURE_SCAM_DETECTION = 55; + // Target for assessing embedding model performance. + OPTIMIZATION_TARGET_EXPERIMENTAL_EMBEDDER = 57; } // The model engine versions that can be used to do model inference.
diff --git a/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc b/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc index 0fcdd74f..6e2a030b 100644 --- a/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc +++ b/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc
@@ -107,6 +107,12 @@ WebDXFeature::kStorageAccess}, {WebFeature::kStorageAccessAPI_requestStorageAccess_Method, WebDXFeature::kStorageAccess}, + {WebFeature::kStorageAccessAPI_requestStorageAccessFor_Method, + WebDXFeature::kStorageAccess}, + {WebFeature::kStorageAccessAPI_requestStorageAccess_BeyondCookies, + WebDXFeature::kNonCookieStorageAccess}, + {WebFeature::kStorageAccessAPI_hasUnpartitionedCookieAccess, + WebDXFeature::kNonCookieStorageAccess}, {WebFeature::kStorageBucketsOpen, WebDXFeature::kStorageBuckets}, {WebFeature::kCSSSelectorTargetText, WebDXFeature::kTargetText}, {WebFeature::kHTMLTemplateElement, WebDXFeature::kTemplate}, @@ -304,6 +310,9 @@ {WebFeature::kVirtualKeyboardOverlayPolicy, WebDXFeature::kVirtualKeyboard}, {WebFeature::kVirtualKeyboardShow, WebDXFeature::kVirtualKeyboard}, + {WebFeature::kDurationFormat, WebDXFeature::kIntlDurationFormat}, + {WebFeature::kWebAppWindowControlsOverlay, + WebDXFeature::kWindowControlsOverlay}, }}; return *kMap;
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index e0fc97d9..ed6fa3b 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -96,8 +96,6 @@ "graph/graph_impl_util.h", "graph/graph_operations.cc", "graph/graph_registered.cc", - "graph/initializing_frame_node_observer.cc", - "graph/initializing_frame_node_observer.h", "graph/node.cc", "graph/node_attached_data.cc", "graph/node_attached_data_storage.cc",
diff --git a/components/performance_manager/decorators/frame_visibility_decorator.cc b/components/performance_manager/decorators/frame_visibility_decorator.cc index b4e1e160..c3fd4eb2 100644 --- a/components/performance_manager/decorators/frame_visibility_decorator.cc +++ b/components/performance_manager/decorators/frame_visibility_decorator.cc
@@ -67,11 +67,11 @@ void FrameVisibilityDecorator::OnPassedToGraph(Graph* graph) { DCHECK(graph->HasOnlySystemNode()); graph->AddPageNodeObserver(this); - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void FrameVisibilityDecorator::OnTakenFromGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); graph->RemovePageNodeObserver(this); } @@ -107,11 +107,15 @@ OnPageUserVisibilityChanged(page_node, IsBeingMirrored(page_node)); } -void FrameVisibilityDecorator::OnFrameNodeInitializing( - const FrameNode* frame_node) { +void FrameVisibilityDecorator::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { FrameNodeImpl* frame_node_impl = FrameNodeImpl::FromNode(frame_node); frame_node_impl->SetInitialVisibility(GetFrameNodeVisibility( - frame_node_impl, IsPageUserVisible(frame_node_impl->page_node()))); + frame_node_impl, IsPageUserVisible(pending_page_node))); } void FrameVisibilityDecorator::OnCurrentFrameChanged(
diff --git a/components/performance_manager/decorators/frame_visibility_decorator.h b/components/performance_manager/decorators/frame_visibility_decorator.h index b4e7e43..3218d21 100644 --- a/components/performance_manager/decorators/frame_visibility_decorator.h +++ b/components/performance_manager/decorators/frame_visibility_decorator.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FRAME_VISIBILITY_DECORATOR_H_ #define COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FRAME_VISIBILITY_DECORATOR_H_ -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/decorators/page_live_state_decorator.h" #include "components/performance_manager/public/graph/frame_node.h" #include "components/performance_manager/public/graph/graph.h" @@ -25,7 +24,7 @@ class FrameVisibilityDecorator : public GraphOwnedDefaultImpl, public PageNode::ObserverDefaultImpl, public PageLiveStateObserver, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: FrameVisibilityDecorator(); ~FrameVisibilityDecorator() override; @@ -63,7 +62,12 @@ void OnAccessibilityModeChanged(const PageNode* page_node) override {} // FrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; void OnCurrentFrameChanged(const FrameNode* previous_frame_node, const FrameNode* current_frame_node) override; void OnViewportIntersectionChanged(const FrameNode* frame_node) override;
diff --git a/components/performance_manager/decorators/important_frame_decorator.cc b/components/performance_manager/decorators/important_frame_decorator.cc index ff7335b..c6d88bf3 100644 --- a/components/performance_manager/decorators/important_frame_decorator.cc +++ b/components/performance_manager/decorators/important_frame_decorator.cc
@@ -70,15 +70,19 @@ void ImportantFrameDecorator::OnPassedToGraph(Graph* graph) { DCHECK(graph->HasOnlySystemNode()); - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void ImportantFrameDecorator::OnTakenFromGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } -void ImportantFrameDecorator::OnFrameNodeInitializing( - const FrameNode* frame_node) { +void ImportantFrameDecorator::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { CHECK(!frame_node->HadUserActivation()); CHECK(!frame_node->GetViewportIntersection() || frame_node->GetViewportIntersection()->is_intersecting_large_area());
diff --git a/components/performance_manager/decorators/important_frame_decorator.h b/components/performance_manager/decorators/important_frame_decorator.h index 217d936..d895edf 100644 --- a/components/performance_manager/decorators/important_frame_decorator.h +++ b/components/performance_manager/decorators/important_frame_decorator.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_IMPORTANT_FRAME_DECORATOR_H_ #define COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_IMPORTANT_FRAME_DECORATOR_H_ -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/decorators/page_live_state_decorator.h" #include "components/performance_manager/public/graph/frame_node.h" #include "components/performance_manager/public/graph/graph.h" @@ -15,7 +14,7 @@ // Responsible for maintaining the IsImportant() property of frame nodes. class ImportantFrameDecorator : public GraphOwnedDefaultImpl, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: ImportantFrameDecorator(); ~ImportantFrameDecorator() override; @@ -27,8 +26,13 @@ void OnPassedToGraph(Graph* graph) override; void OnTakenFromGraph(Graph* graph) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; void OnHadUserActivationChanged(const FrameNode* frame_node) override; void OnViewportIntersectionChanged(const FrameNode* frame_node) override; };
diff --git a/components/performance_manager/decorators/process_metrics_decorator_unittest.cc b/components/performance_manager/decorators/process_metrics_decorator_unittest.cc index 171f064..e96126e 100644 --- a/components/performance_manager/decorators/process_metrics_decorator_unittest.cc +++ b/components/performance_manager/decorators/process_metrics_decorator_unittest.cc
@@ -11,6 +11,7 @@ #include "base/run_loop.h" #include "base/time/time.h" #include "components/performance_manager/graph/process_node_impl.h" +#include "components/performance_manager/test_support/graph/mock_system_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "content/public/common/process_type.h" @@ -62,20 +63,6 @@ std::move(global_dump))); } -class LenientMockSystemNodeObserver - : public SystemNodeImpl::ObserverDefaultImpl { - public: - LenientMockSystemNodeObserver() = default; - ~LenientMockSystemNodeObserver() override = default; - - MOCK_METHOD(void, - OnProcessMemoryMetricsAvailable, - (const SystemNode*), - (override)); -}; -using MockSystemNodeObserver = - ::testing::StrictMock<LenientMockSystemNodeObserver>; - struct MemoryDumpProcInfo { base::ProcessId pid; uint32_t resident_set_kb;
diff --git a/components/performance_manager/execution_context/execution_context_impl.cc b/components/performance_manager/execution_context/execution_context_impl.cc index f707477..41a6be9 100644 --- a/components/performance_manager/execution_context/execution_context_impl.cc +++ b/components/performance_manager/execution_context/execution_context_impl.cc
@@ -61,6 +61,11 @@ return frame_node_->graph(); } +NodeState FrameExecutionContext::GetNodeState() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return frame_node_->GetNodeState(); +} + const GURL& FrameExecutionContext::GetUrl() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return frame_node_->GetURL(); @@ -113,6 +118,11 @@ return worker_node_->graph(); } +NodeState WorkerExecutionContext::GetNodeState() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return worker_node_->GetNodeState(); +} + const GURL& WorkerExecutionContext::GetUrl() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return worker_node_->GetURL();
diff --git a/components/performance_manager/execution_context/execution_context_impl.h b/components/performance_manager/execution_context/execution_context_impl.h index e95ec5a..8e4310f 100644 --- a/components/performance_manager/execution_context/execution_context_impl.h +++ b/components/performance_manager/execution_context/execution_context_impl.h
@@ -35,6 +35,7 @@ ExecutionContextType GetType() const override; blink::ExecutionContextToken GetToken() const override; Graph* GetGraph() const override; + NodeState GetNodeState() const override; const GURL& GetUrl() const override; const ProcessNode* GetProcessNode() const override; const PriorityAndReason& GetPriorityAndReason() const override; @@ -65,6 +66,7 @@ ExecutionContextType GetType() const override; blink::ExecutionContextToken GetToken() const override; Graph* GetGraph() const override; + NodeState GetNodeState() const override; const GURL& GetUrl() const override; const ProcessNode* GetProcessNode() const override; const PriorityAndReason& GetPriorityAndReason() const override;
diff --git a/components/performance_manager/execution_context/execution_context_registry_impl.cc b/components/performance_manager/execution_context/execution_context_registry_impl.cc index ae3d1ff8..9e5c8f1f 100644 --- a/components/performance_manager/execution_context/execution_context_registry_impl.cc +++ b/components/performance_manager/execution_context/execution_context_registry_impl.cc
@@ -40,6 +40,8 @@ Graph* GetGraph() const override { NOTREACHED(); } + NodeState GetNodeState() const override { NOTREACHED(); } + const GURL& GetUrl() const override { NOTREACHED(); } const ProcessNode* GetProcessNode() const override { NOTREACHED(); }
diff --git a/components/performance_manager/execution_context_priority/ad_frame_voter.cc b/components/performance_manager/execution_context_priority/ad_frame_voter.cc index a11872b..bfce2ad 100644 --- a/components/performance_manager/execution_context_priority/ad_frame_voter.cc +++ b/components/performance_manager/execution_context_priority/ad_frame_voter.cc
@@ -33,14 +33,19 @@ AdFrameVoter::~AdFrameVoter() = default; void AdFrameVoter::InitializeOnGraph(Graph* graph) { - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void AdFrameVoter::TearDownOnGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } -void AdFrameVoter::OnFrameNodeInitializing(const FrameNode* frame_node) { +void AdFrameVoter::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { if (!frame_node->IsAdFrame()) return; @@ -48,7 +53,7 @@ voting_channel_.SubmitVote(GetExecutionContext(frame_node), vote); } -void AdFrameVoter::OnFrameNodeTearingDown(const FrameNode* frame_node) { +void AdFrameVoter::OnBeforeFrameNodeRemoved(const FrameNode* frame_node) { if (!frame_node->IsAdFrame()) return;
diff --git a/components/performance_manager/execution_context_priority/ad_frame_voter.h b/components/performance_manager/execution_context_priority/ad_frame_voter.h index e1fdb5be..e3030378 100644 --- a/components/performance_manager/execution_context_priority/ad_frame_voter.h +++ b/components/performance_manager/execution_context_priority/ad_frame_voter.h
@@ -6,17 +6,17 @@ #define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_AD_FRAME_VOTER_H_ #include "components/performance_manager/execution_context_priority/voter_base.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/public/graph/frame_node.h" namespace performance_manager { namespace execution_context_priority { // This voter tracks frame nodes and casts a TaskPriority::LOWEST vote for each // ad frame. No votes will be cast for non-ad frames. -// Uses `InitializingFrameNodeObserver` because it can affect the initial -// priority of a frame. -class AdFrameVoter : public VoterBase, public InitializingFrameNodeObserver { +// Note: This FrameNodeObserver can affect the initial priority of a frame and +// thus uses `OnBeforeFrameNodeAdded`. +class AdFrameVoter : public VoterBase, public FrameNode::ObserverDefaultImpl { public: static const char kAdFrameReason[]; @@ -30,9 +30,14 @@ void InitializeOnGraph(Graph* graph) override; void TearDownOnGraph(Graph* graph) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; - void OnFrameNodeTearingDown(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; + void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; void OnIsAdFrameChanged(const FrameNode* frame_node) override; VoterId voter_id() const { return voting_channel_.voter_id(); }
diff --git a/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc b/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc index 9a01b9e..fd0d0b3 100644 --- a/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc +++ b/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc
@@ -38,10 +38,10 @@ // GraphOwned: void OnPassedToGraph(Graph* graph) override { - graph->AddInitializingFrameNodeObserver(&ad_frame_voter_); + ad_frame_voter_.InitializeOnGraph(graph); } void OnTakenFromGraph(Graph* graph) override { - graph->RemoveInitializingFrameNodeObserver(&ad_frame_voter_); + ad_frame_voter_.TearDownOnGraph(graph); } // Exposes the DummyVoteObserver to validate expectations.
diff --git a/components/performance_manager/execution_context_priority/boosting_vote_aggregator_unittest.cc b/components/performance_manager/execution_context_priority/boosting_vote_aggregator_unittest.cc index 52bbf18..86638daa 100644 --- a/components/performance_manager/execution_context_priority/boosting_vote_aggregator_unittest.cc +++ b/components/performance_manager/execution_context_priority/boosting_vote_aggregator_unittest.cc
@@ -4,6 +4,7 @@ #include "components/performance_manager/execution_context_priority/boosting_vote_aggregator.h" +#include "base/notreached.h" #include "components/performance_manager/public/execution_context/execution_context.h" #include "components/performance_manager/test_support/voting.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,6 +29,7 @@ return blink::ExecutionContextToken(); } Graph* GetGraph() const override { return nullptr; } + NodeState GetNodeState() const override { NOTREACHED(); } const GURL& GetUrl() const override { return url_; } const ProcessNode* GetProcessNode() const override { return nullptr; } const PriorityAndReason& GetPriorityAndReason() const override {
diff --git a/components/performance_manager/execution_context_priority/frame_audible_voter.cc b/components/performance_manager/execution_context_priority/frame_audible_voter.cc index 103c9d4..76b585c 100644 --- a/components/performance_manager/execution_context_priority/frame_audible_voter.cc +++ b/components/performance_manager/execution_context_priority/frame_audible_voter.cc
@@ -40,19 +40,24 @@ FrameAudibleVoter::~FrameAudibleVoter() = default; void FrameAudibleVoter::InitializeOnGraph(Graph* graph) { - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void FrameAudibleVoter::TearDownOnGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } -void FrameAudibleVoter::OnFrameNodeInitializing(const FrameNode* frame_node) { +void FrameAudibleVoter::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { const Vote vote = GetVote(frame_node->IsAudible()); voting_channel_.SubmitVote(GetExecutionContext(frame_node), vote); } -void FrameAudibleVoter::OnFrameNodeTearingDown(const FrameNode* frame_node) { +void FrameAudibleVoter::OnBeforeFrameNodeRemoved(const FrameNode* frame_node) { voting_channel_.InvalidateVote(GetExecutionContext(frame_node)); }
diff --git a/components/performance_manager/execution_context_priority/frame_audible_voter.h b/components/performance_manager/execution_context_priority/frame_audible_voter.h index f60c9e6..1d104e4 100644 --- a/components/performance_manager/execution_context_priority/frame_audible_voter.h +++ b/components/performance_manager/execution_context_priority/frame_audible_voter.h
@@ -6,18 +6,18 @@ #define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_FRAME_AUDIBLE_VOTER_H_ #include "components/performance_manager/execution_context_priority/voter_base.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/public/graph/frame_node.h" namespace performance_manager { namespace execution_context_priority { // This voter casts a TaskPriority::USER_BLOCKING vote to all audible frames, -// and a TaskPriority::LOWEST vote to non-audible frames. Note: Uses -// `InitializingFrameNodeObserver` because it can affect the initial priority of -// a frame. +// and a TaskPriority::LOWEST vote to non-audible frames. +// Note: This FrameNodeObserver can affect the initial priority of a frame and +// thus uses `OnBeforeFrameNodeAdded`. class FrameAudibleVoter : public VoterBase, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: static const char kFrameAudibleReason[]; @@ -31,9 +31,14 @@ void InitializeOnGraph(Graph* graph) override; void TearDownOnGraph(Graph* graph) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; - void OnFrameNodeTearingDown(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; + void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; void OnIsAudibleChanged(const FrameNode* frame_node) override; VoterId voter_id() const { return voting_channel_.voter_id(); }
diff --git a/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.cc b/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.cc index 897d20f..13057f14 100644 --- a/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.cc +++ b/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.cc
@@ -41,20 +41,24 @@ FrameCapturingMediaStreamVoter::~FrameCapturingMediaStreamVoter() = default; void FrameCapturingMediaStreamVoter::InitializeOnGraph(Graph* graph) { - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void FrameCapturingMediaStreamVoter::TearDownOnGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } -void FrameCapturingMediaStreamVoter::OnFrameNodeInitializing( - const FrameNode* frame_node) { +void FrameCapturingMediaStreamVoter::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { const Vote vote = GetVote(frame_node->IsCapturingMediaStream()); voting_channel_.SubmitVote(GetExecutionContext(frame_node), vote); } -void FrameCapturingMediaStreamVoter::OnFrameNodeTearingDown( +void FrameCapturingMediaStreamVoter::OnBeforeFrameNodeRemoved( const FrameNode* frame_node) { voting_channel_.InvalidateVote(GetExecutionContext(frame_node)); }
diff --git a/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.h b/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.h index f87d09a..5d140b3 100644 --- a/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.h +++ b/components/performance_manager/execution_context_priority/frame_capturing_media_stream_voter.h
@@ -6,18 +6,18 @@ #define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_FRAME_CAPTURING_MEDIA_STREAM_VOTER_H_ #include "components/performance_manager/execution_context_priority/voter_base.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/public/graph/frame_node.h" namespace performance_manager::execution_context_priority { // This voter casts a TaskPriority::USER_BLOCKING vote to all frames that are // capturing a media stream (audio or video), and a TaskPriority::LOWEST vote // otherwise. -// Note: Uses `InitializingFrameNodeObserver` because it can affect the initial -// priority of a frame. +// Note: This FrameNodeObserver can affect the initial priority of a frame and +// thus uses `OnBeforeFrameNodeAdded`. class FrameCapturingMediaStreamVoter : public VoterBase, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: static const char kFrameCapturingMediaStreamReason[]; @@ -33,9 +33,14 @@ void InitializeOnGraph(Graph* graph) override; void TearDownOnGraph(Graph* graph) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; - void OnFrameNodeTearingDown(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; + void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; void OnIsCapturingMediaStreamChanged(const FrameNode* frame_node) override; VoterId voter_id() const { return voting_channel_.voter_id(); }
diff --git a/components/performance_manager/execution_context_priority/frame_visibility_voter.cc b/components/performance_manager/execution_context_priority/frame_visibility_voter.cc index 3bea240..5054c99 100644 --- a/components/performance_manager/execution_context_priority/frame_visibility_voter.cc +++ b/components/performance_manager/execution_context_priority/frame_visibility_voter.cc
@@ -54,21 +54,26 @@ FrameVisibilityVoter::~FrameVisibilityVoter() = default; void FrameVisibilityVoter::InitializeOnGraph(Graph* graph) { - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void FrameVisibilityVoter::TearDownOnGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } -void FrameVisibilityVoter::OnFrameNodeInitializing( - const FrameNode* frame_node) { +void FrameVisibilityVoter::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { const Vote vote = GetVote(frame_node->GetVisibility(), frame_node->IsImportant()); voting_channel_.SubmitVote(GetExecutionContext(frame_node), vote); } -void FrameVisibilityVoter::OnFrameNodeTearingDown(const FrameNode* frame_node) { +void FrameVisibilityVoter::OnBeforeFrameNodeRemoved( + const FrameNode* frame_node) { voting_channel_.InvalidateVote(GetExecutionContext(frame_node)); }
diff --git a/components/performance_manager/execution_context_priority/frame_visibility_voter.h b/components/performance_manager/execution_context_priority/frame_visibility_voter.h index 488c6b6..95ae08a0 100644 --- a/components/performance_manager/execution_context_priority/frame_visibility_voter.h +++ b/components/performance_manager/execution_context_priority/frame_visibility_voter.h
@@ -6,8 +6,8 @@ #define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_FRAME_VISIBILITY_VOTER_H_ #include "components/performance_manager/execution_context_priority/voter_base.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/public/graph/frame_node.h" namespace performance_manager { namespace execution_context_priority { @@ -19,10 +19,10 @@ // If the kUnimportantFrame feature is enabled, a lesser // TaskPriority::USER_VISIBLE vote is cast for frames that are deemed // unimportant. -// Note: Uses `InitializingFrameNodeObserver` because it can affect the initial -// priority of a frame. +// Note: This FrameNodeObserver can affect the initial priority of a frame and +// thus uses `OnBeforeFrameNodeAdded`. class FrameVisibilityVoter : public VoterBase, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: static const char kFrameVisibilityReason[]; @@ -36,9 +36,14 @@ void InitializeOnGraph(Graph* graph) override; void TearDownOnGraph(Graph* graph) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; - void OnFrameNodeTearingDown(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; + void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; void OnFrameVisibilityChanged(const FrameNode* frame_node, FrameNode::Visibility previous_value) override; void OnIsImportantChanged(const FrameNode* frame_node) override;
diff --git a/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.cc b/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.cc index 69de410a..26b957a 100644 --- a/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.cc +++ b/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.cc
@@ -25,7 +25,9 @@ // Returns the priority that should be used to cast a vote for `frame_node`, // which is basically the parent's priority. Returns std::nullopt when no vote // should be cast. -std::optional<base::TaskPriority> GetVotePriority(const FrameNode* frame_node) { +std::optional<base::TaskPriority> GetVotePriority( + const FrameNode* frame_node, + const FrameNode* parent_frame_node) { // Main frames have no parents to inherit their priority from. if (frame_node->IsMainFrame()) { return std::nullopt; @@ -37,7 +39,7 @@ } const base::TaskPriority parent_priority = - frame_node->GetParentFrameNode()->GetPriorityAndReason().priority(); + parent_frame_node->GetPriorityAndReason().priority(); // Don't cast a vote with the default priority as it wouldn't have any effect // anyways, and this prevent unnecessary work in the aggregators. @@ -50,8 +52,10 @@ return base::TaskPriority::USER_VISIBLE; } -std::optional<Vote> GetVote(const FrameNode* frame_node) { - std::optional<base::TaskPriority> vote_priority = GetVotePriority(frame_node); +std::optional<Vote> GetVote(const FrameNode* frame_node, + const FrameNode* parent_frame_node) { + std::optional<base::TaskPriority> vote_priority = + GetVotePriority(frame_node, parent_frame_node); if (!vote_priority) { return std::nullopt; } @@ -73,28 +77,33 @@ InheritParentPriorityVoter::~InheritParentPriorityVoter() = default; void InheritParentPriorityVoter::InitializeOnGraph(Graph* graph) { - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void InheritParentPriorityVoter::TearDownOnGraph(Graph* graph) { - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } -void InheritParentPriorityVoter::OnFrameNodeInitializing( - const FrameNode* frame_node) { +void InheritParentPriorityVoter::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { voting_channel_.SubmitVote(GetExecutionContext(frame_node), - GetVote(frame_node)); + GetVote(frame_node, pending_parent_frame_node)); } -void InheritParentPriorityVoter::OnFrameNodeTearingDown( +void InheritParentPriorityVoter::OnBeforeFrameNodeRemoved( const FrameNode* frame_node) { voting_channel_.InvalidateVote(GetExecutionContext(frame_node)); } void InheritParentPriorityVoter::OnIsAdFrameChanged( const FrameNode* frame_node) { - voting_channel_.ChangeVote(GetExecutionContext(frame_node), - GetVote(frame_node)); + voting_channel_.ChangeVote( + GetExecutionContext(frame_node), + GetVote(frame_node, frame_node->GetParentFrameNode())); } void InheritParentPriorityVoter::OnPriorityAndReasonChanged( @@ -109,7 +118,7 @@ // Maybe change the vote for every children. for (const FrameNode* child_frame_node : frame_node->GetChildFrameNodes()) { voting_channel_.ChangeVote(GetExecutionContext(child_frame_node), - GetVote(child_frame_node)); + GetVote(child_frame_node, frame_node)); } }
diff --git a/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.h b/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.h index 7091a7c..c97d1f49 100644 --- a/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.h +++ b/components/performance_manager/execution_context_priority/inherit_parent_priority_voter.h
@@ -6,7 +6,6 @@ #define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_INHERIT_PARENT_PRIORITY_VOTER_H_ #include "components/performance_manager/execution_context_priority/voter_base.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" #include "components/performance_manager/public/graph/frame_node.h" @@ -20,8 +19,11 @@ // to do (See https://crbug.com/336161235 for example). // // Ad frames do not inherit the priority of their parent as it is not necessary. +// +// Note: This FrameNodeObserver can affect the initial priority of a frame and +// thus uses `OnBeforeFrameNodeAdded`. class InheritParentPriorityVoter : public VoterBase, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: static const char kPriorityInheritedReason[]; @@ -36,9 +38,14 @@ void InitializeOnGraph(Graph* graph) override; void TearDownOnGraph(Graph* graph) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; - void OnFrameNodeTearingDown(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; + void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; void OnIsAdFrameChanged(const FrameNode* frame_node) override; void OnPriorityAndReasonChanged( const FrameNode* frame_node,
diff --git a/components/performance_manager/execution_context_priority/inherit_parent_priority_voter_unittest.cc b/components/performance_manager/execution_context_priority/inherit_parent_priority_voter_unittest.cc index 051268a..fbc18df7 100644 --- a/components/performance_manager/execution_context_priority/inherit_parent_priority_voter_unittest.cc +++ b/components/performance_manager/execution_context_priority/inherit_parent_priority_voter_unittest.cc
@@ -38,10 +38,10 @@ // GraphOwned: void OnPassedToGraph(Graph* graph) override { - graph->AddInitializingFrameNodeObserver(&inherit_parent_priority_voter_); + inherit_parent_priority_voter_.InitializeOnGraph(graph); } void OnTakenFromGraph(Graph* graph) override { - graph->RemoveInitializingFrameNodeObserver(&inherit_parent_priority_voter_); + inherit_parent_priority_voter_.TearDownOnGraph(graph); } // Exposes the DummyVoteObserver to validate expectations.
diff --git a/components/performance_manager/execution_context_priority/loading_page_voter.cc b/components/performance_manager/execution_context_priority/loading_page_voter.cc index 03318b1..0e2e32c 100644 --- a/components/performance_manager/execution_context_priority/loading_page_voter.cc +++ b/components/performance_manager/execution_context_priority/loading_page_voter.cc
@@ -38,12 +38,12 @@ void LoadingPageVoter::InitializeOnGraph(Graph* graph) { graph->AddPageNodeObserver(this); - graph->AddInitializingFrameNodeObserver(this); + graph->AddFrameNodeObserver(this); } void LoadingPageVoter::TearDownOnGraph(Graph* graph) { graph->RemovePageNodeObserver(this); - graph->RemoveInitializingFrameNodeObserver(this); + graph->RemoveFrameNodeObserver(this); } void LoadingPageVoter::OnPageNodeAdded(const PageNode* page_node) { @@ -76,8 +76,13 @@ } } -void LoadingPageVoter::OnFrameNodeInitializing(const FrameNode* frame_node) { - if (!IsLoading(frame_node->GetPageNode()->GetLoadingState())) { +void LoadingPageVoter::OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) { + if (!IsLoading(pending_page_node->GetLoadingState())) { return; } @@ -86,7 +91,7 @@ Vote(base::TaskPriority::USER_VISIBLE, kPageIsLoadingReason)); } -void LoadingPageVoter::OnFrameNodeTearingDown(const FrameNode* frame_node) { +void LoadingPageVoter::OnBeforeFrameNodeRemoved(const FrameNode* frame_node) { if (!IsLoading(frame_node->GetPageNode()->GetLoadingState())) { return; }
diff --git a/components/performance_manager/execution_context_priority/loading_page_voter.h b/components/performance_manager/execution_context_priority/loading_page_voter.h index 619e71c3..df11bbe 100644 --- a/components/performance_manager/execution_context_priority/loading_page_voter.h +++ b/components/performance_manager/execution_context_priority/loading_page_voter.h
@@ -6,19 +6,19 @@ #define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_LOADING_PAGE_VOTER_H_ #include "components/performance_manager/execution_context_priority/voter_base.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/public/graph/frame_node.h" #include "components/performance_manager/public/graph/page_node.h" namespace performance_manager::execution_context_priority { // This voter casts a TaskPriority::USER_BLOCKING vote to all frames that are // part of a loading page. This makes switching to a loading tab faster. -// Note: Uses `InitializingFrameNodeObserver` because it can affect the initial -// priority of a frame. +// Note: This FrameNodeObserver can affect the initial priority of a frame and +// thus uses `OnBeforeFrameNodeAdded`. class LoadingPageVoter : public VoterBase, public PageNode::ObserverDefaultImpl, - public InitializingFrameNodeObserver { + public FrameNode::ObserverDefaultImpl { public: static const char kPageIsLoadingReason[]; @@ -38,9 +38,14 @@ void OnLoadingStateChanged(const PageNode* page_node, PageNode::LoadingState previous_state) override; - // InitializingFrameNodeObserver: - void OnFrameNodeInitializing(const FrameNode* frame_node) override; - void OnFrameNodeTearingDown(const FrameNode* frame_node) override; + // FrameNodeObserver: + void OnBeforeFrameNodeAdded( + const FrameNode* frame_node, + const FrameNode* pending_parent_frame_node, + const PageNode* pending_page_node, + const ProcessNode* pending_process_node, + const FrameNode* pending_parent_or_outer_document_or_embedder) override; + void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; VoterId voter_id() const { return voting_channel_.voter_id(); }
diff --git a/components/performance_manager/execution_context_priority/root_vote_observer.cc b/components/performance_manager/execution_context_priority/root_vote_observer.cc index 9cd14d5f..8a18a88 100644 --- a/components/performance_manager/execution_context_priority/root_vote_observer.cc +++ b/components/performance_manager/execution_context_priority/root_vote_observer.cc
@@ -18,6 +18,11 @@ void SetPriorityAndReason( const execution_context::ExecutionContext* execution_context, const PriorityAndReason& priority_and_reason) { + // No property changes while the node is leaving graph. + if (execution_context->GetNodeState() == NodeState::kLeavingGraph) { + return; + } + switch (execution_context->GetType()) { case execution_context::ExecutionContextType::kFrameNode: FrameNodeImpl::FromNode(execution_context->GetFrameNode())
diff --git a/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc b/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc index 9816e97..a6e6c3a 100644 --- a/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc +++ b/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc
@@ -6,6 +6,7 @@ #include "components/performance_manager/graph/frame_node_impl.h" #include "components/performance_manager/public/execution_context/execution_context.h" +#include "components/performance_manager/test_support/graph/mock_frame_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "components/performance_manager/test_support/voting.h" @@ -21,23 +22,6 @@ static const char kReason[] = "test reason"; -class LenientMockFrameNodeObserver : public FrameNode::ObserverDefaultImpl { - public: - LenientMockFrameNodeObserver() = default; - LenientMockFrameNodeObserver(const LenientMockFrameNodeObserver&) = delete; - LenientMockFrameNodeObserver& operator=(const LenientMockFrameNodeObserver&) = - delete; - ~LenientMockFrameNodeObserver() override = default; - - MOCK_METHOD(void, - OnPriorityAndReasonChanged, - (const FrameNode*, const PriorityAndReason&), - (override)); -}; - -using MockFrameNodeObserver = - ::testing::StrictMock<LenientMockFrameNodeObserver>; - using RootVoteObserverTest = GraphTestHarness; } // namespace
diff --git a/components/performance_manager/freezing/frozen_frame_aggregator_unittest.cc b/components/performance_manager/freezing/frozen_frame_aggregator_unittest.cc index c1c06fad..8b1c594 100644 --- a/components/performance_manager/freezing/frozen_frame_aggregator_unittest.cc +++ b/components/performance_manager/freezing/frozen_frame_aggregator_unittest.cc
@@ -11,6 +11,7 @@ #include "components/performance_manager/graph/frame_node_impl.h" #include "components/performance_manager/graph/page_node_impl.h" #include "components/performance_manager/graph/process_node_impl.h" +#include "components/performance_manager/test_support/graph/mock_process_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,26 +22,6 @@ using LifecycleState = PageNodeImpl::LifecycleState; -class LenientMockProcessNodeObserver : public ProcessNode::ObserverDefaultImpl { - public: - LenientMockProcessNodeObserver() = default; - - LenientMockProcessNodeObserver(const LenientMockProcessNodeObserver&) = - delete; - LenientMockProcessNodeObserver& operator=( - const LenientMockProcessNodeObserver&) = delete; - - ~LenientMockProcessNodeObserver() override = default; - - MOCK_METHOD(void, - OnAllFramesInProcessFrozen, - (const ProcessNode*), - (override)); -}; - -using MockProcessNodeObserver = - ::testing::StrictMock<LenientMockProcessNodeObserver>; - } // namespace class FrozenFrameAggregatorTest : public GraphTestHarness { @@ -126,7 +107,7 @@ } TEST_F(FrozenFrameAggregatorTest, ProcessAggregation) { - MockProcessNodeObserver obs; + LenientMockProcessNodeObserver obs; graph()->AddProcessNodeObserver(&obs); ExpectProcessData(0, 0);
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc index 5dddc84..10a6e8b 100644 --- a/components/performance_manager/graph/frame_node_impl.cc +++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -13,7 +13,6 @@ #include "base/functional/overloaded.h" #include "base/memory/raw_ptr.h" #include "components/performance_manager/graph/graph_impl.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/graph/page_node_impl.h" #include "components/performance_manager/graph/process_node_impl.h" #include "components/performance_manager/graph/worker_node_impl.h" @@ -765,9 +764,6 @@ parent_frame_node_->AddChildFrame(this); page_node_->AddFrame(base::PassKey<FrameNodeImpl>(), this); process_node_->AddFrame(this); - - // Notify the initializing observers. - graph()->NotifyFrameNodeInitializing(this); } void FrameNodeImpl::OnBeforeLeavingGraph() { @@ -783,9 +779,6 @@ DCHECK(child_frame_nodes_.empty()); - // Notify the initializing observers for cleanup. - graph()->NotifyFrameNodeTearingDown(this); - // Leave the page. DCHECK(graph()->NodeInGraph(page_node_)); page_node_->RemoveFrame(base::PassKey<FrameNodeImpl>(), this);
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc index e637a02..8a91b768 100644 --- a/components/performance_manager/graph/frame_node_impl_unittest.cc +++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -16,6 +16,8 @@ #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" #include "components/performance_manager/public/render_process_host_id.h" #include "components/performance_manager/public/render_process_host_proxy.h" +#include "components/performance_manager/test_support/graph/mock_frame_node_observer.h" +#include "components/performance_manager/test_support/graph/mock_page_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "testing/gmock/include/gmock/gmock.h" @@ -141,86 +143,8 @@ namespace { -class LenientMockObserver : public FrameNodeImpl::Observer { +class MockObserver : public MockFrameNodeObserver { public: - LenientMockObserver() = default; - ~LenientMockObserver() override = default; - - MOCK_METHOD(void, - OnBeforeFrameNodeAdded, - (const FrameNode*, - const FrameNode*, - const PageNode*, - const ProcessNode*, - const FrameNode*), - (override)); - MOCK_METHOD(void, OnFrameNodeAdded, (const FrameNode*), (override)); - MOCK_METHOD(void, OnBeforeFrameNodeRemoved, (const FrameNode*), (override)); - MOCK_METHOD(void, - OnFrameNodeRemoved, - (const FrameNode*, - const FrameNode*, - const PageNode*, - const ProcessNode*, - const FrameNode*), - (override)); - MOCK_METHOD(void, - OnCurrentFrameChanged, - (const FrameNode*, const FrameNode*), - (override)); - MOCK_METHOD(void, OnNetworkAlmostIdleChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, - OnFrameLifecycleStateChanged, - (const FrameNode*), - (override)); - MOCK_METHOD(void, OnURLChanged, (const FrameNode*, const GURL&), (override)); - MOCK_METHOD(void, - OnOriginChanged, - (const FrameNode*, const std::optional<url::Origin>&), - (override)); - MOCK_METHOD(void, OnIsAdFrameChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, - OnFrameIsHoldingWebLockChanged, - (const FrameNode*), - (override)); - MOCK_METHOD(void, - OnFrameIsHoldingIndexedDBLockChanged, - (const FrameNode*), - (override)); - MOCK_METHOD(void, - OnPriorityAndReasonChanged, - (const FrameNode*, const PriorityAndReason& previous_value), - (override)); - MOCK_METHOD(void, OnFrameUsesWebRTCChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, OnHadUserActivationChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, - OnHadFormInteractionChanged, - (const FrameNode*), - (override)); - MOCK_METHOD(void, OnHadUserEditsChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, OnIsAudibleChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, - OnIsCapturingMediaStreamChanged, - (const FrameNode*), - (override)); - MOCK_METHOD(void, - OnViewportIntersectionChanged, - (const FrameNode*), - (override)); - MOCK_METHOD(void, - OnFrameVisibilityChanged, - (const FrameNode*, FrameNode::Visibility), - (override)); - MOCK_METHOD(void, OnIsImportantChanged, (const FrameNode*), (override)); - MOCK_METHOD(void, - OnNonPersistentNotificationCreated, - (const FrameNode*), - (override)); - MOCK_METHOD(void, - OnFirstContentfulPaint, - (const FrameNode*, base::TimeDelta), - (override)); - void SetCreatedFrameNode( const FrameNode* frame_node, const FrameNode* pending_parent_frame_node, @@ -271,8 +195,6 @@ nullptr; }; -using MockObserver = ::testing::StrictMock<LenientMockObserver>; - using ::testing::_; using ::testing::Eq; using ::testing::InSequence; @@ -930,34 +852,6 @@ EXPECT_EQ(child_frame_nodes.size(), frame_node->child_frame_nodes().size()); } -namespace { - -class LenientMockPageObserver : public PageNode::ObserverDefaultImpl { - public: - LenientMockPageObserver() = default; - ~LenientMockPageObserver() override = default; - - MOCK_METHOD(void, - OnBeforePageNodeRemoved, - (const PageNode* page_node), - (override)); - - // Note that embedder functionality is actually tested in the - // performance_manager_browsertest. - MOCK_METHOD(void, - OnOpenerFrameNodeChanged, - (const PageNode*, const FrameNode*), - (override)); - MOCK_METHOD(void, - OnEmbedderFrameNodeChanged, - (const PageNode*, const FrameNode*, EmbeddingType), - (override)); -}; - -using MockPageObserver = ::testing::StrictMock<LenientMockPageObserver>; - -} // namespace - TEST_F(FrameNodeImplTest, PageRelationships) { using EmbeddingType = PageNode::EmbeddingType; @@ -975,7 +869,7 @@ const FrameNode* pframeA1 = static_cast<const FrameNode*>(frameA1.get()); const PageNode* ppageB = static_cast<const PageNode*>(pageB.get()); - MockPageObserver obs; + MockPageNodeObserver obs; graph()->AddPageNodeObserver(&obs); // You can always call the pre-delete embedder clearing helper, even if you @@ -1088,6 +982,7 @@ // These must occur in sequence. EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA2.get())); EXPECT_CALL(obs, OnBeforePageNodeRemoved(pageB.get())); + EXPECT_CALL(obs, OnPageNodeRemoved(pageB.get())); } frameB1.reset(); pageB.reset();
diff --git a/components/performance_manager/graph/graph_impl.cc b/components/performance_manager/graph/graph_impl.cc index 8d5fda63..e13f71a 100644 --- a/components/performance_manager/graph/graph_impl.cc +++ b/components/performance_manager/graph/graph_impl.cc
@@ -142,8 +142,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CreateSystemNode(); - AddFrameNodeObserver(&initializing_frame_node_observer_manager_); - execution_context_registry_impl_.SetUp(this); CHECK_EQ(lifecycle_state_, LifecycleState::kBeforeSetUp); @@ -159,8 +157,6 @@ execution_context_registry_impl_.TearDown(this); - RemoveFrameNodeObserver(&initializing_frame_node_observer_manager_); - // At this point, all typed observers should be empty. DCHECK(frame_node_observers_.empty()); DCHECK(page_node_observers_.empty()); @@ -313,16 +309,6 @@ } #endif -void GraphImpl::AddInitializingFrameNodeObserver( - InitializingFrameNodeObserver* frame_node_observer) { - initializing_frame_node_observer_manager_.AddObserver(frame_node_observer); -} - -void GraphImpl::RemoveInitializingFrameNodeObserver( - InitializingFrameNodeObserver* frame_node_observer) { - initializing_frame_node_observer_manager_.RemoveObserver(frame_node_observer); -} - GraphRegistered* GraphImpl::GetRegisteredObject(uintptr_t type_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return registered_objects_.GetRegisteredObject(type_id); @@ -446,16 +432,6 @@ DCHECK_EQ(1u, erased); } -void GraphImpl::NotifyFrameNodeInitializing(const FrameNode* frame_node) { - initializing_frame_node_observer_manager_.NotifyFrameNodeInitializing( - frame_node); -} - -void GraphImpl::NotifyFrameNodeTearingDown(const FrameNode* frame_node) { - initializing_frame_node_observer_manager_.NotifyFrameNodeTearingDown( - frame_node); -} - size_t GraphImpl::NodeDataDescriberCountForTesting() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!describer_registry_) {
diff --git a/components/performance_manager/graph/graph_impl.h b/components/performance_manager/graph/graph_impl.h index 1a41a26..713d23a 100644 --- a/components/performance_manager/graph/graph_impl.h +++ b/components/performance_manager/graph/graph_impl.h
@@ -17,7 +17,6 @@ #include "base/process/process_handle.h" #include "base/sequence_checker.h" #include "components/performance_manager/execution_context/execution_context_registry_impl.h" -#include "components/performance_manager/graph/initializing_frame_node_observer.h" #include "components/performance_manager/owned_objects.h" #include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/graph_registered.h" @@ -95,10 +94,6 @@ #if DCHECK_IS_ON() bool IsOnGraphSequence() const override; #endif - void AddInitializingFrameNodeObserver( - InitializingFrameNodeObserver* frame_node_observer) override; - void RemoveInitializingFrameNodeObserver( - InitializingFrameNodeObserver* frame_node_observer) override; GraphRegistered* GetRegisteredObject(uintptr_t type_id) override; // Helper function for safely downcasting to the implementation. This also @@ -141,12 +136,6 @@ void AddNewNode(NodeBase* new_node); void RemoveNode(NodeBase* node); - // Sends the `OnFrameNodeInitializing()` and `OnFrameNodeTearingDown()` - // notifications to initializing frame node observers (See - // InitializingFrameNodeObserver for details). - void NotifyFrameNodeInitializing(const FrameNode* frame_node); - void NotifyFrameNodeTearingDown(const FrameNode* frame_node); - // Allows explicitly invoking SystemNode destruction for testing. void ReleaseSystemNodeForTesting() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -272,9 +261,6 @@ RegisteredObjects<GraphRegistered> registered_objects_ GUARDED_BY_CONTEXT(sequence_checker_); - InitializingFrameNodeObserverManager - initializing_frame_node_observer_manager_; - execution_context::ExecutionContextRegistryImpl execution_context_registry_impl_;
diff --git a/components/performance_manager/graph/initializing_frame_node_observer.cc b/components/performance_manager/graph/initializing_frame_node_observer.cc deleted file mode 100644 index 8155e19..0000000 --- a/components/performance_manager/graph/initializing_frame_node_observer.cc +++ /dev/null
@@ -1,217 +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. - -#include "components/performance_manager/graph/initializing_frame_node_observer.h" - -namespace performance_manager { - -InitializingFrameNodeObserverManager::InitializingFrameNodeObserverManager() = - default; - -InitializingFrameNodeObserverManager::~InitializingFrameNodeObserverManager() = - default; - -void InitializingFrameNodeObserverManager::AddObserver( - InitializingFrameNodeObserver* observer) { - observer_list_.AddObserver(observer); -} - -void InitializingFrameNodeObserverManager::RemoveObserver( - InitializingFrameNodeObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -void InitializingFrameNodeObserverManager::NotifyFrameNodeInitializing( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameNodeInitializing(frame_node); - } -} - -void InitializingFrameNodeObserverManager::NotifyFrameNodeTearingDown( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameNodeTearingDown(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnBeforeFrameNodeAdded( - const FrameNode* frame_node, - const FrameNode* pending_parent_frame_node, - const PageNode* pending_page_node, - const ProcessNode* pending_process_node, - const FrameNode* pending_parent_or_outer_document_or_embedder) { - // Ignore this as this class manually notifies observers of new frame nodes - // using `OnFrameNodeInitializing()`. -} - -void InitializingFrameNodeObserverManager::OnFrameNodeAdded( - const FrameNode* frame_node) { - // Ignore this as this class manually notifies observers of new frame nodes - // using `OnFrameNodeInitializing()`. -} - -void InitializingFrameNodeObserverManager::OnBeforeFrameNodeRemoved( - const FrameNode* frame_node) { - // Ignore this as this class manually notifies observers of the removal of - // frame nodes using `NotifyFrameNodeTearingDown()`. -} - -void InitializingFrameNodeObserverManager::OnFrameNodeRemoved( - const FrameNode* frame_node, - const FrameNode* previous_parent_frame_node, - const PageNode* previous_page_node, - const ProcessNode* previous_process_node, - const FrameNode* previous_parent_or_outer_document_or_embedder) { - // Ignore this as this class manually notifies observers of the removal of - // frame nodes using `NotifyFrameNodeTearingDown()`. -} - -void InitializingFrameNodeObserverManager::OnCurrentFrameChanged( - const FrameNode* previous_frame_node, - const FrameNode* current_frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnCurrentFrameChanged(previous_frame_node, current_frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnNetworkAlmostIdleChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnNetworkAlmostIdleChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnFrameLifecycleStateChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameLifecycleStateChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnURLChanged( - const FrameNode* frame_node, - const GURL& previous_value) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnURLChanged(frame_node, previous_value); - } -} - -void InitializingFrameNodeObserverManager::OnOriginChanged( - const FrameNode* frame_node, - const std::optional<url::Origin>& previous_value) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnOriginChanged(frame_node, previous_value); - } -} - -void InitializingFrameNodeObserverManager::OnIsAdFrameChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnIsAdFrameChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnFrameIsHoldingWebLockChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameIsHoldingWebLockChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnFrameIsHoldingIndexedDBLockChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameIsHoldingIndexedDBLockChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnPriorityAndReasonChanged( - const FrameNode* frame_node, - const PriorityAndReason& previous_value) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnPriorityAndReasonChanged(frame_node, previous_value); - } -} - -void InitializingFrameNodeObserverManager::OnHadUserActivationChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnHadUserActivationChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnHadFormInteractionChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnHadFormInteractionChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnHadUserEditsChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnHadUserEditsChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnFrameUsesWebRTCChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameUsesWebRTCChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnIsAudibleChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnIsAudibleChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnIsCapturingMediaStreamChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnIsCapturingMediaStreamChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnViewportIntersectionChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnViewportIntersectionChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnFrameVisibilityChanged( - const FrameNode* frame_node, - FrameNode::Visibility previous_value) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFrameVisibilityChanged(frame_node, previous_value); - } -} - -void InitializingFrameNodeObserverManager::OnIsImportantChanged( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnIsImportantChanged(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnNonPersistentNotificationCreated( - const FrameNode* frame_node) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnNonPersistentNotificationCreated(frame_node); - } -} - -void InitializingFrameNodeObserverManager::OnFirstContentfulPaint( - const FrameNode* frame_node, - base::TimeDelta time_since_navigation_start) { - for (InitializingFrameNodeObserver& observer : observer_list_) { - observer.OnFirstContentfulPaint(frame_node, time_since_navigation_start); - } -} - -} // namespace performance_manager
diff --git a/components/performance_manager/graph/initializing_frame_node_observer.h b/components/performance_manager/graph/initializing_frame_node_observer.h deleted file mode 100644 index 30d9a9e..0000000 --- a/components/performance_manager/graph/initializing_frame_node_observer.h +++ /dev/null
@@ -1,134 +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. - -#ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_INITIALIZING_FRAME_NODE_OBSERVER_H_ -#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_INITIALIZING_FRAME_NODE_OBSERVER_H_ - -#include "base/observer_list.h" -#include "components/performance_manager/public/graph/frame_node.h" -#include "components/performance_manager/public/graph/graph.h" -#include "url/origin.h" - -namespace performance_manager { - -// This class is for FrameNodeObservers that need to initialize values on the -// actual frame nodes before other observers are notified of their existence. -// This is needed because modifying frames nodes during the `OnFrameNodeAdded()` -// notification is disallowed. This class should be used sparingly. -class InitializingFrameNodeObserver { - public: - virtual ~InitializingFrameNodeObserver() = default; - - // Called when a `frame_node` that is being added to the graph is - // initializing. This should be used to set the initial value for a property. - virtual void OnFrameNodeInitializing(const FrameNode* frame_node) {} - - // Called when a `frame_node` that is being removed from the graph is tearing - // down. Used to clean up any state related to this node. - virtual void OnFrameNodeTearingDown(const FrameNode* frame_node) {} - - // Same interface as FrameNodeObserver. Look up frame_node.h for their - // descriptions. - virtual void OnCurrentFrameChanged(const FrameNode* previous_frame_node, - const FrameNode* current_frame_node) {} - virtual void OnNetworkAlmostIdleChanged(const FrameNode* frame_node) {} - virtual void OnFrameLifecycleStateChanged(const FrameNode* frame_node) {} - virtual void OnURLChanged(const FrameNode* frame_node, - const GURL& previous_value) {} - virtual void OnOriginChanged( - const FrameNode* frame_node, - const std::optional<url::Origin>& previous_value) {} - virtual void OnIsAdFrameChanged(const FrameNode* frame_node) {} - virtual void OnFrameIsHoldingWebLockChanged(const FrameNode* frame_node) {} - virtual void OnFrameIsHoldingIndexedDBLockChanged( - const FrameNode* frame_node) {} - virtual void OnPriorityAndReasonChanged( - const FrameNode* frame_node, - const PriorityAndReason& previous_value) {} - virtual void OnHadUserActivationChanged(const FrameNode* frame_node) {} - virtual void OnHadFormInteractionChanged(const FrameNode* frame_node) {} - virtual void OnHadUserEditsChanged(const FrameNode* frame_node) {} - virtual void OnFrameUsesWebRTCChanged(const FrameNode* frame_node) {} - virtual void OnIsAudibleChanged(const FrameNode* frame_node) {} - virtual void OnIsCapturingMediaStreamChanged(const FrameNode* frame_node) {} - virtual void OnViewportIntersectionChanged(const FrameNode* frame_node) {} - virtual void OnFrameVisibilityChanged(const FrameNode* frame_node, - FrameNode::Visibility previous_value) {} - virtual void OnIsImportantChanged(const FrameNode* frame_node) {} - virtual void OnNonPersistentNotificationCreated(const FrameNode* frame_node) { - } - virtual void OnFirstContentfulPaint( - const FrameNode* frame_node, - base::TimeDelta time_since_navigation_start) {} -}; - -class InitializingFrameNodeObserverManager final : public FrameNodeObserver { - public: - InitializingFrameNodeObserverManager(); - ~InitializingFrameNodeObserverManager() override; - - // Adds/removes observers. - void AddObserver(InitializingFrameNodeObserver* observer); - void RemoveObserver(InitializingFrameNodeObserver* observer); - - // Used to notify all observers when the frame node is added, while the node - // is still modifiable. - void NotifyFrameNodeInitializing(const FrameNode* frame_node); - // Used to notify all observers when the frame node is about to be removed, - // while the node is modifiable. - void NotifyFrameNodeTearingDown(const FrameNode* frame_node); - - private: - // FrameNodeObserver: - void OnBeforeFrameNodeAdded( - const FrameNode* frame_node, - const FrameNode* pending_parent_frame_node, - const PageNode* pending_page_node, - const ProcessNode* pending_process_node, - const FrameNode* pending_parent_or_outer_document_or_embedder) override; - void OnFrameNodeAdded(const FrameNode* frame_node) override; - void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override; - void OnFrameNodeRemoved( - const FrameNode* frame_node, - const FrameNode* previous_parent_frame_node, - const PageNode* previous_page_node, - const ProcessNode* previous_process_node, - const FrameNode* previous_parent_or_outer_document_or_embedder) override; - void OnCurrentFrameChanged(const FrameNode* previous_frame_node, - const FrameNode* current_frame_node) override; - void OnNetworkAlmostIdleChanged(const FrameNode* frame_node) override; - void OnFrameLifecycleStateChanged(const FrameNode* frame_node) override; - void OnURLChanged(const FrameNode* frame_node, - const GURL& previous_value) override; - void OnOriginChanged( - const FrameNode* frame_node, - const std::optional<url::Origin>& previous_value) override; - void OnIsAdFrameChanged(const FrameNode* frame_node) override; - void OnFrameIsHoldingWebLockChanged(const FrameNode* frame_node) override; - void OnFrameIsHoldingIndexedDBLockChanged( - const FrameNode* frame_node) override; - void OnPriorityAndReasonChanged( - const FrameNode* frame_node, - const PriorityAndReason& previous_value) override; - void OnHadUserActivationChanged(const FrameNode* frame_node) override; - void OnHadFormInteractionChanged(const FrameNode* frame_node) override; - void OnHadUserEditsChanged(const FrameNode* frame_node) override; - void OnFrameUsesWebRTCChanged(const FrameNode* frame_node) override; - void OnIsAudibleChanged(const FrameNode* frame_node) override; - void OnIsCapturingMediaStreamChanged(const FrameNode* frame_node) override; - void OnViewportIntersectionChanged(const FrameNode* frame_node) override; - void OnFrameVisibilityChanged(const FrameNode* frame_node, - FrameNode::Visibility previous_value) override; - void OnIsImportantChanged(const FrameNode* frame_node) override; - void OnNonPersistentNotificationCreated(const FrameNode* frame_node) override; - void OnFirstContentfulPaint( - const FrameNode* frame_node, - base::TimeDelta time_since_navigation_start) override; - - base::ObserverList<InitializingFrameNodeObserver>::Unchecked observer_list_; -}; - -} // namespace performance_manager - -#endif // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_INITIALIZING_FRAME_NODE_OBSERVER_H_
diff --git a/components/performance_manager/graph/node_base.h b/components/performance_manager/graph/node_base.h index b2712fd4..ed93d3e 100644 --- a/components/performance_manager/graph/node_base.h +++ b/components/performance_manager/graph/node_base.h
@@ -211,10 +211,6 @@ Graph* GetGraph() const override { return static_cast<const NodeImplClass*>(this)->graph(); } - NodeState GetNodeState() const override { - return static_cast<const NodeBase*>(static_cast<const NodeImplClass*>(this)) - ->GetNodeState(); - } uintptr_t GetImplType() const override { return NodeBase::kNodeBaseType; } const void* GetImpl() const override { // This exposes NodeBase, so that we can complete the triangle of casting
diff --git a/components/performance_manager/graph/page_node_impl_unittest.cc b/components/performance_manager/graph/page_node_impl_unittest.cc index a8ab931..be17f60 100644 --- a/components/performance_manager/graph/page_node_impl_unittest.cc +++ b/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -14,6 +14,7 @@ #include "components/performance_manager/graph/process_node_impl.h" #include "components/performance_manager/public/freezing/freezing.h" #include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/test_support/graph/mock_page_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "testing/gmock/include/gmock/gmock.h" @@ -241,59 +242,8 @@ namespace { -class LenientMockObserver : public PageNodeImpl::Observer { +class MockObserver : public MockPageNodeObserver { public: - LenientMockObserver() = default; - ~LenientMockObserver() override = default; - - MOCK_METHOD(void, OnBeforePageNodeAdded, (const PageNode*), (override)); - MOCK_METHOD(void, OnPageNodeAdded, (const PageNode*), (override)); - MOCK_METHOD(void, OnBeforePageNodeRemoved, (const PageNode*), (override)); - MOCK_METHOD(void, OnPageNodeRemoved, (const PageNode*), (override)); - // Note that opener/embedder functionality is actually tested in the - // FrameNodeImpl and GraphImpl unittests. - MOCK_METHOD(void, - OnOpenerFrameNodeChanged, - (const PageNode*, const FrameNode*), - (override)); - MOCK_METHOD(void, - OnEmbedderFrameNodeChanged, - (const PageNode*, const FrameNode*, EmbeddingType), - (override)); - MOCK_METHOD(void, OnTypeChanged, (const PageNode*, PageType), (override)); - MOCK_METHOD(void, OnIsFocusedChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnIsVisibleChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnIsAudibleChanged, (const PageNode*), (override)); - MOCK_METHOD(void, - OnHasPictureInPictureChanged, - (const PageNode*), - (override)); - MOCK_METHOD(void, - OnLoadingStateChanged, - (const PageNode*, PageNode::LoadingState), - (override)); - MOCK_METHOD(void, OnUkmSourceIdChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnPageLifecycleStateChanged, (const PageNode*), (override)); - MOCK_METHOD(void, - OnPageIsHoldingWebLockChanged, - (const PageNode*), - (override)); - MOCK_METHOD(void, - OnPageIsHoldingIndexedDBLockChanged, - (const PageNode*), - (override)); - MOCK_METHOD(void, OnPageUsesWebRTCChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnMainFrameUrlChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnMainFrameDocumentChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnTitleUpdated, (const PageNode*), (override)); - MOCK_METHOD(void, OnFaviconUpdated, (const PageNode*), (override)); - MOCK_METHOD(void, OnHadFormInteractionChanged, (const PageNode*), (override)); - MOCK_METHOD(void, OnHadUserEditsChanged, (const PageNode*), (override)); - MOCK_METHOD(void, - OnAboutToBeDiscarded, - (const PageNode*, const PageNode*), - (override)); - void SetNotifiedPageNode(const PageNode* page_node) { notified_page_node_ = page_node; } @@ -320,8 +270,6 @@ raw_ptr<const PageNode, DanglingUntriaged> notified_page_node_ = nullptr; }; -using MockObserver = ::testing::StrictMock<LenientMockObserver>; - using ::testing::_; using ::testing::DoAll; using ::testing::InSequence;
diff --git a/components/performance_manager/graph/process_node_impl_unittest.cc b/components/performance_manager/graph/process_node_impl_unittest.cc index 3300be26..6cac78cb 100644 --- a/components/performance_manager/graph/process_node_impl_unittest.cc +++ b/components/performance_manager/graph/process_node_impl_unittest.cc
@@ -20,6 +20,7 @@ #include "components/performance_manager/public/render_process_host_id.h" #include "components/performance_manager/public/render_process_host_proxy.h" #include "components/performance_manager/public/scenarios/performance_scenarios.h" +#include "components/performance_manager/test_support/graph/mock_process_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "content/public/common/content_switches.h" @@ -102,32 +103,8 @@ namespace { -class LenientMockObserver : public ProcessNodeImpl::Observer { +class MockObserver : public MockProcessNodeObserver { public: - LenientMockObserver() = default; - ~LenientMockObserver() override = default; - - MOCK_METHOD(void, OnBeforeProcessNodeAdded, (const ProcessNode*), (override)); - MOCK_METHOD(void, OnProcessNodeAdded, (const ProcessNode*), (override)); - MOCK_METHOD(void, OnProcessLifetimeChange, (const ProcessNode*), (override)); - MOCK_METHOD(void, - OnBeforeProcessNodeRemoved, - (const ProcessNode*), - (override)); - MOCK_METHOD(void, OnProcessNodeRemoved, (const ProcessNode*), (override)); - MOCK_METHOD(void, - OnMainThreadTaskLoadIsLow, - (const ProcessNode*), - (override)); - MOCK_METHOD(void, - OnPriorityChanged, - (const ProcessNode*, base::TaskPriority), - (override)); - MOCK_METHOD(void, - OnAllFramesInProcessFrozen, - (const ProcessNode*), - (override)); - void SetNotifiedProcessNode(const ProcessNode* process_node) { notified_process_node_ = process_node; } @@ -153,8 +130,6 @@ nullptr; }; -using MockObserver = ::testing::StrictMock<LenientMockObserver>; - using ::testing::_; using ::testing::DoAll; using ::testing::InSequence;
diff --git a/components/performance_manager/graph/system_node_impl_unittest.cc b/components/performance_manager/graph/system_node_impl_unittest.cc index 41b79c4b..ae91eba 100644 --- a/components/performance_manager/graph/system_node_impl_unittest.cc +++ b/components/performance_manager/graph/system_node_impl_unittest.cc
@@ -11,6 +11,7 @@ #include "components/performance_manager/graph/frame_node_impl.h" #include "components/performance_manager/graph/page_node_impl.h" #include "components/performance_manager/graph/process_node_impl.h" +#include "components/performance_manager/test_support/graph/mock_system_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/mock_graphs.h" #include "testing/gmock/include/gmock/gmock.h" @@ -20,15 +21,6 @@ namespace { -// Observer used to make sure that signals are dispatched correctly. -class SystemObserver : public SystemNodeImpl::ObserverDefaultImpl { - public: - size_t system_event_seen_count() const { return system_event_seen_count_; } - - private: - size_t system_event_seen_count_ = 0; -}; - using SystemNodeImplTest = GraphTestHarness; } // namespace @@ -52,24 +44,13 @@ namespace { -class LenientMockObserver : public SystemNodeImpl::Observer { +using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; +using testing::_; +using testing::Invoke; +using testing::InvokeWithoutArgs; + +class MockObserver : public MockSystemNodeObserver { public: - LenientMockObserver() = default; - ~LenientMockObserver() override = default; - - MOCK_METHOD(void, - OnProcessMemoryMetricsAvailable, - (const SystemNode*), - (override)); - MOCK_METHOD(void, - OnMemoryPressure, - (base::MemoryPressureListener::MemoryPressureLevel), - (override)); - MOCK_METHOD(void, - OnBeforeMemoryPressure, - (base::MemoryPressureListener::MemoryPressureLevel), - (override)); - void SetNotifiedSystemNode(const SystemNode* system_node) { notified_system_node_ = system_node; } @@ -84,13 +65,6 @@ raw_ptr<const SystemNode> notified_system_node_ = nullptr; }; -using MockObserver = ::testing::StrictMock<LenientMockObserver>; - -using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; -using testing::_; -using testing::Invoke; -using testing::InvokeWithoutArgs; - } // namespace TEST_F(SystemNodeImplTest, ObserverWorks) {
diff --git a/components/performance_manager/graph/worker_node_impl_unittest.cc b/components/performance_manager/graph/worker_node_impl_unittest.cc index f615d91..96322d9c 100644 --- a/components/performance_manager/graph/worker_node_impl_unittest.cc +++ b/components/performance_manager/graph/worker_node_impl_unittest.cc
@@ -9,6 +9,7 @@ #include "components/performance_manager/graph/page_node_impl.h" #include "components/performance_manager/graph/process_node_impl.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/test_support/graph/mock_worker_node_observer.h" #include "components/performance_manager/test_support/graph_test_harness.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,58 +25,6 @@ protected: }; -// Mock observer for the basic ObserverWorks test. -class LenientMockObserver : public WorkerNodeImpl::Observer { - public: - LenientMockObserver() = default; - ~LenientMockObserver() override = default; - - MOCK_METHOD(void, - OnBeforeWorkerNodeAdded, - (const WorkerNode*, const ProcessNode*), - (override)); - MOCK_METHOD(void, OnWorkerNodeAdded, (const WorkerNode*), (override)); - MOCK_METHOD(void, OnBeforeWorkerNodeRemoved, (const WorkerNode*), (override)); - MOCK_METHOD(void, - OnWorkerNodeRemoved, - (const WorkerNode*, const ProcessNode*), - (override)); - MOCK_METHOD(void, - OnFinalResponseURLDetermined, - (const WorkerNode*), - (override)); - MOCK_METHOD(void, - OnBeforeClientFrameAdded, - (const WorkerNode*, const FrameNode*), - (override)); - MOCK_METHOD(void, - OnClientFrameAdded, - (const WorkerNode*, const FrameNode*), - (override)); - MOCK_METHOD(void, - OnBeforeClientFrameRemoved, - (const WorkerNode*, const FrameNode*), - (override)); - MOCK_METHOD(void, - OnBeforeClientWorkerAdded, - (const WorkerNode*, const WorkerNode*), - (override)); - MOCK_METHOD(void, - OnClientWorkerAdded, - (const WorkerNode*, const WorkerNode*), - (override)); - MOCK_METHOD(void, - OnBeforeClientWorkerRemoved, - (const WorkerNode*, const WorkerNode*), - (override)); - MOCK_METHOD(void, - OnPriorityAndReasonChanged, - (const WorkerNode*, const PriorityAndReason&), - (override)); -}; - -using MockObserver = ::testing::StrictMock<LenientMockObserver>; - using ::testing::_; using ::testing::ElementsAre; using ::testing::InSequence; @@ -274,9 +223,9 @@ TEST_F(WorkerNodeImplTest, ObserverWorks) { auto process = CreateNode<ProcessNodeImpl>(); - MockObserver head_obs; - MockObserver obs; - MockObserver tail_obs; + MockWorkerNodeObserver head_obs; + MockWorkerNodeObserver obs; + MockWorkerNodeObserver tail_obs; graph()->AddWorkerNodeObserver(&head_obs); graph()->AddWorkerNodeObserver(&obs); graph()->AddWorkerNodeObserver(&tail_obs); @@ -333,7 +282,7 @@ TEST_F(WorkerNodeImplTest, Observer_AddWorkerNodes) { InSequence s; - MockObserver obs; + MockWorkerNodeObserver obs; graph()->AddWorkerNodeObserver(&obs); auto process = CreateNode<ProcessNodeImpl>(); @@ -433,7 +382,7 @@ TEST_F(WorkerNodeImplTest, Observer_ClientsOfServiceWorkers) { InSequence s; - MockObserver obs; + MockWorkerNodeObserver obs; graph()->AddWorkerNodeObserver(&obs); auto process = CreateNode<ProcessNodeImpl>(); @@ -501,7 +450,7 @@ TEST_F(WorkerNodeImplTest, Observer_OnFinalResponseURLDetermined) { InSequence s; - MockObserver obs; + MockWorkerNodeObserver obs; graph()->AddWorkerNodeObserver(&obs); auto process = CreateNode<ProcessNodeImpl>(); @@ -522,7 +471,7 @@ TEST_F(WorkerNodeImplTest, Observer_OnPriorityAndReasonChanged) { InSequence s; - MockObserver obs; + MockWorkerNodeObserver obs; graph()->AddWorkerNodeObserver(&obs); auto process = CreateNode<ProcessNodeImpl>();
diff --git a/components/performance_manager/performance_manager_tab_helper_unittest.cc b/components/performance_manager/performance_manager_tab_helper_unittest.cc index a8a30e4..32f02434 100644 --- a/components/performance_manager/performance_manager_tab_helper_unittest.cc +++ b/components/performance_manager/performance_manager_tab_helper_unittest.cc
@@ -20,6 +20,7 @@ #include "components/performance_manager/public/graph/graph_operations.h" #include "components/performance_manager/public/graph/page_node.h" #include "components/performance_manager/render_process_user_data.h" +#include "components/performance_manager/test_support/graph/mock_page_node_observer.h" #include "components/performance_manager/test_support/performance_manager_test_harness.h" #include "components/performance_manager/test_support/run_in_graph.h" #include "content/public/browser/browser_context.h" @@ -354,23 +355,6 @@ EXPECT_TRUE(new_frame_node); } -namespace { - -class LenientMockPageNodeObserver : public PageNode::ObserverDefaultImpl { - public: - LenientMockPageNodeObserver() = default; - ~LenientMockPageNodeObserver() override = default; - LenientMockPageNodeObserver(const LenientMockPageNodeObserver& other) = - delete; - LenientMockPageNodeObserver& operator=(const LenientMockPageNodeObserver&) = - delete; - - MOCK_METHOD(void, OnFaviconUpdated, (const PageNode*), (override)); -}; -using MockPageNodeObserver = ::testing::StrictMock<LenientMockPageNodeObserver>; - -} // namespace - TEST_P(PerformanceManagerTabHelperTest, NotificationsFromInactiveFrameTreeAreIgnored) { SetContents(CreateTestWebContents());
diff --git a/components/performance_manager/public/execution_context/execution_context.h b/components/performance_manager/public/execution_context/execution_context.h index 357e20e..d78ef118 100644 --- a/components/performance_manager/public/execution_context/execution_context.h +++ b/components/performance_manager/public/execution_context/execution_context.h
@@ -7,6 +7,7 @@ #include "base/observer_list_types.h" #include "components/performance_manager/public/execution_context_priority/execution_context_priority.h" +#include "components/performance_manager/public/graph/node_state.h" #include "third_party/blink/public/common/tokens/tokens.h" class GURL; @@ -69,6 +70,9 @@ // Returns the graph to which this ExecutionContext belongs. virtual Graph* GetGraph() const = 0; + // Returns the state of this node. + virtual NodeState GetNodeState() const = 0; + // Returns the final post-redirect committed URL associated with this // ExecutionContext. This is the URL of the HTML document (not the javascript) // in the case of a FrameNode, or the URL of the worker javascript in the case
diff --git a/components/performance_manager/public/graph/graph.h b/components/performance_manager/public/graph/graph.h index b5c291b..0beca05 100644 --- a/components/performance_manager/public/graph/graph.h +++ b/components/performance_manager/public/graph/graph.h
@@ -26,7 +26,6 @@ class GraphRegistered; class FrameNode; class FrameNodeObserver; -class InitializingFrameNodeObserver; class NodeDataDescriberRegistry; class PageNode; class PageNodeObserver; @@ -147,14 +146,6 @@ virtual bool IsOnGraphSequence() const = 0; #endif - // Adds/removes a special type of FrameNodeObserver that needs to initialize - // a property on frame nodes before other observers are notified of their - // existence. This should be used sparingly. - virtual void AddInitializingFrameNodeObserver( - InitializingFrameNodeObserver* frame_node_observer) = 0; - virtual void RemoveInitializingFrameNodeObserver( - InitializingFrameNodeObserver* frame_node_observer) = 0; - private: // Retrieves the object with the given |type_id|, returning nullptr if none // exists. Clients must use the GetRegisteredObjectAs wrapper instead.
diff --git a/components/performance_manager/public/graph/node.h b/components/performance_manager/public/graph/node.h index cdf27fa..1e8f3024 100644 --- a/components/performance_manager/public/graph/node.h +++ b/components/performance_manager/public/graph/node.h
@@ -31,9 +31,6 @@ // Returns the graph to which this node belongs. virtual Graph* GetGraph() const = 0; - // Returns the state of this node. - virtual NodeState GetNodeState() const = 0; - // The following functions are implementation detail and should not need to be // used by external clients. They provide the ability to safely downcast to // the underlying implementation.
diff --git a/components/performance_manager/test_support/BUILD.gn b/components/performance_manager/test_support/BUILD.gn index de8d7bed..6628701 100644 --- a/components/performance_manager/test_support/BUILD.gn +++ b/components/performance_manager/test_support/BUILD.gn
@@ -45,6 +45,16 @@ testonly = true sources = [ + "graph/mock_frame_node_observer.cc", + "graph/mock_frame_node_observer.h", + "graph/mock_page_node_observer.cc", + "graph/mock_page_node_observer.h", + "graph/mock_process_node_observer.cc", + "graph/mock_process_node_observer.h", + "graph/mock_system_node_observer.cc", + "graph/mock_system_node_observer.h", + "graph/mock_worker_node_observer.cc", + "graph/mock_worker_node_observer.h", "graph_test_harness.cc", "graph_test_harness.h", "mock_graphs.cc",
diff --git a/components/performance_manager/test_support/graph/mock_frame_node_observer.cc b/components/performance_manager/test_support/graph/mock_frame_node_observer.cc new file mode 100644 index 0000000..e6a9883 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_frame_node_observer.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 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/performance_manager/test_support/graph/mock_frame_node_observer.h" + +namespace performance_manager { + +LenientMockFrameNodeObserver::LenientMockFrameNodeObserver() = default; +LenientMockFrameNodeObserver::~LenientMockFrameNodeObserver() = default; + +} // namespace performance_manager
diff --git a/components/performance_manager/test_support/graph/mock_frame_node_observer.h b/components/performance_manager/test_support/graph/mock_frame_node_observer.h new file mode 100644 index 0000000..563c2906 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_frame_node_observer.h
@@ -0,0 +1,99 @@ +// Copyright 2024 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_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_FRAME_NODE_OBSERVER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_FRAME_NODE_OBSERVER_H_ + +#include "components/performance_manager/public/graph/frame_node.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace performance_manager { + +class LenientMockFrameNodeObserver : public FrameNode::ObserverDefaultImpl { + public: + LenientMockFrameNodeObserver(); + ~LenientMockFrameNodeObserver() override; + + MOCK_METHOD(void, + OnBeforeFrameNodeAdded, + (const FrameNode*, + const FrameNode*, + const PageNode*, + const ProcessNode*, + const FrameNode*), + (override)); + MOCK_METHOD(void, OnFrameNodeAdded, (const FrameNode*), (override)); + MOCK_METHOD(void, OnBeforeFrameNodeRemoved, (const FrameNode*), (override)); + MOCK_METHOD(void, + OnFrameNodeRemoved, + (const FrameNode*, + const FrameNode*, + const PageNode*, + const ProcessNode*, + const FrameNode*), + (override)); + MOCK_METHOD(void, + OnCurrentFrameChanged, + (const FrameNode*, const FrameNode*), + (override)); + MOCK_METHOD(void, OnNetworkAlmostIdleChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, + OnFrameLifecycleStateChanged, + (const FrameNode*), + (override)); + MOCK_METHOD(void, OnURLChanged, (const FrameNode*, const GURL&), (override)); + MOCK_METHOD(void, + OnOriginChanged, + (const FrameNode*, const std::optional<url::Origin>&), + (override)); + MOCK_METHOD(void, OnIsAdFrameChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, + OnFrameIsHoldingWebLockChanged, + (const FrameNode*), + (override)); + MOCK_METHOD(void, + OnFrameIsHoldingIndexedDBLockChanged, + (const FrameNode*), + (override)); + MOCK_METHOD(void, + OnPriorityAndReasonChanged, + (const FrameNode*, const PriorityAndReason& previous_value), + (override)); + MOCK_METHOD(void, OnFrameUsesWebRTCChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, OnHadUserActivationChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, + OnHadFormInteractionChanged, + (const FrameNode*), + (override)); + MOCK_METHOD(void, OnHadUserEditsChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, OnIsAudibleChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, + OnIsCapturingMediaStreamChanged, + (const FrameNode*), + (override)); + MOCK_METHOD(void, + OnViewportIntersectionChanged, + (const FrameNode*), + (override)); + MOCK_METHOD(void, + OnFrameVisibilityChanged, + (const FrameNode*, FrameNode::Visibility), + (override)); + MOCK_METHOD(void, OnIsImportantChanged, (const FrameNode*), (override)); + MOCK_METHOD(void, + OnNonPersistentNotificationCreated, + (const FrameNode*), + (override)); + MOCK_METHOD(void, + OnFirstContentfulPaint, + (const FrameNode*, base::TimeDelta), + (override)); +}; + +using MockFrameNodeObserver = + ::testing::StrictMock<LenientMockFrameNodeObserver>; + +} // namespace performance_manager + +#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_FRAME_NODE_OBSERVER_H_
diff --git a/components/performance_manager/test_support/graph/mock_page_node_observer.cc b/components/performance_manager/test_support/graph/mock_page_node_observer.cc new file mode 100644 index 0000000..95e4f39 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_page_node_observer.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 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/performance_manager/test_support/graph/mock_page_node_observer.h" + +namespace performance_manager { + +LenientMockPageNodeObserver::LenientMockPageNodeObserver() = default; +LenientMockPageNodeObserver::~LenientMockPageNodeObserver() = default; + +} // namespace performance_manager
diff --git a/components/performance_manager/test_support/graph/mock_page_node_observer.h b/components/performance_manager/test_support/graph/mock_page_node_observer.h new file mode 100644 index 0000000..ffa8a6d --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_page_node_observer.h
@@ -0,0 +1,69 @@ +// Copyright 2024 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_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_PAGE_NODE_OBSERVER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_PAGE_NODE_OBSERVER_H_ + +#include "components/performance_manager/public/graph/page_node.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace performance_manager { + +class LenientMockPageNodeObserver : public PageNode::ObserverDefaultImpl { + public: + LenientMockPageNodeObserver(); + ~LenientMockPageNodeObserver() override; + + MOCK_METHOD(void, OnBeforePageNodeAdded, (const PageNode*), (override)); + MOCK_METHOD(void, OnPageNodeAdded, (const PageNode*), (override)); + MOCK_METHOD(void, OnBeforePageNodeRemoved, (const PageNode*), (override)); + MOCK_METHOD(void, OnPageNodeRemoved, (const PageNode*), (override)); + MOCK_METHOD(void, + OnOpenerFrameNodeChanged, + (const PageNode*, const FrameNode*), + (override)); + MOCK_METHOD(void, + OnEmbedderFrameNodeChanged, + (const PageNode*, const FrameNode*, EmbeddingType), + (override)); + MOCK_METHOD(void, OnTypeChanged, (const PageNode*, PageType), (override)); + MOCK_METHOD(void, OnIsFocusedChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnIsVisibleChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnIsAudibleChanged, (const PageNode*), (override)); + MOCK_METHOD(void, + OnHasPictureInPictureChanged, + (const PageNode*), + (override)); + MOCK_METHOD(void, + OnLoadingStateChanged, + (const PageNode*, PageNode::LoadingState), + (override)); + MOCK_METHOD(void, OnUkmSourceIdChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnPageLifecycleStateChanged, (const PageNode*), (override)); + MOCK_METHOD(void, + OnPageIsHoldingWebLockChanged, + (const PageNode*), + (override)); + MOCK_METHOD(void, + OnPageIsHoldingIndexedDBLockChanged, + (const PageNode*), + (override)); + MOCK_METHOD(void, OnPageUsesWebRTCChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnMainFrameUrlChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnMainFrameDocumentChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnTitleUpdated, (const PageNode*), (override)); + MOCK_METHOD(void, OnFaviconUpdated, (const PageNode*), (override)); + MOCK_METHOD(void, OnHadFormInteractionChanged, (const PageNode*), (override)); + MOCK_METHOD(void, OnHadUserEditsChanged, (const PageNode*), (override)); + MOCK_METHOD(void, + OnAboutToBeDiscarded, + (const PageNode*, const PageNode*), + (override)); +}; + +using MockPageNodeObserver = ::testing::StrictMock<LenientMockPageNodeObserver>; + +} // namespace performance_manager + +#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_PAGE_NODE_OBSERVER_H_
diff --git a/components/performance_manager/test_support/graph/mock_process_node_observer.cc b/components/performance_manager/test_support/graph/mock_process_node_observer.cc new file mode 100644 index 0000000..d596443 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_process_node_observer.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 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/performance_manager/test_support/graph/mock_process_node_observer.h" + +namespace performance_manager { + +LenientMockProcessNodeObserver::LenientMockProcessNodeObserver() = default; +LenientMockProcessNodeObserver::~LenientMockProcessNodeObserver() = default; + +} // namespace performance_manager
diff --git a/components/performance_manager/test_support/graph/mock_process_node_observer.h b/components/performance_manager/test_support/graph/mock_process_node_observer.h new file mode 100644 index 0000000..9e66224a --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_process_node_observer.h
@@ -0,0 +1,45 @@ +// Copyright 2024 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_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_PROCESS_NODE_OBSERVER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_PROCESS_NODE_OBSERVER_H_ + +#include "components/performance_manager/public/graph/process_node.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace performance_manager { + +class LenientMockProcessNodeObserver : public ProcessNode::ObserverDefaultImpl { + public: + LenientMockProcessNodeObserver(); + ~LenientMockProcessNodeObserver() override; + + MOCK_METHOD(void, OnBeforeProcessNodeAdded, (const ProcessNode*), (override)); + MOCK_METHOD(void, OnProcessNodeAdded, (const ProcessNode*), (override)); + MOCK_METHOD(void, OnProcessLifetimeChange, (const ProcessNode*), (override)); + MOCK_METHOD(void, + OnBeforeProcessNodeRemoved, + (const ProcessNode*), + (override)); + MOCK_METHOD(void, OnProcessNodeRemoved, (const ProcessNode*), (override)); + MOCK_METHOD(void, + OnMainThreadTaskLoadIsLow, + (const ProcessNode*), + (override)); + MOCK_METHOD(void, + OnPriorityChanged, + (const ProcessNode*, base::TaskPriority), + (override)); + MOCK_METHOD(void, + OnAllFramesInProcessFrozen, + (const ProcessNode*), + (override)); +}; + +using MockProcessNodeObserver = + ::testing::StrictMock<LenientMockProcessNodeObserver>; + +} // namespace performance_manager + +#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_PROCESS_NODE_OBSERVER_H_
diff --git a/components/performance_manager/test_support/graph/mock_system_node_observer.cc b/components/performance_manager/test_support/graph/mock_system_node_observer.cc new file mode 100644 index 0000000..a16d39a8 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_system_node_observer.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 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/performance_manager/test_support/graph/mock_system_node_observer.h" + +namespace performance_manager { + +LenientMockSystemNodeObserver::LenientMockSystemNodeObserver() = default; +LenientMockSystemNodeObserver::~LenientMockSystemNodeObserver() = default; + +} // namespace performance_manager
diff --git a/components/performance_manager/test_support/graph/mock_system_node_observer.h b/components/performance_manager/test_support/graph/mock_system_node_observer.h new file mode 100644 index 0000000..ec85baf6 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_system_node_observer.h
@@ -0,0 +1,37 @@ +// Copyright 2024 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_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_SYSTEM_NODE_OBSERVER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_SYSTEM_NODE_OBSERVER_H_ + +#include "components/performance_manager/public/graph/system_node.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace performance_manager { + +class LenientMockSystemNodeObserver : public SystemNode::ObserverDefaultImpl { + public: + LenientMockSystemNodeObserver(); + ~LenientMockSystemNodeObserver() override; + + MOCK_METHOD(void, + OnProcessMemoryMetricsAvailable, + (const SystemNode*), + (override)); + MOCK_METHOD(void, + OnMemoryPressure, + (base::MemoryPressureListener::MemoryPressureLevel), + (override)); + MOCK_METHOD(void, + OnBeforeMemoryPressure, + (base::MemoryPressureListener::MemoryPressureLevel), + (override)); +}; + +using MockSystemNodeObserver = + ::testing::StrictMock<LenientMockSystemNodeObserver>; + +} // namespace performance_manager + +#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_SYSTEM_NODE_OBSERVER_H_
diff --git a/components/performance_manager/test_support/graph/mock_worker_node_observer.cc b/components/performance_manager/test_support/graph/mock_worker_node_observer.cc new file mode 100644 index 0000000..2e12056 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_worker_node_observer.cc
@@ -0,0 +1,12 @@ +// Copyright 2024 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/performance_manager/test_support/graph/mock_worker_node_observer.h" + +namespace performance_manager { + +LenientMockWorkerNodeObserver::LenientMockWorkerNodeObserver() = default; +LenientMockWorkerNodeObserver::~LenientMockWorkerNodeObserver() = default; + +} // namespace performance_manager
diff --git a/components/performance_manager/test_support/graph/mock_worker_node_observer.h b/components/performance_manager/test_support/graph/mock_worker_node_observer.h new file mode 100644 index 0000000..adb6398 --- /dev/null +++ b/components/performance_manager/test_support/graph/mock_worker_node_observer.h
@@ -0,0 +1,67 @@ +// Copyright 2024 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_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_WORKER_NODE_OBSERVER_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_WORKER_NODE_OBSERVER_H_ + +#include "components/performance_manager/public/graph/worker_node.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace performance_manager { + +class LenientMockWorkerNodeObserver : public WorkerNode::ObserverDefaultImpl { + public: + LenientMockWorkerNodeObserver(); + ~LenientMockWorkerNodeObserver() override; + + MOCK_METHOD(void, + OnBeforeWorkerNodeAdded, + (const WorkerNode*, const ProcessNode*), + (override)); + MOCK_METHOD(void, OnWorkerNodeAdded, (const WorkerNode*), (override)); + MOCK_METHOD(void, OnBeforeWorkerNodeRemoved, (const WorkerNode*), (override)); + MOCK_METHOD(void, + OnWorkerNodeRemoved, + (const WorkerNode*, const ProcessNode*), + (override)); + MOCK_METHOD(void, + OnFinalResponseURLDetermined, + (const WorkerNode*), + (override)); + MOCK_METHOD(void, + OnBeforeClientFrameAdded, + (const WorkerNode*, const FrameNode*), + (override)); + MOCK_METHOD(void, + OnClientFrameAdded, + (const WorkerNode*, const FrameNode*), + (override)); + MOCK_METHOD(void, + OnBeforeClientFrameRemoved, + (const WorkerNode*, const FrameNode*), + (override)); + MOCK_METHOD(void, + OnBeforeClientWorkerAdded, + (const WorkerNode*, const WorkerNode*), + (override)); + MOCK_METHOD(void, + OnClientWorkerAdded, + (const WorkerNode*, const WorkerNode*), + (override)); + MOCK_METHOD(void, + OnBeforeClientWorkerRemoved, + (const WorkerNode*, const WorkerNode*), + (override)); + MOCK_METHOD(void, + OnPriorityAndReasonChanged, + (const WorkerNode*, const PriorityAndReason&), + (override)); +}; + +using MockWorkerNodeObserver = + ::testing::StrictMock<LenientMockWorkerNodeObserver>; + +} // namespace performance_manager + +#endif // COMPONENTS_PERFORMANCE_MANAGER_TEST_SUPPORT_GRAPH_MOCK_WORKER_NODE_OBSERVER_H_
diff --git a/components/performance_manager/test_support/test_browser_child_process.cc b/components/performance_manager/test_support/test_browser_child_process.cc index 7f71a988..cecfac16 100644 --- a/components/performance_manager/test_support/test_browser_child_process.cc +++ b/components/performance_manager/test_support/test_browser_child_process.cc
@@ -41,10 +41,10 @@ // Simulate a successful process launch with a copy of ChildProcessData that // has an existing process attached. ChildProcessData is move-only, but // GetData() returns a const ref, so must copy each field individually. - content::ChildProcessData data(host_->GetData().process_type); + content::ChildProcessData data(host_->GetData().process_type, + host_->GetData().GetChildProcessId()); data.name = host_->GetData().name; data.metrics_name = host_->GetData().metrics_name; - data.id = host_->GetData().id; data.sandbox_type = host_->GetData().sandbox_type; data.SetProcess(std::move(process)); PerformanceManagerRegistryImpl::GetInstance()
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service.cc b/components/safe_browsing/core/browser/realtime/url_lookup_service.cc index 37d50f14..2f802b6 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service.cc +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service.cc
@@ -8,6 +8,7 @@ #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/rand_util.h" #include "base/strings/strcat.h" #include "base/task/sequenced_task_runner.h" @@ -40,6 +41,11 @@ constexpr char kCookieHistogramPrefix[] = "SafeBrowsing.RT.Request.HadCookie"; +GURL* GetRealTimeLookupUrlTestOverride() { + static base::NoDestructor<GURL> test_override; + return test_override.get(); +} + } // namespace namespace safe_browsing { @@ -181,6 +187,11 @@ } GURL RealTimeUrlLookupService::GetRealTimeLookupUrl() const { + GURL* url_for_tests = GetRealTimeLookupUrlTestOverride(); + if (url_for_tests->is_valid()) { + return *url_for_tests; + } + return GURL( "https://safebrowsing.google.com/safebrowsing/clientreport/realtime"); } @@ -237,6 +248,11 @@ return CanGetReputationOfUrl(url); } +// static +void RealTimeUrlLookupService::OverrideUrlForTesting(const GURL& url) { + *GetRealTimeLookupUrlTestOverride() = url; +} + bool RealTimeUrlLookupService::ShouldIncludeCredentials() const { return true; }
diff --git a/components/safe_browsing/core/browser/realtime/url_lookup_service.h b/components/safe_browsing/core/browser/realtime/url_lookup_service.h index 6716f08..c8c21f8 100644 --- a/components/safe_browsing/core/browser/realtime/url_lookup_service.h +++ b/components/safe_browsing/core/browser/realtime/url_lookup_service.h
@@ -52,6 +52,9 @@ using ClientConfiguredForTokenFetchesCallback = base::RepeatingCallback<bool(bool user_has_enabled_enhanced_protection)>; + // Set the URL used for lookups in tests. + static void OverrideUrlForTesting(const GURL& url); + // |cache_manager|, |sync_service|, and |pref_service| may be null in tests. // |token_fetcher| may also be null, but in that case the passed-in // |client_token_config_callback| should return false to ensure that access
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc index e1a05e9..e78b6f4 100644 --- a/components/safe_browsing/core/common/features.cc +++ b/components/safe_browsing/core/common/features.cc
@@ -177,10 +177,6 @@ "SafeBrowsingExtensionTelemetryReportContactedHosts", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kExtensionTelemetryReportHostsContactedViaWebSocket, - "SafeBrowsingExtensionTelemetryReportHostsContactedViaWebsocket", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE( kExtensionTelemetryInterceptRemoteHostsContactedInRenderer, "SafeBrowsingExtensionTelmetryInterceptRemoteHostsContactedInRenderer", @@ -358,7 +354,6 @@ &kExtensionTelemetryForEnterprise, &kExtensionTelemetryInterceptRemoteHostsContactedInRenderer, &kExtensionTelemetryReportContactedHosts, - &kExtensionTelemetryReportHostsContactedViaWebSocket, &kExtensionTelemetryTabsExecuteScriptSignal, &kExternalAppRedirectTelemetry, &kHashPrefixRealTimeLookups,
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h index 9f0d99c..32f6570b 100644 --- a/components/safe_browsing/core/common/features.h +++ b/components/safe_browsing/core/common/features.h
@@ -171,9 +171,6 @@ // Enables reporting of remote hosts contacted by extensions in telemetry. BASE_DECLARE_FEATURE(kExtensionTelemetryReportContactedHosts); -// Enables reporting of remote hosts contacted by extensions via websockets; -BASE_DECLARE_FEATURE(kExtensionTelemetryReportHostsContactedViaWebSocket); - // Enables intercepting remote hosts contacted by extensions in renderer // throttles. BASE_DECLARE_FEATURE(
diff --git a/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc b/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc index f13e3e0..e917a4f 100644 --- a/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc +++ b/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc
@@ -10,6 +10,7 @@ #include "base/functional/callback_helpers.h" #include "base/memory/scoped_refptr.h" #include "base/observer_list.h" +#include "base/strings/escape.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/uuid.h" @@ -78,7 +79,8 @@ if (page_entities_metadata.has_value() && !page_entities_metadata->alternative_title().empty()) { use_url_as_title = false; - title = base::ASCIIToUTF16(page_entities_metadata->alternative_title()); + title = base::UnescapeForHTML( + base::UTF8ToUTF16(page_entities_metadata->alternative_title())); } } stats::RecordSharedGroupTitleSanitization(use_url_as_title, type);
diff --git a/components/search_engines/default_search_manager.cc b/components/search_engines/default_search_manager.cc index 02d9985..cdb0330 100644 --- a/components/search_engines/default_search_manager.cc +++ b/components/search_engines/default_search_manager.cc
@@ -21,11 +21,6 @@ #include "components/search_engines/template_url_data_util.h" #include "components/search_engines/template_url_prepopulate_data.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/crosapi/mojom/prefs.mojom.h" -#include "chromeos/lacros/lacros_service.h" -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - namespace { bool g_fallback_search_engines_disabled = false; } // namespace @@ -93,19 +88,11 @@ DefaultSearchManager::DefaultSearchManager( PrefService* pref_service, search_engines::SearchEngineChoiceService* search_engine_choice_service, - const ObserverCallback& change_observer -#if BUILDFLAG(IS_CHROMEOS_LACROS) - , - bool for_lacros_main_profile -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - ) + const ObserverCallback& change_observer) : pref_service_(pref_service), search_engine_choice_service_(search_engine_choice_service), change_observer_(change_observer), search_engine_choice_service_observation_(this), -#if BUILDFLAG(IS_CHROMEOS_LACROS) - for_lacros_main_profile_(for_lacros_main_profile), -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) prefs_default_search_(pref_service, search_engine_choice_service) { if (pref_service_) { pref_change_registrar_.Init(pref_service_); @@ -279,26 +266,6 @@ // both before and after the above load. if (!source_was_fallback || (GetDefaultSearchEngineSource() != FROM_FALLBACK)) NotifyObserver(); - -#if BUILDFLAG(IS_CHROMEOS_LACROS) - if (for_lacros_main_profile_) { - auto* lacros_service = chromeos::LacrosService::Get(); - if (!lacros_service || - !lacros_service->IsAvailable<crosapi::mojom::Prefs>()) { - LOG(WARNING) << "crosapi: Prefs API not available"; - return; - } - - const base::Value::Dict& dict = - pref_service_->GetDict(kDefaultSearchProviderDataPrefName); - if (dict.empty()) { - return; - } - lacros_service->GetRemote<crosapi::mojom::Prefs>()->SetPref( - crosapi::mojom::PrefPath::kDefaultSearchProviderDataPrefName, - base::Value(dict.Clone()), base::DoNothing()); - } -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) } void DefaultSearchManager::OnOverridesPrefChanged() {
diff --git a/components/search_engines/default_search_manager.h b/components/search_engines/default_search_manager.h index 71425c4..4b4d7df7 100644 --- a/components/search_engines/default_search_manager.h +++ b/components/search_engines/default_search_manager.h
@@ -11,7 +11,6 @@ #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "base/values.h" -#include "build/chromeos_buildflags.h" #include "components/prefs/pref_change_registrar.h" #include "components/search_engines/reconciling_template_url_data_holder.h" #include "components/search_engines/search_engine_choice/search_engine_choice_service.h" @@ -113,12 +112,7 @@ DefaultSearchManager( PrefService* pref_service, search_engines::SearchEngineChoiceService* search_engine_choice_service, - const ObserverCallback& change_observer -#if BUILDFLAG(IS_CHROMEOS_LACROS) - , - bool for_lacros_main_profile -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - ); + const ObserverCallback& change_observer); DefaultSearchManager(const DefaultSearchManager&) = delete; DefaultSearchManager& operator=(const DefaultSearchManager&) = delete; @@ -226,11 +220,6 @@ // True if the default search is currently recommended by policy. bool default_search_recommended_by_policy_ = false; - -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // True if this instance is used for the Lacros primary profile. - bool for_lacros_main_profile_ = false; -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) }; #endif // COMPONENTS_SEARCH_ENGINES_DEFAULT_SEARCH_MANAGER_H_
diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc index fb317c0..e3ee2b5f 100644 --- a/components/search_engines/template_url.cc +++ b/components/search_engines/template_url.cc
@@ -1761,7 +1761,7 @@ } std::u16string TemplateURL::AdjustedShortNameForLocaleDirection() const { - std::u16string bidi_safe_short_name = data_.short_name(); + std::u16string bidi_safe_short_name = data().short_name(); base::i18n::AdjustStringForLocaleDirection(&bidi_safe_short_name); return bidi_safe_short_name; } @@ -1788,17 +1788,17 @@ bool TemplateURL::IsGoogleSearchURLWithReplaceableKeyword( const SearchTermsData& search_terms_data) const { return (type_ == NORMAL) && url_ref().HasGoogleBaseURLs(search_terms_data) && - google_util::IsGoogleHostname(base::UTF16ToUTF8(data_.keyword()), + google_util::IsGoogleHostname(base::UTF16ToUTF8(data().keyword()), google_util::DISALLOW_SUBDOMAIN); } bool TemplateURL::HasSameKeywordAs( const TemplateURLData& other, const SearchTermsData& search_terms_data) const { - return (data_.keyword() == other.keyword()) || - (IsGoogleSearchURLWithReplaceableKeyword(search_terms_data) && - TemplateURL(other).IsGoogleSearchURLWithReplaceableKeyword( - search_terms_data)); + return (data().keyword() == other.keyword()) || + (IsGoogleSearchURLWithReplaceableKeyword(search_terms_data) && + TemplateURL(other).IsGoogleSearchURLWithReplaceableKeyword( + search_terms_data)); } std::string TemplateURL::GetExtensionId() const { @@ -1818,10 +1818,10 @@ } BuiltinEngineType TemplateURL::GetBuiltinEngineType() const { - if (data_.prepopulate_id != 0) { + if (data().prepopulate_id != 0) { return KEYWORD_MODE_PREPOPULATED_ENGINE; - } else if (data_.starter_pack_id != 0) { - switch (data_.starter_pack_id) { + } else if (data().starter_pack_id != 0) { + switch (data().starter_pack_id) { case TemplateURLStarterPackData::kBookmarks: return KEYWORD_MODE_STARTER_PACK_BOOKMARKS; case TemplateURLStarterPackData::kHistory: @@ -1882,9 +1882,9 @@ } std::vector<std::string> query_params; - if (keep_search_intent_params && !data_.search_intent_params.empty()) { + if (keep_search_intent_params && !data().search_intent_params.empty()) { for (net::QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { - if (!base::Contains(data_.search_intent_params, it.GetKey())) { + if (!base::Contains(data().search_intent_params, it.GetKey())) { continue; } query_params.push_back(base::StrCat({it.GetKey(), "=", it.GetValue()})); @@ -2002,7 +2002,7 @@ } RegulatoryExtensionType TemplateURL::GetRegulatoryExtensionType() const { - if (data_.created_from_play_api) { + if (data().created_from_play_api) { return RegulatoryExtensionType::kAndroidEEA; } return RegulatoryExtensionType::kDefault; @@ -2010,8 +2010,8 @@ const TemplateURLData::RegulatoryExtension* TemplateURL::GetRegulatoryExtension( RegulatoryExtensionType type) const { - auto extension_iter = data_.regulatory_extensions.find(type); - auto* extension = extension_iter == data_.regulatory_extensions.end() + auto extension_iter = data().regulatory_extensions.find(type); + auto* extension = extension_iter == data().regulatory_extensions.end() ? nullptr : extension_iter->second.get(); @@ -2073,17 +2073,17 @@ data_ = other.data_; ResizeURLRefVector(); InvalidateCachedValues(); - SetPrepopulateId(other.data_.prepopulate_id); + SetPrepopulateId(other.data().prepopulate_id); } void TemplateURL::SetURL(const std::string& url) { - data_.SetURL(url); + const_cast<TemplateURLData&>(data()).SetURL(url); engine_type_ = SEARCH_ENGINE_UNKNOWN; url_ref().InvalidateCachedValues(); } void TemplateURL::SetPrepopulateId(int id) { - data_.prepopulate_id = id; + const_cast<TemplateURLData&>(data()).prepopulate_id = id; const bool prepopulated = id > 0; for (TemplateURLRef& ref : url_refs_) ref.prepopulated_ = prepopulated; @@ -2101,7 +2101,7 @@ DCHECK_NE(OMNIBOX_API_EXTENSION, type_); GURL url(GenerateSearchURL(search_terms_data)); if (url.is_valid()) - data_.SetKeyword(GenerateKeyword(url)); + const_cast<TemplateURLData&>(data()).SetKeyword(GenerateKeyword(url)); } } @@ -2131,14 +2131,15 @@ } void TemplateURL::ResizeURLRefVector() { - const size_t new_size = data_.alternate_urls.size() + 1; + const size_t new_size = data().alternate_urls.size() + 1; if (url_refs_.size() == new_size) return; url_refs_.clear(); url_refs_.reserve(new_size); - for (size_t i = 0; i != data_.alternate_urls.size(); ++i) + for (size_t i = 0; i != data().alternate_urls.size(); ++i) { url_refs_.emplace_back(this, i); + } url_refs_.emplace_back(this, TemplateURLRef::SEARCH); } @@ -2185,3 +2186,7 @@ &side_image_search_value); return !side_image_search_value.empty(); } + +const TemplateURLData& TemplateURL::data() const { + return data_; +}
diff --git a/components/search_engines/template_url.h b/components/search_engines/template_url.h index d9e2fd9f..c766b5be 100644 --- a/components/search_engines/template_url.h +++ b/components/search_engines/template_url.h
@@ -727,93 +727,93 @@ const TemplateURLData* data, const SearchTermsData& search_terms_data); - const TemplateURLData& data() const { return data_; } + const TemplateURLData& data() const; - const std::u16string& short_name() const { return data_.short_name(); } + const std::u16string& short_name() const { return data().short_name(); } // An accessor for the short_name, but adjusted so it can be appropriately // displayed even if it is LTR and the UI is RTL. std::u16string AdjustedShortNameForLocaleDirection() const; - const std::u16string& keyword() const { return data_.keyword(); } + const std::u16string& keyword() const { return data().keyword(); } - const std::string& url() const { return data_.url(); } - const std::string& suggestions_url() const { return data_.suggestions_url; } - const std::string& image_url() const { return data_.image_url; } + const std::string& url() const { return data().url(); } + const std::string& suggestions_url() const { return data().suggestions_url; } + const std::string& image_url() const { return data().image_url; } const std::string& image_translate_url() const { - return data_.image_translate_url; + return data().image_translate_url; } - const std::string& new_tab_url() const { return data_.new_tab_url; } + const std::string& new_tab_url() const { return data().new_tab_url; } const std::string& contextual_search_url() const { - return data_.contextual_search_url; + return data().contextual_search_url; } const std::string& search_url_post_params() const { - return data_.search_url_post_params; + return data().search_url_post_params; } const std::string& suggestions_url_post_params() const { - return data_.suggestions_url_post_params; + return data().suggestions_url_post_params; } const std::string& image_url_post_params() const { - return data_.image_url_post_params; + return data().image_url_post_params; } const std::string& side_search_param() const { - return data_.side_search_param; + return data().side_search_param; } const std::string& side_image_search_param() const { - return data_.side_image_search_param; + return data().side_image_search_param; } const std::string& image_translate_source_language_param_key() const { - return data_.image_translate_source_language_param_key; + return data().image_translate_source_language_param_key; } const std::string& image_translate_target_language_param_key() const { - return data_.image_translate_target_language_param_key; + return data().image_translate_target_language_param_key; } const std::u16string& image_search_branding_label() const { - return !data_.image_search_branding_label.empty() - ? data_.image_search_branding_label + return !data().image_search_branding_label.empty() + ? data().image_search_branding_label : short_name(); } const std::vector<std::string>& search_intent_params() const { - return data_.search_intent_params; + return data().search_intent_params; } const std::vector<std::string>& alternate_urls() const { - return data_.alternate_urls; + return data().alternate_urls; } - const GURL& favicon_url() const { return data_.favicon_url; } + const GURL& favicon_url() const { return data().favicon_url; } - const GURL& logo_url() const { return data_.logo_url; } + const GURL& logo_url() const { return data().logo_url; } - const GURL& doodle_url() const { return data_.doodle_url; } + const GURL& doodle_url() const { return data().doodle_url; } - const GURL& originating_url() const { return data_.originating_url; } + const GURL& originating_url() const { return data().originating_url; } - bool safe_for_autoreplace() const { return data_.safe_for_autoreplace; } + bool safe_for_autoreplace() const { return data().safe_for_autoreplace; } const std::vector<std::string>& input_encodings() const { - return data_.input_encodings; + return data().input_encodings; } - TemplateURLID id() const { return data_.id; } + TemplateURLID id() const { return data().id; } - base::Time date_created() const { return data_.date_created; } - base::Time last_modified() const { return data_.last_modified; } - base::Time last_visited() const { return data_.last_visited; } + base::Time date_created() const { return data().date_created; } + base::Time last_modified() const { return data().last_modified; } + base::Time last_visited() const { return data().last_visited; } TemplateURLData::CreatedByPolicy created_by_policy() const { - return data_.created_by_policy; + return data().created_by_policy; } - bool enforced_by_policy() const { return data_.enforced_by_policy; } - bool created_from_play_api() const { return data_.created_from_play_api; } - bool featured_by_policy() const { return data_.featured_by_policy; } + bool enforced_by_policy() const { return data().enforced_by_policy; } + bool created_from_play_api() const { return data().created_from_play_api; } + bool featured_by_policy() const { return data().featured_by_policy; } - int usage_count() const { return data_.usage_count; } + int usage_count() const { return data().usage_count; } - int prepopulate_id() const { return data_.prepopulate_id; } + int prepopulate_id() const { return data().prepopulate_id; } - const std::string& sync_guid() const { return data_.sync_guid; } + const std::string& sync_guid() const { return data().sync_guid; } - TemplateURLData::ActiveStatus is_active() const { return data_.is_active; } + TemplateURLData::ActiveStatus is_active() const { return data().is_active; } - int starter_pack_id() const { return data_.starter_pack_id; } + int starter_pack_id() const { return data().starter_pack_id; } const std::vector<TemplateURLRef>& url_refs() const { return url_refs_; } const TemplateURLRef& url_ref() const {
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc index 318d3917..a2b2afb 100644 --- a/components/search_engines/template_url_service.cc +++ b/components/search_engines/template_url_service.cc
@@ -772,6 +772,7 @@ default_search_provider_ = nullptr; } Remove(url); + RemoveFromUnscopedModeExtensionIdsIfPresent(extension_id); } void TemplateURLService::RemoveAutoGeneratedBetween(base::Time created_after, @@ -801,12 +802,13 @@ } } -void TemplateURLService::RegisterOmniboxKeyword( +void TemplateURLService::RegisterExtensionControlledTURL( const std::string& extension_id, const std::string& extension_name, const std::string& keyword, const std::string& template_url_string, - const base::Time& extension_install_time) { + const base::Time& extension_install_time, + const bool unscoped_mode_allowed) { DCHECK(loaded_); if (FindTemplateURLForExtension(extension_id, @@ -814,6 +816,10 @@ return; } + if (unscoped_mode_allowed) { + AddToUnscopedModeExtensionIds(extension_id); + } + TemplateURLData data; data.SetShortName(base::UTF8ToUTF16(extension_name)); data.SetKeyword(base::UTF8ToUTF16(keyword)); @@ -2395,6 +2401,28 @@ } } +void TemplateURLService::AddToUnscopedModeExtensionIds( + const std::string& extension_id) { + CHECK(!extension_id.empty()); + unscoped_mode_extension_ids_.insert(extension_id); +} + +void TemplateURLService::RemoveFromUnscopedModeExtensionIdsIfPresent( + const std::string& extension_id) { + if (unscoped_mode_extension_ids_.contains(extension_id)) { + unscoped_mode_extension_ids_.erase(extension_id); + } +} + +std::set<std::string> TemplateURLService::GetUnscopedModeExtensionIds() const { + return unscoped_mode_extension_ids_; +} + +bool TemplateURLService::IsUnscopedModeExtensionId( + const std::string& extension_id) { + return unscoped_mode_extension_ids_.contains(extension_id); +} + void TemplateURLService::UpdateTemplateURLVisitTime(TemplateURL* url) { TemplateURLData data(url->data()); data.last_visited = clock_->Now();
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h index 54b7252c..e0e4341e 100644 --- a/components/search_engines/template_url_service.h +++ b/components/search_engines/template_url_service.h
@@ -281,11 +281,27 @@ // Adds a TemplateURL for an extension with an omnibox keyword. // Only 1 keyword is allowed for a given extension. If a keyword // already exists for this extension, does nothing. - void RegisterOmniboxKeyword(const std::string& extension_id, - const std::string& extension_name, - const std::string& keyword, - const std::string& template_url_string, - const base::Time& extension_install_time); + void RegisterExtensionControlledTURL(const std::string& extension_id, + const std::string& extension_name, + const std::string& keyword, + const std::string& template_url_string, + const base::Time& extension_install_time, + const bool unscoped_mode_allowed); + + // Adds extension_id to the list of extensions that are allowed to add + // unscoped keywords. + void AddToUnscopedModeExtensionIds(const std::string& extension_id); + + // Removes extension_id from the list of extensions if it was present. + void RemoveFromUnscopedModeExtensionIdsIfPresent( + const std::string& extension_id); + + // Returns extensions that can run in unscoped mode (without keyword mode). + // It's OK to return a copy since we expect this set to be very small. + std::set<std::string> GetUnscopedModeExtensionIds() const; + + // Returns whether `unscoped_mode_extension_ids_` contains `extension_id`. + bool IsUnscopedModeExtensionId(const std::string& extension_id); // Returns the set of URLs describing the keywords. The elements are owned // by TemplateURLService and should not be deleted. @@ -932,6 +948,10 @@ base::ObserverList<TemplateURLServiceObserver> model_observers_; + // The IDs of the extensions that can receive Omnibox events without requiring + // scoped mode. + std::set<std::string> unscoped_mode_extension_ids_; + // Maps from host to set of TemplateURLs whose search url host is host. std::unique_ptr<SearchHostToURLsMap> provider_map_ = std::make_unique<SearchHostToURLsMap>();
diff --git a/components/security_interstitials/content/ssl_error_handler.cc b/components/security_interstitials/content/ssl_error_handler.cc index c2cadcc2..4eea44a 100644 --- a/components/security_interstitials/content/ssl_error_handler.cc +++ b/components/security_interstitials/content/ssl_error_handler.cc
@@ -60,10 +60,6 @@ "MITMSoftwareInterstitial", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kCaptivePortalInterstitial, - "CaptivePortalInterstitial", - base::FEATURE_ENABLED_BY_DEFAULT); - namespace { BASE_FEATURE(kSSLCommonNameMismatchHandling, @@ -152,10 +148,6 @@ SSLErrorHandler::SSL_ERROR_HANDLER_EVENT_COUNT); } -bool IsCaptivePortalInterstitialEnabled() { - return base::FeatureList::IsEnabled(kCaptivePortalInterstitial); -} - bool IsMITMSoftwareInterstitialEnabled() { return base::FeatureList::IsEnabled(kMITMSoftwareInterstitial); } @@ -689,8 +681,7 @@ // opens a new tab if it detects a portal ignoring the types of SSL errors. To // be consistent with captive portal detector, use the result of OS detection // without checking only_error_is_name_mismatch. - if (IsCaptivePortalInterstitialEnabled() && - (g_config.Pointer()->DoesOSReportCaptivePortalForTesting() || + if ((g_config.Pointer()->DoesOSReportCaptivePortalForTesting() || // IN-TEST delegate_->DoesOSReportCaptivePortal())) { delegate_->ReportNetworkConnectivity( g_config.Pointer()->report_network_connectivity_callback()); @@ -772,7 +763,7 @@ captive_portal_tab_helper->OnSSLCertError(ssl_info_); } - if (IsCaptivePortalInterstitialEnabled() && !is_captive_portal_login_tab) { + if (!is_captive_portal_login_tab) { delegate_->CheckForCaptivePortal(); timer_.Start(FROM_HERE, g_config.Pointer()->interstitial_delay(), this, &SSLErrorHandler::ShowSSLInterstitial);
diff --git a/components/security_interstitials/content/ssl_error_handler.h b/components/security_interstitials/content/ssl_error_handler.h index 3979585..ceb7f83 100644 --- a/components/security_interstitials/content/ssl_error_handler.h +++ b/components/security_interstitials/content/ssl_error_handler.h
@@ -44,7 +44,6 @@ } BASE_DECLARE_FEATURE(kMITMSoftwareInterstitial); -BASE_DECLARE_FEATURE(kCaptivePortalInterstitial); // This class is responsible for deciding what type of interstitial to display // for an SSL validation error and actually displaying it. The display of the
diff --git a/components/security_interstitials/content/ssl_error_handler_unittest.cc b/components/security_interstitials/content/ssl_error_handler_unittest.cc index 4bbf312..fec423c 100644 --- a/components/security_interstitials/content/ssl_error_handler_unittest.cc +++ b/components/security_interstitials/content/ssl_error_handler_unittest.cc
@@ -955,43 +955,6 @@ SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 1); } -class SSLErrorHandlerNameMismatchCaptivePortalInterstitialDisabledTest - : public SSLErrorHandlerNameMismatchTest { - public: - SSLErrorHandlerNameMismatchCaptivePortalInterstitialDisabledTest() { - scoped_feature_list_.InitAndDisableFeature(kCaptivePortalInterstitial); - } - - private: - // This should only be accessed from a test's constructor, to avoid tsan data - // races with threads kicked off by RenderViewHostTestHarness::SetUp(). - base::test::ScopedFeatureList scoped_feature_list_; -}; - -// Test that a captive portal interstitial isn't shown if the OS reports a -// portal but CaptivePortalInterstitial feature is disabled. -TEST_F(SSLErrorHandlerNameMismatchCaptivePortalInterstitialDisabledTest, - OSReportsCaptivePortal_FeatureDisabled) { - base::HistogramTester histograms; - delegate()->set_os_reports_captive_portal(); - - EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); - error_handler()->StartHandlingError(); - EXPECT_FALSE(error_handler()->IsTimerRunningForTesting()); - EXPECT_FALSE(delegate()->captive_portal_checked()); - EXPECT_TRUE(delegate()->ssl_interstitial_shown()); - EXPECT_FALSE(delegate()->captive_portal_interstitial_shown()); - - histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(), 2); - histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::HANDLE_ALL, 1); - histograms.ExpectBucketCount( - SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1); - histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(), - SSLErrorHandler::OS_REPORTS_CAPTIVE_PORTAL, 0); -} - TEST_F(SSLErrorHandlerNameMismatchTest, ShouldShowSSLInterstitialOnTimerExpiredWhenSuggestedUrlExists) { base::HistogramTester histograms;
diff --git a/components/user_education/common/user_education_metadata.h b/components/user_education/common/user_education_metadata.h index 5fa9dc2b..7d2180a41 100644 --- a/components/user_education/common/user_education_metadata.h +++ b/components/user_education/common/user_education_metadata.h
@@ -18,7 +18,7 @@ // Badge, etc.). // // Metadata will be shown and used on the tester page -// (chrome://internals/user-education), and also provides information as to when +// (chrome://user-education-internals), and also provides information as to when // the journey was added to Chrome and by whom. struct Metadata { // The platform the experience can be shown on.
diff --git a/components/user_education/feature-promos.md b/components/user_education/feature-promos.md index 132c6be..9b99cf6 100644 --- a/components/user_education/feature-promos.md +++ b/components/user_education/feature-promos.md
@@ -273,7 +273,7 @@ not reshow when dismissed or after your feature is used. If you want to see or clear the data around your IPH feature (including whether -it has been permanently dismissed) go to `chrome://internals/user-education`, +it has been permanently dismissed) go to `chrome://user-education-internals`, find your feature, and expand the trays underneath to see and optionally clear the recorded data. Clearing the data can allow you to trigger your feature over and over on the same profile. @@ -293,7 +293,7 @@ ### Manual approach 3: Tester Page If you just want to preview what your help bubble will look like, you can go to -the tester page at `chrome://internals/user-education`, find your promo, and +the tester page at `chrome://user-education-internals`, find your promo, and click the "Launch" button. This will attempt to show your IPH in the current UI. Note that if your IPH anchors to an element that is not present, it will not be able to show.
diff --git a/components/user_education/tutorials.md b/components/user_education/tutorials.md index c249a97..fcf7a5f 100644 --- a/components/user_education/tutorials.md +++ b/components/user_education/tutorials.md
@@ -134,7 +134,7 @@ test an IPH, suggestions are [in the documentation](./feature-promos.md). You can also launch your Tutorial directly from the tester page -(chrome://internals/user-education). Note that unlike IPH, you do not need to +(chrome://user-education-internals). Note that unlike IPH, you do not need to have the starting point of the tutorial present when you click the "Launch" button; you merely need to be able to bring it up in 20-30 seconds. The tutorial will start as soon as the anchor view for the first bubble of the tutorial
diff --git a/components/viz/client/client_resource_provider.cc b/components/viz/client/client_resource_provider.cc index 788c099..6da6f3d 100644 --- a/components/viz/client/client_resource_provider.cc +++ b/components/viz/client/client_resource_provider.cc
@@ -229,16 +229,6 @@ } gpu::SyncToken ClientResourceProvider::GenerateSyncTokenHelper( - gpu::gles2::GLES2Interface* gl) { - DCHECK(gl); - gpu::SyncToken sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); - DCHECK(sync_token.HasData() || - gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR); - return sync_token; -} - -gpu::SyncToken ClientResourceProvider::GenerateSyncTokenHelper( gpu::raster::RasterInterface* ri) { DCHECK(ri); gpu::SyncToken sync_token;
diff --git a/components/viz/client/client_resource_provider.h b/components/viz/client/client_resource_provider.h index 4a5f79cb..445eb25 100644 --- a/components/viz/client/client_resource_provider.h +++ b/components/viz/client/client_resource_provider.h
@@ -22,9 +22,6 @@ #include "third_party/khronos/GLES2/gl2.h" namespace gpu { -namespace gles2 { -class GLES2Interface; -} namespace raster { class RasterInterface; } @@ -79,7 +76,6 @@ ~ClientResourceProvider(); - static gpu::SyncToken GenerateSyncTokenHelper(gpu::gles2::GLES2Interface* gl); static gpu::SyncToken GenerateSyncTokenHelper( gpu::raster::RasterInterface* ri);
diff --git a/components/viz/host/renderer_settings_creation.cc b/components/viz/host/renderer_settings_creation.cc index 0bedc28..0cff5ef9 100644 --- a/components/viz/host/renderer_settings_creation.cc +++ b/components/viz/host/renderer_settings_creation.cc
@@ -69,8 +69,14 @@ &renderer_settings.slow_down_compositing_scale_factor); } +#if BUILDFLAG(IS_CHROMEOS) + // Used finch experiment to determine the best value. See b:330617490 for + // details. + renderer_settings.occlusion_culler_settings.quad_split_limit = 12; +#else renderer_settings.occlusion_culler_settings.quad_split_limit = features::DrawQuadSplitLimit(); +#endif #if BUILDFLAG(IS_OZONE) if (command_line->HasSwitch(switches::kEnableHardwareOverlays)) {
diff --git a/components/webcrypto/algorithms/aes_ctr.cc b/components/webcrypto/algorithms/aes_ctr.cc index 7539a7c..3fe0b30 100644 --- a/components/webcrypto/algorithms/aes_ctr.cc +++ b/components/webcrypto/algorithms/aes_ctr.cc
@@ -88,13 +88,14 @@ // Extracts the counter as a `absl::uint128`. The counter is the rightmost // `counter_length_bits` of the block, interpreted as a big-endian number. -absl::uint128 GetCounter(base::span<const uint8_t, 16> counter_block, - unsigned int counter_length_bits) { +absl::uint128 GetCounter( + base::span<const uint8_t, AES_BLOCK_SIZE> counter_block, + unsigned int counter_length_bits) { unsigned int counter_length_remainder_bits = counter_length_bits % 8; unsigned int byte_length = CeilDiv(counter_length_bits, 8u); DCHECK_GT(byte_length, 0u); - base::span<const uint8_t> suffix = counter_block.last(byte_length); + base::span suffix = counter_block.last(byte_length); absl::uint128 ret = suffix[0]; // The first byte may be partial. if (counter_length_remainder_bits != 0) { @@ -150,8 +151,8 @@ if (params->Counter().size() != AES_BLOCK_SIZE) return Status::ErrorIncorrectSizeAesCtrCounter(); - base::span<const uint8_t, AES_BLOCK_SIZE> counter_block( - params->Counter().data(), params->Counter().size()); + auto counter_block = + *base::span(params->Counter()).to_fixed_extent<AES_BLOCK_SIZE>(); unsigned int counter_length_bits = params->LengthBits(); if (counter_length_bits < 1 || counter_length_bits > 128)
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 4b7cfa5f..6edd9c52 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2868,20 +2868,6 @@ } } - if (is_chromeos_lacros) { - sources += [ - "accessibility/browser_accessibility_state_impl_lacros.cc", - "accessibility/browser_accessibility_state_impl_lacros.h", - "screenlock_monitor/screenlock_monitor_device_source_lacros.cc", - ] - deps += [ - "//chromeos/crosapi/mojom", - "//chromeos/lacros", - "//chromeos/startup", - "//chromeos/startup:constants", - ] - } - if (is_win) { sources += [ "accessibility/browser_accessibility_state_impl_win.cc", @@ -3480,7 +3466,7 @@ "renderer_host/render_widget_host_view_event_handler.h", ] - if (is_linux || is_chromeos_lacros) { + if (is_linux) { deps += [ "//ui/base/ime/linux" ] } } else { # Not aura.
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc index 90ebe65..e17a5c4 100644 --- a/content/browser/accessibility/browser_accessibility_state_impl.cc +++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -191,9 +191,8 @@ return g_instance; } -// On Android, Mac, Lacros, and Windows there are platform-specific subclasses. -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC) && \ - !BUILDFLAG(IS_CHROMEOS_LACROS) +// On Android, Mac, and Windows there are platform-specific subclasses. +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC) // static std::unique_ptr<BrowserAccessibilityStateImpl> BrowserAccessibilityStateImpl::Create() {
diff --git a/content/browser/accessibility/browser_accessibility_state_impl_lacros.cc b/content/browser/accessibility/browser_accessibility_state_impl_lacros.cc deleted file mode 100644 index 8c168ae..0000000 --- a/content/browser/accessibility/browser_accessibility_state_impl_lacros.cc +++ /dev/null
@@ -1,38 +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 "content/browser/accessibility/browser_accessibility_state_impl_lacros.h" - -#include <memory> - -#include "content/public/browser/scoped_accessibility_mode.h" - -namespace content { - -BrowserAccessibilityStateImplLacros::BrowserAccessibilityStateImplLacros() - : crosapi_pref_observer_( - crosapi::mojom::PrefPath::kAccessibilitySpokenFeedbackEnabled, - base::BindRepeating( - &BrowserAccessibilityStateImplLacros::OnSpokenFeedbackPrefChanged, - base::Unretained(this))) {} - -BrowserAccessibilityStateImplLacros::~BrowserAccessibilityStateImplLacros() = - default; - -void BrowserAccessibilityStateImplLacros::OnSpokenFeedbackPrefChanged( - base::Value value) { - if (!value.GetIfBool().value_or(false)) { - screen_reader_mode_.reset(); - } else if (!screen_reader_mode_) { - screen_reader_mode_ = CreateScopedModeForProcess(ui::AXMode::kScreenReader); - } -} - -// static -std::unique_ptr<BrowserAccessibilityStateImpl> -BrowserAccessibilityStateImpl::Create() { - return std::make_unique<BrowserAccessibilityStateImplLacros>(); -} - -} // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_state_impl_lacros.h b/content/browser/accessibility/browser_accessibility_state_impl_lacros.h deleted file mode 100644 index 379fafc..0000000 --- a/content/browser/accessibility/browser_accessibility_state_impl_lacros.h +++ /dev/null
@@ -1,41 +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. - -#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_STATE_IMPL_LACROS_H_ -#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_STATE_IMPL_LACROS_H_ - -#include <memory> - -#include "base/values.h" -#include "chromeos/lacros/crosapi_pref_observer.h" -#include "content/browser/accessibility/browser_accessibility_state_impl.h" - -namespace content { - -class ScopedAccessibilityMode; - -class BrowserAccessibilityStateImplLacros - : public BrowserAccessibilityStateImpl { - public: - BrowserAccessibilityStateImplLacros(); - ~BrowserAccessibilityStateImplLacros() override; - - BrowserAccessibilityStateImplLacros( - const BrowserAccessibilityStateImplLacros&) = delete; - BrowserAccessibilityStateImplLacros& operator=( - const BrowserAccessibilityStateImplLacros&) = delete; - - private: - void OnSpokenFeedbackPrefChanged(base::Value value); - - CrosapiPrefObserver crosapi_pref_observer_; - - // Applies AXMode::kScreenReader to all WebContents in the process while - // spoken feedback is enabled. - std::unique_ptr<ScopedAccessibilityMode> screen_reader_mode_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_STATE_IMPL_LACROS_H_
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc index 5032f43..d12a0f7 100644 --- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc +++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -2009,10 +2009,9 @@ .ToString()); } -// Flaky on Lacros: https://crbug.com/1292527 // TODO(crbug.com/40835208): Enable on Fuchsia when content_browsertests // runs in non-headless mode. -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_FUCHSIA) +#if BUILDFLAG(IS_FUCHSIA) #define MAYBE_ControlsIdsForDateTimePopup DISABLED_ControlsIdsForDateTimePopup #else #define MAYBE_ControlsIdsForDateTimePopup ControlsIdsForDateTimePopup
diff --git a/content/browser/accessibility/hit_testing_browsertest.cc b/content/browser/accessibility/hit_testing_browsertest.cc index d541919..b2c3e8c0 100644 --- a/content/browser/accessibility/hit_testing_browsertest.cc +++ b/content/browser/accessibility/hit_testing_browsertest.cc
@@ -435,8 +435,8 @@ // this platform. #if !BUILDFLAG(IS_ANDROID) -// crbug.com/1317505: Flaky on Lacros and Linux Wayland -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX) +// crbug.com/1317505: Flaky on Linux Wayland +#if BUILDFLAG(IS_LINUX) #define MAYBE_HitTestInPopup DISABLED_HitTestInPopup #else #define MAYBE_HitTestInPopup HitTestInPopup
diff --git a/content/browser/android/content_feature_map.cc b/content/browser/android/content_feature_map.cc index 8a2085d..7a6fc21 100644 --- a/content/browser/android/content_feature_map.cc +++ b/content/browser/android/content_feature_map.cc
@@ -24,7 +24,6 @@ const base::Feature* const kFeaturesExposedToJava[] = { &blink::features::kCursorAnchorInfoMojoPipe, &blink::features::kDevicePosture, - &blink::features::kStylusPointerAdjustment, &blink::features::kStylusRichGestures, &blink::features::kViewportSegments, &input::features::kInputOnViz,
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index cce139b..3237face 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -1152,19 +1152,11 @@ // trigger unload handlers and be destroyed directly. } -// TODO(crbug.com/330798156): Flaky on Lacros. -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_DoesNotFireDidFirstVisuallyNonEmptyPaintForSameDocumentNavigation \ - DISABLED_DoesNotFireDidFirstVisuallyNonEmptyPaintForSameDocumentNavigation -#else -#define MAYBE_DoesNotFireDidFirstVisuallyNonEmptyPaintForSameDocumentNavigation \ - DoesNotFireDidFirstVisuallyNonEmptyPaintForSameDocumentNavigation -#endif // Do a same document navigation and make sure we do not fire the // DidFirstVisuallyNonEmptyPaint again IN_PROC_BROWSER_TEST_F( BackForwardCacheBrowserTest, - MAYBE_DoesNotFireDidFirstVisuallyNonEmptyPaintForSameDocumentNavigation) { + DoesNotFireDidFirstVisuallyNonEmptyPaintForSameDocumentNavigation) { ASSERT_TRUE(embedded_test_server()->Start()); GURL url_a_1(embedded_test_server()->GetURL( "a.com", "/accessibility/html/a-name.html")); @@ -1184,7 +1176,7 @@ // Make sure we fire DidFirstVisuallyNonEmptyPaint when restoring from bf-cache. // TODO(crbug.com/327195951): Re-enable this test -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) #define MAYBE_FiresDidFirstVisuallyNonEmptyPaintWhenRestoredFromCache \ DISABLED_FiresDidFirstVisuallyNonEmptyPaintWhenRestoredFromCache #else @@ -1218,8 +1210,7 @@ EXPECT_TRUE(web_contents()->CompletedFirstVisuallyNonEmptyPaint()); EXPECT_TRUE(observer.did_fire()); } -// TODO(crbug.com/330798156): Flaky on Lacros. -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) #define MAYBE_SetsThemeColorWhenRestoredFromCache \ DISABLED_SetsThemeColorWhenRestoredFromCache #else @@ -1748,8 +1739,6 @@ // Tests that pagehide handlers of the old RFH are run for bfcached pages even // if the page is already hidden (and visibilitychange won't run). // Disabled on Linux and Win because of flakiness, see crbug.com/40165901. -// TODO(crbug.com/40118868): Revisit once build flag switch of lacros-chrome is -// complete. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) #define MAYBE_PagehideRunsWhenPageIsHidden DISABLED_PagehideRunsWhenPageIsHidden #else
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index 50bc96e..cea4b4a1 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc
@@ -184,12 +184,10 @@ content::ProcessType process_type, BrowserChildProcessHostDelegate* delegate, ChildProcessHost::IpcMode ipc_mode) - : data_(process_type), delegate_(delegate) { + : data_(process_type, ChildProcessHostImpl::GenerateChildProcessUniqueId()), + delegate_(delegate) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - data_.id = - ChildProcessHostImpl::GenerateChildProcessUniqueId().GetUnsafeValue(); - // Create a persistent memory segment for subprocess histograms. CreateMetricsAllocator();
diff --git a/content/browser/compositor/image_transport_factory_browsertest.cc b/content/browser/compositor/image_transport_factory_browsertest.cc index cd3fd89..2b75d61 100644 --- a/content/browser/compositor/image_transport_factory_browsertest.cc +++ b/content/browser/compositor/image_transport_factory_browsertest.cc
@@ -30,8 +30,7 @@ // TODO(crbug.com/394083, crbug.com/1305007, crbug.com/1302879): Flaky on // ChromeOS, Linux, and Windows. -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) #define MAYBE_TestLostContext DISABLED_TestLostContext #else #define MAYBE_TestLostContext TestLostContext
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 7230c00b..79ab4de 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -853,10 +853,8 @@ // TODO(crbug.com/40157725) Android has a problem with changing scale. // TODO(crbug.com/40156819) Android Lollipop has a problem with capturing // screenshot. -// TODO(crbug.com/40736077) Flaky on linux-lacros-tester-rel // TODO(crbug.com/40815512): Failing on MacOS. -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) #define MAYBE_CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown \ DISABLED_CaptureScreenshotBeyondViewport_InnerScrollbarsAreShown #else
diff --git a/content/browser/file_system_access/file_system_access_file_modification_host_impl_browsertest.cc b/content/browser/file_system_access/file_system_access_file_modification_host_impl_browsertest.cc index eba5e56..a63ab87e 100644 --- a/content/browser/file_system_access/file_system_access_file_modification_host_impl_browsertest.cc +++ b/content/browser/file_system_access/file_system_access_file_modification_host_impl_browsertest.cc
@@ -159,9 +159,7 @@ } // TODO(crbug.com/40826793): Failing on various builders. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - (BUILDFLAG(IS_CHROMEOS_LACROS) && defined(ADDRESS_SANITIZER) && \ - defined(LEAK_SANITIZER)) +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) #define MAYBE_QuotaUsageOverallocation DISABLED_QuotaUsageOverallocation #else #define MAYBE_QuotaUsageOverallocation QuotaUsageOverallocation
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index 5fab709e..486d4fc 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc
@@ -479,8 +479,6 @@ #if BUILDFLAG(IS_APPLE) return true; -#elif BUILDFLAG(IS_CHROMEOS_LACROS) - return features::IsDelegatedCompositingEnabled(); #elif BUILDFLAG(IS_WIN) return features::IsDelegatedCompositingEnabled() && features::kDelegatedCompositingModeParam.Get() ==
diff --git a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc index c0e51d0c..3cec508 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -586,8 +586,6 @@ #endif // defined(CAST_AUDIO_ONLY) #if BUILDFLAG(ENABLE_VULKAN) -// TODO(crbug.com/40735511): enable tests when Vulkan is supported on LaCrOS. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) TEST_F(GpuDataManagerImplPrivateTest, GpuStartsWithVulkanFeatureFlag) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(features::kVulkan); @@ -656,7 +654,6 @@ #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) && // !BUILDFLAG(IS_IOS) #endif // !BUILDFLAG(IS_FUCHSIA) -#endif // !IS_CHROMEOS_LACROS #endif // BUILDFLAG(ENABLE_VULKAN) } // namespace content
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index ecb75b9..2681a46 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -160,9 +160,7 @@ // Test fails on Chromeos + Mac, flaky on Windows because UI Compositor // establishes a GPU channel. -// TODO(crbug.com/40118868): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) #define MAYBE_Basic Basic #else #define MAYBE_Basic DISABLED_Basic @@ -176,9 +174,7 @@ #if !BUILDFLAG(IS_ANDROID) // Test fails on Chromeos + Mac, flaky on Windows because UI Compositor // establishes a GPU channel. -// TODO(crbug.com/40118868): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) #define MAYBE_AlreadyEstablished AlreadyEstablished #else #define MAYBE_AlreadyEstablished DISABLED_AlreadyEstablished @@ -201,9 +197,7 @@ // Test fails on Chromeos + Mac, flaky on Windows because UI Compositor // establishes a GPU channel. -// TODO(crbug.com/40118868): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) #define MAYBE_CrashAndRecover CrashAndRecover #else #define MAYBE_CrashAndRecover DISABLED_CrashAndRecover @@ -232,10 +226,8 @@ } // Disabled outside linux like other tests here sadface. -// crbug.com/1224892: the test if flaky on linux and lacros. -// TODO(crbug.com/40118868): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +// crbug.com/1224892: the test if flaky on linux. +#if BUILDFLAG(IS_LINUX) IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, DISABLED_CreateTransferBuffer) { DCHECK(!IsChannelEstablished()); @@ -247,10 +239,9 @@ auto impl = std::make_unique<gpu::CommandBufferProxyImpl>( GetGpuChannel(), content::kGpuStreamIdDefault, base::SingleThreadTaskRunner::GetCurrentDefault()); - ASSERT_EQ( - impl->Initialize(gpu::kNullSurfaceHandle, nullptr, - content::kGpuStreamPriorityDefault, attributes, GURL()), - gpu::ContextResult::kSuccess); + ASSERT_EQ(impl->Initialize(nullptr, content::kGpuStreamPriorityDefault, + attributes, GURL()), + gpu::ContextResult::kSuccess); // Creating a transfer buffer works normally. int32_t id = -1;
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 26054bde..9112c7c4 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -323,11 +323,6 @@ #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) switches::kHardwareVideoDecodeFrameRate, #endif -#if BUILDFLAG(IS_CHROMEOS_LACROS) - switches::kLacrosEnablePlatformHevc, - switches::kLacrosUseChromeosProtectedMedia, - switches::kLacrosUseChromeosProtectedAv1, -#endif #if BUILDFLAG(WEBNN_USE_TFLITE) switches::kWebNNTfliteDumpModel, #endif
diff --git a/content/browser/handwriting/handwriting_recognition_service_impl_cros.cc b/content/browser/handwriting/handwriting_recognition_service_impl_cros.cc index 5445392..aa1af7b 100644 --- a/content/browser/handwriting/handwriting_recognition_service_impl_cros.cc +++ b/content/browser/handwriting/handwriting_recognition_service_impl_cros.cc
@@ -19,10 +19,6 @@ #include "chromeos/services/machine_learning/public/cpp/ml_switches.h" #endif -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/startup/browser_params_proxy.h" -#endif - namespace content { namespace { @@ -38,9 +34,6 @@ return command_line->HasSwitch(::switches::kOndeviceHandwritingSwitch) && command_line->GetSwitchValueASCII( ::switches::kOndeviceHandwritingSwitch) == "use_rootfs"; -#elif BUILDFLAG(IS_CHROMEOS_LACROS) - return chromeos::BrowserParamsProxy::Get()->OndeviceHandwritingSupport() == - crosapi::mojom::OndeviceHandwritingSupport::kUseRootfs; #else return false; #endif
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc index 35e7065..456811fc 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -207,7 +207,8 @@ } std::array<uint8_t, 8u> chars; - base::span(chars).copy_from(base::U64ToBigEndian(modified_bits)); + base::span(chars).copy_from_nonoverlapping( + base::U64ToBigEndian(modified_bits)); into->insert(into->end(), chars.begin(), chars.end()); } @@ -219,8 +220,8 @@ return false; } - uint64_t host_bits = base::U64FromBigEndian(base::as_bytes( - base::span<const char, kLengthInBytes>{data.data(), kLengthInBytes})); + uint64_t host_bits = + base::U64FromBigEndian(base::as_byte_span(data).first<kLengthInBytes>()); data = data.substr(kLengthInBytes); static constexpr uint64_t kSignBit = base::bits::LeftmostBit<uint64_t>(); @@ -603,7 +604,7 @@ if (slice->size() < size) return false; - *value = base::as_byte_span(slice->substr(0, size)); + *value = base::as_byte_span(*slice).first(size); slice->remove_prefix(size); return true; } @@ -1353,9 +1354,7 @@ break; case kScopesPrefixByte: result << "Scopes key: " - << leveldb_scopes::KeyToDebugString( - base::span(reinterpret_cast<const uint8_t*>(key.data()), - key.size())); + << leveldb_scopes::KeyToDebugString(base::as_byte_span(key)); break; case kDatabaseFreeListTypeByte: { DatabaseFreeListKey db_free_list_key;
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc index b8cba68e..f6bbfbd4 100644 --- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc +++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -12672,8 +12672,6 @@ "Ads.InterestGroup.ServerAuction.KeyFetch.NetworkCached", false, 1); hist.ExpectTotalCount("Ads.InterestGroup.ServerAuction.KeyFetch.NetworkTime", 1); - hist.ExpectTotalCount("Ads.InterestGroup.ServerAuction.KeyFetch.TotalTime2", - 1); hist.ExpectTotalCount("Ads.InterestGroup.ServerAuction.ReportDelay", 1); // There should be no on-device metrics
diff --git a/content/browser/interest_group/bidding_and_auction_server_key_fetcher.cc b/content/browser/interest_group/bidding_and_auction_server_key_fetcher.cc index 133b58e6..086e8f4 100644 --- a/content/browser/interest_group/bidding_and_auction_server_key_fetcher.cc +++ b/content/browser/interest_group/bidding_and_auction_server_key_fetcher.cc
@@ -338,8 +338,6 @@ PerCoordinatorFetcherState& state = fetcher_state_map_.at(coordinator); state.keys = keys; state.expiration = expiration; - base::UmaHistogramTimes("Ads.InterestGroup.ServerAuction.KeyFetch.TotalTime2", - base::TimeTicks::Now() - state.fetch_start); while (!state.queue.empty()) { // We call the callback *before* removing the current request from the list.
diff --git a/content/browser/interest_group/trusted_signals_cache_impl.cc b/content/browser/interest_group/trusted_signals_cache_impl.cc index fe46345..d1543d6e 100644 --- a/content/browser/interest_group/trusted_signals_cache_impl.cc +++ b/content/browser/interest_group/trusted_signals_cache_impl.cc
@@ -864,6 +864,14 @@ base::BindOnce(&TrustedSignalsCacheImpl::GetCoordinatorKey, fetch_it->second.weak_ptr_factory.GetWeakPtr(), fetch_it)); + + // Automatically start fetch if no consumer starts it soon enough. + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TrustedSignalsCacheImpl::SetFetchCanStart, + fetch_it->second.weak_ptr_factory.GetWeakPtr(), + fetch_it), + kAutoStartDelay); } Fetch* fetch = &fetch_it->second;
diff --git a/content/browser/interest_group/trusted_signals_cache_impl.h b/content/browser/interest_group/trusted_signals_cache_impl.h index 199df3b..e315731 100644 --- a/content/browser/interest_group/trusted_signals_cache_impl.h +++ b/content/browser/interest_group/trusted_signals_cache_impl.h
@@ -16,6 +16,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" +#include "base/time/time.h" #include "base/types/optional_ref.h" #include "base/unguessable_token.h" #include "base/values.h" @@ -152,8 +153,11 @@ // Attempts to start the network fetch, if it hasn't started already. Not // guaranteed to immediately start the fetch, as it may currently be - // retrieving the coordinator key. Fetches will not start until this is - // invoked for at least one of the Handles that share a Fetch. + // retrieving the coordinator key. If this isn't called within + // `kAutoStartDelay` of a fetch being created, it will automatically be + // invoked for the fetch. Note that since fetches may be reused, it's + // possible for a fetch of any age to be assigned to a new Handle, and for + // another Handle to start the fetch assigned to a Handle. // // Handles that share a `compression_group_token` always share a Fetch, // though other Handles may share the fetch as well. @@ -171,6 +175,10 @@ static constexpr size_t kNonceCacheSize = 50; + // If StartFetch() isn't called on any handle for a request that has been + // around this long, automatically call SetFetchCanStart() for the fetch. + static constexpr base::TimeDelta kAutoStartDelay = base::Milliseconds(10); + TrustedSignalsCacheImpl( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GetCoordinatorKeyCallback get_coordinator_key_callback);
diff --git a/content/browser/interest_group/trusted_signals_cache_impl_unittest.cc b/content/browser/interest_group/trusted_signals_cache_impl_unittest.cc index 8388694..5833a2f 100644 --- a/content/browser/interest_group/trusted_signals_cache_impl_unittest.cc +++ b/content/browser/interest_group/trusted_signals_cache_impl_unittest.cc
@@ -1319,6 +1319,150 @@ client.WaitForError(); } +// Check that fetches are automatically started after kAutoStartDelay has +// elapsed. +TYPED_TEST(TrustedSignalsCacheTest, AutoStart) { + base::TimeDelta kTinyTime = base::Milliseconds(1); + + auto params = this->CreateDefaultParams(); + auto [handle, partition_id] = + this->RequestTrustedSignals(params, /*start_fetch=*/false); + + // Request should only start once `kAutoStartDelay` has elapsed + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay - kTinyTime); + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 0u); + this->task_environment_.FastForwardBy(kTinyTime); + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 1u); + + auto fetch = this->WaitForSignalsFetch(); + ValidateFetchParams(fetch, params, /*expected_compression_group_id=*/0, + partition_id); + RespondToFetchWithSuccess(fetch); + + TestTrustedSignalsCacheClient client(handle, this->cache_mojo_pipe_); + client.WaitForSuccess(); +} + +// Check that fetches are automatically started after kAutoStartDelay, even if a +// second request is merged into it. +TYPED_TEST(TrustedSignalsCacheTest, AutoStartTwoRequests) { + base::TimeDelta kTinyTime = base::Milliseconds(1); + + auto params = this->CreateDefaultParams(); + auto [handle1, partition_id1] = + this->RequestTrustedSignals(params, /*start_fetch=*/false); + + // After a delay less than `kAutoStartDelay`, create a second request that + // matches the first one. The old fetch should be reused. + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay - kTinyTime); + auto [handle2, partition_id2] = + this->RequestTrustedSignals(params, /*start_fetch=*/false); + EXPECT_EQ(handle1, handle2); + EXPECT_EQ(partition_id1, partition_id2); + + // No fetches should have been started. + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 0u); + + // After exactly `kAutoStartDelay`, the fetch should be started. + this->task_environment_.FastForwardBy(kTinyTime); + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 1u); + + auto fetch = this->WaitForSignalsFetch(); + ValidateFetchParams(fetch, params, /*expected_compression_group_id=*/0, + partition_id1); + RespondToFetchWithSuccess(fetch); + + TestTrustedSignalsCacheClient client(handle1, this->cache_mojo_pipe_); + client.WaitForSuccess(); +} + +// Check that manually starting a request that has already automatically started +// doesn't cause any issues. +TYPED_TEST(TrustedSignalsCacheTest, AutoStartThenManuallyStart) { + auto params = this->CreateDefaultParams(); + auto [handle, partition_id] = + this->RequestTrustedSignals(params, /*start_fetch=*/false); + + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay); + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 1u); + + // This should not cause another fetch to be started, nor cause a crash. + handle->StartFetch(); + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 1u); + + // Can safely call StartFetch() more than once, and no new fetches should be + // started. + handle->StartFetch(); + handle->StartFetch(); + handle->StartFetch(); + handle->StartFetch(); + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 1u); + + auto fetch = this->WaitForSignalsFetch(); + ValidateFetchParams(fetch, params, /*expected_compression_group_id=*/0, + partition_id); + RespondToFetchWithSuccess(fetch); + + TestTrustedSignalsCacheClient client(handle, this->cache_mojo_pipe_); + client.WaitForSuccess(); +} + +// Check that the auto-start delay passing after a request was manually started +// doesn't cause issues. Test 3 cases: Auto start duration passes while Fetch is +// live, after Fetch has completed but cache entry is still live, and after +// cache entry has been destroyed. +TYPED_TEST(TrustedSignalsCacheTest, ManuallyStartThenAutoStart) { + enum class TestCase { + kAutoStartDuringFetch, + kAutoStartAfterFetch, + kAutoStartAfterHandleDestroyed, + }; + + for (TestCase test_case : + {TestCase::kAutoStartDuringFetch, TestCase::kAutoStartAfterFetch, + TestCase::kAutoStartAfterHandleDestroyed}) { + SCOPED_TRACE(static_cast<int>(test_case)); + + // Start with a clean slate for each test. + this->CreateCache(); + + auto params = this->CreateDefaultParams(); + // Create request and start the fetch. + auto [handle, partition_id] = this->RequestTrustedSignals(params); + + // Wait for fetch creation. + auto fetch = this->WaitForSignalsFetch(); + ValidateFetchParams(fetch, params, /*expected_compression_group_id=*/0, + partition_id); + + if (test_case == TestCase::kAutoStartDuringFetch) { + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay); + } + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 0u); + + RespondToFetchWithSuccess(fetch); + if (test_case == TestCase::kAutoStartAfterFetch) { + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay); + } + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 0u); + + TestTrustedSignalsCacheClient client(handle, this->cache_mojo_pipe_); + client.WaitForSuccess(); + + handle.reset(); + if (test_case == TestCase::kAutoStartAfterHandleDestroyed) { + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay); + } + EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 0u); + } +} + // Test the case where a Handle is destroyed without ever calling StartFetch() // on it. TYPED_TEST(TrustedSignalsCacheTest, HandleDestroyedWithoutStartingFetch) { @@ -1367,7 +1511,8 @@ handle.reset(); // No fetches should have been started. - this->task_environment_.RunUntilIdle(); + this->task_environment_.FastForwardBy( + TrustedSignalsCacheImpl::kAutoStartDelay - base::Milliseconds(1)); EXPECT_EQ(this->trusted_signals_cache_->num_pending_fetches(), 0u); TestTrustedSignalsCacheClient client(compression_group_token,
diff --git a/content/browser/largest_contentful_paint_browsertests.cc b/content/browser/largest_contentful_paint_browsertests.cc index eeb385b..36df070b 100644 --- a/content/browser/largest_contentful_paint_browsertests.cc +++ b/content/browser/largest_contentful_paint_browsertests.cc
@@ -50,13 +50,8 @@ base::test::ScopedFeatureList features_; }; -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_NonTAOImageLCPRenderTime DISABLED_NonTAOImageLCPRenderTime -#else -#define MAYBE_NonTAOImageLCPRenderTime NonTAOImageLCPRenderTime -#endif IN_PROC_BROWSER_TEST_F(LargestContentfulPaintTestBrowserTest, - MAYBE_NonTAOImageLCPRenderTime) { + NonTAOImageLCPRenderTime) { const GURL url1(embedded_test_server()->GetURL( "a.com", "/performance_timeline/cross-origin-non-tao-image.html"));
diff --git a/content/browser/launch_as_mojo_client_browsertest.cc b/content/browser/launch_as_mojo_client_browsertest.cc index 97e1fd19..30169a1 100644 --- a/content/browser/launch_as_mojo_client_browsertest.cc +++ b/content/browser/launch_as_mojo_client_browsertest.cc
@@ -158,10 +158,6 @@ mojo::Remote<mojom::ShellController> shell_controller_; }; -// TODO(http://crbug.com/323984075): This test invokes content_shell in a way -// that is not supported on Lacros (without crosapi data). Figure out what to -// do about that. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) IN_PROC_BROWSER_TEST_F(LaunchAsMojoClientBrowserTest, LaunchAndBindInterface) { // Verifies that we can launch an instance of Content Shell with a Mojo // invitation on the command line and reach the new browser process's exposed @@ -187,7 +183,6 @@ shell_controller->ShutDown(); } -#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) } // namespace } // namespace content
diff --git a/content/browser/loader/cors_file_origin_browsertest.cc b/content/browser/loader/cors_file_origin_browsertest.cc index 08e81d9a..c7486b333 100644 --- a/content/browser/loader/cors_file_origin_browsertest.cc +++ b/content/browser/loader/cors_file_origin_browsertest.cc
@@ -244,8 +244,7 @@ // TODO(lukasza, nasko): https://crbug.com/981018: Enable this test on Macs // after understanding what makes it flakily fail on the mac-rel trybot. -// Also flaky on Lacros: https://crbug.com/1247748. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_MAC) #define MAYBE_UniversalAccessFromFileUrls DISABLED_UniversalAccessFromFileUrls #else #define MAYBE_UniversalAccessFromFileUrls UniversalAccessFromFileUrls
diff --git a/content/browser/media/audio_stream_monitor_unittest.cc b/content/browser/media/audio_stream_monitor_unittest.cc index 71882d1..2abe07f 100644 --- a/content/browser/media/audio_stream_monitor_unittest.cc +++ b/content/browser/media/audio_stream_monitor_unittest.cc
@@ -22,10 +22,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/lacros/lacros_test_helper.h" -#endif - using ::testing::InvokeWithoutArgs; namespace content { @@ -170,11 +166,6 @@ EXPECT_FALSE(monitor_->WasRecentlyAudible()); } -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // Instantiate LacrosService for WakeLock support. - chromeos::ScopedLacrosServiceTestHelper scoped_lacros_service_test_helper_; -#endif - MockWebContentsDelegate mock_web_contents_delegate_; };
diff --git a/content/browser/media/cdm_registry_impl.cc b/content/browser/media/cdm_registry_impl.cc index 85e5489..539a6b4 100644 --- a/content/browser/media/cdm_registry_impl.cc +++ b/content/browser/media/cdm_registry_impl.cc
@@ -402,12 +402,7 @@ using Status = CdmInfo::Status; if (robustness == CdmInfo::Robustness::kHardwareSecure) { -#if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kLacrosUseChromeosProtectedMedia)) { - return {std::nullopt, Status::kHardwareSecureDecryptionDisabled}; - } -#elif !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) +#if !BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) if (!media::IsHardwareSecureDecryptionEnabled()) { DVLOG(1) << "Hardware secure decryption disabled"; return {std::nullopt, Status::kHardwareSecureDecryptionDisabled};
diff --git a/content/browser/media/cdm_registry_impl_unittest.cc b/content/browser/media/cdm_registry_impl_unittest.cc index 0f62c2c9..4402ff64 100644 --- a/content/browser/media/cdm_registry_impl_unittest.cc +++ b/content/browser/media/cdm_registry_impl_unittest.cc
@@ -240,15 +240,6 @@ } void SelectHardwareSecureDecryption(bool enabled) { -#if BUILDFLAG(IS_CHROMEOS_LACROS) - if (enabled) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kLacrosUseChromeosProtectedMedia); - } else { - base::CommandLine::ForCurrentProcess()->RemoveSwitch( - switches::kLacrosUseChromeosProtectedMedia); - } -#else const std::vector<base::test::FeatureRef> kHardwareSecureFeatures = { media::kHardwareSecureDecryption, media::kHardwareSecureDecryptionExperiment}; @@ -257,7 +248,6 @@ auto enabled_features = enabled ? kHardwareSecureFeatures : kNoFeatures; auto disabled_features = enabled ? kNoFeatures : kHardwareSecureFeatures; scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); -#endif } #if BUILDFLAG(IS_ANDROID)
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc index d255b88..2153e46 100644 --- a/content/browser/media/media_interface_proxy.cc +++ b/content/browser/media/media_interface_proxy.cc
@@ -442,13 +442,7 @@ // Handle `use_hw_secure_codecs` cases first. #if BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) -#if BUILDFLAG(IS_CHROMEOS_LACROS) - bool enable_cdm_factory_daemon = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kLacrosUseChromeosProtectedMedia); -#else // BUILDFLAG(IS_CHROMEOS_LACROS) bool enable_cdm_factory_daemon = true; -#endif // else BUILDFLAG(IS_CHROMEOS_LACROS) #if defined(ARCH_CPU_ARM_FAMILY) if (!base::FeatureList::IsEnabled(media::kEnableArmHwdrm)) { enable_cdm_factory_daemon = false;
diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc index 0f09c6d..96c0aa8 100644 --- a/content/browser/media/media_keys_listener_manager_impl.cc +++ b/content/browser/media/media_keys_listener_manager_impl.cc
@@ -333,7 +333,7 @@ return; } -#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) // Create SystemMediaControls with the SingletonHwnd. browser_system_media_controls_ = system_media_controls::SystemMediaControls::Create(
diff --git a/content/browser/media/media_keys_listener_manager_impl_browsertest.cc b/content/browser/media/media_keys_listener_manager_impl_browsertest.cc index 50b35ce1..dc9264a 100644 --- a/content/browser/media/media_keys_listener_manager_impl_browsertest.cc +++ b/content/browser/media/media_keys_listener_manager_impl_browsertest.cc
@@ -19,9 +19,6 @@ #include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/media_keys_listener.h" -// Disable on CrOS because MediaKeysListenerManager is disabled. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) - namespace content { using media_session::mojom::MediaPlaybackState; @@ -352,5 +349,3 @@ } } // namespace content - -#endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/content/browser/media/stable_video_decoder_factory.cc b/content/browser/media/stable_video_decoder_factory.cc index aa3bd538..8dee2eb 100644 --- a/content/browser/media/stable_video_decoder_factory.cc +++ b/content/browser/media/stable_video_decoder_factory.cc
@@ -21,10 +21,6 @@ #include "media/mojo/mojom/stable/stable_video_decoder.mojom.h" #include "mojo/public/cpp/bindings/remote_set.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/lacros/lacros_service.h" -#endif - namespace content { #if BUILDFLAG(ALLOW_HOSTING_OOP_VIDEO_DECODER) @@ -177,15 +173,6 @@ #if BUILDFLAG(ALLOW_HOSTING_OOP_VIDEO_DECODER) StableVideoDecoderFactoryProcessLauncher::Instance() .LaunchWhenGpuFeatureInfoIsKnown(std::move(receiver)); -#elif BUILDFLAG(IS_CHROMEOS_LACROS) - // For LaCrOS, we need to use crosapi to establish a - // StableVideoDecoderFactory connection to ash-chrome. - auto* lacros_service = chromeos::LacrosService::Get(); - if (lacros_service && - lacros_service - ->IsSupported<media::stable::mojom::StableVideoDecoderFactory>()) { - lacros_service->BindStableVideoDecoderFactory(std::move(receiver)); - } #endif }
diff --git a/content/browser/media_session/media_session_service.cc b/content/browser/media_session/media_session_service.cc index bd4dc14..6c62153a 100644 --- a/content/browser/media_session/media_session_service.cc +++ b/content/browser/media_session/media_session_service.cc
@@ -5,84 +5,13 @@ #include "content/public/browser/media_session_service.h" #include "base/no_destructor.h" -#include "base/threading/sequence_local_storage_slot.h" -#include "build/chromeos_buildflags.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/remote.h" #include "services/media_session/media_session_service_impl.h" -#include "services/media_session/public/cpp/features.h" - -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/lacros/lacros_service.h" -#include "services/media_session/public/cpp/media_session_service.h" -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) namespace content { -#if BUILDFLAG(IS_CHROMEOS_LACROS) -namespace { - -class LacrosMediaSessionServiceImpl - : public media_session::MediaSessionService { - public: - LacrosMediaSessionServiceImpl() = default; - ~LacrosMediaSessionServiceImpl() override = default; - LacrosMediaSessionServiceImpl(const LacrosMediaSessionServiceImpl&) = delete; - LacrosMediaSessionServiceImpl& operator=( - const LacrosMediaSessionServiceImpl&) = delete; - - void BindAudioFocusManager( - mojo::PendingReceiver<media_session::mojom::AudioFocusManager> receiver) - override { - auto* lacros_service = chromeos::LacrosService::Get(); - if (lacros_service && - lacros_service - ->IsSupported<media_session::mojom::AudioFocusManager>()) { - lacros_service->BindAudioFocusManager(std::move(receiver)); - } - } - - void BindAudioFocusManagerDebug( - mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug> - receiver) override { - auto* lacros_service = chromeos::LacrosService::Get(); - if (lacros_service && - lacros_service - ->IsSupported<media_session::mojom::AudioFocusManagerDebug>()) { - lacros_service->BindAudioFocusManagerDebug(std::move(receiver)); - } - } - - void BindMediaControllerManager( - mojo::PendingReceiver<media_session::mojom::MediaControllerManager> - receiver) override { - auto* lacros_service = chromeos::LacrosService::Get(); - if (lacros_service && - lacros_service - ->IsSupported<media_session::mojom::MediaControllerManager>()) { - lacros_service->BindMediaControllerManager(std::move(receiver)); - } - } -}; - -} // namespace -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - media_session::MediaSessionService& GetMediaSessionService() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - -#if BUILDFLAG(IS_CHROMEOS_LACROS) - auto* lacros_service = chromeos::LacrosService::Get(); - if (lacros_service && - lacros_service - ->IsSupported<media_session::mojom::MediaControllerManager>() && - lacros_service - ->IsSupported<media_session::mojom::AudioFocusManagerDebug>() && - lacros_service->IsSupported<media_session::mojom::AudioFocusManager>()) { - static base::NoDestructor<LacrosMediaSessionServiceImpl> service; - return *service; - } -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) static base::NoDestructor<media_session::MediaSessionServiceImpl> service; return *service; }
diff --git a/content/browser/memory_pressure/user_level_memory_pressure_signal_generator.cc b/content/browser/memory_pressure/user_level_memory_pressure_signal_generator.cc index b75ffb8..3788103 100644 --- a/content/browser/memory_pressure/user_level_memory_pressure_signal_generator.cc +++ b/content/browser/memory_pressure/user_level_memory_pressure_signal_generator.cc
@@ -51,17 +51,11 @@ } base::TimeDelta MeasurementIntervalFor4GbDevices() { - static const base::FeatureParam<base::TimeDelta> kMeasurementInterval{ - &content::features::kUserLevelMemoryPressureSignalOn4GbDevices, - "measurement_interval", kDefaultMeasurementInterval}; - return kMeasurementInterval.Get(); + return kDefaultMeasurementInterval; } base::TimeDelta MeasurementIntervalFor6GbDevices() { - static const base::FeatureParam<base::TimeDelta> kMeasurementInterval{ - &content::features::kUserLevelMemoryPressureSignalOn6GbDevices, - "measurement_interval", kDefaultMeasurementInterval}; - return kMeasurementInterval.Get(); + return kDefaultMeasurementInterval; } // The memory threshold: 738 was selected at around the 99th percentile of @@ -82,10 +76,7 @@ constexpr size_t kMemoryThresholdMBOf4GbDevices = 458; uint64_t MemoryThresholdParamFor4GbDevices() { - static const base::FeatureParam<int> kMemoryThresholdParam{ - &content::features::kUserLevelMemoryPressureSignalOn4GbDevices, - "memory_threshold_mb", kMemoryThresholdMBOf4GbDevices}; - return base::as_unsigned(kMemoryThresholdParam.Get()) * k1MB; + return kMemoryThresholdMBOf4GbDevices * k1MB; } // The memory threshold: 494 was selected at around the 99th percentile of @@ -94,10 +85,7 @@ constexpr size_t kMemoryThresholdMBOf6GbDevices = 494; uint64_t MemoryThresholdParamFor6GbDevices() { - static const base::FeatureParam<int> kMemoryThresholdParam{ - &content::features::kUserLevelMemoryPressureSignalOn6GbDevices, - "memory_threshold_mb", kMemoryThresholdMBOf6GbDevices}; - return base::as_unsigned(kMemoryThresholdParam.Get()) * k1MB; + return kMemoryThresholdMBOf6GbDevices * k1MB; } } // namespace
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc index 6a90bf3..84fc35a 100644 --- a/content/browser/network_service_instance_impl.cc +++ b/content/browser/network_service_instance_impl.cc
@@ -871,10 +871,9 @@ !factory_remote_storage.is_connected()) { factory_remote_storage.reset(); #if BUILDFLAG(IS_CHROMEOS) - // In-process CertVerifierService in Ash and Lacros should run on the IO - // thread because it interacts with IO-bound NSS and ChromeOS user slots. - // See for example InitializeNSSForChromeOSUser() or - // CertDbInitializerIOImpl. + // In-process CertVerifierService should run on the IO thread because it + // interacts with IO-bound NSS and ChromeOS user slots. See for example + // InitializeNSSForChromeOSUser() or CertDbInitializerIOImpl. GetIOThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&RunInProcessCertVerifierServiceFactory,
diff --git a/content/browser/performance_timeline_browsertest.cc b/content/browser/performance_timeline_browsertest.cc index 437db7c..0b302a5c 100644 --- a/content/browser/performance_timeline_browsertest.cc +++ b/content/browser/performance_timeline_browsertest.cc
@@ -186,13 +186,8 @@ int32_t precision_ = 10; }; -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_LCPStartTimePrecision DISABLED_LCPStartTimePrecision -#else -#define MAYBE_LCPStartTimePrecision LCPStartTimePrecision -#endif IN_PROC_BROWSER_TEST_F(PerformanceTimelineLCPStartTimePrecisionBrowserTest, - MAYBE_LCPStartTimePrecision) { + LCPStartTimePrecision) { ASSERT_TRUE(embedded_test_server()->Start()); const GURL url1(embedded_test_server()->GetURL( "a.com", "/performance_timeline/lcp-start-time-precision.html"));
diff --git a/content/browser/preloading/prefetch/prefetch_container.cc b/content/browser/preloading/prefetch/prefetch_container.cc index 57ae7c3..21a4be2 100644 --- a/content/browser/preloading/prefetch/prefetch_container.cc +++ b/content/browser/preloading/prefetch/prefetch_container.cc
@@ -1618,7 +1618,9 @@ CancelStreamingURLLoaderIfNotServing(); } -void PrefetchContainer::OnDetectedCookiesChange2() { +void PrefetchContainer::OnDetectedCookiesChange2( + std::optional<bool> + is_unblock_for_cookies_changed_triggered_by_this_prefetch_container) { CHECK(UseNewWaitLoop()); // If `kPrefetchNewWaitLoop` is enabled, multiple `PrefetchMatchResolver2` can @@ -1635,6 +1637,27 @@ return; } + // There are cases that `prefetch_status_` is failure but this method is + // called. For more details, see + // https://docs.google.com/document/d/1G48SaWbdOy1yNBT1wio2IHVuUtddF5VLFsT6BRSYPMI/edit?tab=t.hpkotaxo7tfh#heading=h.woaoy8erwx63 + // + // To prevent crash, we don't call `SetPrefetchStatus()`. + if (prefetch_status_ && + TriggeringOutcomeFromStatus(prefetch_status_.value()) == + PreloadingTriggeringOutcome::kFailure) { + SCOPED_CRASH_KEY_NUMBER("PrefetchContainer", "ODCC2_from", + static_cast<int>(prefetch_status_.value())); + if (is_unblock_for_cookies_changed_triggered_by_this_prefetch_container + .has_value()) { + SCOPED_CRASH_KEY_BOOL( + "PrefetchContainer", "ODCC2_iufcctbtpc", + is_unblock_for_cookies_changed_triggered_by_this_prefetch_container + .value()); + } + base::debug::DumpWithoutCrashing(); + return; + } + OnDetectedCookiesChange(); }
diff --git a/content/browser/preloading/prefetch/prefetch_container.h b/content/browser/preloading/prefetch/prefetch_container.h index b6b38df..c246f0f7 100644 --- a/content/browser/preloading/prefetch/prefetch_container.h +++ b/content/browser/preloading/prefetch/prefetch_container.h
@@ -573,7 +573,9 @@ // - When `PrefetchURLLoaderInterceptor::MaybeCreateLoader()` handles // redirects in the serving prefetch. void OnDetectedCookiesChange(); - void OnDetectedCookiesChange2(); + void OnDetectedCookiesChange2( + std::optional<bool> + is_unblock_for_cookies_changed_triggered_by_this_prefetch_container); // Called when the prefetch request is started (i.e. the URL loader is created // & started).
diff --git a/content/browser/preloading/prefetch/prefetch_match_resolver.cc b/content/browser/preloading/prefetch/prefetch_match_resolver.cc index a9787ef..af3b7c0b 100644 --- a/content/browser/preloading/prefetch/prefetch_match_resolver.cc +++ b/content/browser/preloading/prefetch/prefetch_match_resolver.cc
@@ -238,7 +238,7 @@ case PrefetchContainer::ServableState::kServable: if (candidate.second->prefetch_container->CreateReader() .HaveDefaultContextCookiesChanged()) { - UnblockForCookiesChanged(); + UnblockForCookiesChanged(candidate.second->prefetch_container->key()); return; } break; @@ -397,7 +397,7 @@ } if (prefetch_container.CreateReader().HaveDefaultContextCookiesChanged()) { - UnblockForCookiesChanged(); + UnblockForCookiesChanged(prefetch_container.key()); return; } @@ -486,7 +486,8 @@ // It still waits for other `PrefetchContainer`s. } -void PrefetchMatchResolver2::UnblockForCookiesChanged() { +void PrefetchMatchResolver2::UnblockForCookiesChanged( + const PrefetchContainer::Key& key) { // Unregister remaining candidates as not served, with calling // `PrefetchContainer::OnDetectedCookiesChange2()`. for (auto& prefetch_key : Keys(candidates_)) { @@ -498,7 +499,9 @@ UnregisterCandidate(prefetch_key, /*is_served=*/false); - prefetch_container.OnDetectedCookiesChange2(); + prefetch_container.OnDetectedCookiesChange2( + /*is_unblock_for_cookies_changed_triggered_by_this_prefetch_container*/ + prefetch_key == key); } UnblockForNoCandidates();
diff --git a/content/browser/preloading/prefetch/prefetch_match_resolver.h b/content/browser/preloading/prefetch/prefetch_match_resolver.h index b0103d5..524c94e6 100644 --- a/content/browser/preloading/prefetch/prefetch_match_resolver.h +++ b/content/browser/preloading/prefetch/prefetch_match_resolver.h
@@ -195,7 +195,7 @@ // Unregisters unmatched prefetch and unblocks if there are no other waiting // prefetches. void MaybeUnblockForUnmatch(const PrefetchContainer::Key& prefetch_key); - void UnblockForCookiesChanged(); + void UnblockForCookiesChanged(const PrefetchContainer::Key& key); void UnblockInternal(PrefetchContainer::Reader reader); // Lifetime of this class is from the call of `FindPrefetch()` to calling
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc index 32fda648..a31c605 100644 --- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -2294,7 +2294,7 @@ ExpectServingMetricsSuccess(/*required_private_prefetch_proxy=*/false); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(FailedCookiesChangedAfterPrefetchStarted)) { base::HistogramTester histogram_tester; @@ -2356,7 +2356,7 @@ PrefetchStatus::kPrefetchNotUsedCookiesChanged, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(SameOriginPrefetchIgnoresProxyRequirement)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -2390,7 +2390,7 @@ ExpectServingMetricsSuccess(); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(NotEligibleSameSiteCrossOriginPrefetchRequiresProxy)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -2847,7 +2847,7 @@ ExpectServingMetrics(PrefetchStatus::kPrefetchIneligibleUserHasCookies); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_F(PrefetchServiceAlwaysMakeDecoyRequestTest, DISABLED_CHROMEOS(RedirectDecoyRequest)) { base::HistogramTester histogram_tester; @@ -2987,7 +2987,7 @@ PrefetchServiceStreamingURLLoaderTest, testing::Bool()); -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceStreamingURLLoaderTest, DISABLED_CHROMEOS(StreamingURLLoaderSuccessCase)) { base::HistogramTester histogram_tester; @@ -3064,7 +3064,7 @@ ExpectServingMetricsSuccess(); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(NoVarySearchSuccessCase)) { base::HistogramTester histogram_tester; @@ -3144,7 +3144,7 @@ GURL("https://example.com/?a=1")); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(PrefetchEligibleRedirect)) { base::HistogramTester histogram_tester; @@ -3195,7 +3195,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 2, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(IneligibleRedirectCookies)) { base::HistogramTester histogram_tester; @@ -3257,7 +3257,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 0); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(IneligibleRedirectServiceWorker)) { base::HistogramTester histogram_tester; @@ -3316,7 +3316,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 0); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(InvalidRedirect)) { base::HistogramTester histogram_tester; @@ -3363,7 +3363,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 0); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(PrefetchSameOriginEligibleRedirect)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -3417,7 +3417,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 2, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. // TODO(crbug.com/40265797): This test is testing the current // functionality, and should be removed while fixing this bug. TEST_P(PrefetchServiceTest, @@ -3475,7 +3475,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 0); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(RedirectDefaultToIsolatedNetworkContextTransition)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -3535,7 +3535,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 2, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS( RedirectDefaultToIsolatedNetworkContextTransitionWithProxy)) { @@ -3599,7 +3599,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 2, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(RedirectIsolatedToDefaultNetworkContextTransition)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -3676,7 +3676,7 @@ } }; -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_F(PrefetchServiceAllowRedirectsAndAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(RedirectNetworkContextTransitionBlockUntilHead)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -3748,7 +3748,7 @@ "PrefetchProxy.AfterClick.RedirectChainSize", 2, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceTest, DISABLED_CHROMEOS(RedirectInsufficientReferrerPolicy)) { NavigationSimulator::NavigateAndCommitFromBrowser( @@ -3817,7 +3817,7 @@ } }; -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_F(PrefetchServiceNeverBlockUntilHeadTest, DISABLED_CHROMEOS(HeadNotReceived)) { base::HistogramTester histogram_tester; @@ -3890,7 +3890,7 @@ } }; -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(BlockUntilHeadReceived)) { base::HistogramTester histogram_tester; @@ -3953,7 +3953,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(NVSBlockUntilHeadReceived)) { base::HistogramTester histogram_tester; @@ -4024,7 +4024,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(NVSBlockUntilHeadReceivedNoMatchNoNVSHeader)) { base::HistogramTester histogram_tester; @@ -4094,7 +4094,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(NVSBlockUntilHeadReceivedNoMatchByNVSHeader)) { base::HistogramTester histogram_tester; @@ -4165,7 +4165,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(FailedCookiesChangedWhileBlockUntilHead)) { base::HistogramTester histogram_tester; @@ -4248,7 +4248,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(FailedTimeoutWhileBlockUntilHead)) { base::HistogramTester histogram_tester; @@ -4301,7 +4301,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(FailedTimeoutWhileBlockUntilHeadForOlderNavigation)) { base::HistogramTester histogram_tester; @@ -4392,7 +4392,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS(FailedNetErrorWhileBlockUntilHead)) { base::HistogramTester histogram_tester; @@ -4453,7 +4453,7 @@ // FailedCookiesChangedAfterPrefetchStartedNVSHintPrefetch and // NVSBlockUntilHeadReceivedMultipleMatchesByNVSHint, consider only keeping one // of them and removing the remaining, as they almost test the same logic. -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P( PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS_AND_CASTOS(NVSBlockUntilHeadReceivedOneMatchOneTimeout)) { @@ -4597,7 +4597,7 @@ } } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS_AND_CASTOS( FailedCookiesChangedAfterPrefetchStartedTimedoutNVSHintPrefetch)) { @@ -4725,7 +4725,7 @@ } } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS_AND_CASTOS( FailedCookiesChangedAfterPrefetchStartedNVSHintPrefetch)) { @@ -4829,7 +4829,7 @@ /*required_private_prefetch_proxy=*/false); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadTest, DISABLED_CHROMEOS_AND_CASTOS( NVSBlockUntilHeadReceivedMultipleMatchesByNVSHint)) { @@ -5091,7 +5091,7 @@ true, 1); } -// TODO(crbug.com/40249481): Test flaky on lacros trybots. +// TODO(crbug.com/40249481): Test flaky on trybots. TEST_P(PrefetchServiceAlwaysBlockUntilHeadWithTimeoutTest, DISABLED_CHROMEOS(MultipleGetPrefetchToServe)) { base::HistogramTester histogram_tester;
diff --git a/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc b/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc index 4ee87db..a9275bb3 100644 --- a/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc +++ b/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc
@@ -88,7 +88,11 @@ redirect_reader_.GetPrefetchContainer(); CHECK(prefetch_container); if (UseNewWaitLoop()) { - prefetch_container->OnDetectedCookiesChange2(); + // Use `std::nullopt` as we need to record the crash key to identify + // which case in `PrefetchMatchResolver2` is the cause. + prefetch_container->OnDetectedCookiesChange2( + /*is_unblock_for_cookies_changed_triggered_by_this_prefetch_container*/ + std::nullopt); } else { // Note: This method can only be called once per PrefetchContainer (we // have a CHECK in the method). This is guaranteed to be the first time
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index 9ed20ad..2ac71910 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -6824,10 +6824,6 @@ PrerenderCancelledInterface::kGamepadMonitor, 1); } -// TODO(crbug.com/40178939) LaCrOS binds the HidManager interface, which -// might be required by Gamepad Service, in a different way. Disable this test -// before figuring out how to set the test context correctly. -#if !BUILDFLAG(IS_CHROMEOS_LACROS) // Tests that requesting to bind the GamepadMonitor interface after the // prerenderingchange event dispatched does not cancel prerendering. // This test cannot be a web test because web tests handles the GamepadMonitor @@ -6855,7 +6851,6 @@ // navigation. EXPECT_EQ(GetRequestCount(kPrerenderingUrl), 1); } -#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) // Tests that accessing the clipboard via the execCommand API fails because the // page does not has any user activation.
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc index 94bd75f..b5132979 100644 --- a/content/browser/renderer_host/clipboard_host_impl.cc +++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -225,8 +225,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) // ChromeOS FilesApp must include the custom 'fs/sources', etc data for - // paste that it put on the clipboard during copy (b/271078230). This can be - // removed when ash is fully replaced by lacros. + // paste that it put on the clipboard during copy (b/271078230). if (render_frame_host().GetMainFrame()->GetLastCommittedURL().SchemeIs( kChromeUIScheme)) { file_type_only = false;
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 489edfc..a5528d57 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -318,7 +318,7 @@ if (!primary_surface_id || primary_surface_id->local_surface_id() != local_surface_id_) { -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) // On Windows and Linux, we would like to produce new content as soon as // possible or the OS will create an additional black gutter. Until we can // block resize on surface synchronization on these platforms, we will not @@ -676,7 +676,7 @@ // static bool DelegatedFrameHost::ShouldIncludeUiCompositorForEviction() { -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_WIN) if (!base::FeatureList::IsEnabled( features::kApplyNativeOcclusionToCompositor)) { return false;
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc index fd41723..2df7253 100644 --- a/content/browser/renderer_host/frame_tree_browsertest.cc +++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -577,6 +577,47 @@ EXPECT_EQ(new_url, root->current_url()); } +// Asserts that a process pinned with a keep-alive ref hosting only discarded +// frames is successfully shutdown after the keep-alive timeout. +IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, + DiscardedFrameRendererShutdownAfterKeepAliveTimeout) { + WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); + FrameTree& frame_tree = wc->GetPrimaryFrameTree(); + + EXPECT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); + + // Ensure the view, frame and process are reported alive. + RenderFrameHostImpl* rfh = + static_cast<RenderFrameHostImpl*>(wc->GetPrimaryMainFrame()); + RenderViewHostImpl* rvh = rfh->render_view_host(); + RenderProcessHostImpl* rph = + static_cast<RenderProcessHostImpl*>(rfh->GetProcess()); + EXPECT_TRUE(rvh->IsRenderViewLive()); + EXPECT_TRUE(rfh->IsRenderFrameLive()); + EXPECT_TRUE(rph->IsInitializedAndNotDead()); + + // Set a keep-alive on the renderer process. + rph->IncrementKeepAliveRefCount(0); + + // Discard the frame tree. The process should remain alive. + frame_tree.Discard(); + EXPECT_TRUE(rvh->IsRenderViewLive()); + EXPECT_TRUE(rfh->IsRenderFrameLive()); + EXPECT_TRUE(rph->IsInitializedAndNotDead()); + + // Simulate a keep-alive timeout, the process should be promptly shutdown. + rfh->SimulateDiscardShutdownKeepAliveTimeoutForTesting(); + RenderProcessHostWatcher process_exit_observer( + wc, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + process_exit_observer.Wait(); + + // Ensure the process has been successfully shutdown. + EXPECT_FALSE(rvh->IsRenderViewLive()); + EXPECT_FALSE(rfh->IsRenderFrameLive()); + EXPECT_FALSE(rph->IsInitializedAndNotDead()); +} + class DedicatedWorkerObserver : public DedicatedWorkerService::Observer { public: explicit DedicatedWorkerObserver(DedicatedWorkerService* worker_service) {
diff --git a/content/browser/renderer_host/input/input_event_browsertest.cc b/content/browser/renderer_host/input/input_event_browsertest.cc index 98518db7..99fac73 100644 --- a/content/browser/renderer_host/input/input_event_browsertest.cc +++ b/content/browser/renderer_host/input/input_event_browsertest.cc
@@ -252,13 +252,7 @@ EXPECT_NEAR(event_time_ms, monotonic_time, 1); } -// TODO(crbug.com/41489011): Flaky on LaCros. -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_TouchStartEventTimeStamp DISABLED_TouchStartEventTimeStamp -#else -#define MAYBE_TouchStartEventTimeStamp TouchStartEventTimeStamp -#endif -IN_PROC_BROWSER_TEST_F(InputEventBrowserTest, MAYBE_TouchStartEventTimeStamp) { +IN_PROC_BROWSER_TEST_F(InputEventBrowserTest, TouchStartEventTimeStamp) { LoadURL(kEventListenerDataURL); MainThreadFrameObserver frame_observer(GetWidgetHost());
diff --git a/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc b/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc index 09ec546..798d7cb 100644 --- a/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc +++ b/content/browser/renderer_host/input/main_thread_event_queue_browsertest.cc
@@ -200,7 +200,7 @@ } // Disabled on MacOS because it doesn't support touch input. -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_MAC) #define MAYBE_TouchMove DISABLED_TouchMove #else #define MAYBE_TouchMove TouchMove
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index c5a2b85..46c8f54f 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -4105,8 +4105,7 @@ MediaStreamUI::SourceCallback device_changed_callback; if (request->stream_controls().dynamic_surface_switching_requested && ChangeSourceSupported( - blink::ToMediaStreamDevicesList(request->stream_devices_set)) && - base::FeatureList::IsEnabled(features::kDesktopCaptureChangeSource)) { + blink::ToMediaStreamDevicesList(request->stream_devices_set))) { device_changed_callback = base::BindRepeating( &MediaStreamManager::ChangeMediaStreamSourceFromBrowser, base::Unretained(this), label);
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index b1094e7..202ac766 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -54,10 +54,6 @@ #include "url/gurl.h" #include "url/origin.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/lacros/lacros_test_helper.h" -#endif - #if defined(USE_ALSA) #include "media/audio/alsa/audio_manager_alsa.h" #elif BUILDFLAG(IS_ANDROID) @@ -471,11 +467,6 @@ _, _, _, _, blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE_SET, MEDIA_REQUEST_STATE_OPENING)); -#if BUILDFLAG(IS_CHROMEOS_LACROS) - EXPECT_CALL(*browser_content_client_, - NotifyMultiCaptureStateChanged( - _, _, ContentBrowserClient::MultiCaptureChanged::kStarted)); -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) stream_provider_listener_ = std::make_unique<MediaStreamProviderListenerMock>(); media_stream_manager_->video_capture_manager_->RegisterListener( @@ -1304,11 +1295,6 @@ _, _, _, _, blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE_SET, MEDIA_REQUEST_STATE_DONE)) .Times(0); -#if BUILDFLAG(IS_CHROMEOS_LACROS) - EXPECT_CALL(*browser_content_client_, - NotifyMultiCaptureStateChanged( - _, _, ContentBrowserClient::MultiCaptureChanged::kStopped)); -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) } TEST_F(MediaStreamManagerTest, RegisterUnregisterHosts) {
diff --git a/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc b/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc index 0fad2fd..1146ca6 100644 --- a/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc +++ b/content/browser/renderer_host/media/render_frame_audio_input_stream_factory_unittest.cc
@@ -42,10 +42,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/lacros/lacros_test_helper.h" -#endif - namespace content { // RenderViewHostTestHarness works poorly on Android. @@ -184,10 +180,6 @@ const std::string kDeviceName = "test name"; const bool kAGC = false; const uint32_t kSharedMemoryCount = 123; -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // Instantiate LacrosService for WakeLock support. - chromeos::ScopedLacrosServiceTestHelper scoped_lacros_service_test_helper_; -#endif MockStreamFactory audio_service_stream_factory_; media::FakeAudioLogFactory log_factory_; media::FakeAudioManager audio_manager_;
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc index 9c116dc..5b81be69 100644 --- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -16354,8 +16354,8 @@ UtilizationOfSpareRenderProcessHost) { GURL first_url = embedded_test_server()->GetURL("a.com", "/title1.html"); GURL second_url = embedded_test_server()->GetURL("b.com", "/title2.html"); - std::vector<int> prev_spare_ids; - std::vector<int> curr_spare_ids; + std::vector<ChildProcessId> prev_spare_ids; + std::vector<ChildProcessId> curr_spare_ids; RenderProcessHost* prev_host = nullptr; RenderProcessHost* curr_host = nullptr; @@ -16373,7 +16373,8 @@ EXPECT_TRUE(NavigateToURL(shell(), first_url)); curr_spare_ids = spare_manager.GetSpareIds(); curr_host = shell()->web_contents()->GetPrimaryMainFrame()->GetProcess(); - EXPECT_FALSE(base::Contains(curr_spare_ids, curr_host->GetDeprecatedID())); + EXPECT_FALSE(base::Contains(curr_spare_ids, curr_host->GetID())); + // No process swap when navigating away from the initial blank page. EXPECT_EQ(prev_host, curr_host); // We should always keep a spare RenderProcessHost around in site-per-process @@ -16407,7 +16408,7 @@ EXPECT_NE(prev_host, curr_host); // If present, the spare RenderProcessHost should have been be used. if (!prev_spare_ids.empty()) { - EXPECT_TRUE(base::Contains(prev_spare_ids, curr_host->GetDeprecatedID())); + EXPECT_TRUE(base::Contains(prev_spare_ids, curr_host->GetID())); } // A new spare should be warmed-up in site-per-process mode. if (AreAllSitesIsolatedForTesting()) { @@ -16429,7 +16430,7 @@ EXPECT_NE(prev_host, curr_host); // If present, the spare RenderProcessHost should have been used. if (!prev_spare_ids.empty()) { - EXPECT_TRUE(base::Contains(prev_spare_ids, curr_host->GetDeprecatedID())); + EXPECT_TRUE(base::Contains(prev_spare_ids, curr_host->GetID())); } // A new spare should be warmed-up in site-per-process mode. if (AreAllSitesIsolatedForTesting()) {
diff --git a/content/browser/renderer_host/page_lifecycle_state_manager_browsertest.cc b/content/browser/renderer_host/page_lifecycle_state_manager_browsertest.cc index e7670708..6cbc547 100644 --- a/content/browser/renderer_host/page_lifecycle_state_manager_browsertest.cc +++ b/content/browser/renderer_host/page_lifecycle_state_manager_browsertest.cc
@@ -142,8 +142,8 @@ EvalJs(rfh, "window.performanceObserverEntries")); } -// TODO(crbug.com/40786254): Test is flaky on Win and Lacros -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/40786254): Test is flaky on Win +#if BUILDFLAG(IS_WIN) #define MAYBE_CrossProcessIframeHiddenAnFrozen \ DISABLED_CrossProcessIframeHiddenAnFrozen #else
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index d73ae4f..222a3d5 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1461,6 +1461,10 @@ base::Unretained(this))); } + void SimulateKeepAliveTimeoutForTesting() { + keep_alive_timeout_for_testing_ = true; + } + private: // A task that attempts to shutdown the render process for the case where only // discarded frames remain. @@ -1494,15 +1498,32 @@ } }); - // Attempt shutdown without running unload handlers, the discard operation - // has been acknowledged by the render process at this point. - if (discarded_widgets.size() > 0 && only_discarded_frames && - (retries_ * kProcessShutdownRetryDelay <= - RenderProcessHostImpl::kKeepAliveHandleFactoryTimeout) && - !host_->FastShutdownIfPossible( + // Attempt a shutdown if the the renderer is hosting only discarded frames. + if (discarded_widgets.empty() || !only_discarded_frames) { + return; + } + + // If shutdown re-attempts have exceeded the kKeepAliveHandleFactoryTimeout + // then attempt a final shutdown ignoring any active keep-alive refs. + if (keep_alive_timeout_for_testing_ || + retries_ * kProcessShutdownRetryDelay >= + RenderProcessHostImpl::kKeepAliveHandleFactoryTimeout) { + host_->FastShutdownIfPossible( + /*page_count=*/discarded_widgets.size(), + /*skip_unload_handlers=*/true, + /*ignore_workers=*/true, + /*ignore_keep_alive=*/true); + return; + } + + // If re-attempts have not yet reached kKeepAliveHandleFactoryTimeout + // attempt a shutdown honoring any existing keep-alive refs. Schedule a + // retry if fast shutdown is blocked. + if (!host_->FastShutdownIfPossible( /*page_count=*/discarded_widgets.size(), /*skip_unload_handlers=*/true, - /*ignore_workers=*/true)) { + /*ignore_workers=*/true, + /*ignore_keep_alive=*/false)) { retries_++; shutdown_attempt_timer_.Start( FROM_HERE, kProcessShutdownRetryDelay, @@ -1519,6 +1540,8 @@ // Owns this. const raw_ptr<RenderProcessHost> host_; + + bool keep_alive_timeout_for_testing_ = false; }; } // namespace @@ -6273,6 +6296,11 @@ return !IsNestedWithinFencedFrame() && delegate_->IsPartitionedPopin(); } +void RenderFrameHostImpl::SimulateDiscardShutdownKeepAliveTimeoutForTesting() { + DiscardedRFHProcessHelper::GetForRenderProcessHost(GetProcess()) + ->SimulateKeepAliveTimeoutForTesting(); +} + bool RenderFrameHostImpl::IsBackForwardCacheEvictionTimeRunningForTesting() const { return back_forward_cache_eviction_timer_.IsRunning();
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 4f985361..4849f49 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -3163,6 +3163,8 @@ // See https://explainers-by-googlers.github.io/partitioned-popins/ bool ShouldPartitionAsPopin() const; + void SimulateDiscardShutdownKeepAliveTimeoutForTesting(); + protected: friend class RenderFrameHostFactory;
diff --git a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc index 763e46d8..98c72d3 100644 --- a/content/browser/renderer_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/renderer_host/render_frame_host_manager_browsertest.cc
@@ -6148,7 +6148,7 @@ spare_manager.GetSpares(), testing::Each(testing::Property(&RenderProcessHost::GetPriority, base::Process::Priority::kBestEffort))); - std::vector<int> spare_rph_ids = spare_manager.GetSpareIds(); + std::vector<ChildProcessId> spare_rph_ids = spare_manager.GetSpareIds(); ASSERT_FALSE(spare_rph_ids.empty()); // Start a navigation to b.com to ensure a cross-process navigation is @@ -6168,8 +6168,7 @@ // In this test case, a spare RenderProcessHost will be used, so verify it // and ensure it is ready. - EXPECT_THAT(spare_rph_ids, - testing::Contains(speculative_rph->GetDeprecatedID())); + EXPECT_THAT(spare_rph_ids, testing::Contains(speculative_rph->GetID())); // If LoadUrl finished before the task to call // RenderProcessHostImpl::OnChannelConnected is run, wait for the task to be
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index a512cb6..cf6dcc86 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3290,8 +3290,7 @@ switches::kDisableInProcessStackTraces, sandbox::policy::switches::kDisableSeccompFilterSandbox, sandbox::policy::switches::kNoSandbox, -#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ - !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) switches::kDisableDevShmUsage, #endif #if BUILDFLAG(IS_MAC) @@ -3473,11 +3472,6 @@ #if BUILDFLAG(IS_CHROMEOS) switches::kSchedulerBoostUrgent, #endif -#if BUILDFLAG(IS_CHROMEOS_LACROS) - switches::kLacrosEnablePlatformHevc, - switches::kLacrosUseChromeosProtectedMedia, - switches::kLacrosUseChromeosProtectedAv1, -#endif }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames); @@ -3615,7 +3609,8 @@ bool RenderProcessHostImpl::FastShutdownIfPossible(size_t page_count, bool skip_unload_handlers, - bool ignore_workers) { + bool ignore_workers, + bool ignore_keep_alive) { base::UmaHistogramBoolean( "BrowserRenderProcessHost.FastShutdownIfPossible.Total", true); // Do not shut down the process if there are active or pending views other @@ -3647,7 +3642,7 @@ } // TODO(crbug.com/40236167): Remove this block once the migration is launched. - if (keep_alive_ref_count_ != 0) { + if (!ignore_keep_alive && keep_alive_ref_count_ != 0) { CHECK(IsKeepAliveRefCountAllowed()); LogDelayReasonForFastShutdown(DelayShutdownReason::kFetchKeepAlive); return false;
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index df17aa0..f938e8d6 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -248,7 +248,8 @@ bool ShutdownRequested() override; bool FastShutdownIfPossible(size_t page_count = 0, bool skip_unload_handlers = false, - bool ignore_workers = false) override; + bool ignore_workers = false, + bool ignore_keep_alive = false) override; const base::Process& GetProcess() override; bool IsReady() override; BrowserContext* GetBrowserContext() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 9b258cb5d..4ab0948 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -157,13 +157,7 @@ // to reallocate an LSI for the UI compositor. BASE_FEATURE(kRenderWidgetHostHiddenCheck, "RenderWidgetHostHiddenCheck", -// TODO(b/338354134): LaCrOs video is triggering the associated CHECK. Disable -// for that configuration. -#if BUILDFLAG(IS_CHROMEOS_LACROS) - base::FEATURE_DISABLED_BY_DEFAULT); -#else base::FEATURE_ENABLED_BY_DEFAULT); -#endif } // namespace // We need to watch for mouse events outside a Web Popup or its parent @@ -2164,7 +2158,6 @@ if (!window_->GetRootWindow()) return; - // TODO(crbug.com/40268472): Add unittest for lacros. if (needs_to_update_display_metrics_ || old_device_scale_factor != new_device_scale_factor) { ProcessDisplayMetricsChanged(); @@ -2830,7 +2823,7 @@ } bool RenderWidgetHostViewAura::NeedsMouseCapture() { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) return NeedsInputGrab(); #else return false;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc index 8325266..02296de 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_browsertest.cc
@@ -245,19 +245,8 @@ } #endif // #if BUILDFLAG(IS_CHROMEOS_ASH) -// TODO(crbug.com/40148102): fix the way how exo creates accelerated widgets. At -// the moment, they are created only after the client attaches a buffer to a -// surface, which is incorrect and results in the "[destroyed object]: error 1: -// popup parent not constructed" error. -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_SetKeyboardFocusOnTapAfterDismissingPopup \ - DISABLED_SetKeyboardFocusOnTapAfterDismissingPopup -#else -#define MAYBE_SetKeyboardFocusOnTapAfterDismissingPopup \ - SetKeyboardFocusOnTapAfterDismissingPopup -#endif IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewAuraBrowserTest, - MAYBE_SetKeyboardFocusOnTapAfterDismissingPopup) { + SetKeyboardFocusOnTapAfterDismissingPopup) { GURL page( "data:text/html;charset=utf-8," "<!DOCTYPE html>"
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index b0ca99f1..832dc66 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -1265,7 +1265,7 @@ } #endif -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) // On Desktop Linux, select boxes need mouse capture in order to work. Test that // when a select box is opened via a mouse press that it retains mouse capture // after the mouse is released.
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc index 79f52e7..79c4bc8 100644 --- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -1615,14 +1615,8 @@ base::HistogramTester histogram_tester_; }; -// TODO(crbug.com/353234554): Flaky on linux-lacros-tester-rel. -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_Show DISABLED_Show -#else -#define MAYBE_Show Show -#endif IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, - MAYBE_Show) { + Show) { CreateVisibleTimeRequest(); GetRenderWidgetHostView()->ShowWithVisibility(PageVisibilityState::kVisible); ExpectPresentationFeedback(TabSwitchResult::kSuccess); @@ -1648,14 +1642,8 @@ ExpectNoPresentationFeedback(); } -// TODO(crbug.com/353234554): Flaky on linux-lacros-tester-rel. -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_ShowWhileCapturing DISABLED_ShowWhileCapturing -#else -#define MAYBE_ShowWhileCapturing ShowWhileCapturing -#endif IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, - MAYBE_ShowWhileCapturing) { + ShowWhileCapturing) { // Frame is captured and then becomes visible. CreateVisibleTimeRequest(); GetRenderWidgetHostView()->ShowWithVisibility(
diff --git a/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc b/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc index 5e3e247..d6ac28a 100644 --- a/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc +++ b/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc
@@ -239,7 +239,8 @@ EXPECT_THAT(spares_before_navigation, Contains(window->web_contents() ->GetPrimaryMainFrame() ->GetProcess() - ->GetDeprecatedID())); + ->GetID())); + histogram_tester.ExpectUniqueSample( "BrowserRenderProcessHost.SpareRendererDispatchResult", SpareRendererDispatchResult::kUsed, 1); @@ -255,7 +256,7 @@ Not(Contains(window->web_contents() ->GetPrimaryMainFrame() ->GetProcess() - ->GetDeprecatedID()))); + ->GetID()))); // Check if a fresh spare is available (depending on the operating mode). if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) { @@ -422,7 +423,7 @@ EXPECT_THAT(spares_before_navigation, Not(Contains(window->web_contents() ->GetPrimaryMainFrame() ->GetProcess() - ->GetDeprecatedID()))); + ->GetID()))); // Check if a fresh spare is available (depending on the operating mode). // Note this behavior is identical to what would have happened if the @@ -440,7 +441,8 @@ spare_manager.WarmupSpare(browser_context()); ASSERT_EQ(spare_manager.GetSpares().size(), 1u); RenderProcessHost* spare_renderer = spare_manager.GetSpares().back(); - int spare_rph_id = spare_renderer->GetDeprecatedID(); + + ChildProcessId spare_rph_id = spare_renderer->GetID(); mojo::Remote<mojom::TestService> service; ASSERT_NE(nullptr, spare_renderer); spare_renderer->BindReceiver(service.BindNewPipeAndPassReceiver()); @@ -457,8 +459,7 @@ // The initial spare is gone from the list of spares. EXPECT_THAT(spare_manager.GetSpares(), - Not(Contains(Property(&RenderProcessHost::GetDeprecatedID, - spare_rph_id)))); + Not(Contains(Property(&RenderProcessHost::GetID, spare_rph_id)))); } // A mock ContentBrowserClient that only considers a spare renderer to be a
diff --git a/content/browser/renderer_host/spare_render_process_host_manager_impl.cc b/content/browser/renderer_host/spare_render_process_host_manager_impl.cc index 2b3e5b6..d4af72c 100644 --- a/content/browser/renderer_host/spare_render_process_host_manager_impl.cc +++ b/content/browser/renderer_host/spare_render_process_host_manager_impl.cc
@@ -200,11 +200,11 @@ return spare_rphs_; } -std::vector<int> SpareRenderProcessHostManagerImpl::GetSpareIds() { - std::vector<int> spare_ids; +std::vector<ChildProcessId> SpareRenderProcessHostManagerImpl::GetSpareIds() { + std::vector<ChildProcessId> spare_ids; spare_ids.reserve(spare_rphs_.size()); for (RenderProcessHost* spare_rph : spare_rphs_) { - spare_ids.push_back(spare_rph->GetDeprecatedID()); + spare_ids.push_back(spare_rph->GetID()); } return spare_ids; }
diff --git a/content/browser/renderer_host/spare_render_process_host_manager_impl.h b/content/browser/renderer_host/spare_render_process_host_manager_impl.h index ccdc56fa..57de617 100644 --- a/content/browser/renderer_host/spare_render_process_host_manager_impl.h +++ b/content/browser/renderer_host/spare_render_process_host_manager_impl.h
@@ -80,7 +80,7 @@ void RemoveObserver(Observer* observer) override; void WarmupSpare(BrowserContext* browser_context) override; const std::vector<RenderProcessHost*>& GetSpares() override; - std::vector<int> GetSpareIds() override; + std::vector<ChildProcessId> GetSpareIds() override; void CleanupSparesForTesting() override; // Start a spare renderer immediately, only if there is none.
diff --git a/content/browser/resources/traces_internals/DIR_METADATA b/content/browser/resources/traces_internals/DIR_METADATA index 4b6d731..cc99335 100644 --- a/content/browser/resources/traces_internals/DIR_METADATA +++ b/content/browser/resources/traces_internals/DIR_METADATA
@@ -1,7 +1,7 @@ monorail: { component: "Speed>Tracing" } -team_email: "chrome-catan@chromium.org" +team_email: "catan-team@chromium.org" buganizer_public: { component_id: 1457213 }
diff --git a/content/browser/scheduler/responsiveness/jank_monitor_impl.cc b/content/browser/scheduler/responsiveness/jank_monitor_impl.cc index 8cc2449..6047c4c 100644 --- a/content/browser/scheduler/responsiveness/jank_monitor_impl.cc +++ b/content/browser/scheduler/responsiveness/jank_monitor_impl.cc
@@ -340,8 +340,7 @@ // in context menus, among others). Simply ignore the mismatches for now. // See https://crbug.com/929813 for the details of why the mismatch // happens. -#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \ - BUILDFLAG(IS_OZONE) +#if BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE) task_execution_metadata_.clear(); #endif return;
diff --git a/content/browser/screenlock_monitor/screenlock_monitor_device_source.h b/content/browser/screenlock_monitor/screenlock_monitor_device_source.h index 2c96386..cc460e2 100644 --- a/content/browser/screenlock_monitor/screenlock_monitor_device_source.h +++ b/content/browser/screenlock_monitor/screenlock_monitor_device_source.h
@@ -24,13 +24,6 @@ #include "components/session_manager/core/session_manager_observer.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include <optional> - -#include "chromeos/crosapi/mojom/login_state.mojom.h" // nogncheck -#include "mojo/public/cpp/bindings/receiver.h" -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) - #if BUILDFLAG(IS_WIN) namespace gfx { class SingletonHwndObserver; @@ -119,28 +112,6 @@ ScreenLockListener screenlock_listener_; #endif // BUILDFLAG(IS_CHROMEOS_ASH) - -#if BUILDFLAG(IS_CHROMEOS_LACROS) - class ScreenLockListener - : public crosapi::mojom::SessionStateChangedEventObserver { - public: - ScreenLockListener(); - - ScreenLockListener(const ScreenLockListener&) = delete; - ScreenLockListener& operator=(const ScreenLockListener&) = delete; - - ~ScreenLockListener() override; - - // crosapi::mojom::SessionStateChangedEventObserver: - void OnSessionStateChanged(crosapi::mojom::SessionState state) override; - - private: - std::optional<ScreenlockEvent> prev_event_; - mojo::Receiver<crosapi::mojom::SessionStateChangedEventObserver> receiver_; - }; - - ScreenLockListener screenlock_listener_; -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) }; } // namespace content
diff --git a/content/browser/screenlock_monitor/screenlock_monitor_device_source_lacros.cc b/content/browser/screenlock_monitor/screenlock_monitor_device_source_lacros.cc deleted file mode 100644 index ae3c8b7..0000000 --- a/content/browser/screenlock_monitor/screenlock_monitor_device_source_lacros.cc +++ /dev/null
@@ -1,43 +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 "content/browser/screenlock_monitor/screenlock_monitor_device_source.h" - -#include "chromeos/crosapi/mojom/login_state.mojom.h" -#include "chromeos/lacros/lacros_service.h" - -namespace content { - -ScreenlockMonitorDeviceSource::ScreenLockListener::ScreenLockListener() - : receiver_(this) { - auto* lacros_service = chromeos::LacrosService::Get(); - if (!lacros_service || - !lacros_service->IsAvailable<crosapi::mojom::LoginState>()) { - LOG(WARNING) << "crosapi: LoginState not available."; - return; - } - - lacros_service->GetRemote<crosapi::mojom::LoginState>()->AddObserver( - receiver_.BindNewPipeAndPassRemote()); -} - -ScreenlockMonitorDeviceSource::ScreenLockListener::~ScreenLockListener() = - default; - -void ScreenlockMonitorDeviceSource::ScreenLockListener::OnSessionStateChanged( - crosapi::mojom::SessionState state) { - ScreenlockEvent screenlock_event; - if (state == crosapi::mojom::SessionState::kInLockScreen) { - screenlock_event = SCREEN_LOCK_EVENT; - } else { - screenlock_event = SCREEN_UNLOCK_EVENT; - } - - if (!prev_event_ || *prev_event_ != screenlock_event) { - prev_event_ = screenlock_event; - ProcessScreenlockEvent(screenlock_event); - } -} - -} // namespace content
diff --git a/content/browser/screenlock_monitor/screenlock_monitor_device_source_lacros_unittest.cc b/content/browser/screenlock_monitor/screenlock_monitor_device_source_lacros_unittest.cc deleted file mode 100644 index cb5fc55..0000000 --- a/content/browser/screenlock_monitor/screenlock_monitor_device_source_lacros_unittest.cc +++ /dev/null
@@ -1,154 +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 "content/browser/screenlock_monitor/screenlock_monitor_device_source.h" - -#include "base/check.h" -#include "base/run_loop.h" -#include "base/test/task_environment.h" -#include "chromeos/crosapi/mojom/login_state.mojom.h" -#include "chromeos/lacros/lacros_test_helper.h" -#include "content/browser/screenlock_monitor/screenlock_monitor.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { -namespace { - -class TestScreenlockObserver : public ScreenlockObserver { - public: - TestScreenlockObserver() = default; - ~TestScreenlockObserver() override = default; - - TestScreenlockObserver(const TestScreenlockObserver&) = delete; - TestScreenlockObserver& operator=(const TestScreenlockObserver&) = delete; - - // ScreenlockObserver: - void OnScreenLocked() override { - locked_notified_ = true; - if (notified_callback_) - notified_callback_.Run(); - } - void OnScreenUnlocked() override { - unlocked_notified_ = true; - if (notified_callback_) - notified_callback_.Run(); - } - - bool locked_notified() const { return locked_notified_; } - bool unlocked_notified() const { return unlocked_notified_; } - - void Reset() { - locked_notified_ = false; - unlocked_notified_ = false; - notified_callback_ = base::RepeatingClosure(); - } - - void set_notified_callback(base::RepeatingClosure callback) { - notified_callback_ = std::move(callback); - } - - private: - bool locked_notified_ = false; - bool unlocked_notified_ = false; - - base::RepeatingClosure notified_callback_; -}; - -class ScreenlockMonitorDeviceSourceLacrosTest - : public testing::Test, - public crosapi::mojom::LoginState { - public: - ScreenlockMonitorDeviceSourceLacrosTest( - const ScreenlockMonitorDeviceSourceLacrosTest&) = delete; - ScreenlockMonitorDeviceSourceLacrosTest& operator=( - const ScreenlockMonitorDeviceSourceLacrosTest&) = delete; - - protected: - ScreenlockMonitorDeviceSourceLacrosTest() : receiver_(this) {} - ~ScreenlockMonitorDeviceSourceLacrosTest() override = default; - - void SetUp() override { - chromeos::LacrosService::Get()->InjectRemoteForTesting( - receiver_.BindNewPipeAndPassRemote()); - - screenlock_monitor_ = std::make_unique<ScreenlockMonitor>( - std::make_unique<ScreenlockMonitorDeviceSource>()); - screenlock_monitor_->AddObserver(&observer_); - - observer_pending_receiver_ = observer_remote_.BindNewPipeAndPassReceiver(); - } - - // crosapi::mojom::LoginState: - void AddObserver( - mojo::PendingRemote<crosapi::mojom::SessionStateChangedEventObserver> - observer) override { - DCHECK(observer_pending_receiver_); - mojo::FusePipes(std::move(observer_pending_receiver_), std::move(observer)); - } - void GetSessionState(GetSessionStateCallback callback) override { - NOTREACHED(); - } - - void SetSessionStateAndNotify(crosapi::mojom::SessionState state) { - observer_remote_->OnSessionStateChanged(state); - } - - base::test::TaskEnvironment task_environment_; - chromeos::ScopedLacrosServiceTestHelper lacros_service_test_helper_; - - TestScreenlockObserver observer_; - std::unique_ptr<ScreenlockMonitor> screenlock_monitor_; - - mojo::Receiver<crosapi::mojom::LoginState> receiver_; - mojo::Remote<crosapi::mojom::SessionStateChangedEventObserver> - observer_remote_; - mojo::PendingReceiver<crosapi::mojom::SessionStateChangedEventObserver> - observer_pending_receiver_; -}; - -} // namespace - -TEST_F(ScreenlockMonitorDeviceSourceLacrosTest, Notifications) { - // Use RunUntilIdle() for some places where it is expected that something - // doesn't happen and therefore no suitable place to call QuitClosure(). - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(observer_.locked_notified()); - EXPECT_FALSE(observer_.unlocked_notified()); - - { - base::RunLoop run_loop; - observer_.set_notified_callback(run_loop.QuitClosure()); - SetSessionStateAndNotify(crosapi::mojom::SessionState::kInSession); - run_loop.Run(); - EXPECT_FALSE(observer_.locked_notified()); - EXPECT_TRUE(observer_.unlocked_notified()); - } - - observer_.Reset(); - - // Test that there are no surplus notifications for unlocked state. - SetSessionStateAndNotify(crosapi::mojom::SessionState::kInOobeScreen); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(observer_.locked_notified()); - EXPECT_FALSE(observer_.unlocked_notified()); - - { - base::RunLoop run_loop; - observer_.set_notified_callback(run_loop.QuitClosure()); - SetSessionStateAndNotify(crosapi::mojom::SessionState::kInLockScreen); - run_loop.Run(); - EXPECT_TRUE(observer_.locked_notified()); - EXPECT_FALSE(observer_.unlocked_notified()); - } - - observer_.Reset(); - - // Test that there are no surplus notifications for locked state. - SetSessionStateAndNotify(crosapi::mojom::SessionState::kInLockScreen); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(observer_.locked_notified()); - EXPECT_FALSE(observer_.unlocked_notified()); -} - -} // namespace content
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.cc b/content/browser/service_worker/service_worker_main_resource_loader.cc index 74b556b5..3784141 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader.cc
@@ -450,7 +450,7 @@ // improve the coverage. if (base::GetFieldTrialParamByFeatureAsBool( features::kServiceWorkerAutoPreload, "has_web_request_api_proxy", - /*default_value=*/false) && + /*default_value=*/true) && (GetContentClient()->browser()->HasWebRequestAPIProxy( context->browser_context()))) { return false;
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 442d005..bb97f3e 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -12372,8 +12372,8 @@ // the hung renderer dialog used to undesirably show up for background tabs // (typically during session restore when many navigations would be happening in // backgrounded processes). -// TODO(crbug.com/40196588): Flaky on LaCrOS, Mac, and Windows. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/40196588): Flaky on Mac and Windows. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) #define MAYBE_NoCommitTimeoutForInvisibleWebContents \ DISABLED_NoCommitTimeoutForInvisibleWebContents #else
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index c5cc4d41..0487ef56 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -922,9 +922,8 @@ testing::Combine(testing::ValuesIn(kMultiScale))); // Flaky on MSAN. https://crbug.com/959924 -// Flaky on Linux Wayland and Lacros. https://crbug.com/1158437 -#if defined(MEMORY_SANITIZER) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) +// Flaky on Linux Wayland. https://crbug.com/1158437 +#if defined(MEMORY_SANITIZER) || BUILDFLAG(IS_LINUX) #define MAYBE_ScrollNestedLocalNonFastScrollableDiv \ DISABLED_ScrollNestedLocalNonFastScrollableDiv #else @@ -6682,9 +6681,9 @@ } // MacOSX does not have fractional device scales. -// Linux/Lacros started failing after Wayland window configuration fixes have +// Linux started failing after Wayland window configuration fixes have // landed. TODO(crbug.com/40832051): Re-enable once the test issue is addressed. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) #define MAYBE_NestedSurfaceHitTestTest DISABLED_NestedSurfaceHitTestTest #else #define MAYBE_NestedSurfaceHitTestTest NestedSurfaceHitTestTest
diff --git a/content/browser/site_per_process_layout_browsertest.cc b/content/browser/site_per_process_layout_browsertest.cc index f99f9448..0d5b370 100644 --- a/content/browser/site_per_process_layout_browsertest.cc +++ b/content/browser/site_per_process_layout_browsertest.cc
@@ -1698,8 +1698,8 @@ // This test verifies that changing the CSS visibility of a cross-origin // <iframe> is forwarded to its corresponding RenderWidgetHost and all other // RenderWidgetHosts corresponding to the nested cross-origin frame. -// TODO(crbug.com/40865141): Flaky on mac, linux-lacros, android. -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/40865141): Flaky on mac and android. +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) #define MAYBE_CSSVisibilityChanged DISABLED_CSSVisibilityChanged #else #define MAYBE_CSSVisibilityChanged CSSVisibilityChanged
diff --git a/content/browser/snapshot_browsertest.cc b/content/browser/snapshot_browsertest.cc index 33892af2..2f4d0aee9 100644 --- a/content/browser/snapshot_browsertest.cc +++ b/content/browser/snapshot_browsertest.cc
@@ -259,10 +259,10 @@ // Linux TSAN Tests // See crbug.com/771119 // TODO(crbug.com/40834774): Fix and enable on Fuchsia. -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || \ - ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \ - defined(THREAD_SANITIZER)) || \ - BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || \ + ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \ + defined(THREAD_SANITIZER)) || \ + BUILDFLAG(IS_FUCHSIA) #define MAYBE_SyncMultiWindowTest DISABLED_SyncMultiWindowTest #else #define MAYBE_SyncMultiWindowTest SyncMultiWindowTest
diff --git a/content/browser/tracing/cast_tracing_agent.cc b/content/browser/tracing/cast_tracing_agent.cc index fba46437..c29d5347 100644 --- a/content/browser/tracing/cast_tracing_agent.cc +++ b/content/browser/tracing/cast_tracing_agent.cc
@@ -218,7 +218,6 @@ {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) { DETACH_FROM_SEQUENCE(perfetto_sequence_checker_); - tracing::PerfettoTracedProcess::Get()->AddDataSource(this); perfetto::DataSourceDescriptor dsd; dsd.set_name(tracing::mojom::kSystemTraceDataSourceName); DataSourceProxy::Register(dsd, this); @@ -278,8 +277,7 @@ } // namespace CastTracingAgent::CastTracingAgent() { - tracing::PerfettoTracedProcess::Get()->AddDataSource( - &CastDataSource::GetInstance()); + CastDataSource::GetInstance(); } CastTracingAgent::~CastTracingAgent() = default;
diff --git a/content/browser/tracing/cros_tracing_agent.cc b/content/browser/tracing/cros_tracing_agent.cc index fff14eba..0ed8491dd 100644 --- a/content/browser/tracing/cros_tracing_agent.cc +++ b/content/browser/tracing/cros_tracing_agent.cc
@@ -140,7 +140,6 @@ CrOSDataSource() : DataSourceBase(tracing::mojom::kSystemTraceDataSourceName) { DETACH_FROM_SEQUENCE(ui_sequence_checker_); - tracing::PerfettoTracedProcess::Get()->AddDataSource(this); perfetto::DataSourceDescriptor dsd; dsd.set_name(tracing::mojom::kSystemTraceDataSourceName); DataSourceProxy::Register(dsd, this); @@ -232,10 +231,8 @@ } // namespace CrOSTracingAgent::CrOSTracingAgent() { - tracing::PerfettoTracedProcess::Get()->AddDataSource( - &CrOSDataSource::GetInstance()); + CrOSDataSource::GetInstance(); } - CrOSTracingAgent::~CrOSTracingAgent() = default; } // namespace content
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index f9eca6d..bdbe7ca 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -228,10 +228,6 @@ base::Unretained(this))); metadata_source->AddGeneratorFunction(base::BindRepeating( &TracingControllerImpl::GenerateMetadataPacket, base::Unretained(this))); -#if BUILDFLAG(IS_ANDROID) - tracing::PerfettoTracedProcess::Get()->AddDataSource( - tracing::JavaHeapProfiler::GetInstance()); -#endif } void TracingControllerImpl::GenerateMetadataPacketFieldTrials(
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index afbd2d7..ad94b8f 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -92,10 +92,6 @@ #include "url/gurl.h" #include "url/url_constants.h" -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chromeos/lacros/lacros_test_helper.h" -#endif - namespace content { namespace { @@ -127,12 +123,6 @@ GURL isolated_cross_site_url() const { return GURL("http://isolated-cross-site.com"); } - - private: -#if BUILDFLAG(IS_CHROMEOS_LACROS) - // Instantiate LacrosService for WakeLock support. - chromeos::ScopedLacrosServiceTestHelper scoped_lacros_service_test_helper_; -#endif }; class TestWebContentsObserver : public WebContentsObserver {
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc index e220cb80..dcfc9d6 100644 --- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -896,9 +896,7 @@ // tests. http://crbug.com/305722 // TODO(tdresser): Re-enable this once eager GR is back on. See // crbug.com/410280. -// TODO(crbug.com/40118868): Revisit the macro expression once build flag switch -// of lacros-chrome is complete. -#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) #define MAYBE_OverscrollNavigationTouchThrottling \ DISABLED_OverscrollNavigationTouchThrottling #else
diff --git a/content/browser/webid/jwt_signer.h b/content/browser/webid/jwt_signer.h index 3f05f55..131e777 100644 --- a/content/browser/webid/jwt_signer.h +++ b/content/browser/webid/jwt_signer.h
@@ -5,10 +5,11 @@ #ifndef CONTENT_BROWSER_WEBID_JWT_SIGNER_H_ #define CONTENT_BROWSER_WEBID_JWT_SIGNER_H_ -#include <optional> -#include <vector> -#include <string_view> +#include <cstdint> #include <memory> +#include <optional> +#include <string_view> +#include <vector> #include "base/functional/callback_forward.h" #include "content/common/content_export.h"
diff --git a/content/browser/webrtc/webrtc_constraints_browsertest.cc b/content/browser/webrtc/webrtc_constraints_browsertest.cc index 584d8f5..f06b045 100644 --- a/content/browser/webrtc/webrtc_constraints_browsertest.cc +++ b/content/browser/webrtc/webrtc_constraints_browsertest.cc
@@ -56,7 +56,7 @@ }; // Test fails under MSan, https://crbug.com/445745. -// Test is also flaky (on Mac, Linux, LaCrOS, Android, but mostly on Mac): +// Test is also flaky (on Mac, Linux, Android, but mostly on Mac): // https://crbug.com/1241538 // TODO(crbug.com/40835236): Fix and enable on Fuchsia. #if defined(MEMORY_SANITIZER) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_FUCHSIA)
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc index a83a32a..fac490b6 100644 --- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc +++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -501,9 +501,8 @@ } // This test calls getUserMedia and checks for aspect ratio behavior. -// TODO(crbug.com/40229233): Flaky for tsan, mac, lacros. -#if defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/40229233): Flaky for tsan, mac. +#if defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC) #define MAYBE_TestGetUserMediaAspectRatio4To3 \ DISABLED_TestGetUserMediaAspectRatio4To3 #else @@ -538,9 +537,8 @@ } // This test calls getUserMedia and checks for aspect ratio behavior. -// TODO(crbug.com/40229233): Flaky for tsan, mac, lacros. -#if defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC) || \ - BUILDFLAG(IS_CHROMEOS_LACROS) +// TODO(crbug.com/40229233): Flaky for tsan, mac. +#if defined(THREAD_SANITIZER) || BUILDFLAG(IS_MAC) #define MAYBE_TestGetUserMediaAspectRatio1To1 \ DISABLED_TestGetUserMediaAspectRatio1To1 #else @@ -589,8 +587,8 @@ // This test calls getUserMedia in an iframe and immediately close the iframe // in the scope of the failure callback. -// Flaky on lacros-chrome and mac bots. http://crbug.com/1196389 -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC) +// Flaky on mac bots. http://crbug.com/1196389 +#if BUILDFLAG(IS_MAC) #define MAYBE_VideoWithBadConstraintsInIFrameAndCloseInFailureCb \ DISABLED_VideoWithBadConstraintsInIFrameAndCloseInFailureCb #else
diff --git a/content/common/features.cc b/content/common/features.cc index 7e2e0a9a..93e57cd 100644 --- a/content/common/features.cc +++ b/content/common/features.cc
@@ -124,11 +124,6 @@ "CriticalClientHint", base::FEATURE_ENABLED_BY_DEFAULT); -// Enable changing source dynamically for desktop capture. -BASE_FEATURE(kDesktopCaptureChangeSource, - "DesktopCaptureChangeSource", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enables caching of media devices for the purpose of enumerating them. #if BUILDFLAG(IS_MAC) BASE_FEATURE(kDeviceMonitorMac,
diff --git a/content/common/features.h b/content/common/features.h index a6e4265..497d854 100644 --- a/content/common/features.h +++ b/content/common/features.h
@@ -28,7 +28,6 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kCommittedOriginEnforcements); CONTENT_EXPORT BASE_DECLARE_FEATURE(kCommittedOriginTracking); CONTENT_EXPORT BASE_DECLARE_FEATURE(kCriticalClientHint); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kDesktopCaptureChangeSource); #if BUILDFLAG(IS_MAC) CONTENT_EXPORT BASE_DECLARE_FEATURE(kDeviceMonitorMac); #endif
diff --git a/content/common/user_level_memory_pressure_signal_features.cc b/content/common/user_level_memory_pressure_signal_features.cc index a5140a5..32d5cb5 100644 --- a/content/common/user_level_memory_pressure_signal_features.cc +++ b/content/common/user_level_memory_pressure_signal_features.cc
@@ -37,14 +37,6 @@ BASE_FEATURE(kUserLevelMemoryPressureSignalOn3GbDevices, "UserLevelMemoryPressureSignalOn3GbDevices", base::FEATURE_DISABLED_BY_DEFAULT); -// (for Android 4GB devices) -BASE_FEATURE(kUserLevelMemoryPressureSignalOn4GbDevices, - "UserLevelMemoryPressureSignalOn4GbDevices", - base::FEATURE_ENABLED_BY_DEFAULT); -// (for Android 6GB devices) -BASE_FEATURE(kUserLevelMemoryPressureSignalOn6GbDevices, - "UserLevelMemoryPressureSignalOn6GbDevices", - base::FEATURE_ENABLED_BY_DEFAULT); bool IsUserLevelMemoryPressureSignalEnabledOn3GbDevices() { static bool s_enabled = @@ -57,16 +49,12 @@ // Because of Android carveouts, AmountOfPhysicalMemory() returns smaller // than the actual memory size, So we will use a small lowerbound than 4GB // to discriminate real 4GB devices from lower memory ones. - static bool s_enabled = - base::SysInfo::Is4GbDevice() && - base::FeatureList::IsEnabled(kUserLevelMemoryPressureSignalOn4GbDevices); + static bool s_enabled = base::SysInfo::Is4GbDevice(); return s_enabled; } bool IsUserLevelMemoryPressureSignalEnabledOn6GbDevices() { - static bool s_enabled = - base::SysInfo::Is6GbDevice() && - base::FeatureList::IsEnabled(kUserLevelMemoryPressureSignalOn6GbDevices); + static bool s_enabled = base::SysInfo::Is6GbDevice(); return s_enabled; } @@ -79,17 +67,11 @@ } base::TimeDelta MinUserMemoryPressureIntervalOn4GbDevices() { - static const base::FeatureParam<base::TimeDelta> kMinimumInterval{ - &kUserLevelMemoryPressureSignalOn4GbDevices, "minimum_interval", - kDefaultMinimumInterval}; - return kMinimumInterval.Get(); + return kDefaultMinimumInterval; } base::TimeDelta MinUserMemoryPressureIntervalOn6GbDevices() { - static const base::FeatureParam<base::TimeDelta> kMinimumInterval{ - &kUserLevelMemoryPressureSignalOn6GbDevices, "minimum_interval", - kDefaultMinimumInterval}; - return kMinimumInterval.Get(); + return kDefaultMinimumInterval; } base::TimeDelta InertIntervalFor3GbDevices() { @@ -100,17 +82,11 @@ } base::TimeDelta InertIntervalFor4GbDevices() { - static const base::FeatureParam<base::TimeDelta> kInertInterval{ - &features::kUserLevelMemoryPressureSignalOn4GbDevices, - "inert_interval_after_loading", kDefaultInertInterval}; - return kInertInterval.Get(); + return kDefaultInertInterval; } base::TimeDelta InertIntervalFor6GbDevices() { - static const base::FeatureParam<base::TimeDelta> kInertInterval{ - &features::kUserLevelMemoryPressureSignalOn6GbDevices, - "inert_interval_after_loading", kDefaultInertInterval}; - return kInertInterval.Get(); + return kDefaultInertInterval; } } // namespace content::features
diff --git a/content/common/user_level_memory_pressure_signal_features.h b/content/common/user_level_memory_pressure_signal_features.h index 3800445..80917388 100644 --- a/content/common/user_level_memory_pressure_signal_features.h +++ b/content/common/user_level_memory_pressure_signal_features.h
@@ -15,8 +15,6 @@ namespace content::features { CONTENT_EXPORT BASE_DECLARE_FEATURE(kUserLevelMemoryPressureSignalOn3GbDevices); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kUserLevelMemoryPressureSignalOn4GbDevices); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kUserLevelMemoryPressureSignalOn6GbDevices); // Helper functions for UserLevelMemoryPressureSignal features. CONTENT_EXPORT bool IsUserLevelMemoryPressureSignalEnabledOn3GbDevices();
diff --git a/content/common/web_ui_loading_util.cc b/content/common/web_ui_loading_util.cc index 03545788..e3dfc91d 100644 --- a/content/common/web_ui_loading_util.cc +++ b/content/common/web_ui_loading_util.cc
@@ -4,6 +4,8 @@ #include "content/common/web_ui_loading_util.h" +#include "base/check.h" +#include "base/debug/crash_logging.h" #include "base/types/expected.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" @@ -82,7 +84,11 @@ mojo::ScopedDataPipeConsumerHandle pipe_consumer_handle; MojoResult create_result = mojo::CreateDataPipe( &options, pipe_producer_handle, pipe_consumer_handle); - CHECK_EQ(create_result, MOJO_RESULT_OK); + if (create_result != MOJO_RESULT_OK) { + SCOPED_CRASH_KEY_NUMBER("WebUI", "mojo_CreateDataPipe_result", + create_result); + CHECK(false); + } base::span<uint8_t> buffer; MojoResult result = pipe_producer_handle->BeginWriteData(
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index 59ab3b7..87dc9008 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc
@@ -61,6 +61,7 @@ #include "mojo/public/cpp/bindings/interface_endpoint_client.h" #include "mojo/public/cpp/bindings/sync_call_restrictions.h" #include "services/tracing/public/cpp/trace_startup.h" +#include "services/tracing/public/cpp/trace_startup_config.h" #include "third_party/angle/src/gpu_info_util/SystemInfo.h" #include "ui/base/ui_base_features.h" #include "ui/events/platform/platform_event_source.h" @@ -72,6 +73,7 @@ #include "ui/gl/gl_switches.h" #include "ui/gl/gpu_switching_manager.h" #include "ui/gl/init/gl_factory.h" +#include "ui/gl/startup_trace.h" #if BUILDFLAG(IS_WIN) #include <windows.h> @@ -143,6 +145,7 @@ private: // SandboxHelper: void PreSandboxStartup(const gpu::GpuPreferences& gpu_prefs) override { + GPU_STARTUP_TRACE_EVENT("gpu_main::PreSandboxStartup"); // Warm up resources that don't need access to GPUInfo. { TRACE_EVENT0("gpu", "Warm up rand"); @@ -175,6 +178,7 @@ bool EnsureSandboxInitialized(gpu::GpuWatchdogThread* watchdog_thread, const gpu::GPUInfo* gpu_info, const gpu::GpuPreferences& gpu_prefs) override { + GPU_STARTUP_TRACE_EVENT("gpu_main::EnsureSandboxInitialized"); #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) return StartSandboxLinux(watchdog_thread, gpu_info, gpu_prefs); #elif BUILDFLAG(IS_WIN) @@ -193,6 +197,7 @@ void LoadMetalShaderCacheIfNecessary() { #if BUILDFLAG(IS_MAC) + GPU_STARTUP_TRACE_EVENT("gpu_main::LoadMetalShaderCacheIfNecessary"); if (base::FeatureList::IsEnabled(features::kUseBuiltInMetalShaderCache)) { gpu::BuiltInShaderCacheLoader::StartLoading(); } @@ -203,6 +208,10 @@ // Main function for starting the Gpu process. int GpuMain(MainFunctionParams parameters) { + if (tracing::TraceStartupConfig::GetInstance().IsEnabled()) { + gl::StartupTrace::Startup(); + } + TRACE_EVENT0("gpu", "GpuMain"); base::CurrentProcess::GetInstance().SetProcessType( base::CurrentProcessType::PROCESS_GPU); @@ -314,6 +323,7 @@ base::MessagePumpType::DEFAULT); #endif } + gl::StartupTrace::GetInstance()->BindToCurrentThread(); base::PlatformThread::SetName("CrGpuMain"); mojo::InterfaceEndpointClient::SetThreadNameSuffixForMetrics("GpuMain"); @@ -345,7 +355,10 @@ // Since GPU initialization calls into skia, it's important to initialize skia // before it. - InitializeSkia(); + { + GPU_STARTUP_TRACE_EVENT("gpu_main::InitializeSkia"); + InitializeSkia(); + } // The ThreadPool must have been created before invoking |gpu_init| as it // needs the ThreadPool (in angle::InitializePlatform()). Do not start it @@ -439,6 +452,9 @@ /*wall_time_based_metrics_enabled_for_testing=*/true); } + DCHECK(tracing::IsTracingInitialized()); + gl::StartupTrace::StarupDone(); + { TRACE_EVENT0("gpu", "Run Message Loop"); run_loop.Run(); @@ -454,6 +470,7 @@ const gpu::GPUInfo* gpu_info, const gpu::GpuPreferences& gpu_prefs) { TRACE_EVENT0("gpu,startup", "Initialize sandbox"); + GPU_STARTUP_TRACE_EVENT("Initialize sandbox"); if (watchdog_thread) { // SandboxLinux needs to be able to ensure that the thread @@ -517,6 +534,7 @@ #if BUILDFLAG(IS_WIN) bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) { TRACE_EVENT0("gpu,startup", "Lower token"); + GPU_STARTUP_TRACE_EVENT("Lower token"); // For Windows, if the target_services interface is not zero, the process // is sandboxed and we must call LowerToken() before rendering untrusted
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java index 9982721..41fd8fb 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java
@@ -116,6 +116,10 @@ public static final String ACCESSIBILITY_CREATE_ACCESSIBILITY_NODE_INFO_TOTAL_TIME = "Accessibility.Android.Performance.CreateAccessibilityNodeInfo.TotalTime"; + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public static final String ACCESSIBILITY_TIME_UNTIL_FIRST_ACCESSIBILITY_FOCUS = + "Accessibility.Android.Performance.TimeUntilFirstAccessibilityFocus"; + private static final int EVENTS_DROPPED_HISTOGRAM_MIN_BUCKET = 1; private static final int EVENTS_DROPPED_HISTOGRAM_MAX_BUCKET = 10000; private static final int EVENTS_DROPPED_HISTOGRAM_BUCKET_COUNT = 100; @@ -156,6 +160,12 @@ private long mCurrentNodeConstructionStartTime; private long mTotalTimeCreateAccessibilityNodeInfo; + // We track the time it takes to go from native initialization (first request of the Android + // framework for accessibility support), to the first time a node receives accessibility focus, + // which happens automatically for screenreaders. Performance improvements around jank should + // decrease this number. We only want to track this once per instance. + private boolean mHasRecordedTimeToFirstAccessibilityFocus; + /** Record that the Auto-disable Accessibility feature has disabled accessibility. */ public void onDisableCalled(boolean initialCall) { TraceEvent.begin("AccessibilityHistogramRecorder.onDisabledCalled"); @@ -435,4 +445,25 @@ DateUtils.MINUTE_IN_MILLIS, 80); } + + /** + * Record UMA histogram for the length of time from native initialization to first accessibility + * focus. + */ + public void recordTimeToFirstAccessibilityFocus() { + if (mHasRecordedTimeToFirstAccessibilityFocus) return; + + // We are only interested in this for TalkBack, which always focuses the root node on load. + if (!AccessibilityState.isTalkBackEnabled()) return; + + // TODO(mschillaci): This uses a 5 sec max, check scale after initial data collection. + RecordHistogram.recordCustomTimesHistogram( + ACCESSIBILITY_TIME_UNTIL_FIRST_ACCESSIBILITY_FOCUS, + SystemClock.elapsedRealtime() - mTimeOfNativeInitialization, + 1, + DateUtils.SECOND_IN_MILLIS * 5, + 80); + + mHasRecordedTimeToFirstAccessibilityFocus = true; + } }
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 e9d89be2..cb8de4b 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
@@ -1784,6 +1784,9 @@ // The container view is indicated by a virtualViewId of NO_ID; post these events directly // since there's no web-specific information to attach. if (virtualViewId == View.NO_ID) { + if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { + mHistogramRecorder.recordTimeToFirstAccessibilityFocus(); + } mView.sendAccessibilityEvent(eventType); return; } @@ -2056,6 +2059,9 @@ // accessibility is still enabled, throttling may result in events sent late. if (mView.getParent() != null && isAccessibilityEnabled()) { mHistogramRecorder.incrementDispatchedEvents(); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { + mHistogramRecorder.recordTimeToFirstAccessibilityFocus(); + } if (mTracker != null) mTracker.addEvent(event); try { mView.getParent().requestSendAccessibilityEvent(mView, event);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java index 3478c11..a9b1ea35 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java
@@ -32,6 +32,7 @@ import org.chromium.base.task.TaskTraits; 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.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UrlUtils; @@ -357,6 +358,7 @@ @MediumTest @Feature({"TextSelection"}) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P) /* getSecondaryAssistItems requires >= P */ + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testCorrectPasteMenuItemsAddedWhenThereIsNoSelection() throws Throwable { SelectionActionMenuDelegate selectionActionMenuDelegate = new TestSelectionActionMenuDelegate(); @@ -391,6 +393,7 @@ @Test @MediumTest @Feature({"TextSelection"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testCorrectSelectionMenuItemsAddedForInputSelection() throws Throwable { SelectionActionMenuDelegate selectionActionMenuDelegate = new TestSelectionActionMenuDelegate(); @@ -765,6 +768,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPlainTextCopy() throws Exception { DOMUtils.longPressNode(mWebContents, "plain_text_1"); waitForSelectActionBarVisible(true); @@ -777,6 +781,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarInputCopy() throws Exception { DOMUtils.longPressNode(mWebContents, "input_text"); waitForSelectActionBarVisible(true); @@ -789,6 +794,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPasswordCopy() throws Exception { DOMUtils.longPressNode(mWebContents, "plain_text_1"); waitForSelectActionBarVisible(true); @@ -809,6 +815,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarTextAreaCopy() throws Exception { DOMUtils.longPressNode(mWebContents, "textarea"); waitForSelectActionBarVisible(true); @@ -821,6 +828,7 @@ @Test @SmallTest @Feature({"TextSelection"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPlainTextCut() throws Throwable { copyStringToClipboard("SampleTextToCopy"); DOMUtils.longPressNode(mWebContents, "plain_text_1"); @@ -839,6 +847,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarInputCut() throws Exception { DOMUtils.longPressNode(mWebContents, "input_text"); waitForSelectActionBarVisible(true); @@ -855,6 +864,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPasswordCut() throws Throwable { copyStringToClipboard("SampleTextToCopy"); DOMUtils.longPressNode(mWebContents, "password"); @@ -872,6 +882,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarTextAreaCut() throws Exception { DOMUtils.longPressNode(mWebContents, "textarea"); waitForSelectActionBarVisible(true); @@ -902,6 +913,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarInputSelectAll() throws Exception { DOMUtils.longPressNode(mWebContents, "input_text"); waitForSelectActionBarVisible(true); @@ -916,6 +928,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPasswordSelectAll() throws Exception { DOMUtils.longPressNode(mWebContents, "password"); waitForSelectActionBarVisible(true); @@ -929,6 +942,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarTextAreaSelectAll() throws Exception { DOMUtils.longPressNode(mWebContents, "textarea"); waitForSelectActionBarVisible(true); @@ -975,6 +989,7 @@ @Test @SmallTest @Feature({"TextSelection"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPlainTextPaste() throws Throwable { copyStringToClipboard("SampleTextToCopy"); DOMUtils.longPressNode(mWebContents, "plain_text_1"); @@ -993,6 +1008,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarInputPaste() throws Throwable { copyStringToClipboard("SampleTextToCopy"); @@ -1017,6 +1033,7 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.R, message = "crbug.com/343808767") public void testSelectActionBarPasswordPaste() throws Throwable { copyStringToClipboard("SamplePassword2");
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 da65437..27f4682 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
@@ -53,6 +53,7 @@ import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.ACCESSIBILITY_CREATE_ACCESSIBILITY_NODE_INFO_TOTAL_TIME; import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.ACCESSIBILITY_INLINE_TEXT_BOXES_BUNDLE; import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.ACCESSIBILITY_INLINE_TEXT_BOXES_COUNT; +import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.ACCESSIBILITY_TIME_UNTIL_FIRST_ACCESSIBILITY_FOCUS; import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.AUTO_DISABLE_ACCESSIBILITY_DISABLED_TIME_INITIAL; import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.AUTO_DISABLE_ACCESSIBILITY_DISABLED_TIME_SUCCESSIVE; import static org.chromium.content.browser.accessibility.AccessibilityHistogramRecorder.AUTO_DISABLE_ACCESSIBILITY_DISABLE_METHOD_CALLED_INITIAL; @@ -83,12 +84,14 @@ import static org.chromium.content.browser.accessibility.AccessibilityNodeInfoBuilder.EXTRAS_KEY_UNCLIPPED_TOP; import static org.chromium.ui.accessibility.AccessibilityState.EVENT_TYPE_MASK_NONE; import static org.chromium.ui.accessibility.AccessibilityState.StateIdentifierForTesting.EVENT_TYPE_MASK; +import static org.chromium.ui.accessibility.AccessibilityState.TALKBACK_SERVICE_ID; import android.annotation.SuppressLint; import android.content.ClipData; import android.content.ClipboardManager; import android.graphics.Rect; import android.graphics.RectF; +import android.os.Build; import android.os.Bundle; import android.text.InputType; import android.text.Spannable; @@ -108,6 +111,7 @@ import org.chromium.base.ThreadUtils; 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.DisabledTest; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.Restriction; @@ -806,6 +810,42 @@ histogramWatcher.assertExpected(); } + /** + * Test that UMA histograms are recorded for the time it takes for a node to receive + * accessibility focus. + */ + @Test + @SmallTest + public void testUMAHistograms_timeToFirstAccessibilityFocus() throws Throwable { + setupTestWithHTML("<p>This is a test</p>"); + + int paragraphId = waitForNodeMatching(sTextMatcher, "This is a test"); + mNodeInfo = createAccessibilityNodeInfo(paragraphId); + Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo); + Assert.assertEquals(NODE_TIMEOUT_ERROR, "This is a test", mNodeInfo.getText()); + + // Set the relevant features and accessibility state. + ThreadUtils.runOnUiThreadBlocking( + () -> { + AccessibilityState.setIsScreenReaderEnabledForTesting(true); + AccessibilityState.setIsOnlyPasswordManagersEnabledForTesting(false); + AccessibilityState.setServiceIdsForTesting(TALKBACK_SERVICE_ID); + }); + + var histogramWatcher = + HistogramWatcher.newBuilder() + .expectAnyRecordTimes(ACCESSIBILITY_TIME_UNTIL_FIRST_ACCESSIBILITY_FOCUS, 1) + .build(); + + focusNode(paragraphId); + + // Send end of test signal. + mActivityTestRule.sendEndOfTestSignal(); + + // Assert that we recorded histograms and there was a count present. + histogramWatcher.assertExpected(); + } + /** Test that the {resetFocus} method performs as expected with accessibility enabled. */ @Test @SmallTest @@ -2100,6 +2140,11 @@ /** Test that the performAction for ACTION_CUT works properly with accessibility. */ @Test @SmallTest + @DisableIf.Build(sdk_equals = Build.VERSION_CODES.S, message = "crbug.com/40213937") + @DisableIf.Build(sdk_equals = Build.VERSION_CODES.S_V2, message = "crbug.com/40213937") + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/40213937") public void testPerformAction_cut() throws Throwable { // Build a simple web page with an input field. setupTestWithHTML("<input type='text' value='test text'>"); @@ -2156,6 +2201,11 @@ /** Test that the performAction for ACTION_COPY works properly with accessibility. */ @Test @SmallTest + @DisableIf.Build(sdk_equals = Build.VERSION_CODES.S, message = "crbug.com/40213937") + @DisableIf.Build(sdk_equals = Build.VERSION_CODES.S_V2, message = "crbug.com/40213937") + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/40213937") public void testPerformAction_copy() throws Throwable { // Build a simple web page with an input field. setupTestWithHTML("<input type='text' value='test text'>"); @@ -2212,6 +2262,7 @@ /** Test that the performAction for ACTION_PASTE works properly with accessibility. */ @Test @SmallTest + @DisabledTest(message = "crbug.com/40213937") public void testPerformAction_paste() throws Throwable { // Build a simple web page with an input field. setupTestWithHTML("<input type='text'>");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index 15b95087..9640e763 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -8,6 +8,7 @@ import android.content.ClipboardManager; import android.content.Context; import android.graphics.Color; +import android.os.Build; import android.os.SystemClock; import android.text.InputType; import android.text.SpannableString; @@ -37,6 +38,7 @@ import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.CriteriaNotSatisfiedException; +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.UrlUtils; @@ -408,6 +410,9 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/343821701") public void testImeCopy() throws Exception { mRule.commitText("hello", 1); mRule.waitAndVerifyUpdateSelection(0, 5, 5, -1, -1); @@ -616,6 +621,9 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/343821701") public void testKeyboardNotDismissedAfterCopySelection() throws Exception { mRule.commitText("Sample_Text", 1); mRule.waitAndVerifyUpdateSelection(0, 11, 11, -1, -1); @@ -823,6 +831,9 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/343821701") public void testImeCut() throws Exception { mRule.commitText("snarful", 1); mRule.waitAndVerifyUpdateSelection(0, 7, 7, -1, -1); @@ -839,6 +850,9 @@ @Test @SmallTest @Feature({"TextInput"}) + @DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/343821701") public void testImePaste() throws Exception { ThreadUtils.runOnUiThreadBlocking( () -> {
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/StylusGestureEndToEndTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/StylusGestureEndToEndTest.java index 8480aa3..1582e19 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/StylusGestureEndToEndTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/StylusGestureEndToEndTest.java
@@ -36,6 +36,7 @@ import org.chromium.base.ThreadUtils; 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.MinAndroidSdkLevel; import org.chromium.content.browser.RenderCoordinatesImpl; import org.chromium.content.browser.webcontents.WebContentsImpl; @@ -47,8 +48,8 @@ import java.util.concurrent.TimeoutException; /** - * Tests the entire flow of performing a stylus gesture on a website. Uses JavaScript to get an - * area of text, simulates a handwriting gesture object over that area and asserts that the correct + * Tests the entire flow of performing a stylus gesture on a website. Uses JavaScript to get an area + * of text, simulates a handwriting gesture object over that area and asserts that the correct * change has been made to the page. */ @RunWith(ContentJUnit4ClassRunner.class) @@ -56,6 +57,7 @@ @CommandLineFlags.Add({"enable-features=StylusRichGestures"}) @MinAndroidSdkLevel(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) +@DisabledTest(message = "crbug.com/343810189") public class StylusGestureEndToEndTest { @Rule public ImeActivityTestRule mRule = new ImeActivityTestRule();
diff --git a/content/public/browser/child_process_data.cc b/content/public/browser/child_process_data.cc index 12d091f..f63a6aa 100644 --- a/content/public/browser/child_process_data.cc +++ b/content/public/browser/child_process_data.cc
@@ -6,11 +6,21 @@ namespace content { -ChildProcessData::ChildProcessData(int process_type) - : process_type(process_type) {} +ChildProcessData::ChildProcessData(int process_type, ChildProcessId id) + : process_type(process_type), + // TODO(crbug.com/379869738): Remove once id references are deleted + id(id.GetUnsafeValue()), + child_process_id_(id) {} ChildProcessData::ChildProcessData(ChildProcessData&& rhs) = default; ChildProcessData::~ChildProcessData() {} +const ChildProcessId& ChildProcessData::GetChildProcessId() const { + // To reduce the number of changes necessary as APIs switch, + // id must be accessible to outside parties. + CHECK_EQ(child_process_id_, ChildProcessId(id)); + return child_process_id_; +} + } // namespace content
diff --git a/content/public/browser/child_process_data.h b/content/public/browser/child_process_data.h index 8bc6a21e..004230e 100644 --- a/content/public/browser/child_process_data.h +++ b/content/public/browser/child_process_data.h
@@ -10,6 +10,7 @@ #include "base/process/process.h" #include "content/common/content_export.h" +#include "content/public/browser/child_process_id.h" #include "sandbox/policy/mojom/sandbox.mojom.h" namespace content { @@ -27,25 +28,30 @@ // The non-localized name of the process used for metrics reporting. std::string metrics_name; - // The unique identifier for this child process. This identifier is NOT a - // process ID, and will be unique for all types of child process for - // one run of the browser. + // TODO(crbug.com/379869738): Deprecated, please use GetChildProcessId(). int id = 0; // The Sandbox that this process was launched at. May be invalid prior to // process launch. std::optional<sandbox::mojom::Sandbox> sandbox_type; + const ChildProcessId& GetChildProcessId() const; + const base::Process& GetProcess() const { return process_; } // Since base::Process is non-copyable, the caller has to provide a rvalue. void SetProcess(base::Process process) { process_ = std::move(process); } - explicit ChildProcessData(int process_type); + ChildProcessData(int process_type, ChildProcessId id); ~ChildProcessData(); ChildProcessData(ChildProcessData&& rhs); private: + // The unique identifier for this child process. This identifier is NOT a + // process ID, and will be unique for all types of child process for + // one run of the browser. + ChildProcessId child_process_id_; + // May be invalid if the process isn't started or is the current process. base::Process process_; };
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index f5df3f2..58bc7cf8 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -267,9 +267,14 @@ // If |ignore_workers| is false and this renderer has any workers, then this // function does nothing. Otherwise, the function will ignore checking for // worker references. + // If |ignore_keep_alive| is false and this renderer has any keep-alive ref + // counts, then this function does nothing. Otherwise, the function will + // ignore checking for keep-alive references. This can be removed once + // keep-alive migration has landed (see crbug.com/40236167). virtual bool FastShutdownIfPossible(size_t page_count = 0, bool skip_unload_handlers = false, - bool ignore_workers = false) = 0; + bool ignore_workers = false, + bool ignore_keep_alive = false) = 0; // Returns true if fast shutdown was started for the renderer. virtual bool FastShutdownStarted() = 0;
diff --git a/content/public/browser/spare_render_process_host_manager.h b/content/public/browser/spare_render_process_host_manager.h index c27d8dd4..fdd3872 100644 --- a/content/public/browser/spare_render_process_host_manager.h +++ b/content/public/browser/spare_render_process_host_manager.h
@@ -7,6 +7,7 @@ #include "base/observer_list_types.h" #include "content/common/content_export.h" +#include "content/public/browser/child_process_id.h" namespace content { @@ -48,7 +49,7 @@ // spare before the navigation. Using `GetSpares()` and comparing pointers // wouldn't work because there is always a chance that a RPH is destroyed and // a new one is created reusing the same address). - virtual std::vector<int> GetSpareIds() = 0; + virtual std::vector<ChildProcessId> GetSpareIds() = 0; // Possibly start an unbound, spare RenderProcessHost. A subsequent creation // of a RenderProcessHost with a matching browser_context may use this
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index 05bace8..bf22c96 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -272,6 +272,7 @@ # This looks needless as we have //content/common in public_deps, but it's # needed because of allow_circular_includes_from. "//content/common:mojo_bindings", + "//content/public/common:buildflags", "//device/vr/buildflags", "//media", "//media/mojo/mojom",
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 429d50b..62097e9 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -12,6 +12,7 @@ #include "build/build_config.h" #include "build/config/chromebox_for_meetings/buildflags.h" #include "content/common/buildflags.h" +#include "content/public/common/buildflags.h" #include "content/public/common/dips_utils.h" namespace features { @@ -1378,10 +1379,17 @@ "SelectionMenuItemModification", base::FEATURE_ENABLED_BY_DEFAULT); -// Screen Capture API support for Android +// Screen Capture API support for Android. +// This should not be enabled unless ENABLE_SCREEN_CAPTURE is on, otherwise +// it won't work. BASE_FEATURE(kUserMediaScreenCapturing, "UserMediaScreenCapturing", - base::FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(ENABLE_SCREEN_CAPTURE) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +); // Kill switch for the WebNFC feature. This feature can be enabled for all sites // using the kEnableExperimentalWebPlatformFeatures flag.
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 7e26ca1..2b3dcd3 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -242,7 +242,8 @@ bool MockRenderProcessHost::FastShutdownIfPossible(size_t page_count, bool skip_unload_handlers, - bool ignore_workers) { + bool ignore_workers, + bool ignore_keep_alive) { if (GetActiveViewCount() != page_count) return false; // We aren't actually going to do anything, but set |fast_shutdown_started_|
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index aa67241..8d278df 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -112,7 +112,8 @@ bool ShutdownRequested() override; bool FastShutdownIfPossible(size_t page_count, bool skip_unload_handlers, - bool ignore_workers) override; + bool ignore_workers, + bool ignore_keep_alive) override; bool FastShutdownStarted() override; const base::Process& GetProcess() override; bool IsReady() override;
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc index 7a8c83d..90ff6c20 100644 --- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl_unittest.cc
@@ -447,7 +447,7 @@ gpu_channel_host_, content::kGpuStreamIdDefault, task_environment_.GetMainThreadTaskRunner()); gpu_command_buffer_proxy_->Initialize( - gpu::kNullSurfaceHandle, nullptr, content::kGpuStreamPriorityDefault, + nullptr, content::kGpuStreamPriorityDefault, gpu::ContextCreationAttribs(), GURL()); ON_CALL(*mock_context_provider_, GetCommandBufferProxy()) .WillByDefault(Return(gpu_command_buffer_proxy_.get()));
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index c9b37ee..523a643 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -370,8 +370,7 @@ std::move(channel), kGpuStreamIdDefault, base::SingleThreadTaskRunner::GetCurrentDefault()); auto result = command_buffer_->Initialize( - gpu::kNullSurfaceHandle, share_buffer, kGpuStreamPriorityDefault, - attrib_helper, GURL()); + share_buffer, kGpuStreamPriorityDefault, attrib_helper, GURL()); if (result != gpu::ContextResult::kSuccess) return false;
diff --git a/device/fido/cable/noise.cc b/device/fido/cable/noise.cc index 2ed841e..f00837e 100644 --- a/device/fido/cable/noise.cc +++ b/device/fido/cable/noise.cc
@@ -106,8 +106,9 @@ chaining_key_.data(), chaining_key_.size(), /*info=*/nullptr, 0); DCHECK_EQ(chaining_key_.size(), 32u); memcpy(chaining_key_.data(), output, 32); - MixHash(base::span<const uint8_t>(&output[32], 32u)); - InitializeKey(base::span<const uint8_t, 32>(&output[64], 32u)); + const auto [hash, key] = base::span(output).subspan<32>().split_at<32>(); + MixHash(hash); + InitializeKey(key); } std::vector<uint8_t> Noise::EncryptAndHash( @@ -156,7 +157,7 @@ std::tuple<std::array<uint8_t, 32>, std::array<uint8_t, 32>> Noise::traffic_keys() const { - return HKDF2(chaining_key_, base::span<const uint8_t>()); + return HKDF2(chaining_key_, {}); } void Noise::InitializeKey(base::span<const uint8_t, 32> key) {
diff --git a/device/fido/cable/v2_handshake.cc b/device/fido/cable/v2_handshake.cc index d8e1c774..0ae0411 100644 --- a/device/fido/cable/v2_handshake.cc +++ b/device/fido/cable/v2_handshake.cc
@@ -57,12 +57,12 @@ // will ever reach. constexpr uint32_t kMaxSequence = (1 << 24) - 1; -bool ConstructNonce(uint32_t counter, base::span<uint8_t, 12u> out_nonce) { +bool ConstructNonce(uint32_t counter, base::span<uint8_t, 12> out_nonce) { if (counter > kMaxSequence) { return false; } - auto [zeros, counter_span] = out_nonce.split_at<12u - 4u>(); + auto [zeros, counter_span] = out_nonce.split_at<8>(); std::ranges::fill(zeros, uint8_t{0}); counter_span.copy_from(base::numerics::U32ToBigEndian(counter)); return true; @@ -425,12 +425,10 @@ std::string Encode(base::span<const uint8_t, kQRKeySize> qr_key, RequestType request_type) { cbor::Value::MapValue qr_contents; - qr_contents.emplace( - 0, SeedToCompressedPublicKey( - base::span<const uint8_t, device::cablev2::kQRSeedSize>( - qr_key.data(), device::cablev2::kQRSeedSize))); + qr_contents.emplace(0, SeedToCompressedPublicKey( + qr_key.first<device::cablev2::kQRSeedSize>())); - qr_contents.emplace(1, qr_key.subspan(device::cablev2::kQRSeedSize)); + qr_contents.emplace(1, qr_key.subspan<device::cablev2::kQRSeedSize>()); qr_contents.emplace( 2, static_cast<int64_t>(std::size(tunnelserver::kAssignedDomains))); @@ -466,7 +464,7 @@ static_cast<int>(sizeof(digits))); ret += digits; - in = in.subspan(kChunkSize); + in = in.subspan<kChunkSize>(); } if (in.size()) { @@ -625,7 +623,7 @@ bssl::UniquePtr<EC_KEY> IdentityKey(base::span<const uint8_t, 32> root_secret) { std::array<uint8_t, 32> seed; seed = device::cablev2::Derive<seed.size()>( - root_secret, /*nonce=*/base::span<uint8_t>(), + root_secret, /*nonce=*/{}, device::cablev2::DerivedValueType::kIdentityKeySeed); bssl::UniquePtr<EC_GROUP> p256( EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); @@ -704,7 +702,7 @@ // TODO(agl): remove support for this padding format. (Chromium started sending // the new format with M99.) std::optional<cbor::Value> DecodePaddedCBORMap8( - const base::span<const uint8_t> input) { + base::span<const uint8_t> input) { if (input.empty()) { return std::nullopt; } @@ -811,9 +809,7 @@ aes_key.Init(write_key_); DCHECK_EQ(nonce.size(), aes_key.NonceLength()); - base::span<const uint8_t> additional_data; - std::vector<uint8_t> ciphertext = - aes_key.Seal(padded_message, nonce, additional_data); + std::vector<uint8_t> ciphertext = aes_key.Seal(padded_message, nonce, {}); message_to_encrypt->swap(ciphertext); return true; } @@ -829,14 +825,13 @@ aes_key.Init(read_key_); DCHECK_EQ(nonce.size(), aes_key.NonceLength()); - base::span<const uint8_t> additional_data; std::optional<std::vector<uint8_t>> plaintext = - aes_key.Open(ciphertext, nonce, additional_data); + aes_key.Open(ciphertext, nonce, {}); if (!plaintext) { return false; } - read_sequence_num_++; + ++read_sequence_num_; if (plaintext->empty()) { FIDO_LOG(ERROR) << "Invalid caBLE message."; @@ -924,8 +919,7 @@ noise_.MixKey(es_key); } - std::vector<uint8_t> ciphertext = - noise_.EncryptAndHash(base::span<const uint8_t>()); + std::vector<uint8_t> ciphertext = noise_.EncryptAndHash({}); std::vector<uint8_t> handshake_message; handshake_message.reserve(sizeof(ephemeral_key_public_bytes) + @@ -946,8 +940,7 @@ << " bytes)"; return std::nullopt; } - auto peer_point_bytes = response.first(kP256X962Length); - auto ciphertext = response.subspan(kP256X962Length); + auto [peer_point_bytes, ciphertext] = response.split_at<kP256X962Length>(); bssl::UniquePtr<EC_POINT> peer_point( EC_POINT_new(EC_KEY_get0_group(ephemeral_key_.get()))); @@ -1000,8 +993,7 @@ FIDO_LOG(DEBUG) << "Handshake truncated (" << in.size() << " bytes)"; return std::nullopt; } - auto peer_point_bytes = in.first(kP256X962Length); - auto ciphertext = in.subspan(kP256X962Length); + auto [peer_point_bytes, ciphertext] = in.split_at<kP256X962Length>(); Noise noise; uint8_t prologue[1]; @@ -1087,8 +1079,7 @@ noise.MixKey(shared_key_se); } - const std::vector<uint8_t> my_ciphertext = - noise.EncryptAndHash(base::span<const uint8_t>()); + const std::vector<uint8_t> my_ciphertext = noise.EncryptAndHash({}); out_response->insert( out_response->end(), ephemeral_key_public_bytes, ephemeral_key_public_bytes + sizeof(ephemeral_key_public_bytes));
diff --git a/device/fido/cable/v2_test_util.cc b/device/fido/cable/v2_test_util.cc index 7796157..5e9be6c3 100644 --- a/device/fido/cable/v2_test_util.cc +++ b/device/fido/cable/v2_test_util.cc
@@ -142,13 +142,13 @@ const std::vector<uint8_t>& pairing_id_vec = map.find(cbor::Value(1))->second.GetBytestring(); - base::span<const uint8_t, kPairingIDSize> pairing_id( - pairing_id_vec.data(), pairing_id_vec.size()); + auto pairing_id = + *base::span(pairing_id_vec).to_fixed_extent<kPairingIDSize>(); const std::vector<uint8_t>& client_nonce_vec = map.find(cbor::Value(2))->second.GetBytestring(); - base::span<const uint8_t, kClientNonceSize> client_nonce( - client_nonce_vec.data(), client_nonce_vec.size()); + auto client_nonce = + *base::span(client_nonce_vec).to_fixed_extent<kClientNonceSize>(); const std::string& request_type_hint = map.find(cbor::Value(3))->second.GetString(); @@ -516,15 +516,15 @@ if (!result || result->empty()) { std::move(callback).Run( static_cast<uint32_t>(device::CtapDeviceResponseCode::kCtap2ErrOther), - base::span<const uint8_t>(), /* prf_enabled= */ false); + {}, /* prf_enabled= */ false); return; } - const base::span<const uint8_t> payload = *result; + const base::span payload = *result; if (payload.size() == 1 || payload[0] != static_cast<uint8_t>(device::CtapDeviceResponseCode::kSuccess)) { - std::move(callback).Run(payload[0], base::span<const uint8_t>(), + std::move(callback).Run(payload[0], {}, /* prf_enabled= */ false); return; } @@ -568,7 +568,7 @@ nullptr); return; } - const base::span<const uint8_t> payload = *result; + const base::span payload = *result; if (payload.size() == 1 || payload[0] != @@ -652,11 +652,11 @@ network_context_factory_(std::move(network_context_factory)), tunnel_id_(device::cablev2::Derive<kTunnelIdSize>( qr_secret, - base::span<uint8_t>(), + {}, DerivedValueType::kTunnelID)), eid_key_(device::cablev2::Derive<kEIDKeySize>( qr_secret, - base::span<const uint8_t>(), + {}, device::cablev2::DerivedValueType::kEIDKey)), peer_identity_(device::fido_parsing_utils::Materialize(peer_identity)), secret_(fido_parsing_utils::Materialize(qr_secret)) { @@ -873,11 +873,11 @@ network_context_factory_(std::move(network_context_factory)), tunnel_id_(device::cablev2::Derive<kTunnelIdSize>( qr_secret, - base::span<uint8_t>(), + {}, DerivedValueType::kTunnelID)), eid_key_(device::cablev2::Derive<kEIDKeySize>( qr_secret, - base::span<const uint8_t>(), + {}, device::cablev2::DerivedValueType::kEIDKey)), secret_(fido_parsing_utils::Materialize(qr_secret)) { websocket_client_ = std::make_unique<device::cablev2::WebSocketAdapter>(
diff --git a/device/fido/ctap_get_assertion_request.cc b/device/fido/ctap_get_assertion_request.cc index c995dc0..b645181 100644 --- a/device/fido/ctap_get_assertion_request.cc +++ b/device/fido/ctap_get_assertion_request.cc
@@ -93,9 +93,9 @@ kClientDataHashLength) { return std::nullopt; } - base::span<const uint8_t, kClientDataHashLength> client_data_hash( - client_data_hash_it->second.GetBytestring().data(), - kClientDataHashLength); + auto client_data_hash = + base::span(client_data_hash_it->second.GetBytestring()) + .first<kClientDataHashLength>(); CtapGetAssertionRequest request(rp_id_it->second.GetString(), /*client_data_json=*/std::string());
diff --git a/device/fido/ctap_make_credential_request.cc b/device/fido/ctap_make_credential_request.cc index 32a95c9..ef46a2f 100644 --- a/device/fido/ctap_make_credential_request.cc +++ b/device/fido/ctap_make_credential_request.cc
@@ -58,9 +58,9 @@ kClientDataHashLength) { return std::nullopt; } - base::span<const uint8_t, kClientDataHashLength> client_data_hash( - client_data_hash_it->second.GetBytestring().data(), - kClientDataHashLength); + auto client_data_hash = + base::span(client_data_hash_it->second.GetBytestring()) + .first<kClientDataHashLength>(); const auto rp_entity_it = request_map.find(cbor::Value(2)); if (rp_entity_it == request_map.end() || !rp_entity_it->second.is_map())
diff --git a/device/gamepad/public/cpp/gamepad.h b/device/gamepad/public/cpp/gamepad.h index 009adff..d28fff1 100644 --- a/device/gamepad/public/cpp/gamepad.h +++ b/device/gamepad/public/cpp/gamepad.h
@@ -11,6 +11,7 @@ #include <cstdint> #include <limits> #include <string> +#include <type_traits> #include "base/component_export.h"
diff --git a/docs/adding_to_third_party.md b/docs/adding_to_third_party.md index 601fbed..0988820 100644 --- a/docs/adding_to_third_party.md +++ b/docs/adding_to_third_party.md
@@ -78,25 +78,15 @@ ### Rust -Rust is allowed for third-party libraries as long as there is a business need, -which includes the following: +Rust is allowed for third party libraries. Unlike C++ libraries, Rust third +party libraries are [regularly rolled to updated versions by a +rotation](https://chromium.googlesource.com/chromium/src/tools/+/HEAD/crates/create_update_cl.md) +and can be audited for unsafety. The process for adding a Googler adding new Rust third-party +dependencies is documented at go/chrome-rust. External contributors adding a new +third party Rust dependency will be shepherded through the process as part of +their ATL review. -* The Rust implementation is the best (e.g., speed, memory, lack of bugs) or -only existing implementation available for the third-party library. -* The Rust implementation allows the operation to move to a higher privileged -process, and this benefits the product by improving on guardrail metrics (e.g. -through avoiding process startup, IPC overheads, or C++ memory-unsafety -mitigations). -* The Rust implementation can meaningfully reduce our expected risk of -(memory/crashes/undefined behavior) bugs, when compared to the existing -third-party library and related C++ code required to use the library. We realize -assessing risk is quite complex and very nuanced. If this is the criteria by -which the third-party library is being added, chrome-atls-discuss@google.com and -chrome-rust@google.com may ask for more data. - -Support for third-party libraries written in Rust is in active development. If -the library you wish to add is in Rust, reach out to chrome-rust@google.com -first. +Email rust-dev@chromium.org with any questions about the Rust toolchain. ### A note on size constraints
diff --git a/docs/cr_user_manual.md b/docs/cr_user_manual.md index c03e6f6..0141bba 100644 --- a/docs/cr_user_manual.md +++ b/docs/cr_user_manual.md
@@ -149,7 +149,7 @@ select. This enables you to omit it from most commands. Both init and select do additional work to prepare the output directory, which -include things like running gyp. You can do that work on it's own with the +include things like running gyp. You can do that work on its own with the prepare command if you want, something you need to do when changing between branches where you have modified the build files.
diff --git a/docs/rust.md b/docs/rust.md index f917fced..cf10de5 100644 --- a/docs/rust.md +++ b/docs/rust.md
@@ -19,8 +19,11 @@ environments that are supported by the Chromium project. The first milestone to include full production-ready support was M119. -Rust is approved by Chrome ATLs for production use in -[certain third-party scenarios](../docs/adding_to_third_party.md#Rust). +Rust can be used anywhere in the Chromium repository (not just `//third_party`) +subject to [current interop capabilities][interop-rust-doc], however it is +currently subject to a internal approval and FYI process. Googlers can view +go/chrome-rust for details. New usages of Rust are documented at +[`rust-fyi@chromium.org`](https://groups.google.com/a/chromium.org/g/rust-fyi). For questions or help, reach out to `rust-dev@chromium.org` or `#rust` on the [Chromium Slack](https://www.chromium.org/developers/slack/). @@ -334,3 +337,5 @@ [dependencies] log = "0.4" ``` + +[interop-rust-doc]: https://docs.google.com/document/d/1kvgaVMB_isELyDQ4nbMJYWrqrmL3UZI4tDxnyxy9RTE/edit?tab=t.0#heading=h.fpqr6hf3c3j0
diff --git a/docs/unsafe_buffers.md b/docs/unsafe_buffers.md index ed3cabf..df35ca54 100644 --- a/docs/unsafe_buffers.md +++ b/docs/unsafe_buffers.md
@@ -171,26 +171,30 @@ Instead, keep the byte array as a `base::span<uint8_t>`, and write to it directly by chunking it up into pieces of the size you want to write. -Using `first()`: +Using `take_first()` (good for repeated modifications and loops): ```cc void write_floats(base::span<uint8_t> out, float f1, float f2) { - out.first<4>().copy_from(base::byte_span_from_ref(f1)); - out = out.subspan(4u); // Advance the span past what we wrote. - out.first<4>().copy_from(base::byte_span_from_ref(f2)); + // Write `f1` into `out`'s prefix, moving `out` forward. + out.take_first<4>().copy_from(base::byte_span_from_ref(f1)); + // Write `f2` into `out`'s new prefix (after `f1`). + out.copy_prefix_from(base::byte_span_from_ref(f2)); } ``` -Using `split_at()`: +Using `split_at()` (good when there are exactly two pieces): ```cc void write_floats(base::span<uint8_t> out, float f1, float f2) { + // Split `out` into a prefix to write `f1` into, and a remainder. auto [write_f1, rem] = out.split_at<4>(); - auto [write_f2, rem2] = rem.split_at<4>(); + // Write `f1` into the prefix portion, `write_f1`. write_f1.copy_from(base::byte_span_from_ref(f1)); - write_f2.copy_from(base::byte_span_from_ref(f2)); + // Write `f2` into the beginning of the remainder. + rem.copy_prefix_from(base::byte_span_from_ref(f2)); } ``` -Using `SpanWriter` and endian-aware `FloatToLittleEndian()`: +Using `SpanWriter` and endian-aware `FloatToLittleEndian()` (good when non-fatal +APIs are desired): ```cc void write_floats(base::span<uint8_t> out, float f1, float f2) { auto writer = base::SpanWriter(out); @@ -216,9 +220,9 @@ ```cc void write_floats(base::span<uint8_t> out, std::vector<const float> floats) { base::span<const uint8_t> byte_floats = base::as_byte_span(floats); - // Or skip the first() if you want to CHECK at runtime that all of `out` has + // Or use copy_from() if you want to CHECK at runtime that all of `out` has // been written to. - out.first(byte_floats.size()).copy_from(byte_floats); + out.copy_prefix_from(byte_floats); } ``` @@ -228,11 +232,11 @@ which can cause Undefined Behaviour, read values out of the byte span and convert each one as a value (not as a pointer). -Using `subspan()` and endian-aware conversion `FloatFromLittleEndian`: +Using `take_first()` and endian-aware conversion `FloatFromLittleEndian`: ```cc void read_floats(base::span<const uint8_t> in, float& f1, float& f2) { - f1 = base::FloatFromLittleEndian(in.subspan<0, 4>()); - f2 = base::FloatFromLittleEndian(in.subspan<4, 4>()); + f1 = base::FloatFromLittleEndian(in.take_first<4>()); + f2 = base::FloatFromLittleEndian(in.take_first<4>()); } ``` @@ -275,19 +279,14 @@ uint8_t array1[12]; uint8_t array2[16]; uint64_t array3[2]; -base::span(array1).first(4u).copy_from(base::span(array2).subspan(8u, 4u)); -base::span(array1).subspan(4u).copy_from(base::as_byte_span(array3).first(8u)); +base::span<uint8_t> span1(array1); +span1.take_first<4>().copy_from(base::span(array2).subspan<8, 4>()); +span1.copy_from(base::as_byte_span(array3).first<8>()); // Use `split_at()` to ensure `array1` is fully written. -auto [from2, from3] = base::span(array1).split_at(4u); -from2.copy_from(base::span(array2).subspan(8u, 4u)); -from3.copy_from(base::as_byte_span(array3).first(8u)); - -// This can even be ensured at compile time (if sizes and offsets are all -// constants). -auto [from2, from3] = base::span(array1).split_at<4u>(); -from2.copy_from(base::span(array2).subspan<8u, 4u>()); -from3.copy_from(base::as_byte_span(array3).first<8u>()); +auto [from2, from3] = base::span(array1).split_at<4>(); +from2.copy_from(base::span(array2).subspan<8, 4>()); +from3.copy_from(base::as_byte_span(array3).first<8>()); ``` ### Zeroing arrays (`memset`) @@ -313,9 +312,9 @@ uint8_t array1[12]; uint64_t array2[2]; Object array3[4]; -std::ranges::fill(array1, 0u); -std::ranges::fill(array2, 0u); -std::ranges::fill(base::as_writable_byte_span(array3), 0u); +std::ranges::fill(array1, 0); +std::ranges::fill(array2, 0); +std::ranges::fill(base::as_writable_byte_span(array3), 0); ``` ### Comparing arrays (`memcmp`)
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md index d86605102..b5017f0 100644 --- a/docs/webui_explainer.md +++ b/docs/webui_explainer.md
@@ -1258,22 +1258,24 @@ StoragePartition, a separate frame tree, and restricts postMessage communication by default. Note that `<webview>` is only available on desktop platforms. -## JavaScript Error Reporting +## Error Reporting -By default, errors in the JavaScript or TypeScript of a WebUI page will generate -error reports which appear in Google's internal [go/crash](http://go/crash) -reports page. These error reports will only be generated for Google Chrome -builds, not Chromium or other Chromium-based browsers. +By default, DevTools error messages in a WebUI page will generate error reports +and will appear in Google's internal [go/crash](http://go/crash) reports page. +These error reports will only be generated for Google Chrome builds, not +Chromium or other Chromium-based browsers. -Specifically, an error report will be generated when the JavaScript or -TypeScript for a WebUI-based chrome:// page does one of the following: +Specifically, an error report will be generated when a WebUI-based chrome:// +page does one of the following: * Generates an uncaught exception, * Has a promise which is rejected, and no rejection handler is provided, or * Calls `console.error()`. +* Generates any other [error level](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/devtools/console_message.mojom;l=11;drc=047c7dc4ee1ce908d7fea38ca063fa2f80f92c77) +DevTools message, e.g. bad websocket. -Such errors will appear alongside other crashes in the -`product_name=Chrome_ChromeOS` or `product_name=Chrome_Linux` lists on -[go/crash](http://go/crash). +Such errors will appear alongside other crashes on [go/crash](http://go/crash) +with a product data type of [JavascriptError](https://crash.corp.google.com/browse?q=product_name%3D%27Chrome_Mac%27+AND+EXISTS+%28SELECT+1+FROM+UNNEST%28productdata%29+WHERE+key%3D%27type%27+AND+value%3D%27JavascriptError%27%29&stbtiq=&reportid=&index=0). +They will also appear locally on the chrome://crashes page. The signature of the error is the error message followed by the URL on which the error appeared. For example, if chrome://settings/lazy_load.js throws a @@ -1318,8 +1320,10 @@ computing stability metrics. ### Known issues -1. Error reporting is currently enabled only on ChromeOS and Linux. -2. Errors are only reported for chrome:// URLs. +1. Android does not support error reporting. +2. Errors are only reported for chrome:// URLs, except for pages that don't +create a WebUI object (chrome://dino and chrome://network-error). Other schemes, +e.g. chrome-untrusted:// and chrome-extension:// are not supported either. 3. Unhandled promise rejections do not have a good stack. 4. The line numbers and column numbers in the stacks are for the minified JavaScript and do not correspond to the line and column numbers of the
diff --git a/extensions/browser/api/declarative_net_request/BUILD.gn b/extensions/browser/api/declarative_net_request/BUILD.gn index 786e080..68713f7 100644 --- a/extensions/browser/api/declarative_net_request/BUILD.gn +++ b/extensions/browser/api/declarative_net_request/BUILD.gn
@@ -16,13 +16,12 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ "//base", "//content/public/browser", + "//extensions/browser:browser_sources", "//extensions/common", "//extensions/common/api", - "//services/preferences/public/cpp", + "//net", ] - - public_deps = [ "//extensions/browser:browser_sources" ] }
diff --git a/extensions/browser/api/diagnostics/BUILD.gn b/extensions/browser/api/diagnostics/BUILD.gn index 256de2b7..30a3a66 100644 --- a/extensions/browser/api/diagnostics/BUILD.gn +++ b/extensions/browser/api/diagnostics/BUILD.gn
@@ -18,12 +18,13 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ - "//chromeos/ash/components/dbus", - "//chromeos/ash/components/dbus/debug_daemon", - "//extensions/common", + public_deps = [ + "//extensions/browser:browser_sources", "//extensions/common/api", ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ + "//base", + "//chromeos/ash/components/dbus/debug_daemon", + ] }
diff --git a/extensions/browser/api/dns/BUILD.gn b/extensions/browser/api/dns/BUILD.gn index a80cf17f..29e30cc 100644 --- a/extensions/browser/api/dns/BUILD.gn +++ b/extensions/browser/api/dns/BUILD.gn
@@ -15,11 +15,18 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ - "//content/public/browser", - "//extensions/common", - "//extensions/common/api", + public_deps = [ + "//extensions/browser:browser_sources", + "//mojo/public/cpp/bindings", + "//net", + "//services/network/public/cpp", + "//services/network/public/mojom", ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ + "//base", + "//content/public/browser", + "//extensions/common/api", + "//url", + ] }
diff --git a/extensions/browser/api/feedback_private/BUILD.gn b/extensions/browser/api/feedback_private/BUILD.gn index b62ea15..3d059d0 100644 --- a/extensions/browser/api/feedback_private/BUILD.gn +++ b/extensions/browser/api/feedback_private/BUILD.gn
@@ -19,23 +19,33 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ "//base", "//build:chromeos_buildflags", "//components/feedback", - "//components/feedback/content", - "//components/feedback/redaction_tool", - "//components/variations/net", - "//content/public/browser", "//extensions/browser:browser_sources", - "//extensions/common", "//extensions/common/api", - "//google_apis", - "//net", "//services/data_decoder/public/cpp", + "//ui/gfx/geometry", ] - if (is_chromeos) { + deps = [ + "//components/account_id", + "//components/feedback/content", + "//components/variations/net", + "//content/public/browser", + "//extensions/browser/api/feedback_private/proto", + "//extensions/common", + "//google_apis", + "//net", + "//services/network/public/cpp", + "//services/network/public/mojom:url_loader_base", + "//third_party/boringssl", + ] + + if (!is_chromeos) { + deps += [ "//components/feedback/redaction_tool" ] + } else { sources += [ "access_rate_limiter.cc", "access_rate_limiter.h", @@ -45,17 +55,16 @@ "log_source_resource.h", ] + public_deps += [ + "//chromeos/ash/components/dbus/debug_daemon", + "//components/feedback/redaction_tool", + ] + deps += [ "//ash/public/cpp", "//chromeos/ash/components/cryptohome", "//chromeos/ash/components/dbus/cryptohome:cryptohome_proto", - "//chromeos/ash/components/dbus/debug_daemon", "//chromeos/ash/services/assistant/public/cpp", - "//chromeos/ash/services/assistant/public/mojom", - "//components/account_id", - "//components/user_manager", - "//extensions/browser/api/feedback_private/proto", - "//third_party/boringssl", ] } }
diff --git a/extensions/browser/api/file_handlers/BUILD.gn b/extensions/browser/api/file_handlers/BUILD.gn index 31f8c63..733b7f5 100644 --- a/extensions/browser/api/file_handlers/BUILD.gn +++ b/extensions/browser/api/file_handlers/BUILD.gn
@@ -24,17 +24,19 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ - "//base:base", - "//build:chromeos_buildflags", - "//components/file_access", - "//content/public/browser", - "//content/public/common", + public_deps = [ + "//base", "//extensions/common", - "//extensions/common/api", - "//net", - "//storage/browser", ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ + "//build:chromeos_buildflags", + "//components/file_access", + "//components/services/app_service", + "//content/public/browser", + "//extensions/browser:browser_sources", + "//net", + "//storage/browser", + "//storage/common", + ] }
diff --git a/extensions/browser/api/file_system/BUILD.gn b/extensions/browser/api/file_system/BUILD.gn index fec41894..8868cc7 100644 --- a/extensions/browser/api/file_system/BUILD.gn +++ b/extensions/browser/api/file_system/BUILD.gn
@@ -20,20 +20,25 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ "//base", "//build:chromeos_buildflags", - "//components/filename_generation", - "//content/public/browser", - "//extensions/browser/api/file_handlers", + "//extensions/browser:browser_sources", "//extensions/common", "//extensions/common/api", - "//net", - "//storage/browser", - "//storage/common", - "//ui/base", "//ui/shell_dialogs", ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ + "//base:i18n", + "//components/filename_generation", + "//content/public/browser", + "//extensions/browser/api/file_handlers", + "//net", + "//storage/browser", + "//storage/common", + "//third_party/blink/public/common", + "//ui/base", + "//url", + ] }
diff --git a/extensions/browser/api/i18n/BUILD.gn b/extensions/browser/api/i18n/BUILD.gn index 5c255ab..220870f 100644 --- a/extensions/browser/api/i18n/BUILD.gn +++ b/extensions/browser/api/i18n/BUILD.gn
@@ -15,12 +15,12 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] + public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ "//base", - "//components/language/core/browser:browser", + "//components/language/core/browser", "//components/prefs", "//extensions/common/api", ] - - public_deps = [ "//extensions/browser:browser_sources" ] }
diff --git a/extensions/browser/api/idle/BUILD.gn b/extensions/browser/api/idle/BUILD.gn index caf1fc8..d30a678 100644 --- a/extensions/browser/api/idle/BUILD.gn +++ b/extensions/browser/api/idle/BUILD.gn
@@ -22,18 +22,22 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] + public_deps = [ + "//base", + "//components/keyed_service/content", + "//components/keyed_service/core", + "//extensions/browser:browser_sources", + "//extensions/common", + "//ui/base/idle", + ] + deps = [ "//build:chromeos_buildflags", - "//components/keyed_service/content", "//content/public/browser", - "//extensions/common", "//extensions/common/api", - "//ui/base/idle", ] if (is_chromeos) { deps += [ "//chromeos/dbus/power" ] } - - public_deps = [ "//extensions/browser:browser_sources" ] }
diff --git a/extensions/browser/api/management/BUILD.gn b/extensions/browser/api/management/BUILD.gn index 9c4c40a..b8feb24 100644 --- a/extensions/browser/api/management/BUILD.gn +++ b/extensions/browser/api/management/BUILD.gn
@@ -18,17 +18,22 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] + public_deps = [ + "//base", + "//components/keyed_service/core", + "//extensions/browser:browser_sources", + "//extensions/common", + "//extensions/common:common_constants", + "//extensions/common/api", + "//services/data_decoder/public/cpp", + "//url", + ] + deps = [ "//build:chromeos_buildflags", "//components/supervised_user/core/common:buildflags", - "//components/supervised_user/core/common:common", + "//components/supervised_user/core/common:features", "//content/public/browser", - "//extensions/common", - "//extensions/common/api", - ] - - public_deps = [ - "//extensions/browser:browser_sources", - "//services/data_decoder/public/cpp", + "//extensions/common:mojom", ] }
diff --git a/extensions/browser/api/media_perception_private/BUILD.gn b/extensions/browser/api/media_perception_private/BUILD.gn index 6294d47..0933c8b 100644 --- a/extensions/browser/api/media_perception_private/BUILD.gn +++ b/extensions/browser/api/media_perception_private/BUILD.gn
@@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/common/features.gni") import("//extensions/buildflags/buildflags.gni") assert(enable_extensions, "Cannot depend on extensions because enable_extensions=false.") +assert(is_chromeos) source_set("media_perception_private") { sources = [ @@ -20,16 +22,21 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ "//base", - "//chromeos/ash/components/dbus", "//chromeos/ash/components/dbus/media_analytics", "//chromeos/ash/components/dbus/media_analytics:media_perception_proto", - "//chromeos/ash/components/dbus/upstart", "//chromeos/services/media_perception/public/mojom", - "//chromeos/services/media_perception/public/mojom:mojom_js_data_deps", "//extensions/browser:browser_sources", - "//extensions/common", "//extensions/common/api", + "//mojo/public/cpp/bindings", + "//services/video_capture/public/mojom", + ] + + deps = [ + "//chromeos/ash/components/dbus", + "//chromeos/ash/components/dbus/upstart", + "//mojo/public/cpp/platform", + "//mojo/public/cpp/system", ] }
diff --git a/extensions/browser/api/messaging/BUILD.gn b/extensions/browser/api/messaging/BUILD.gn index 3f8d0df8..d1e65f2 100644 --- a/extensions/browser/api/messaging/BUILD.gn +++ b/extensions/browser/api/messaging/BUILD.gn
@@ -24,20 +24,24 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ ":native_messaging", "//base", - "//components/back_forward_cache", - "//components/crx_file:crx_file", - "//components/keyed_service/content:content", "//content/public/browser", - "//content/public/common", - "//extensions/buildflags", + "//extensions/browser:browser_sources", "//extensions/common", - "//extensions/common/api", + "//extensions/common:mojom", + "//mojo/public/cpp/bindings", + "//url", ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ + "//components/back_forward_cache", + "//content/public/common", + "//extensions/common:common_constants", + "//extensions/common:mojom_shared", + "//extensions/common:mojom_shared_cpp_sources", + ] } # Split up from messaging to avoid circular dependency. @@ -50,7 +54,7 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ "//base", "//ui/gfx:native_widget_types", ]
diff --git a/extensions/browser/api/metrics_private/BUILD.gn b/extensions/browser/api/metrics_private/BUILD.gn index f626dc7..7d56b0c 100644 --- a/extensions/browser/api/metrics_private/BUILD.gn +++ b/extensions/browser/api/metrics_private/BUILD.gn
@@ -16,11 +16,13 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] + public_deps = [ + "//base", + "//extensions/browser:browser_sources", + ] + deps = [ - "//components/variations", "//content/public/browser", "//extensions/common/api", ] - - public_deps = [ "//extensions/browser:browser_sources" ] }
diff --git a/extensions/browser/api/mime_handler_private/BUILD.gn b/extensions/browser/api/mime_handler_private/BUILD.gn index 34348d4..332cc16 100644 --- a/extensions/browser/api/mime_handler_private/BUILD.gn +++ b/extensions/browser/api/mime_handler_private/BUILD.gn
@@ -15,11 +15,15 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ - "//content/public/browser", - "//extensions/common:common_constants", - "//extensions/common/api", + public_deps = [ + "//base", + "//extensions/common/api:mojom", ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps = [ + "//base", + "//extensions/browser:browser_sources", + "//extensions/common:common_constants", + "//net", + ] }
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 3e199aed..d3618efc 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -593,9 +593,6 @@ browser_context_) && base::FeatureList::IsEnabled( safe_browsing::kExtensionTelemetryReportContactedHosts) && - base::FeatureList::IsEnabled( - safe_browsing:: - kExtensionTelemetryReportHostsContactedViaWebSocket) && !base::FeatureList::IsEnabled( safe_browsing:: kExtensionTelemetryInterceptRemoteHostsContactedInRenderer);
diff --git a/extensions/common/stack_frame.h b/extensions/common/stack_frame.h index dd7d7783..c1a22447 100644 --- a/extensions/common/stack_frame.h +++ b/extensions/common/stack_frame.h
@@ -6,6 +6,7 @@ #define EXTENSIONS_COMMON_STACK_FRAME_H_ #include <stddef.h> +#include <stdint.h> #include <memory> #include <string>
diff --git a/gpu/command_buffer/client/shared_image_pool.cc b/gpu/command_buffer/client/shared_image_pool.cc index d0a6c018..448e06b 100644 --- a/gpu/command_buffer/client/shared_image_pool.cc +++ b/gpu/command_buffer/client/shared_image_pool.cc
@@ -4,7 +4,6 @@ #include "gpu/command_buffer/client/shared_image_pool.h" -#include "base/atomic_sequence_num.h" #include "gpu/command_buffer/client/shared_image_interface.h" namespace { @@ -17,8 +16,6 @@ shared_image->alpha_type(), shared_image->buffer_usage()); } -base::AtomicSequenceNumber g_pool_id; - } // namespace namespace gpu { @@ -47,16 +44,17 @@ sync_token_ = std::move(release_sync_token); } -int ClientImage::GetPoolIdForTesting() const { +const PoolId& ClientImage::GetPoolIdForTesting() const { return pool_id_; } SharedImagePoolBase::SharedImagePoolBase( + const PoolId& pool_id, const ImageInfo& image_info, const scoped_refptr<SharedImageInterface> sii, std::optional<uint8_t> max_pool_size, std::optional<base::TimeDelta> unused_resource_expiration_time) - : pool_id_(g_pool_id.GetNext()), + : pool_id_(pool_id), image_info_(image_info), sii_(std::move(sii)), max_pool_size_(std::move(max_pool_size)), @@ -113,7 +111,7 @@ } // Ensure that the |image| belongs to |this| pool. - CHECK_EQ(image->pool_id_, pool_id_); + CHECK_EQ(image->pool_id_.ToString(), pool_id_.ToString()); // Ensure that there is only one reference which the current |image| and // clients are not accidentally keeping more references alive while releasing
diff --git a/gpu/command_buffer/client/shared_image_pool.h b/gpu/command_buffer/client/shared_image_pool.h index e2e0cd5..75f9516 100644 --- a/gpu/command_buffer/client/shared_image_pool.h +++ b/gpu/command_buffer/client/shared_image_pool.h
@@ -15,6 +15,7 @@ #include "components/viz/common/resources/shared_image_format.h" #include "gpu/command_buffer/client/client_shared_image.h" #include "gpu/command_buffer/client/shared_image_interface.h" +#include "gpu/command_buffer/common/shared_image_pool_id.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/common/sync_token.h" #include "gpu/gpu_export.h" @@ -90,7 +91,7 @@ void SetReleaseSyncToken(SyncToken release_sync_token); // Only used for testing purposes. - int GetPoolIdForTesting() const; + const PoolId& GetPoolIdForTesting() const; protected: friend class base::RefCounted<ClientImage>; @@ -114,8 +115,8 @@ // the client. base::TimeTicks last_used_time_ = base::TimeTicks::Now(); - // Unique identifier to identify the pool this image belongs to. - int pool_id_; + // Unique unguessable identifier to identify the pool this image belongs to. + PoolId pool_id_; }; // This class is designed to handle bulk of functionality of the image pool. @@ -133,6 +134,7 @@ protected: SharedImagePoolBase( + const PoolId& pool_id, const ImageInfo& image_info, const scoped_refptr<SharedImageInterface> sii, std::optional<uint8_t> max_pool_size, @@ -145,7 +147,7 @@ void ReconfigureInternal(const ImageInfo& image_info); // Unique identifier to identify this pool and all images generated from it. - const int pool_id_; + const PoolId pool_id_; // Information used to create new ClientSharedImage. ImageInfo image_info_; @@ -249,7 +251,8 @@ scoped_refptr<SharedImageInterface> sii, std::optional<uint8_t> max_pool_size, std::optional<base::TimeDelta> unused_resource_expiration_time) - : SharedImagePoolBase(image_info, + : SharedImagePoolBase(PoolId::Create(), + image_info, std::move(sii), std::move(max_pool_size), std::move(unused_resource_expiration_time)) {}
diff --git a/gpu/command_buffer/common/shared_image_pool_id.cc b/gpu/command_buffer/common/shared_image_pool_id.cc index 5f61c6b..a023558 100644 --- a/gpu/command_buffer/common/shared_image_pool_id.cc +++ b/gpu/command_buffer/common/shared_image_pool_id.cc
@@ -14,7 +14,7 @@ return PoolId(base::UnguessableToken::Create()); } -std::string PoolId::ToDebugString() const { +std::string PoolId::ToString() const { return token_.ToString(); }
diff --git a/gpu/command_buffer/common/shared_image_pool_id.h b/gpu/command_buffer/common/shared_image_pool_id.h index f9f221a..d24ed52 100644 --- a/gpu/command_buffer/common/shared_image_pool_id.h +++ b/gpu/command_buffer/common/shared_image_pool_id.h
@@ -20,8 +20,8 @@ // Creates a new PoolId with a cryptographically random value. static PoolId Create(); - // Generates a debug string representation of the PoolId. - std::string ToDebugString() const; + // Generates a string representation of the PoolId. + std::string ToString() const; bool operator==(const PoolId& other) const { return token_ == other.token_; }
diff --git a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc index eb7f8e3..fa21d78 100644 --- a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc +++ b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory_unittest.cc
@@ -231,7 +231,7 @@ wgpu::RequestAdapterOptions adapter_options; adapter_options.backendType = wgpu::BackendType::OpenGLES; - adapter_options.compatibilityMode = true; + adapter_options.featureLevel = wgpu::FeatureLevel::Compatibility; dawn::native::opengl::RequestAdapterOptionsGetGLProc adapter_options_get_gl_proc = {};
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc index 4c1471b7..254cd52 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc +++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
@@ -509,7 +509,7 @@ // Create a Dawn OpenGLES device. wgpu::RequestAdapterOptions adapter_options; adapter_options.backendType = wgpu::BackendType::OpenGLES; - adapter_options.compatibilityMode = true; + adapter_options.featureLevel = wgpu::FeatureLevel::Compatibility; std::vector<dawn::native::Adapter> adapters = instance.EnumerateAdapters(&adapter_options);
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.cc b/gpu/command_buffer/service/shared_image/shared_image_backing.cc index 31eafd2..30dd166 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_backing.cc
@@ -81,7 +81,8 @@ std::string debug_label, size_t estimated_size, bool is_thread_safe, - std::optional<gfx::BufferUsage> buffer_usage) + std::optional<gfx::BufferUsage> buffer_usage, + std::optional<PoolId> pool_id) : mailbox_(mailbox), format_(format), size_(size), @@ -91,7 +92,8 @@ usage_(usage), debug_label_(std::move(debug_label)), estimated_size_(estimated_size), - buffer_usage_(std::move(buffer_usage)) { + buffer_usage_(std::move(buffer_usage)), + pool_id_(std::move(pool_id)) { DCHECK_CALLED_ON_VALID_THREAD(factory_thread_checker_); if (is_thread_safe) @@ -446,7 +448,8 @@ std::string debug_label, size_t estimated_size, bool is_thread_safe, - std::optional<gfx::BufferUsage> buffer_usage) + std::optional<gfx::BufferUsage> buffer_usage, + std::optional<PoolId> pool_id) : SharedImageBacking(mailbox, format, size, @@ -457,7 +460,8 @@ std::move(debug_label), estimated_size, is_thread_safe, - std::move(buffer_usage)) {} + std::move(buffer_usage), + std::move(pool_id)) {} gfx::Rect ClearTrackingSharedImageBacking::ClearedRect() const { AutoLock auto_lock(this);
diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing.h b/gpu/command_buffer/service/shared_image/shared_image_backing.h index e7ddbb8..0d7af1f 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_backing.h +++ b/gpu/command_buffer/service/shared_image/shared_image_backing.h
@@ -22,6 +22,7 @@ #include "build/build_config.h" #include "components/viz/common/resources/shared_image_format.h" #include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/shared_image_pool_id.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/gpu_gles2_export.h" #include "gpu/vulkan/buildflags.h" @@ -128,7 +129,8 @@ std::string debug_label, size_t estimated_size, bool is_thread_safe, - std::optional<gfx::BufferUsage> buffer_usage = std::nullopt); + std::optional<gfx::BufferUsage> buffer_usage = std::nullopt, + std::optional<PoolId> pool_id = std::nullopt); virtual ~SharedImageBacking(); @@ -142,6 +144,7 @@ bool is_thread_safe() const { return !!lock_; } bool is_ref_counted() const { return is_ref_counted_; } gfx::BufferUsage buffer_usage() const { return buffer_usage_.value(); } + PoolId pool_id() const { return pool_id_.value(); } const std::string& debug_label() const { return debug_label_; } void OnContextLost(); @@ -419,6 +422,11 @@ // Note that this will be eventually removed and merged into SharedImageUsage. const std::optional<gfx::BufferUsage> buffer_usage_; + // An optional PoolId if the backing was created via a client side + // SharedImagePool. It will be null for backings which are not created via a + // SharedImagePool. + const std::optional<PoolId> pool_id_; + bool is_ref_counted_ = true; raw_ptr<SharedImageFactory> factory_ = nullptr; @@ -457,7 +465,8 @@ std::string debug_label, size_t estimated_size, bool is_thread_safe, - std::optional<gfx::BufferUsage> buffer_usage = std::nullopt); + std::optional<gfx::BufferUsage> buffer_usage = std::nullopt, + std::optional<PoolId> pool_id = std::nullopt); gfx::Rect ClearedRect() const override; void SetClearedRect(const gfx::Rect& cleared_rect) override;
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index ccca969..d2371d7 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -362,7 +362,7 @@ wgpu::Adapter CreatePreferredAdapter(wgpu::PowerPreference power_preference, bool force_fallback, - bool compatibility_mode) const; + wgpu::FeatureLevel feature_level) const; // Decide if a device feature is exposed to render process. bool IsFeatureExposed(wgpu::FeatureName feature) const; @@ -1357,10 +1357,18 @@ } #endif // BUILDFLAG(IS_LINUX) + wgpu::FeatureLevel feature_level = wgpu::FeatureLevel::Core; + if (force_webgpu_compat_ || + (static_cast<wgpu::FeatureLevel>(options->featureLevel) == + wgpu::FeatureLevel::Compatibility && + (safety_level_ == webgpu::SafetyLevel::kUnsafe || + safety_level_ == webgpu::SafetyLevel::kSafeExperimental))) { + feature_level = wgpu::FeatureLevel::Compatibility; + } + wgpu::Adapter adapter = CreatePreferredAdapter( static_cast<wgpu::PowerPreference>(options->powerPreference), - options->forceFallbackAdapter || force_fallback_adapter, - options->compatibilityMode || force_webgpu_compat_); + options->forceFallbackAdapter || force_fallback_adapter, feature_level); if (adapter == nullptr) { // There are no adapters to return since webgpu is not supported here @@ -1673,7 +1681,7 @@ wgpu::Adapter WebGPUDecoderImpl::CreatePreferredAdapter( wgpu::PowerPreference power_preference, bool force_fallback, - bool compatibility_mode) const { + wgpu::FeatureLevel feature_level) const { // Update power_preference based on command-line flag // use_webgpu_power_preference_. switch (use_webgpu_power_preference_) { @@ -1709,7 +1717,7 @@ // Prepare wgpu::RequestAdapterOptions. wgpu::RequestAdapterOptions adapter_options; - adapter_options.compatibilityMode = compatibility_mode; + adapter_options.featureLevel = feature_level; adapter_options.forceFallbackAdapter = force_fallback; adapter_options.powerPreference = power_preference;
diff --git a/gpu/command_buffer/tests/webgpu_test.cc b/gpu/command_buffer/tests/webgpu_test.cc index f2d5dbb..ad3c2ba 100644 --- a/gpu/command_buffer/tests/webgpu_test.cc +++ b/gpu/command_buffer/tests/webgpu_test.cc
@@ -140,7 +140,7 @@ wgpu::RequestAdapterOptions ra_options = {}; ra_options.forceFallbackAdapter = options.force_fallback_adapter; - ra_options.compatibilityMode = options.compatibility_mode; + ra_options.featureLevel = options.feature_level; bool done = false; instance_.RequestAdapter( @@ -459,7 +459,7 @@ TEST_F(WebGPUTest, CompatibilityMode) { auto options = WebGPUTest::Options(); - options.compatibility_mode = true; + options.feature_level = wgpu::FeatureLevel::Compatibility; options.enable_unsafe_webgpu = true; // Initialize attempts to create an adapter. Initialize(options); @@ -475,7 +475,7 @@ TEST_F(WebGPUTest, NonCompatibilityMode) { auto options = WebGPUTest::Options(); - options.compatibility_mode = false; + options.feature_level = wgpu::FeatureLevel::Core; options.enable_unsafe_webgpu = true; // Initialize attempts to create an adapter. Initialize(options);
diff --git a/gpu/command_buffer/tests/webgpu_test.h b/gpu/command_buffer/tests/webgpu_test.h index 30976bc..bd0e43e2 100644 --- a/gpu/command_buffer/tests/webgpu_test.h +++ b/gpu/command_buffer/tests/webgpu_test.h
@@ -46,7 +46,7 @@ SharedMemoryLimits shared_memory_limits = SharedMemoryLimits::ForWebGPUContext(); bool force_fallback_adapter = false; - bool compatibility_mode = false; + wgpu::FeatureLevel feature_level = wgpu::FeatureLevel::Core; bool enable_unsafe_webgpu = false; bool use_skia_graphite = false;
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc index db7b559..9e3245b 100644 --- a/gpu/config/gpu_info_collector.cc +++ b/gpu/config/gpu_info_collector.cc
@@ -416,7 +416,7 @@ #if BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES) // Check for compat adapters on GLES. adapter_options.backendType = wgpu::BackendType::OpenGLES; - adapter_options.compatibilityMode = true; + adapter_options.featureLevel = wgpu::FeatureLevel::Compatibility; dawn::native::opengl::RequestAdapterOptionsGetGLProc adapter_options_get_gl_proc = {}; @@ -922,15 +922,16 @@ }; #endif - for (bool compatibilityMode : {false, true}) { - adapter_options.compatibilityMode = compatibilityMode; + for (wgpu::FeatureLevel featureLevel : + {wgpu::FeatureLevel::Compatibility, wgpu::FeatureLevel::Core}) { + adapter_options.featureLevel = featureLevel; std::vector<dawn::native::Adapter> adapters = instance->EnumerateAdapters( reinterpret_cast<const WGPURequestAdapterOptions*>(&adapter_options)); for (dawn::native::Adapter& native_adapter : adapters) { wgpu::Adapter adapter(native_adapter.Get()); wgpu::AdapterInfo info = {}; adapter.GetInfo(&info); - if (compatibilityMode && + if (featureLevel == wgpu::FeatureLevel::Compatibility && info.backendType != wgpu::BackendType::OpenGLES) { continue; } @@ -941,7 +942,7 @@ std::string gpu_str = GetDawnAdapterTypeString(info.adapterType); gpu_str += " " + GetDawnBackendTypeString(info.backendType); gpu_str += " - " + std::string(info.device); - if (compatibilityMode) { + if (featureLevel == wgpu::FeatureLevel::Compatibility) { gpu_str += " (Compatibility Mode)"; } dawn_info_list->push_back(gpu_str);
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc index 07bddd36..de7baf8 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.cc +++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -67,7 +67,6 @@ } ContextResult CommandBufferProxyImpl::Initialize( - gpu::SurfaceHandle surface_handle, CommandBufferProxyImpl* share_group, gpu::SchedulingPriority stream_priority, const gpu::ContextCreationAttribs& attribs, @@ -80,11 +79,6 @@ auto channel = std::move(channel_); auto params = mojom::CreateCommandBufferParams::New(); -#if BUILDFLAG(IS_ANDROID) - params->surface_handle = surface_handle; -#else - CHECK(surface_handle == gpu::kNullSurfaceHandle); -#endif params->share_group_id = share_group ? share_group->route_id_ : MSG_ROUTING_NONE; params->stream_id = stream_id_;
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.h b/gpu/ipc/client/command_buffer_proxy_impl.h index d3a0807..edfec18 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.h +++ b/gpu/ipc/client/command_buffer_proxy_impl.h
@@ -92,8 +92,7 @@ ~CommandBufferProxyImpl() override; // Connect to a command buffer in the GPU process. - ContextResult Initialize(gpu::SurfaceHandle surface_handle, - CommandBufferProxyImpl* share_group, + ContextResult Initialize(CommandBufferProxyImpl* share_group, gpu::SchedulingPriority stream_priority, const gpu::ContextCreationAttribs& attribs, const GURL& active_url);
diff --git a/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc b/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc index 3e278ee..0598c90 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc +++ b/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc
@@ -136,7 +136,7 @@ return true; })); - proxy->Initialize(kNullSurfaceHandle, nullptr, SchedulingPriority::kNormal, + proxy->Initialize(nullptr, SchedulingPriority::kNormal, ContextCreationAttribs(), GURL()); // Use an arbitrary valid shm_id. The command buffer doesn't use this // directly, but not setting it triggers DCHECKs.
diff --git a/gpu/ipc/common/gpu_channel.mojom b/gpu/ipc/common/gpu_channel.mojom index 7dabc08..36dcce1c 100644 --- a/gpu/ipc/common/gpu_channel.mojom +++ b/gpu/ipc/common/gpu_channel.mojom
@@ -65,7 +65,6 @@ }; struct CreateCommandBufferParams { - [EnableIf=is_android] SurfaceHandle surface_handle; int32 share_group_id; int32 stream_id; SchedulingPriority stream_priority;
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc index c9addaa..4cde2f7c 100644 --- a/gpu/ipc/service/command_buffer_stub.cc +++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -114,9 +114,6 @@ context_type_(init_params.attribs.context_type), active_url_(init_params.active_url), initialized_(false), -#if BUILDFLAG(IS_ANDROID) - offscreen_(init_params.surface_handle == kNullSurfaceHandle), -#endif use_virtualized_gl_context_(false), command_buffer_id_(command_buffer_id), sequence_id_(sequence_id), @@ -311,11 +308,7 @@ if (initialized_) { GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); - // If we are currently shutting down the GPU process to help with recovery - // (exit_on_context_lost workaround), then don't tell the browser about - // offscreen context destruction here since it's not client-invoked, and - // might bypass the 3D API blocking logic. - if (offscreen() && !active_url_.is_empty() && + if (!active_url_.is_empty() && !gpu_channel_manager->delegate()->IsExiting()) { gpu_channel_manager->delegate()->DidDestroyOffscreenContext( active_url_.url());
diff --git a/gpu/ipc/service/command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h index 2d73779..edbac4a 100644 --- a/gpu/ipc/service/command_buffer_stub.h +++ b/gpu/ipc/service/command_buffer_stub.h
@@ -250,14 +250,6 @@ bool MakeCurrent(); - bool offscreen() const { -#if BUILDFLAG(IS_ANDROID) - return offscreen_; -#else - return true; -#endif - } - // The lifetime of objects of this class is managed by a GpuChannel. The // GpuChannels destroy all the CommandBufferStubs that they own when // they are destroyed. So a raw pointer is safe. @@ -267,9 +259,6 @@ ContextUrl active_url_; bool initialized_; -#if BUILDFLAG(IS_ANDROID) - const bool offscreen_; -#endif bool use_virtualized_gl_context_; std::unique_ptr<CommandBufferService> command_buffer_;
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc index 4d03e6de..d1bb10d 100644 --- a/gpu/ipc/service/gles2_command_buffer_stub.cc +++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -179,40 +179,12 @@ } gl::GLSurface* default_surface = manager->default_offscreen_surface(); - -#if BUILDFLAG(IS_ANDROID) - const bool offscreen = init_params.surface_handle == kNullSurfaceHandle; -#else - constexpr bool offscreen = true; -#endif - -#if BUILDFLAG(IS_ANDROID) - if (!offscreen) { - // To use virtualized contexts we need on screen surface format match the - // offscreen. - auto surface_format = default_surface->GetFormat(); - surface_ = ImageTransportSurface::CreateNativeGLSurface( - display, init_params.surface_handle, surface_format); - // CreateNativeGLSurface should have already initialized the surface, and - // doubly initializing it can lead to errors. - if (!surface_) { - surface_ = nullptr; - LOG(ERROR) << "ContextResult::kSurfaceFailure: Failed to create surface."; - return gpu::ContextResult::kSurfaceFailure; - } - if (!features::UseGpuVsync()) { - surface_->SetVSyncEnabled(false); - } - } else -#endif - { - if (default_surface->GetGLDisplay() == display) { - surface_ = default_surface; - } else { - // The default surface was created on a different display, create a - // new surface on the requested display. - surface_ = gl::init::CreateOffscreenGLSurface(display, gfx::Size()); - } + if (default_surface->GetGLDisplay() == display) { + surface_ = default_surface; + } else { + // The default surface was created on a different display, create a + // new surface on the requested display. + surface_ = gl::init::CreateOffscreenGLSurface(display, gfx::Size()); } if (context_group_->use_passthrough_cmd_decoder()) { @@ -323,9 +295,9 @@ } // Initialize the decoder with either the view or pbuffer GLContext. - auto result = gles2_decoder_->Initialize(surface_, context, offscreen, - gpu::gles2::DisallowedFeatures(), - init_params.attribs); + auto result = gles2_decoder_->Initialize( + surface_, context, /*offscreen=*/true, gpu::gles2::DisallowedFeatures(), + init_params.attribs); if (result != gpu::ContextResult::kSuccess) { DLOG(ERROR) << "Failed to initialize decoder."; return result; @@ -346,8 +318,9 @@ command_buffer_->SetSharedStateBuffer(MakeBackingFromSharedMemory( std::move(shared_state_shm), std::move(shared_state_mapping))); - if (offscreen && !active_url_.is_empty()) + if (!active_url_.is_empty()) { manager->delegate()->DidCreateOffscreenContext(active_url_.url()); + } if (use_virtualized_gl_context_) { // If virtualized GL contexts are in use, then real GL context state
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index 978e19c..a4cd2fa8 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc
@@ -1115,15 +1115,6 @@ ScopedCreateCommandBufferResponder responder(std::move(callback)); TRACE_EVENT1("gpu", "GpuChannel::CreateCommandBuffer", "route_id", route_id); -#if BUILDFLAG(IS_ANDROID) - if (init_params->surface_handle != kNullSurfaceHandle && !is_gpu_host_) { - LOG(ERROR) - << "ContextResult::kFatalFailure: " - "attempt to create a view context on a non-privileged channel"; - return; - } -#endif - if (gpu_channel_manager_->delegate()->IsExiting()) { LOG(ERROR) << "ContextResult::kTransientFailure: trying to create command " "buffer during process shutdown.";
diff --git a/gpu/ipc/service/gpu_channel_unittest.cc b/gpu/ipc/service/gpu_channel_unittest.cc index 4074a55b..6c3f412e 100644 --- a/gpu/ipc/service/gpu_channel_unittest.cc +++ b/gpu/ipc/service/gpu_channel_unittest.cc
@@ -22,70 +22,6 @@ ~GpuChannelTest() override = default; }; -#if BUILDFLAG(IS_ANDROID) -const SurfaceHandle kFakeSurfaceHandle = 1; - -TEST_F(GpuChannelTest, CreateViewCommandBufferAllowed) { - // TODO(crbug.com/40062603): Currently it's not possible to create - // onscreen GLSurface with Null binding with angle. - if (channel_manager()->use_passthrough_cmd_decoder()) { - GTEST_SKIP(); - } - - int32_t kClientId = 1; - bool is_gpu_host = true; - GpuChannel* channel = CreateChannel(kClientId, is_gpu_host); - ASSERT_TRUE(channel); - - int32_t kRouteId = - static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1; - auto init_params = mojom::CreateCommandBufferParams::New(); - init_params->surface_handle = kFakeSurfaceHandle; - init_params->share_group_id = MSG_ROUTING_NONE; - init_params->stream_id = 0; - init_params->stream_priority = SchedulingPriority::kNormal; - init_params->attribs = ContextCreationAttribs(); - init_params->active_url = GURL(); - gpu::ContextResult result = gpu::ContextResult::kSuccess; - gpu::Capabilities capabilities; - gpu::GLCapabilities gl_capabilities; - CreateCommandBuffer(*channel, std::move(init_params), kRouteId, - GetSharedMemoryRegion(), &result, &capabilities, - &gl_capabilities); - EXPECT_EQ(result, gpu::ContextResult::kSuccess); - - CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); - ASSERT_TRUE(stub); -} - -TEST_F(GpuChannelTest, CreateViewCommandBufferDisallowed) { - int32_t kClientId = 1; - bool is_gpu_host = false; - GpuChannel* channel = CreateChannel(kClientId, is_gpu_host); - ASSERT_TRUE(channel); - - int32_t kRouteId = - static_cast<int32_t>(GpuChannelReservedRoutes::kMaxValue) + 1; - auto init_params = mojom::CreateCommandBufferParams::New(); - init_params->surface_handle = kFakeSurfaceHandle; - init_params->share_group_id = MSG_ROUTING_NONE; - init_params->stream_id = 0; - init_params->stream_priority = SchedulingPriority::kNormal; - init_params->attribs = ContextCreationAttribs(); - init_params->active_url = GURL(); - gpu::ContextResult result = gpu::ContextResult::kSuccess; - gpu::Capabilities capabilities; - gpu::GLCapabilities gl_capabilities; - CreateCommandBuffer(*channel, std::move(init_params), kRouteId, - GetSharedMemoryRegion(), &result, &capabilities, - &gl_capabilities); - EXPECT_EQ(result, gpu::ContextResult::kFatalFailure); - - CommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId); - EXPECT_FALSE(stub); -} -#endif - TEST_F(GpuChannelTest, CreateOffscreenCommandBuffer) { int32_t kClientId = 1; GpuChannel* channel = CreateChannel(kClientId, true);
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index f1bc882..816005e 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -496,7 +496,7 @@ # Normally set to false (see build/args/headless.gn), but we can optionally # use external v8 startup data too. - if ((!is_win || is_component_build) && v8_use_external_startup_data) { + if (v8_use_external_startup_data) { public_deps += [ "//v8" ] if (use_v8_context_snapshot) { data += [ "$root_out_dir/$v8_context_snapshot_filename" ]
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 9929a60..637bbc3 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1203,6 +1203,21 @@ {" - Variation 3", kSetUpListInFirstRunArm3, std::size(kSetUpListInFirstRunArm3), nullptr}}; +const FeatureEntry::FeatureParam kSetUpListDuration3Days[] = { + {set_up_list::kSetUpListDurationParam, "3"}}; +const FeatureEntry::FeatureParam kSetUpListDuration5Days[] = { + {set_up_list::kSetUpListDurationParam, "5"}}; +const FeatureEntry::FeatureParam kSetUpListDuration7Days[] = { + {set_up_list::kSetUpListDurationParam, "7"}}; + +const FeatureEntry::FeatureVariation kSetUpListDurationVariations[] = { + {" - 3 Days", kSetUpListDuration3Days, std::size(kSetUpListDuration3Days), + nullptr}, + {" - 5 Days", kSetUpListDuration5Days, std::size(kSetUpListDuration5Days), + nullptr}, + {" - 7 Days", kSetUpListDuration7Days, std::size(kSetUpListDuration7Days), + nullptr}}; + // To add a new entry, add to the end of kFeatureEntries. There are four // distinct types of entries: // . ENABLE_DISABLE_VALUE: entry is either enabled, disabled, or uses the @@ -2245,6 +2260,13 @@ flag_descriptions::kLensClearcutLoggerFastQosEnabledName, flag_descriptions::kLensClearcutLoggerFastQosEnabledDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kLensClearcutLoggerFastQosEnabled)}, + {"set-up-list-shortened-duration", + flag_descriptions::kSetUpListShortenedDurationName, + flag_descriptions::kSetUpListShortenedDurationDescription, + flags_ui::kOsIos, + FEATURE_WITH_PARAMS_VALUE_TYPE(set_up_list::kSetUpListShortenedDuration, + kSetUpListDurationVariations, + "SetUpListShortenedDuration")}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index cd5eee6..9278090 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -1095,6 +1095,10 @@ const char kSetUpListInFirstRunNameDescription[] = "Displays the Set Up List in the First Run."; +const char kSetUpListShortenedDurationName[] = "Set Up List Shortened Duration"; +const char kSetUpListShortenedDurationDescription[] = + "Reduces the Set Up List duration in the NTP to the selected parameter."; + const char kShareInWebContextMenuIOSName[] = "Share in web context menu"; const char kShareInWebContextMenuIOSDescription[] = "Enables the Share button in the web context menu in iOS 16.0 and above.";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 0bb80d0..0ed487e 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -975,6 +975,10 @@ extern const char kSetUpListInFirstRunName[]; extern const char kSetUpListInFirstRunNameDescription[]; +// Title and description for the flag to reduce the duration of the Set Up List. +extern const char kSetUpListShortenedDurationName[]; +extern const char kSetUpListShortenedDurationDescription[]; + // Title and description for the flag to enable the Share button // in the web context menu in iOS. extern const char kShareInWebContextMenuIOSName[];
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h index 1e457784..1753df9 100644 --- a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h +++ b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h
@@ -20,15 +20,19 @@ // A wrapper/helper around the `optimization_guide::proto::PageContext` proto // which handles populating all the necessary PageContext fields asynchronously. -// Hopefully generic enough for use with any optimization guide feature. +// By default, no async tasks will be executed, only the title and URL fields +// will be set (synchronous work). Please use the setters below to "enable" some +// or all of those async tasks before calling `populatePageContextFieldsAsync`. +// There are performance implications to enabling some of these, especially if +// the caller is populating PageContext protos for lots of tabs. When adding a +// new async task, ensure a related setter is also created to keep the +// disable-by-default behaviour. @interface PageContextWrapper : NSObject #if BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE) // Initializer which takes everything needed to construct the PageContext proto -// as arguments. Once all the async work is completed by calling -// `populatePageContextFieldsAsync`, the `completionCallback` will be executed -// (which will relinquish ownership of the proto to the callback's handler). +// as arguments. - (instancetype) initWithWebState:(web::WebState*)webState completionCallback: @@ -38,12 +42,24 @@ - (instancetype)init NS_UNAVAILABLE; -// Initiates the synchronous and asynchronous work of populating all the -// PageContext fields, and executes the `completionCallback` when all async work -// is complete. Relinquishes ownership of the PageContext proto back to the -// handler of the callback. +// Initiates the asynchronous work of populating all the PageContext fields, and +// executes the `completionCallback` when all async work is complete. +// Relinquishes ownership of the PageContext proto back to the handler of the +// callback. - (void)populatePageContextFieldsAsync; +// Boolean flags for enabling/disabling the async tasks that the PageContext +// wrapper can execute. + +// Whether a snapshot of the associated WebState should be fetched. If the +// WebState is currently visible, updates the snapshot taken instead of getting +// the previously saved snapshot. +@property(nonatomic, assign) BOOL shouldGetSnapshot; + +// Whether a full page PDF of the associated WebState should be fetched. This +// force-realizes the associated WebState. +@property(nonatomic, assign) BOOL shouldGetFullPagePDF; + #endif // BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE) @end
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm index 52a2fc9032..630ad4a8 100644 --- a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm +++ b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm
@@ -7,6 +7,8 @@ #import <memory> #import "base/barrier_closure.h" +#import "base/check.h" +#import "base/check_op.h" #import "base/memory/weak_ptr.h" #import "base/strings/sys_string_conversions.h" #import "base/strings/utf_string_conversions.h" @@ -16,18 +18,15 @@ #import "components/optimization_guide/proto/features/common_quality_data.pb.h" -// The amount of async tasks which need to complete before the -// `completionCallback` can be executed. This needs to be kept up to date with -// any async tasks added in `populatePageContextFieldsAsync`. Currently, the -// tasks are: -// 1. Get a snapshot of the tab. -const int kAsyncTasksCount = 1; - #endif // BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE) @implementation PageContextWrapper { base::WeakPtr<web::WebState> _webState; + // The amount of async tasks this specific instance of the PageContext wrapper + // needs to complete before executing the `completionCallback`. + NSInteger _asyncTasksToComplete; + #if BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE) // The callback to execute once all async work is complete, whichs @@ -52,6 +51,7 @@ completionCallback { self = [super init]; if (self) { + _asyncTasksToComplete = 0; _webState = webState->GetWeakPtr(); _completion_callback = std::move(completionCallback); @@ -64,34 +64,74 @@ } - (void)populatePageContextFieldsAsync { - __weak PageContextWrapper* weakSelf = self; + CHECK_GE(_asyncTasksToComplete, 0); + + if (_asyncTasksToComplete == 0) { + [self asyncWorkCompletedForPageContext]; + return; + } // Use a `BarrierClosure` to ensure all async tasks are completed before - // executing the overall completion callback. If new async tasks are added - // below, the `kAsyncTasksCount` constant should be incremented. The - // BarrierClosure will wait until the `barrier` callback is itself run - // `kAsyncTasksCount` times. + // executing the overall completion callback. The BarrierClosure will wait + // until the `barrier` callback is itself run `_asyncTasksToComplete` times. + __weak PageContextWrapper* weakSelf = self; base::RepeatingClosure barrier = - base::BarrierClosure(kAsyncTasksCount, base::BindOnce(^{ + base::BarrierClosure(_asyncTasksToComplete, base::BindOnce(^{ [weakSelf asyncWorkCompletedForPageContext]; })); // Asynchronous work. *IMPORTANT NOTES*: - // When adding async tasks below, `kAsyncTasksCount` should be incremented. - // Also, every code path for a given task should eventually execute the - // `barrier` callback, otherwise the `BarrierClosure` will never execute its - // completion block. + // When adding async tasks below, an accompanying setter should also be + // created to follow the disabled-by-default pattern (which + // increments/decrements `_asyncTasksToComplete` accordingly). Also, if a + // given task is enabled, every code path for that task should eventually + // execute the `barrier` callback, otherwise the `BarrierClosure` will never + // execute its completion block. - // Take WebState snapshot. - if (_webState->CanTakeSnapshot()) { - CGRect rect = [_webState->GetView() bounds]; - _webState->TakeSnapshot(rect, base::BindRepeating(^(UIImage* image) { - [weakSelf encodeImageAndSetTabScreenshot:image]; - barrier.Run(); - })); - } else { - barrier.Run(); + // Take WebState snapshot, if enabled. + if (_shouldGetSnapshot) { + if (_webState->CanTakeSnapshot()) { + CGRect rect = [_webState->GetView() bounds]; + _webState->TakeSnapshot(rect, base::BindRepeating(^(UIImage* image) { + [weakSelf encodeImageAndSetTabScreenshot:image]; + barrier.Run(); + })); + } else { + barrier.Run(); + } } + + // Create WebState full page PDF, if enabled. + if (_shouldGetFullPagePDF) { + _webState->CreateFullPagePdf(base::BindOnce(^(NSData* PDFData) { + [weakSelf encodeAndSetFullPagePDF:PDFData]; + barrier.Run(); + })); + } +} + +#pragma mark - Setters + +// Sets the flag to enabled/disabled, and increments/decrements accordingly the +// total amount of async tasks gating the completion callback. +- (void)setShouldGetSnapshot:(BOOL)enabled { + if (_shouldGetSnapshot == enabled) { + return; + } + + _asyncTasksToComplete += enabled ? 1 : -1; + _shouldGetSnapshot = enabled; +} + +// Sets the flag to enabled/disabled, and increments/decrements accordingly the +// total amount of async tasks gating the completion callback. +- (void)setShouldGetFullPagePDF:(BOOL)enabled { + if (_shouldGetFullPagePDF == enabled) { + return; + } + + _asyncTasksToComplete += enabled ? 1 : -1; + _shouldGetFullPagePDF = enabled; } #pragma mark - Private @@ -110,6 +150,17 @@ _page_context->set_tab_screenshot(base::SysNSStringToUTF8(base64String)); } +// If it exists, convert the PDF data to base64 encoded string and set it in the +// PageContext proto. +- (void)encodeAndSetFullPagePDF:(NSData*)PDFData { + if (!PDFData) { + return; + } + + NSString* base64String = [PDFData base64EncodedStringWithOptions:0]; + _page_context->set_pdf_data(base::SysNSStringToUTF8(base64String)); +} + #endif // BUILDFLAG(BUILD_WITH_INTERNAL_OPTIMIZATION_GUIDE) @end
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/tab_organization_request_wrapper.mm b/ios/chrome/browser/intelligence/proto_wrappers/tab_organization_request_wrapper.mm index dad0cb5b..84282fa 100644 --- a/ios/chrome/browser/intelligence/proto_wrappers/tab_organization_request_wrapper.mm +++ b/ios/chrome/browser/intelligence/proto_wrappers/tab_organization_request_wrapper.mm
@@ -78,9 +78,15 @@ // Use a `BarrierClosure` to ensure all async tasks are completed before // executing the overall completion callback. The BarrierClosure will wait - // until the `barrier` callback is itself run once for every WebState. + // until the `barrier` callback is itself run once for every WebState. +1 is + // added to that count to at least finish the execution of this method before + // the completion callback is executed. This is needed in case no async tasks + // need to be executed in the PageContext wrappers (or they execute incredibly + // quickly), which causes them to run their completion callbacks, in turn + // making the TabOrganizationRequestWrapper's completion callback execute, + // which invalidates all of this memory, all before the for loop is completed. base::RepeatingClosure barrier = base::BarrierClosure( - _webStateList->count(), base::BindOnce(^{ + 1 + _webStateList->count(), base::BindOnce(^{ [weakSelf asyncWorkCompletedForTabOrganizationRequest]; })); @@ -106,14 +112,19 @@ barrier.Run(); })]; - // Begin populating the PageContext proto fields. Once completed, - // `completionCallback` will be executed. - [pageContextWrapper populatePageContextFieldsAsync]; + [pageContextWrapper setShouldGetSnapshot:YES]; // Hold references to each PageContextWrapper to keep them alive during // their async work. _page_contexts.push_back(pageContextWrapper); + + // Begin populating the PageContext proto fields. Once completed, + // `completionCallback` will be executed. + [pageContextWrapper populatePageContextFieldsAsync]; } + + // Call this last to ensure looping over all WebStates has completed. + barrier.Run(); } #pragma mark - Private
diff --git a/ios/chrome/browser/ntp/model/features.h b/ios/chrome/browser/ntp/model/features.h index e6133ee..fbb8baf5 100644 --- a/ios/chrome/browser/ntp/model/features.h +++ b/ios/chrome/browser/ntp/model/features.h
@@ -6,6 +6,7 @@ #define IOS_CHROME_BROWSER_NTP_MODEL_FEATURES_H_ #import "base/feature_list.h" +#import "base/time/time.h" namespace set_up_list { @@ -20,14 +21,24 @@ // Feature to enable the Set Up List in the First Run. BASE_DECLARE_FEATURE(kSetUpListInFirstRun); +// Feature to adjust the Set Up List duration. +BASE_DECLARE_FEATURE(kSetUpListShortenedDuration); + // Name of the param that indicates which variation of the kSetUpListInFirstRun // is enabled. The Set Up List items shown depend on the variation. extern const char kSetUpListInFirstRunParam[]; +// Name of the param that indicates the duration of the Set Up List in days. +extern const char kSetUpListDurationParam[]; + // Returns which variation of the kSetUpListInFirstRun feature is enabled. // Returns 0 if the feature is disabled. FirstRunVariationType GetSetUpListInFirstRunVariation(); +// Returns the duration for the SetUpList based off the state of the +// kSetUpListShortenedDuration feature. +base::TimeDelta SetUpListDuration(); + } // namespace set_up_list #endif // IOS_CHROME_BROWSER_NTP_MODEL_FEATURES_H_
diff --git a/ios/chrome/browser/ntp/model/features.mm b/ios/chrome/browser/ntp/model/features.mm index 035582d9..9e25ffaa 100644 --- a/ios/chrome/browser/ntp/model/features.mm +++ b/ios/chrome/browser/ntp/model/features.mm
@@ -12,8 +12,14 @@ "SetUpListInFirstRun", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kSetUpListShortenedDuration, + "SetUpListShortenedDuration", + base::FEATURE_DISABLED_BY_DEFAULT); + const char kSetUpListInFirstRunParam[] = "SetUpListInFirstRunParam"; +const char kSetUpListDurationParam[] = "SetUpListDurationParam"; + FirstRunVariationType GetSetUpListInFirstRunVariation() { if (!base::FeatureList::IsEnabled(kSetUpListInFirstRun)) { return FirstRunVariationType::kDisabled; @@ -23,4 +29,9 @@ kSetUpListInFirstRunParam, 1)); } +base::TimeDelta SetUpListDuration() { + return base::Days(base::GetFieldTrialParamByFeatureAsInt( + kSetUpListShortenedDuration, kSetUpListDurationParam, 14)); +} + } // namespace set_up_list
diff --git a/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn b/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn index d9c8862..5aa6573 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn +++ b/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn
@@ -23,6 +23,8 @@ deps = [ ":constants", "//ios/chrome/app/strings", + "//ios/chrome/browser/push_notification/model:push_notification_client_id", + "//ios/chrome/browser/push_notification/model:push_notification_settings_util_header", "//ios/chrome/browser/shared/public/features", "//ios/chrome/browser/shared/public/features:system_flags", "//ui/base", @@ -33,6 +35,20 @@ ] } +source_set("test_utils") { + testonly = true + sources = [ + "test_utils.h", + "test_utils.mm", + ] + deps = [ + "//components/prefs", + "//ios/chrome/browser/push_notification/model:constants", + "//ios/chrome/browser/shared/model/prefs:pref_names", + "//ios/chrome/test:test_support", + ] +} + source_set("unit_tests") { testonly = true sources = [ "utils_unittest.mm" ]
diff --git a/ios/chrome/browser/safety_check_notifications/utils/DEPS b/ios/chrome/browser/safety_check_notifications/utils/DEPS index 683b34e..2003fbf 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/DEPS +++ b/ios/chrome/browser/safety_check_notifications/utils/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+ios/chrome/browser/passwords/model", + "+ios/chrome/browser/push_notification/model", "+ios/chrome/browser/safety_check/model", ]
diff --git a/ios/chrome/browser/safety_check_notifications/utils/constants.h b/ios/chrome/browser/safety_check_notifications/utils/constants.h index b0b9b1dd..2858b8e 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/constants.h +++ b/ios/chrome/browser/safety_check_notifications/utils/constants.h
@@ -9,6 +9,26 @@ #import "base/time/time.h" +// Enum for the `IOS.Notifications.SafetyCheck.NotificationsOptInSource` +// histogram. +// +// Must be in sync with `IOSSafetyCheckNotificationsOptInSource` enum in +// `tools/metrics/histograms/metadata/ios/enums.xml`. +// +// LINT.IfChange(SafetyCheckNotificationsOptInSource) +enum class SafetyCheckNotificationsOptInSource { + kSafetyCheckPageOptIn = 0, + kSafetyCheckPageOptOut = 1, + kPasswordCheckupPageOptIn = 2, + kPasswordCheckupPageOptOut = 3, + kMagicStackLongPressMenuOptIn = 4, + kMagicStackLongPressMenuOptOut = 5, + kMagicStackTopRightActionButtonOptIn = 6, + kMagicStackTopRightActionButtonOptOut = 7, + kMaxValue = kMagicStackTopRightActionButtonOptOut, +}; +// LINT.ThenChange(/tools/metrics/histograms/metadata/ios/enums.xml:IOSSafetyCheckNotificationsOptInSource) + // Enum for the `IOS.Notifications.SafetyCheck.Interaction` histogram. // // Must be in sync with `IOSSafetyCheckNotificationType` enum in
diff --git a/ios/chrome/browser/safety_check_notifications/utils/test_utils.h b/ios/chrome/browser/safety_check_notifications/utils/test_utils.h new file mode 100644 index 0000000..5540fcbd1 --- /dev/null +++ b/ios/chrome/browser/safety_check_notifications/utils/test_utils.h
@@ -0,0 +1,14 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_SAFETY_CHECK_NOTIFICATIONS_UTILS_TEST_UTILS_H_ +#define IOS_CHROME_BROWSER_SAFETY_CHECK_NOTIFICATIONS_UTILS_TEST_UTILS_H_ + +// Updates the app-level notification permission for Safety Check notifications. +// This function modifies the `kAppLevelPushNotificationPermissions` preference +// dictionary in local Prefs to enable or disable Safety Check notifications. +// Pass `YES` to enable notifications or `NO` to disable them. +void UpdateSafetyCheckNotificationsPermission(bool enable); + +#endif // IOS_CHROME_BROWSER_SAFETY_CHECK_NOTIFICATIONS_UTILS_TEST_UTILS_H_
diff --git a/ios/chrome/browser/safety_check_notifications/utils/test_utils.mm b/ios/chrome/browser/safety_check_notifications/utils/test_utils.mm new file mode 100644 index 0000000..3b2ab60 --- /dev/null +++ b/ios/chrome/browser/safety_check_notifications/utils/test_utils.mm
@@ -0,0 +1,20 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/safety_check_notifications/utils/test_utils.h" + +#import "components/prefs/pref_service.h" +#import "components/prefs/scoped_user_pref_update.h" +#import "ios/chrome/browser/push_notification/model/constants.h" +#import "ios/chrome/browser/shared/model/prefs/pref_names.h" +#import "ios/chrome/test/testing_application_context.h" + +void UpdateSafetyCheckNotificationsPermission(BOOL enable) { + PrefService* pref_service = GetApplicationContext()->GetLocalState(); + + ScopedDictPrefUpdate update(pref_service, + prefs::kAppLevelPushNotificationPermissions); + + update->Set(kSafetyCheckNotificationKey, enable); +}
diff --git a/ios/chrome/browser/safety_check_notifications/utils/utils.h b/ios/chrome/browser/safety_check_notifications/utils/utils.h index 885b2c3..0f8b107 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/utils.h +++ b/ios/chrome/browser/safety_check_notifications/utils/utils.h
@@ -14,6 +14,18 @@ #import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_constants.h" enum class SafetyCheckNotificationType; +enum class SafetyCheckNotificationsOptInSource; + +// Logs the source of a user's decision to opt-in or opt-out of Safety Check +// notifications. Determines the current notification permission status +// internally using +// `push_notification_settings::GetMobileNotificationPermissionStatusForClient` +// and records the appropriate histogram value in +// `IOS.Notifications.SafetyCheck.NotificationsOptInSource` based on whether +// notifications are enabled or disabled. +void LogSafetyCheckNotificationOptInSource( + SafetyCheckNotificationsOptInSource opt_in_source, + SafetyCheckNotificationsOptInSource opt_out_source); // Returns a notification request for the most critical Password issue // found using `state` and `insecure_password_counts`. Returns `nil` if no
diff --git a/ios/chrome/browser/safety_check_notifications/utils/utils.mm b/ios/chrome/browser/safety_check_notifications/utils/utils.mm index 791f1e9..13a003c2 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/utils.mm +++ b/ios/chrome/browser/safety_check_notifications/utils/utils.mm
@@ -4,8 +4,11 @@ #import "ios/chrome/browser/safety_check_notifications/utils/utils.h" +#import "base/metrics/histogram_functions.h" #import "base/strings/sys_string_conversions.h" #import "base/time/time.h" +#import "ios/chrome/browser/push_notification/model/push_notification_client_id.h" +#import "ios/chrome/browser/push_notification/model/push_notification_settings_util.h" #import "ios/chrome/browser/safety_check_notifications/utils/constants.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/shared/public/features/system_flags.h" @@ -116,6 +119,18 @@ } // namespace +void LogSafetyCheckNotificationOptInSource( + SafetyCheckNotificationsOptInSource opt_in_source, + SafetyCheckNotificationsOptInSource opt_out_source) { + bool is_notifications_enabled = push_notification_settings:: + GetMobileNotificationPermissionStatusForClient( + PushNotificationClientId::kSafetyCheck, ""); + + base::UmaHistogramEnumeration( + "IOS.Notifications.SafetyCheck.NotificationsOptInSource", + is_notifications_enabled ? opt_out_source : opt_in_source); +} + UNNotificationRequest* PasswordNotificationRequest( PasswordSafetyCheckState state, password_manager::InsecurePasswordCounts insecure_password_counts) {
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/BUILD.gn index 5764fddd..73a802b 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/BUILD.gn +++ b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/BUILD.gn
@@ -25,6 +25,8 @@ "//ios/chrome/browser/push_notification/model:push_notification_service_header", "//ios/chrome/browser/push_notification/model:push_notification_settings_util_header", "//ios/chrome/browser/push_notification/ui_bundled:opt_in_alert_coordinator", + "//ios/chrome/browser/safety_check_notifications/utils", + "//ios/chrome/browser/safety_check_notifications/utils:constants", "//ios/chrome/browser/settings/ui_bundled/notifications:utils", "//ios/chrome/browser/settings/ui_bundled/password/password_issues", "//ios/chrome/browser/settings/ui_bundled/password/reauthentication", @@ -104,11 +106,15 @@ "//ios/chrome/browser/passwords/model:password_checkup_utils", "//ios/chrome/browser/passwords/model:store_factory", "//ios/chrome/browser/passwords/model/metrics", + "//ios/chrome/browser/push_notification/model:constants", "//ios/chrome/browser/push_notification/model:push_notification_service_header", + "//ios/chrome/browser/safety_check_notifications/utils:constants", + "//ios/chrome/browser/safety_check_notifications/utils:test_utils", "//ios/chrome/browser/settings/ui_bundled/cells", "//ios/chrome/browser/settings/ui_bundled/password/reauthentication:reauthentication_ui", "//ios/chrome/browser/shared/coordinator/scene:scene_state_header", "//ios/chrome/browser/shared/model/browser/test:test_support", + "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/profile/test", "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/DEPS b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/DEPS index ff759cbf..3702b16 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/DEPS +++ b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+ios/chrome/browser/push_notification/ui_bundled", + "+ios/chrome/browser/safety_check_notifications/utils", ]
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator.mm b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator.mm index 52476b07..51596a23 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator.mm
@@ -10,6 +10,8 @@ #import "ios/chrome/browser/passwords/model/password_checkup_utils.h" #import "ios/chrome/browser/push_notification/model/push_notification_client_id.h" #import "ios/chrome/browser/push_notification/model/push_notification_settings_util.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/safety_check_notifications/utils/utils.h" #import "ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_consumer.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/grit/ios_branded_strings.h" @@ -104,6 +106,10 @@ - (void)toggleSafetyCheckNotifications { CHECK(IsSafetyCheckNotificationsEnabled()); + LogSafetyCheckNotificationOptInSource( + SafetyCheckNotificationsOptInSource::kPasswordCheckupPageOptIn, + SafetyCheckNotificationsOptInSource::kPasswordCheckupPageOptOut); + [self.delegate toggleSafetyCheckNotifications]; }
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator_unittest.mm b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator_unittest.mm index c9306fe..e852d56 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator_unittest.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator_unittest.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_mediator.h" #import "base/test/bind.h" +#import "base/test/metrics/histogram_tester.h" #import "base/test/scoped_feature_list.h" #import "components/affiliations/core/browser/fake_affiliation_service.h" #import "components/keyed_service/core/service_access_type.h" @@ -17,11 +18,14 @@ #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h" #import "ios/chrome/browser/passwords/model/password_check_observer_bridge.h" #import "ios/chrome/browser/passwords/model/password_checkup_utils.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/safety_check_notifications/utils/test_utils.h" #import "ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_consumer.h" #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h" #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" +#import "ios/chrome/test/testing_application_context.h" #import "ios/web/public/test/web_task_environment.h" #import "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" @@ -243,3 +247,47 @@ EXPECT_OCMOCK_VERIFY(consumer()); } + +// Verifies that the `kPasswordCheckupPageOptIn` value is correctly logged +// in the `IOS.Notifications.SafetyCheck.NotificationsOptInSource` histogram +// when notifications are enabled. +TEST_F(PasswordCheckupMediatorTest, FiresOptInForSafetyCheckNotifications) { + feature_list_.InitAndEnableFeature(kSafetyCheckNotifications); + + // Configure notifications to be disabled initially. + UpdateSafetyCheckNotificationsPermission(NO); + + base::HistogramTester histogram_tester; + + // Simulate the toggle action. + [mediator() toggleSafetyCheckNotifications]; + + // Verify the histogram was fired for opting in. + histogram_tester.ExpectUniqueSample( + "IOS.Notifications.SafetyCheck.NotificationsOptInSource", + static_cast<int>( + SafetyCheckNotificationsOptInSource::kPasswordCheckupPageOptIn), + 1); +} + +// Verifies that the `kPasswordCheckupPageOptOut` value is correctly logged +// in the `IOS.Notifications.SafetyCheck.NotificationsOptInSource` histogram +// when notifications are disabled. +TEST_F(PasswordCheckupMediatorTest, FiresOptOutForSafetyCheckNotifications) { + feature_list_.InitAndEnableFeature(kSafetyCheckNotifications); + + // Configure notifications to be enabled initially. + UpdateSafetyCheckNotificationsPermission(YES); + + base::HistogramTester histogram_tester; + + // Simulate the toggle action. + [mediator() toggleSafetyCheckNotifications]; + + // Verify the histogram was fired for opting out. + histogram_tester.ExpectUniqueSample( + "IOS.Notifications.SafetyCheck.NotificationsOptInSource", + static_cast<int>( + SafetyCheckNotificationsOptInSource::kPasswordCheckupPageOptOut), + 1); +}
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/safety_check/BUILD.gn index 665e463d..8af9cfe 100644 --- a/ios/chrome/browser/settings/ui_bundled/safety_check/BUILD.gn +++ b/ios/chrome/browser/settings/ui_bundled/safety_check/BUILD.gn
@@ -68,6 +68,8 @@ "//ios/chrome/browser/push_notification/model:push_notification_service_header", "//ios/chrome/browser/push_notification/model:push_notification_settings_util_header", "//ios/chrome/browser/push_notification/ui_bundled:opt_in_alert_coordinator", + "//ios/chrome/browser/safety_check_notifications/utils", + "//ios/chrome/browser/safety_check_notifications/utils:constants", "//ios/chrome/browser/settings/ui_bundled:settings_root", "//ios/chrome/browser/settings/ui_bundled/cells", "//ios/chrome/browser/settings/ui_bundled/cells:public", @@ -85,6 +87,7 @@ "//ios/chrome/browser/shared/model/utils", "//ios/chrome/browser/shared/public/commands", "//ios/chrome/browser/shared/public/features", + "//ios/chrome/browser/shared/ui/list_model", "//ios/chrome/browser/shared/ui/symbols", "//ios/chrome/browser/shared/ui/table_view", "//ios/chrome/browser/shared/ui/table_view:utils", @@ -133,6 +136,8 @@ "//ios/chrome/app/strings", "//ios/chrome/browser/affiliations/model", "//ios/chrome/browser/passwords/model", + "//ios/chrome/browser/safety_check_notifications/utils:constants", + "//ios/chrome/browser/safety_check_notifications/utils:test_utils", "//ios/chrome/browser/settings/ui_bundled/cells", "//ios/chrome/browser/settings/ui_bundled/utils", "//ios/chrome/browser/shared/model/application_context",
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/DEPS b/ios/chrome/browser/settings/ui_bundled/safety_check/DEPS index ff759cbf..3702b16 100644 --- a/ios/chrome/browser/settings/ui_bundled/safety_check/DEPS +++ b/ios/chrome/browser/settings/ui_bundled/safety_check/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+ios/chrome/browser/push_notification/ui_bundled", + "+ios/chrome/browser/safety_check_notifications/utils", ]
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h index 48f3dc3e..3014163 100644 --- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h +++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h
@@ -10,6 +10,7 @@ #import "base/memory/scoped_refptr.h" #import "ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_delegate.h" #import "ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_service_delegate.h" +#import "ios/chrome/browser/shared/ui/list_model/list_model.h" // Webpage with safe browsing toggle. extern const char kSafeBrowsingStringURL[]; @@ -29,6 +30,30 @@ @class SafetyCheckTableViewController; +// Enum representing the different item types used in the Safety Check UI. +// These item types correspond to various sections and functionalities +// displayed within the Safety Check feature, including update checks, +// password checks, Safe Browsing status, and notifications opt-in settings. +// +// The values are grouped as follows: +// - CheckTypes section: Items related to checking updates, passwords, and Safe +// Browsing status. +// - CheckStart section: Items related to starting or stopping the Safety Check +// process. +// - Notifications opt-in section: Items for managing notifications preferences. +typedef NS_ENUM(NSInteger, SafetyCheckItemType) { + // CheckTypes section. + UpdateItemType = kItemTypeEnumZero, + PasswordItemType, + SafeBrowsingItemType, + HeaderItem, + // CheckStart section. + CheckStartItemType, + TimestampFooterItem, + // Notifications opt-in section. + NotificationsOptInItemType, +}; + // The mediator is pushing the data for the safety check to the consumer. @interface SafetyCheckMediator : NSObject <SafetyCheckServiceDelegate>
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm index 32c73100..c618f0a 100644 --- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm +++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm
@@ -31,6 +31,8 @@ #import "ios/chrome/browser/passwords/model/password_store_observer_bridge.h" #import "ios/chrome/browser/push_notification/model/push_notification_client_id.h" #import "ios/chrome/browser/push_notification/model/push_notification_settings_util.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/safety_check_notifications/utils/utils.h" #import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h" #import "ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_constants.h" #import "ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_consumer.h" @@ -75,19 +77,6 @@ typedef NSArray<TableViewItem*>* ItemArray; -typedef NS_ENUM(NSInteger, SafteyCheckItemType) { - // CheckTypes section. - UpdateItemType = kItemTypeEnumZero, - PasswordItemType, - SafeBrowsingItemType, - HeaderItem, - // CheckStart section. - CheckStartItemType, - TimestampFooterItem, - // Notifications opt-in section. - NotificationsOptInItemType, -}; - // The minimum time each of the three checks should show a running state. This // is to prevent any check that finshes quicky from causing the UI to appear // jittery. The numbers are all different so that no 2 tests finish at the same @@ -454,7 +443,7 @@ #pragma mark - SafetyCheckServiceDelegate - (void)didSelectItem:(TableViewItem*)item { - SafteyCheckItemType type = static_cast<SafteyCheckItemType>(item.type); + SafetyCheckItemType type = static_cast<SafetyCheckItemType>(item.type); switch (type) { // Few selections are handled here explicitly, but all states are laid out // to have one location that shows all actions that are taken from the @@ -531,6 +520,10 @@ break; } case NotificationsOptInItemType: { + LogSafetyCheckNotificationOptInSource( + SafetyCheckNotificationsOptInSource::kSafetyCheckPageOptIn, + SafetyCheckNotificationsOptInSource::kSafetyCheckPageOptOut); + [self.delegate toggleSafetyCheckNotifications]; break; } @@ -541,7 +534,7 @@ } - (BOOL)isItemClickable:(TableViewItem*)item { - SafteyCheckItemType type = static_cast<SafteyCheckItemType>(item.type); + SafetyCheckItemType type = static_cast<SafetyCheckItemType>(item.type); switch (type) { case UpdateItemType: return self.updateCheckRowState == UpdateCheckRowStateOutOfDate; @@ -562,7 +555,7 @@ } - (BOOL)isItemWithErrorInfo:(TableViewItem*)item { - SafteyCheckItemType type = static_cast<SafteyCheckItemType>(item.type); + SafetyCheckItemType type = static_cast<SafetyCheckItemType>(item.type); return (type != CheckStartItemType && type != NotificationsOptInItemType); } @@ -609,7 +602,7 @@ // Computes the text needed for a popover on `itemType` if available. - (NSAttributedString*)popoverInfoForType:(NSInteger)itemType { - SafteyCheckItemType type = static_cast<SafteyCheckItemType>(itemType); + SafetyCheckItemType type = static_cast<SafetyCheckItemType>(itemType); switch (type) { case PasswordItemType: return [self passwordCheckErrorInfo];
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm index c2a9a1e..978b7fc 100644 --- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm +++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm
@@ -34,6 +34,8 @@ #import "ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h" #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h" #import "ios/chrome/browser/passwords/model/password_check_observer_bridge.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/safety_check_notifications/utils/test_utils.h" #import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h" #import "ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_constants.h" #import "ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_consumer.h" @@ -74,17 +76,6 @@ using password_manager::InsecureType; using password_manager::TestPasswordStore; -typedef NS_ENUM(NSInteger, SafetyCheckItemType) { - // CheckTypes section. - UpdateItemType = kItemTypeEnumZero, - PasswordItemType, - SafeBrowsingItemType, - HeaderItem, - // CheckStart section. - CheckStartItemType, - TimestampFooterItem, -}; - // The size of trailing symbol icons. NSInteger kTrailingSymbolImagePointSize = 22; @@ -863,3 +854,45 @@ GetNSString( IDS_IOS_SAFETY_CHECK_NOTIFICATIONS_TURN_ON_NOTIFICATIONS_ELLIPSIS)); } + +// Tests that the histogram is correctly fired for opting in to notifications. +TEST_F(SafetyCheckMediatorTest, NotificationsHistogramFiresForOptIn) { + feature_list_.InitWithFeatures({kSafetyCheckNotifications}, {}); + + UpdateSafetyCheckNotificationsPermission(NO); + + TableViewItem* opt_in_item = + [[TableViewItem alloc] initWithType:NotificationsOptInItemType]; + + base::HistogramTester histogram_tester; + + [mediator_ didSelectItem:opt_in_item]; + + // Verify the histogram fired for opting in. + histogram_tester.ExpectUniqueSample( + "IOS.Notifications.SafetyCheck.NotificationsOptInSource", + static_cast<int>( + SafetyCheckNotificationsOptInSource::kSafetyCheckPageOptIn), + 1); +} + +// Tests that the histogram is correctly fired for opting out of notifications. +TEST_F(SafetyCheckMediatorTest, NotificationsHistogramFiresForOptOut) { + feature_list_.InitWithFeatures({kSafetyCheckNotifications}, {}); + + UpdateSafetyCheckNotificationsPermission(YES); + + TableViewItem* opt_in_item = + [[TableViewItem alloc] initWithType:NotificationsOptInItemType]; + + base::HistogramTester histogram_tester; + + [mediator_ didSelectItem:opt_in_item]; + + // Verify the histogram fired for opting out. + histogram_tester.ExpectUniqueSample( + "IOS.Notifications.SafetyCheck.NotificationsOptInSource", + static_cast<int>( + SafetyCheckNotificationsOptInSource::kSafetyCheckPageOptOut), + 1); +}
diff --git a/ios/chrome/browser/tips_notifications/model/BUILD.gn b/ios/chrome/browser/tips_notifications/model/BUILD.gn index 9ce6b05..5c4a5fa3 100644 --- a/ios/chrome/browser/tips_notifications/model/BUILD.gn +++ b/ios/chrome/browser/tips_notifications/model/BUILD.gn
@@ -17,6 +17,7 @@ "//ios/chrome/browser/default_browser/model:utils", "//ios/chrome/browser/feature_engagement/model", "//ios/chrome/browser/lens/ui_bundled:lens_availability", + "//ios/chrome/browser/ntp/model:features", "//ios/chrome/browser/ntp/model:set_up_list_prefs", "//ios/chrome/browser/push_notification/model:constants", "//ios/chrome/browser/push_notification/model:push_notification_client",
diff --git a/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm b/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm index 54a09035..a6f9390 100644 --- a/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm +++ b/ios/chrome/browser/tips_notifications/model/tips_notification_client.mm
@@ -20,6 +20,7 @@ #import "ios/chrome/browser/default_browser/model/utils.h" #import "ios/chrome/browser/feature_engagement/model/tracker_factory.h" #import "ios/chrome/browser/lens/ui_bundled/lens_availability.h" +#import "ios/chrome/browser/ntp/model/features.h" #import "ios/chrome/browser/ntp/model/set_up_list_prefs.h" #import "ios/chrome/browser/push_notification/model/constants.h" #import "ios/chrome/browser/push_notification/model/push_notification_client.h" @@ -437,11 +438,10 @@ return false; } - // The Set Up List only shows for 14 days after FirstRun, so this - // notification should only be requested 14 days minus the trigger interval - // after FirstRun. + // This notification should only be requested during the duration of the Set + // Up List minus the trigger interval after FirstRun. if (!IsFirstRunRecent( - base::Days(14) - + set_up_list::SetUpListDuration() - TipsNotificationTriggerDelta(CanSendReactivation(), user_type_))) { return false; }
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index f4881c9..9860e5b 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -79,6 +79,8 @@ "//ios/chrome/browser/reading_list/model", "//ios/chrome/browser/safety_check/model", "//ios/chrome/browser/safety_check/model:factory", + "//ios/chrome/browser/safety_check_notifications/utils", + "//ios/chrome/browser/safety_check_notifications/utils:constants", "//ios/chrome/browser/search_engines/model:template_url_service_factory", "//ios/chrome/browser/segmentation_platform/model", "//ios/chrome/browser/settings/ui_bundled/notifications:utils",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 6ebbd63..f5ea63a 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -77,6 +77,8 @@ #import "ios/chrome/browser/reading_list/model/reading_list_model_factory.h" #import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.h" #import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_factory.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/safety_check_notifications/utils/utils.h" #import "ios/chrome/browser/search_engines/model/template_url_service_factory.h" #import "ios/chrome/browser/segmentation_platform/model/segmentation_platform_service_factory.h" #import "ios/chrome/browser/shared/coordinator/alert/action_sheet_coordinator.h" @@ -133,7 +135,6 @@ #import "ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_utils.h" #import "ios/chrome/browser/ui/content_suggestions/magic_stack_half_sheet_mediator.h" #import "ios/chrome/browser/ui/content_suggestions/magic_stack_half_sheet_table_view_controller.h" -#import "ios/chrome/browser/ui/content_suggestions/notifications_module_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h" #import "ios/chrome/browser/ui/content_suggestions/parcel_tracking/magic_stack_parcel_list_half_sheet_table_view_controller.h" #import "ios/chrome/browser/ui/content_suggestions/parcel_tracking/parcel_tracking_mediator.h" @@ -167,6 +168,29 @@ #import "ui/base/l10n/l10n_util_mac.h" #import "url/gurl.h" +namespace { + +// Logs the user's decision to opt-in or opt-out of Safety Check notifications +// from the Magic Stack. Determines the source based on the `viaContextMenu` +// flag: if `true`, the action is logged as originating from the long-press +// menu; otherwise, it is logged as originating from the top-right action +// button. +void LogSafetyCheckNotificationOptIn(bool viaContextMenu) { + if (viaContextMenu) { + LogSafetyCheckNotificationOptInSource( + SafetyCheckNotificationsOptInSource::kMagicStackLongPressMenuOptIn, + SafetyCheckNotificationsOptInSource::kMagicStackLongPressMenuOptOut); + } else { + LogSafetyCheckNotificationOptInSource( + SafetyCheckNotificationsOptInSource:: + kMagicStackTopRightActionButtonOptIn, + SafetyCheckNotificationsOptInSource:: + kMagicStackTopRightActionButtonOptOut); + } +} + +} // namespace + using segmentation_platform::TipIdentifier; @interface ContentSuggestionsCoordinator () < @@ -177,7 +201,6 @@ MagicStackModuleContainerDelegate, MagicStackParcelListHalfSheetTableViewControllerDelegate, TipsPasswordsCoordinatorDelegate, - NotificationsModuleDelegate, NotificationsOptInAlertCoordinatorDelegate, NotificationsOptInCoordinatorDelegate, PriceTrackingPromoActionDelegate, @@ -924,13 +947,16 @@ NOTREACHED(); } -- (void)enableNotifications:(ContentSuggestionsModuleType)type { +- (void)enableNotifications:(ContentSuggestionsModuleType)type + viaContextMenu:(BOOL)viaContextMenu { // This is only supported for Set Up List, Tips, Send Tab, and Safety Check // modules. CHECK(IsSetUpListModuleType(type) || IsTipsModuleType(type) || type == ContentSuggestionsModuleType::kSafetyCheck || type == ContentSuggestionsModuleType::kSendTabPromo); + LogSafetyCheckNotificationOptIn(viaContextMenu); + // Ask user for permission to opt-in to notifications. [_notificationsOptInAlertCoordinator stop]; @@ -955,13 +981,16 @@ [_notificationsOptInAlertCoordinator start]; } -- (void)disableNotifications:(ContentSuggestionsModuleType)type { +- (void)disableNotifications:(ContentSuggestionsModuleType)type + viaContextMenu:(BOOL)viaContextMenu { // This is only supported for Set Up List, Tips, Send Tab, and Safety Check // modules. CHECK(IsSetUpListModuleType(type) || IsTipsModuleType(type) || type == ContentSuggestionsModuleType::kSafetyCheck || type == ContentSuggestionsModuleType::kSendTabPromo); + LogSafetyCheckNotificationOptIn(viaContextMenu); + id<SystemIdentity> identity = self.authService->GetPrimaryIdentity(signin::ConsentLevel::kSignin); @@ -1303,7 +1332,8 @@ UNNotificationSettings* settings) { if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) { for (PushNotificationClientId clientId : clientIds) { - [self enableNotifications:[self contentSuggestionsModuleType:clientId]]; + [self enableNotifications:[self contentSuggestionsModuleType:clientId] + viaContextMenu:NO]; } } }];
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/magic_stack/BUILD.gn index 69f52aaa..cabfe5d 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/BUILD.gn
@@ -45,6 +45,7 @@ "//components/send_tab_to_self", "//ios/chrome/browser/lens/ui_bundled:lens_availability", "//ios/chrome/browser/lens/ui_bundled:lens_entrypoint", + "//ios/chrome/browser/ntp/model:features", "//ios/chrome/browser/ntp/ui_bundled", "//ios/chrome/browser/ntp_tiles/model/tab_resumption:tab_resumption_prefs", "//ios/chrome/browser/parcel_tracking:features",
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_collection_view_cell.mm b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_collection_view_cell.mm index e97dcae..ac198c5 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_collection_view_cell.mm +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_collection_view_cell.mm
@@ -234,9 +234,11 @@ identifier:nil handler:^(UIAction* action) { if (optedIn) { - [weakSelf.delegate disableNotifications:weakSelf.type]; + [weakSelf.delegate disableNotifications:weakSelf.type + viaContextMenu:YES]; } else { - [weakSelf.delegate enableNotifications:weakSelf.type]; + [weakSelf.delegate enableNotifications:weakSelf.type + viaContextMenu:YES]; } }]; }
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm index 6fe173e..ce435f6 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container.mm
@@ -491,7 +491,7 @@ // Handles taps on the notifications opt-in button. - (void)notificationsOptInButtonWasTapped:(UIButton*)button { - [_delegate enableNotifications:_type]; + [_delegate enableNotifications:_type viaContextMenu:NO]; } // Determines if a subtitle should be displayed. Currently, a subtitle is
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h index 74821e3..4f46bf1 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h
@@ -20,13 +20,19 @@ // anymore. - (void)neverShowModuleType:(ContentSuggestionsModuleType)type; -// Indicates that the user has tapped the context menu item to enable -// notifications. -- (void)enableNotifications:(ContentSuggestionsModuleType)type; +// Indicates that the user has enabled notifications. The source of the action +// is specified by the `viaContextMenu` parameter, which is YES if the user +// enabled notifications via the context menu, and NO if the action originated +// from the top-right action button. +- (void)enableNotifications:(ContentSuggestionsModuleType)type + viaContextMenu:(BOOL)viaContextMenu; -// Indicates that the user has tapped the context menu item to disable -// notifications. -- (void)disableNotifications:(ContentSuggestionsModuleType)type; +// Indicates that the user has disabled notifications. The source of the action +// is specified by the `viaContextMenu` parameter, which is YES if the user +// disabled notifications via the context menu, and NO if the action originated +// from the top-right action button. +- (void)disableNotifications:(ContentSuggestionsModuleType)type + viaContextMenu:(BOOL)viaContextMenu; // Indicates that the user has tapped the context menu item to edit the Magic // Stack modules.
diff --git a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_ranking_model.mm b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_ranking_model.mm index 7776b55..a3dd8d2a 100644 --- a/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_ranking_model.mm +++ b/ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_ranking_model.mm
@@ -35,6 +35,7 @@ #import "components/send_tab_to_self/pref_names.h" #import "ios/chrome/browser/lens/ui_bundled/lens_availability.h" #import "ios/chrome/browser/lens/ui_bundled/lens_entrypoint.h" +#import "ios/chrome/browser/ntp/model/features.h" #import "ios/chrome/browser/ntp/ui_bundled/home_start_data_source.h" #import "ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.h" #import "ios/chrome/browser/parcel_tracking/features.h" @@ -437,7 +438,7 @@ inputContext->metadata_args.emplace( segmentation_platform::kIsNewUser, segmentation_platform::processing::ProcessedValue::FromFloat( - IsFirstRunRecent(base::Days(14)))); + IsFirstRunRecent(set_up_list::SetUpListDuration()))); } if (base::FeatureList::IsEnabled(commerce::kPriceTrackingPromo)) {
diff --git a/ios/chrome/browser/ui/content_suggestions/notifications_module_delegate.h b/ios/chrome/browser/ui/content_suggestions/notifications_module_delegate.h deleted file mode 100644 index fa61235..0000000 --- a/ios/chrome/browser/ui/content_suggestions/notifications_module_delegate.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NOTIFICATIONS_MODULE_DELEGATE_H_ -#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NOTIFICATIONS_MODULE_DELEGATE_H_ - -enum class ContentSuggestionsModuleType; - -// Protocol for relaying notification events from Magic Stack modules to Content -// Suggestions. -@protocol NotificationsModuleDelegate - -// Enables notifications for the module of the given `type`. -- (void)enableNotifications:(ContentSuggestionsModuleType)type; - -@end - -#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_NOTIFICATIONS_MODULE_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.h b/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.h index 335dab6..7781281 100644 --- a/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.h +++ b/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.h
@@ -10,7 +10,7 @@ #import "ios/chrome/browser/ui/content_suggestions/standalone_module_delegate.h" class FaviconLoader; -@protocol NotificationsModuleDelegate; +@protocol MagicStackModuleContainerDelegate; class PrefService; @class SendTabPromoItem; @@ -36,7 +36,7 @@ // Delegate used to communicate notification events back to the owner of this // class. -@property(nonatomic, weak) id<NotificationsModuleDelegate> +@property(nonatomic, weak) id<MagicStackModuleContainerDelegate> notificationsDelegate; // Default initializer.
diff --git a/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.mm b/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.mm index 31eb759..2d4505f 100644 --- a/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_mediator.mm
@@ -10,7 +10,7 @@ #import "components/send_tab_to_self/pref_names.h" #import "ios/chrome/browser/favicon/model/favicon_loader.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h" -#import "ios/chrome/browser/ui/content_suggestions/notifications_module_delegate.h" +#import "ios/chrome/browser/ui/content_suggestions/magic_stack/magic_stack_module_container_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/send_tab_to_self/send_tab_promo_item.h" #import "ios/chrome/common/ui/favicon/favicon_attributes.h" #import "ios/chrome/common/ui/favicon/favicon_constants.h" @@ -59,7 +59,7 @@ CHECK(moduleType == ContentSuggestionsModuleType::kSendTabPromo); base::UmaHistogramBoolean( "IOS.Notifications.SendTab.MagicStack.AllowNotificationsPressed", true); - [self.notificationsDelegate enableNotifications:moduleType]; + [self.notificationsDelegate enableNotifications:moduleType viaContextMenu:NO]; } #pragma mark - Private
diff --git a/ios/chrome/browser/ui/content_suggestions/set_up_list/utils.mm b/ios/chrome/browser/ui/content_suggestions/set_up_list/utils.mm index b35e752c..2a19820a 100644 --- a/ios/chrome/browser/ui/content_suggestions/set_up_list/utils.mm +++ b/ios/chrome/browser/ui/content_suggestions/set_up_list/utils.mm
@@ -28,7 +28,8 @@ return false; } } - // Check if we are within 14 days of FRE. + // Check if we are within the duration of the Set Up List, relevant to the + // FRE. if (set_up_list::GetSetUpListInFirstRunVariation() == set_up_list::FirstRunVariationType::kDisabled && IsFirstRun()) { @@ -36,9 +37,9 @@ // have been completed yet. In this case, we will wait until the next run. return false; } - if (!IsFirstRunRecent(base::Days(14))) { - // It has been 14+ days since FRE, but if user has interacted in the last - // day the time will be extended. + if (!IsFirstRunRecent(set_up_list::SetUpListDuration())) { + // It is past the max duration of the Set Up List, but if user has + // interacted in the last day the time will be extended. base::Time last_interaction = set_up_list_prefs::GetLastInteraction(local_prefs); if (base::Time::Now() > last_interaction + base::Days(1)) {
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 index 03c2841b..2adf7e8e 100644 --- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -67fa581445b792ee0ce5c4ac15e136de4051335a \ No newline at end of file +1eebf20d60eca97ad0a62a588601310940141104 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 index cc9d957c..3ab745f 100644 --- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@ -b3927dc36b55307e3938f0e9980c65d02148438f \ No newline at end of file +461dcdc35a29a08c3498300a09206a021e882117 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index 61495101..dd3215d 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -6e6d1e63cf2d088c3f9062d3dbeccd71e1d6cf30 \ No newline at end of file +cfc0de4cebae2ec4b10c2a8107c462ec2a4a0684 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 index fbdb8a66..33f0e67 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@ -7a3d731f90d0a797a24bb89c69974e13228d41f3 \ No newline at end of file +64c717b672604c5e820dffa440fd0745ba62a1ea \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index 6f7d5c529..31c0cbfc 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -a672772487b71dd5f190c169077999ce175d0a2a \ No newline at end of file +b8cd0bee8abc190a7c76c1084efa8283357db68a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 index 3e02b38..c36f2ab 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@ -f645741f39da4b07d6285ff0d58b1f3e0dd7115c \ No newline at end of file +df5db730cf6945093fb2b8902eb8116bbeadc5c6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 index f619177..6b0a7f4 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -a64f2ce1a1f181fbf8edc5bb79b8196f7299a917 \ No newline at end of file +44b2a856f4e33bc38f4354edf59bb0b3763e2d7f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 index 3c5cf67c..9a825cdc 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -4dcebd253d5b91faf6e914ed60064101debb8ffa \ No newline at end of file +732c3d3ae1ca74b64f17ea9bce670e21462e8261 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 index 90b6c24..4a15976 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -3ddb67f3c7942f952289aa1a7203b7d415152251 \ No newline at end of file +fc63d8c652b0e2e3edd8d66b38a144e74b66dde6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 index ea60fc24..7d2efa8 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -040f8a616b03b161f10d8de173d1486abb84e7ac \ No newline at end of file +93f4c30be832727ca7f53f12bc75a9a357f52dc6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index fe02ada..bf508221 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -424147614372805a64f29422cbfaeb82c5f34f2b \ No newline at end of file +329017edb637dc43b04cb8e45d9c215479fda0d8 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 index 30ef086a..bd0f1ad 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -01239d6ef9bec692a88e99ac3105c50b8800371c \ No newline at end of file +c75305d72e51e2dfa38b354179ec4f51aa3380d3 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 39b9593..e94c1ef 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -9802069f6eb5773d4ce7c8a8e85578c58a0d3456 \ No newline at end of file +9874c1eb3303451c2927e2821abd156079e3e19f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 0c0b4bb6..d7bae38 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -13c8b2841614789e3166aec59c8b554bbc9f57ab \ No newline at end of file +ec08d93d84ecbeee4e8382f50eed038ea7bfbff5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 64a5e6a..c042699 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -af5592d7124912f372354340ef7ebaa779f70a1e \ No newline at end of file +4f6bbffb87933f555fca7a771ebe8fabd016bfcc \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 index 8eb8fb85..d299763 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -bfae0b4faf37d5b08e9c8502aee2d0c72662f7d5 \ No newline at end of file +451c64b24bf8b9d63fa827917fa70059ce70274d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index d1b594c..c4802aff 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -38b8379d242438860e311364e6d2aa6963a3a87c \ No newline at end of file +4a430fa30e0557bc460f9c8a906553a7cf415cc0 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 8dc8546..b4000788 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -96ecb5ee4eabc045fed85d8badf1989f2802689f \ No newline at end of file +0578721d9b5094c267fd00649ea1f14c1faa107d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index 838c24d0..186958f 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -77d9a2f814c9760d872bcea3a2dc7f3f694bc22c \ No newline at end of file +dd04c8e420d4993d49b379afb4b36a070cda4979 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index 4413b047cb..ea846cf 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -f25f65c0dec373e075f776dd4747c3d20da3f101 \ No newline at end of file +84dc9ba951d491d963299e039f340191a517c7d4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 3044ef39..8d87cda6 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -efbc31bc0c1da473596c3caf46594f3217850527 \ No newline at end of file +f82f9eba19dfd4b6c703509d1cbbddfd4777fda2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 index fdc3e8a..1602fb2 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -e5d6d1dd34c04313e902c37947cc17a7013744ba \ No newline at end of file +9f48816b9998b7910ce0f47612e7e386472d77b1 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 1f0620c4..61b4f877 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -d128cb9cb347d33622dd1d88273872475e95fee4 \ No newline at end of file +b30b76deec6e70282d2a87bf915d45833d3e6502 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 9b6983e..937878c9 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -57dcdace9522a19efccf049c2c716f5ee9b354c7 \ No newline at end of file +39324873fba78cf2275ad8ccb92cd567c660065a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 5b44673..5220ec3 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -df846fc3a0ebca739c7f7270d769bce2cc34676b \ No newline at end of file +3b2988000923fd77149b10043d8869bd20304f7f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 index 2c5f8710..05f130b 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -0ff3b78cddd9b33093d5980631209d1f5dafcd95 \ No newline at end of file +b6bb8d1f464e575bfdba90ed3b614f3b5fc98edc \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 8bf8d9f6..5b4e5de 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -7896c956eed6bc89d17fe024fe1550fccadf6b2b \ No newline at end of file +74e5cec1c4f0a208398893ca8aab27c2ddf56fd6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 index c223c02..727abb3a5a 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -4842d777376c45725f471baa74f97a197e4a7011 \ No newline at end of file +58e482f6d794206f618ecabcaf2e3ad7da541e75 \ No newline at end of file
diff --git a/ios_internal b/ios_internal index 603eaf7..8804f34 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 603eaf71b0c1cccaa12b473013d621fffa56d087 +Subproject commit 8804f341dfbd03ceec57471c98bcaba90b64eaf9
diff --git a/media/cast/cast_config.cc b/media/cast/cast_config.cc index d4a2539..a372a6e 100644 --- a/media/cast/cast_config.cc +++ b/media/cast/cast_config.cc
@@ -22,7 +22,6 @@ uint32_t receiver_ssrc, base::TimeDelta min_playout_delay, base::TimeDelta max_playout_delay, - RtpPayloadType rtp_payload_type, bool use_hardware_encoder, int rtp_timebase, int channels, @@ -38,7 +37,6 @@ receiver_ssrc(receiver_ssrc), min_playout_delay(min_playout_delay), max_playout_delay(max_playout_delay), - rtp_payload_type(rtp_payload_type), use_hardware_encoder(use_hardware_encoder), rtp_timebase(rtp_timebase), channels(channels),
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h index 013ed64..25f6349cfb 100644 --- a/media/cast/cast_config.h +++ b/media/cast/cast_config.h
@@ -24,39 +24,6 @@ namespace cast { -// Describes the content being transported over RTP streams. -enum class RtpPayloadType { - UNKNOWN = -1, - - // Cast Streaming will encode raw audio frames using one of its available - // codec implementations, and transport encoded data in the RTP stream. - FIRST = 96, - AUDIO_OPUS = 96, - AUDIO_AAC = 97, - AUDIO_PCM16 = 98, - - // Audio frame data is not modified, and should be transported reliably and - // in-sequence. No assumptions about the data can be made. - REMOTE_AUDIO = 99, - - AUDIO_LAST = REMOTE_AUDIO, - - // Cast Streaming will encode raw video frames using one of its available - // codec implementations, and transport encoded data in the RTP stream. - VIDEO_VP8 = 100, - VIDEO_H264 = 101, - - // Video frame data is not modified, and should be transported reliably and - // in-sequence. No assumptions about the data can be made. - REMOTE_VIDEO = 102, - - VIDEO_VP9 = 103, - - VIDEO_AV1 = 104, - - LAST = VIDEO_AV1 -}; - // Desired end-to-end latency. constexpr base::TimeDelta kDefaultTargetPlayoutDelay = base::Milliseconds(400); @@ -145,7 +112,6 @@ uint32_t receiver_ssrc, base::TimeDelta min_playout_delay, base::TimeDelta max_playout_delay, - RtpPayloadType rtp_payload_type, bool use_hardware_encoder, int rtp_timebase, int channels, @@ -182,20 +148,12 @@ base::TimeDelta min_playout_delay = kDefaultTargetPlayoutDelay; base::TimeDelta max_playout_delay = kDefaultTargetPlayoutDelay; - // RTP payload type enum: Specifies the type/encoding of frame data. - RtpPayloadType rtp_payload_type = RtpPayloadType::UNKNOWN; - - bool is_audio() const { - return rtp_payload_type >= RtpPayloadType::FIRST && - rtp_payload_type <= RtpPayloadType::AUDIO_LAST; - } - bool is_video() const { - return rtp_payload_type >= RtpPayloadType::VIDEO_VP8 && - rtp_payload_type <= RtpPayloadType::LAST; - } + bool is_audio() const { return audio_codec_params.has_value(); } + bool is_video() const { return video_codec_params.has_value(); } bool is_remoting() const { - return rtp_payload_type == RtpPayloadType::REMOTE_AUDIO || - rtp_payload_type == RtpPayloadType::REMOTE_VIDEO; + return (audio_codec_params && + audio_codec() == media::AudioCodec::kUnknown) || + (video_codec_params && video_codec() == media::VideoCodec::kUnknown); } // If true, use an external HW encoder rather than the built-in
diff --git a/media/cast/encoding/size_adaptable_video_encoder_base.cc b/media/cast/encoding/size_adaptable_video_encoder_base.cc index 9de9c4a3..fd8b9db 100644 --- a/media/cast/encoding/size_adaptable_video_encoder_base.cc +++ b/media/cast/encoding/size_adaptable_video_encoder_base.cc
@@ -84,13 +84,6 @@ } } -void SizeAdaptableVideoEncoderBase::EmitFrames() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - if (encoder_) { - encoder_->EmitFrames(); - } -} - StatusChangeCallback SizeAdaptableVideoEncoderBase::CreateEncoderStatusChangeCallback() { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); @@ -126,12 +119,7 @@ // If prior frames are still encoding in the current encoder, let them finish // first. if (frames_in_encoder_ > 0) { - encoder_->EmitFrames(); - // Check again, since EmitFrames() is a synchronous operation for some - // encoders. - if (frames_in_encoder_ > 0) { - return; - } + return; } if (frames_in_encoder_ == kEncoderIsInitializing) {
diff --git a/media/cast/encoding/size_adaptable_video_encoder_base.h b/media/cast/encoding/size_adaptable_video_encoder_base.h index 8ea670f..0464368 100644 --- a/media/cast/encoding/size_adaptable_video_encoder_base.h +++ b/media/cast/encoding/size_adaptable_video_encoder_base.h
@@ -50,7 +50,6 @@ base::TimeTicks reference_time) final; void SetBitRate(int new_bit_rate) final; void GenerateKeyFrame() final; - void EmitFrames() final; protected: // Accessors for subclasses.
diff --git a/media/cast/encoding/video_encoder.cc b/media/cast/encoding/video_encoder.cc index 8e26d64..ff4bf3a5 100644 --- a/media/cast/encoding/video_encoder.cc +++ b/media/cast/encoding/video_encoder.cc
@@ -46,6 +46,4 @@ status_change_cb, std::move(output_cb)); } -void VideoEncoder::EmitFrames() {} - } // namespace media::cast
diff --git a/media/cast/encoding/video_encoder.h b/media/cast/encoding/video_encoder.h index 47f3a27..efb4bc68 100644 --- a/media/cast/encoding/video_encoder.h +++ b/media/cast/encoding/video_encoder.h
@@ -23,16 +23,19 @@ struct SenderEncodedFrame; -// All these functions are called from the main cast thread. +// This interface encapsulates logic for encoding video frames, and abstracts +// out complexities related to specific encoder implementations. +// +// NOTE: All public methods must be called from the MAIN CastEnvironment thread. class VideoEncoder { public: - // Callback used to deliver an encoded frame on the Cast MAIN thread. + // Callback used to deliver an encoded frame on the MAIN thread. using FrameEncodedCallback = base::RepeatingCallback<void(std::unique_ptr<SenderEncodedFrame>)>; - // Creates a VideoEncoder instance from the given |video_config| and based on + // Creates a VideoEncoder instance from the given `video_config` and based on // the current platform's hardware/library support; or null if no - // implementation will suffice. The instance will run |status_change_cb| at + // implementation will suffice. The instance will run `status_change_cb` at // some point in the future to indicate initialization success/failure. // // All VideoEncoder instances returned by this function support encoding @@ -48,25 +51,20 @@ virtual ~VideoEncoder() {} // If true is returned, the Encoder has accepted the request and will process - // it asynchronously, running |output_cb_| on the MAIN - // CastEnvironment thread with the result. If false is returned, nothing - // happens and the callback will not be run. - virtual bool EncodeVideoFrame(scoped_refptr<media::VideoFrame> video_frame, - base::TimeTicks reference_time) = 0; + // it asynchronously, running `output_cb_` on the MAIN CastEnvironment thread + // with the result. If false is returned, the video frame has been dropped and + // the `output_cb_` will not be called. This may be due to the encoder being + // overloaded, in which case the calling class can just try again. More + // serious errors will be reported through the `status_change_cb_`. + [[nodiscard]] virtual bool EncodeVideoFrame( + scoped_refptr<media::VideoFrame> video_frame, + base::TimeTicks reference_time) = 0; // Inform the encoder about the new target bit rate. virtual void SetBitRate(int new_bit_rate) = 0; // Inform the encoder to encode the next frame as a key frame. virtual void GenerateKeyFrame() = 0; - - // Instructs the encoder to finish and emit all frames that have been - // submitted for encoding. An encoder may hold a certain number of frames for - // analysis. Under certain network conditions, particularly when there is - // network congestion, it is necessary to flush out of the encoder all - // submitted frames so that eventually new frames may be encoded. Like - // EncodeVideoFrame(), the encoder will process this request asynchronously. - virtual void EmitFrames(); }; } // namespace cast
diff --git a/media/cast/encoding/video_encoder_unittest.cc b/media/cast/encoding/video_encoder_unittest.cc index 845a923..11553ec 100644 --- a/media/cast/encoding/video_encoder_unittest.cc +++ b/media/cast/encoding/video_encoder_unittest.cc
@@ -273,9 +273,7 @@ } } - // Flush the encoder and wait until all queued frames have been delivered. - // Then, shut it all down. - video_encoder()->EmitFrames(); + // Wait until all queued frames have been delivered then shut everything down. while (encoded_frames.size() < static_cast<size_t>(count_frames_accepted)) RunTasksAndAdvanceClock(); DestroyEncoder(); @@ -328,8 +326,13 @@ [](std::unique_ptr<SenderEncodedFrame> encoded_frame) {})); // Send a frame to spawn creation of the ExternalVideoEncoder instance. - video_encoder()->EncodeVideoFrame(CreateTestVideoFrame(gfx::Size(128, 72)), - Now()); + const bool encode_result = video_encoder()->EncodeVideoFrame( + CreateTestVideoFrame(gfx::Size(128, 72)), Now()); + + // Hardware encoders should fail to encode at this point, since the VEA has + // not responded yet. Since software encoders don't use VEA, they should + // succeed. + ASSERT_EQ(encode_result, !GetParam().use_hardware_encoder); // Destroy the encoder, and confirm the VEA Factory did not respond yet. DestroyEncoder();
diff --git a/media/cast/sender/audio_sender_unittest.cc b/media/cast/sender/audio_sender_unittest.cc index 8428d5dc..68a33e30 100644 --- a/media/cast/sender/audio_sender_unittest.cc +++ b/media/cast/sender/audio_sender_unittest.cc
@@ -78,7 +78,6 @@ audio_config_.rtp_timebase = kDefaultAudioSamplingRate; audio_config_.channels = 2; audio_config_.max_bitrate = kDefaultAudioEncoderBitrate; - audio_config_.rtp_payload_type = RtpPayloadType::AUDIO_OPUS; openscreen::cast::SessionConfig openscreen_audio_config = ToOpenscreenSessionConfig(audio_config_, /* is_pli_enabled= */ true);
diff --git a/media/cast/sender/openscreen_frame_sender.cc b/media/cast/sender/openscreen_frame_sender.cc index 9501ee4..fc30382 100644 --- a/media/cast/sender/openscreen_frame_sender.cc +++ b/media/cast/sender/openscreen_frame_sender.cc
@@ -74,7 +74,7 @@ sender_(std::move(sender)), client_(client), max_frame_rate_(config.max_frame_rate), - is_audio_(config.rtp_payload_type <= RtpPayloadType::AUDIO_LAST), + is_audio_(config.is_audio()), min_playout_delay_(config.min_playout_delay), max_playout_delay_(config.max_playout_delay) { CHECK_GT(sender_->config().rtp_timebase, 0);
diff --git a/media/cast/sender/openscreen_frame_sender_unittest.cc b/media/cast/sender/openscreen_frame_sender_unittest.cc index a8ff67c..815fc0a 100644 --- a/media/cast/sender/openscreen_frame_sender_unittest.cc +++ b/media/cast/sender/openscreen_frame_sender_unittest.cc
@@ -39,7 +39,6 @@ kFirstSsrc + 1, base::Milliseconds(100), kDefaultTargetPlayoutDelay, - RtpPayloadType::AUDIO_OPUS, /* use_hardware_encoder= */ false, kDefaultAudioSamplingRate, /* channels= */ 2, @@ -59,7 +58,6 @@ kFirstSsrc + 3, base::Milliseconds(100), kDefaultTargetPlayoutDelay, - RtpPayloadType::VIDEO_VP8, /* use_hardware_encoder= */ false, kRtpTimebase, /* channels = */ 1,
diff --git a/media/cast/sender/video_bitrate_suggester_unittest.cc b/media/cast/sender/video_bitrate_suggester_unittest.cc index 1760a6a..569f36d6 100644 --- a/media/cast/sender/video_bitrate_suggester_unittest.cc +++ b/media/cast/sender/video_bitrate_suggester_unittest.cc
@@ -32,7 +32,6 @@ kFirstSsrc + 3, base::Milliseconds(100), kDefaultTargetPlayoutDelay, - RtpPayloadType::VIDEO_VP8, /* use_hardware_encoder= */ false, kRtpTimebase, /* channels = */ 1,
diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc index 1a199fa..a14a550 100644 --- a/media/cast/sender/video_sender.cc +++ b/media/cast/sender/video_sender.cc
@@ -148,7 +148,7 @@ void VideoSender::InsertRawVideoFrame( scoped_refptr<media::VideoFrame> video_frame, base::TimeTicks reference_time) { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); + CHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); CHECK(video_encoder_); const RtpTimeTicks rtp_timestamp = @@ -163,7 +163,8 @@ "rtp_timestamp", rtp_timestamp.lower_32_bits()); { - bool new_low_latency_mode = video_frame->metadata().interactive_content; + const bool new_low_latency_mode = + video_frame->metadata().interactive_content; if (new_low_latency_mode && !low_latency_mode_) { VLOG(1) << "Interactive mode playout time " << min_playout_delay_; playout_delay_change_cb_.Run(min_playout_delay_); @@ -238,13 +239,6 @@ playout_delay_change_cb_.Run(new_target_delay); } - // Some encoder implementations have a frame window for analysis. Since we - // are dropping this frame, unless we instruct the encoder to flush all the - // frames that have been enqueued for encoding, frames_in_encoder_ and - // last_enqueued_frame_reference_time_ will never be updated and we will - // drop every subsequent frame for the rest of the session. - video_encoder_->EmitFrames(); - number_of_frames_dropped_++; base::UmaHistogramEnumeration(kHistogramFrameDropped, reason); TRACE_EVENT_INSTANT2("cast.stream", "Video Frame Drop (raw frame)", @@ -325,11 +319,12 @@ void VideoSender::OnEncodedVideoFrame( std::unique_ptr<SenderEncodedFrame> encoded_frame) { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); + CHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); frames_in_encoder_--; - DCHECK_GE(frames_in_encoder_, 0); - // The encoder drops a frame. + CHECK_GE(frames_in_encoder_, 0); + // The encoder decided to drop a frame. This is likely due to a major error + // that will be reported through the status change callback. if (!encoded_frame) { DVLOG(3) << "Dropped frame"; return; @@ -376,10 +371,6 @@ const CastStreamingFrameDropReason reason = frame_sender_->EnqueueFrame(std::move(encoded_frame)); if (reason != CastStreamingFrameDropReason::kNotDropped) { - // Since we have dropped an already encoded frame, which is much worse than - // dropping a raw frame above, we need to flush the encoder and emit a new - // keyframe. - video_encoder_->EmitFrames(); video_encoder_->GenerateKeyFrame(); base::UmaHistogramEnumeration(kHistogramFrameDropped, reason);
diff --git a/media/cast/test/utility/default_config.cc b/media/cast/test/utility/default_config.cc index a4f5d22..9fd508f 100644 --- a/media/cast/test/utility/default_config.cc +++ b/media/cast/test/utility/default_config.cc
@@ -19,7 +19,6 @@ FrameSenderConfig config; config.sender_ssrc = 1; config.receiver_ssrc = 2; - config.rtp_payload_type = RtpPayloadType::AUDIO_OPUS; config.use_hardware_encoder = false; config.rtp_timebase = 48000; config.channels = 2; @@ -34,7 +33,6 @@ FrameSenderConfig config; config.sender_ssrc = 11; config.receiver_ssrc = 12; - config.rtp_payload_type = RtpPayloadType::VIDEO_VP8; config.use_hardware_encoder = false; config.rtp_timebase = kVideoFrequency; config.start_bitrate = config.min_bitrate = config.max_bitrate =
diff --git a/media/video/vpx_video_encoder.cc b/media/video/vpx_video_encoder.cc index 4b67277..2380b6c3 100644 --- a/media/video/vpx_video_encoder.cc +++ b/media/video/vpx_video_encoder.cc
@@ -94,6 +94,12 @@ config->rc_min_quantizer = 12; } config->rc_resize_allowed = 0; + config->rc_undershoot_pct = 50; + config->rc_overshoot_pct = 50; + config->rc_buf_initial_sz = 600; + config->rc_buf_optimal_sz = 600; + config->rc_buf_sz = 1000; + // Only if latency_mode is real time, a frame might be dropped. config->rc_dropframe_thresh = opts.latency_mode == VideoEncoder::LatencyMode::Realtime @@ -536,6 +542,7 @@ } } vpx_codec_control(codec.get(), VP8E_SET_STATIC_THRESHOLD, static_thresh); + vpx_codec_control(codec.get(), VP8E_SET_MAX_INTRA_BITRATE_PCT, 600); options_ = options; originally_configured_size_ = options.frame_size;
diff --git a/mojo/public/cpp/platform/named_platform_channel_posix.cc b/mojo/public/cpp/platform/named_platform_channel_posix.cc index fb19fa48..2eec6fb4 100644 --- a/mojo/public/cpp/platform/named_platform_channel_posix.cc +++ b/mojo/public/cpp/platform/named_platform_channel_posix.cc
@@ -107,7 +107,7 @@ return PlatformChannelServerEndpoint(); // Bind the socket. - if (bind(handle.GetFD().get(), storage.addr, storage.addr_len) < 0) { + if (bind(handle.GetFD().get(), storage.addr(), storage.addr_len) < 0) { PLOG(ERROR) << "bind " << name; return PlatformChannelServerEndpoint(); } @@ -137,8 +137,8 @@ if (!handle.is_valid()) return PlatformChannelEndpoint(); - if (HANDLE_EINTR( - connect(handle.GetFD().get(), storage.addr, storage.addr_len)) < 0) { + if (HANDLE_EINTR(connect(handle.GetFD().get(), storage.addr(), + storage.addr_len)) < 0) { VPLOG(1) << "connect " << options.server_name; return PlatformChannelEndpoint(); }
diff --git a/net/android/javatests/src/org/chromium/net/AndroidProxySelectorTest.java b/net/android/javatests/src/org/chromium/net/AndroidProxySelectorTest.java index 00802adc..d2232f1 100644 --- a/net/android/javatests/src/org/chromium/net/AndroidProxySelectorTest.java +++ b/net/android/javatests/src/org/chromium/net/AndroidProxySelectorTest.java
@@ -25,6 +25,7 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import java.net.Proxy; @@ -36,6 +37,9 @@ @RunWith(BaseJUnit4ClassRunner.class) @Batch(Batch.PER_CLASS) +@DisableIf.Build( + sdk_is_greater_than = Build.VERSION_CODES.TIRAMISU, + message = "crbug.com/343821809") public class AndroidProxySelectorTest { Properties mProperties;
diff --git a/net/base/address_list_unittest.cc b/net/base/address_list_unittest.cc index aaba8bb..c8eced7 100644 --- a/net/base/address_list_unittest.cc +++ b/net/base/address_list_unittest.cc
@@ -58,7 +58,7 @@ std::array<addrinfo, kNumElements> ai; for (unsigned i = 0; i < kNumElements; ++i) { struct sockaddr_in* addr = - reinterpret_cast<struct sockaddr_in*>(storage[i].addr); + reinterpret_cast<struct sockaddr_in*>(storage[i].addr()); storage[i].addr_len = sizeof(struct sockaddr_in); // Populating the address with { i, i, i, i }. memset(&addr->sin_addr, i, IPAddress::kIPv4AddressSize); @@ -69,7 +69,7 @@ ai[i].ai_family = addr->sin_family; ai[i].ai_socktype = SOCK_STREAM; ai[i].ai_addrlen = storage[i].addr_len; - ai[i].ai_addr = storage[i].addr; + ai[i].ai_addr = storage[i].addr(); if (i + 1 < kNumElements) ai[i].ai_next = &ai[i + 1]; }
diff --git a/net/base/ip_endpoint_unittest.cc b/net/base/ip_endpoint_unittest.cc index 9ebc0a4..26dbe6a 100644 --- a/net/base/ip_endpoint_unittest.cc +++ b/net/base/ip_endpoint_unittest.cc
@@ -164,22 +164,22 @@ // Convert to a sockaddr. SockaddrStorage storage; - EXPECT_TRUE(ip_endpoint.ToSockAddr(storage.addr, &storage.addr_len)); + EXPECT_TRUE(ip_endpoint.ToSockAddr(storage.addr(), &storage.addr_len)); // Basic verification. socklen_t expected_size = test.ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); EXPECT_EQ(expected_size, storage.addr_len); EXPECT_EQ(ip_endpoint.port(), - GetPortFromSockaddr(storage.addr, storage.addr_len)); + GetPortFromSockaddr(storage.addr(), storage.addr_len)); if (test.ipv6) { uint32_t scope_id = - reinterpret_cast<struct sockaddr_in6*>(storage.addr)->sin6_scope_id; + reinterpret_cast<struct sockaddr_in6*>(storage.addr())->sin6_scope_id; EXPECT_EQ(scope_id, test.scope_id.value_or(0)); } // And convert back to an IPEndPoint. IPEndPoint ip_endpoint2; - EXPECT_TRUE(ip_endpoint2.FromSockAddr(storage.addr, storage.addr_len)); + EXPECT_TRUE(ip_endpoint2.FromSockAddr(storage.addr(), storage.addr_len)); EXPECT_EQ(ip_endpoint.port(), ip_endpoint2.port()); EXPECT_EQ(ip_endpoint.address(), ip_endpoint2.address()); EXPECT_EQ(ip_endpoint.scope_id(), ip_endpoint2.scope_id()); @@ -193,7 +193,7 @@ SockaddrStorage storage; storage.addr_len = 3; // size is too small! - EXPECT_FALSE(ip_endpoint.ToSockAddr(storage.addr, &storage.addr_len)); + EXPECT_FALSE(ip_endpoint.ToSockAddr(storage.addr(), &storage.addr_len)); } } @@ -246,7 +246,7 @@ EXPECT_DCHECK_DEATH(bt_endpoint.port()); SockaddrStorage storage; EXPECT_DCHECK_DEATH( - std::ignore = bt_endpoint.ToSockAddr(storage.addr, &storage.addr_len)); + std::ignore = bt_endpoint.ToSockAddr(storage.addr(), &storage.addr_len)); EXPECT_DCHECK_DEATH(bt_endpoint.ToString()); EXPECT_DCHECK_DEATH(bt_endpoint.ToStringWithoutPort()); } @@ -291,7 +291,7 @@ EXPECT_DCHECK_DEATH(bt_endpoint_other.port()); SockaddrStorage storage; EXPECT_DCHECK_DEATH(std::ignore = bt_endpoint_other.ToSockAddr( - storage.addr, &storage.addr_len)); + storage.addr(), &storage.addr_len)); EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString()); EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort()); } @@ -322,7 +322,7 @@ EXPECT_DCHECK_DEATH(bt_endpoint_other.port()); SockaddrStorage storage; EXPECT_DCHECK_DEATH(std::ignore = bt_endpoint_other.ToSockAddr( - storage.addr, &storage.addr_len)); + storage.addr(), &storage.addr_len)); EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString()); EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort()); } @@ -352,7 +352,7 @@ EXPECT_DCHECK_DEATH(bt_endpoint_other.port()); SockaddrStorage storage; EXPECT_DCHECK_DEATH(std::ignore = bt_endpoint_other.ToSockAddr( - storage.addr, &storage.addr_len)); + storage.addr(), &storage.addr_len)); EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString()); EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort()); }
diff --git a/net/base/lookup_string_in_fixed_set_unittest.cc b/net/base/lookup_string_in_fixed_set_unittest.cc index 8658548..96ee4aca 100644 --- a/net/base/lookup_string_in_fixed_set_unittest.cc +++ b/net/base/lookup_string_in_fixed_set_unittest.cc
@@ -216,9 +216,10 @@ // These are the lines of effective_tld_names_unittest1.gperf, in sorted // order. std::vector<std::string> expected_language = { - "ac.jp, 0", "b.c, 1", "bar.baz.com, 0", "bar.jp, 2", - "baz.bar.jp, 2", "c, 2", "jp, 0", "no, 0", - "pref.bar.jp, 1", "priv.no, 4", "private, 4", "xn--fiqs8s, 0", + "ac.jp, 0", "b.c, 1", "bar.baz.com, 0", "bar.jp, 2", + "baz.bar.jp, 2", "c, 2", "er, 2", "jp, 0", + "no, 0", "pref.bar.jp, 1", "priv.no, 4", "private, 4", + "xn--fiqs8s, 0", }; EXPECT_EQ(expected_language, language);
diff --git a/net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf b/net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf index 1237e14..324b05c 100644 --- a/net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf +++ b/net/base/registry_controlled_domains/effective_tld_names_unittest1.gperf
@@ -24,4 +24,5 @@ priv.no, 4 private, 4 xn--fiqs8s, 0 +er, 2 %%
diff --git a/net/base/registry_controlled_domains/registry_controlled_domain.cc b/net/base/registry_controlled_domains/registry_controlled_domain.cc index 95c525a..44ef7de 100644 --- a/net/base/registry_controlled_domains/registry_controlled_domain.cc +++ b/net/base/registry_controlled_domains/registry_controlled_domain.cc
@@ -51,9 +51,13 @@ #include "base/check_op.h" #include "base/containers/span.h" +#include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/notreached.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_local.h" #include "net/base/lookup_string_in_fixed_set.h" #include "net/base/net_module.h" #include "net/base/url_util.h" @@ -78,6 +82,91 @@ size_t canonical_begin; size_t canonical_end; + + // True if this component could be canonicalized. + bool is_canonical; +}; + +// A thread-local cache of the last `kMaxCacheSize` registry lookups. Call +// GetCacheForThread to retrieve a thread-local instance. Implemented with a +// circular array but could just as easily be a std::list if you want LRU, with +// the additional overhead of the doubly-linked list pointers and seemingly +// negligible hit rate win. See crbug.com/383728878 for more information. +class RegistryLookupCache { + public: + constexpr static uint8_t kMaxCacheSize = 5; + RegistryLookupCache() = default; + ~RegistryLookupCache() = default; + RegistryLookupCache(const RegistryLookupCache&) = delete; + RegistryLookupCache& operator=(const RegistryLookupCache&) = delete; + + // Retrieve a thread-local cache. + static RegistryLookupCache* GetCacheForThread(bool reset_cache = false) { + static base::NoDestructor< + base::ThreadLocalOwnedPointer<RegistryLookupCache>> + thread_local_cache; + RegistryLookupCache* cache = thread_local_cache->Get(); + if (!cache || reset_cache) { + thread_local_cache->Set(std::make_unique<RegistryLookupCache>()); + return thread_local_cache->Get(); + } + return cache; + } + + // The returned string_view is a reference to the incoming `host` and + // therefore has the same lifetime. + std::optional<std::string_view> Get(std::string_view host, + PrivateRegistryFilter private_filter) { + std::optional<std::string_view> result; + + for (const CachedRegistryLookup& cached_result : cache_) { + if (cached_result.host == host && + cached_result.private_filter == private_filter) { + result = host.substr(cached_result.offset); + break; + } + } + UMA_HISTOGRAM_BOOLEAN( + "Net.RegistryControlledDomains.GetDomainAndRegistry.CacheHit", + result.has_value()); + return result; + } + + // Stores the input and output of a registry lookup. Rather than make a copy + // of the output string, it stores the offset into the host string. + void Set(std::string_view host, + PrivateRegistryFilter private_filter, + size_t offset) { + CHECK_LE(0u, write_index_); + CHECK_GT(kMaxCacheSize, write_index_); + cache_[write_index_] = CachedRegistryLookup(host, private_filter, offset); + write_index_ = (write_index_ + 1) % kMaxCacheSize; + } + + private: + // Stores the input parameters and the output offset of a registry lookup. + struct CachedRegistryLookup { + public: + CachedRegistryLookup() = default; + CachedRegistryLookup(std::string_view host, + PrivateRegistryFilter private_filter, + size_t offset) + : host(host), + private_filter(private_filter), + offset(base::checked_cast<uint32_t>(offset)) {} + ~CachedRegistryLookup() = default; + + std::string host; + PrivateRegistryFilter private_filter; + uint32_t offset; + }; + + // Note that there is no ThreadChecker for this class because + // CalledOnValidThread will return false when called from tasks posted to + // SingleThreadTaskRunners bound to different sequences. + + std::array<CachedRegistryLookup, kMaxCacheSize> cache_ = {}; + uint8_t write_index_ = 0u; }; // Used as the output of functions that calculate the registry length in a @@ -172,8 +261,9 @@ std::string_view host, UnknownRegistryFilter unknown_filter, PrivateRegistryFilter private_filter) { - if (host.empty()) + if (host.empty()) { return {std::string::npos, false}; + } // Skip leading dots. const size_t host_check_begin = host.find_first_not_of('.'); @@ -184,8 +274,9 @@ // A single trailing dot isn't relevant in this determination, but does need // to be included in the final returned length. size_t host_check_end = host.size(); - if (host.back() == '.') + if (host.back() == '.') { --host_check_end; + } RegistryLengthOutput output = GetRegistryLengthInTrimmedHost( host.substr(host_check_begin, host_check_end - host_check_begin), @@ -200,11 +291,25 @@ return output; } +// DO NOT change the interface of this function without also updating the +// RegistryLookupCache. std::string_view GetDomainAndRegistryImpl( std::string_view host, PrivateRegistryFilter private_filter) { CHECK(!host.empty()); + // Because this function is called frequently, and is quite expensive, we + // 'memoize' previous instantiations of this function by using a thread-local + // cache. + RegistryLookupCache* cache = RegistryLookupCache::GetCacheForThread(); + + // Check for the origin in the cache. + std::optional<std::string_view> cached_result = + cache->Get(host, private_filter); + if (cached_result.has_value()) { + return *cached_result; + } + // Find the length of the registry for this host. const RegistryLengthOutput registry_length_output = GetRegistryLengthImpl(host, INCLUDE_UNKNOWN_REGISTRIES, private_filter); @@ -223,9 +328,15 @@ // no dot. const size_t dot = host.rfind( '.', host.length() - registry_length_output.registry_length - 2); - if (dot == std::string::npos) + if (dot == std::string::npos) { + cache->Set(host, private_filter, 0u); return host; - return host.substr(dot + 1); + } + + std::string_view result = host.substr(dot + 1); + cache->Set(host, private_filter, dot + 1); + + return result; } // Same as GetDomainAndRegistry, but returns the domain and registry as a @@ -274,6 +385,7 @@ mapping.original_begin = begin; mapping.original_end = current; mapping.canonical_begin = canon_output.length(); + mapping.is_canonical = true; // Try to append the canonicalized version of this component. int current_len = static_cast<int>(current - begin); @@ -282,6 +394,7 @@ &canon_output)) { // Failed to canonicalize this component; append as-is. AppendInvalidString(host.substr(begin, current_len), &canon_output); + mapping.is_canonical = false; } mapping.canonical_end = canon_output.length(); @@ -295,20 +408,36 @@ size_t canonical_rcd_len = GetRegistryLengthImpl(canonical_host, unknown_filter, private_filter) .registry_length; - if (canonical_rcd_len == 0 || canonical_rcd_len == std::string::npos) + if (canonical_rcd_len == 0 || canonical_rcd_len == std::string::npos) { return canonical_rcd_len; // Error or no registry controlled domain. + } // Find which host component the result started in. size_t canonical_rcd_begin = canonical_host.length() - canonical_rcd_len; + for (const auto& mapping : components) { // In the common case, GetRegistryLengthImpl will identify the beginning // of a component and we can just return where that component was in the // original string. - if (canonical_rcd_begin == mapping.canonical_begin) + if (canonical_rcd_begin == mapping.canonical_begin) { return host.length() - mapping.original_begin; + } - if (canonical_rcd_begin >= mapping.canonical_end) + if (canonical_rcd_begin >= mapping.canonical_end) { continue; + } + + // Skip brute-force search if the component cannot be canonicalized. + // In practice, we should only get here if mapping is the last item in + // components. If the mapping cannot be canonicalized, RCD can only + // fall into the middle of it if the mapping is the last in components, + // such as "%EF%2E%FF%FE.er". In contrast, a hostname like + // "%EF%2E%FF%FE.test.er" will hit one of the two canonical_rcd_begin checks + // above because its RCD is "test.er" and the RCD doesn't fall in the middle + // of a component. + if (!mapping.is_canonical) { + continue; + } // The registry controlled domain begin was identified as being in the // middle of this dot-separated domain component in the non-canonical @@ -347,7 +476,10 @@ } } - NOTREACHED(); + // We may get here if the host has components that can't be canonicalized. + // This should only happen in fuzzing and tests, as invalid hostnames will get + // blocked much earlier in the stack. + return 0; } bool SameDomainOrHost(std::string_view host1, @@ -510,4 +642,8 @@ g_graph = domains; } +void ResetGetDomainAndRegistryCacheForTesting() { + RegistryLookupCache::GetCacheForThread(/*reset_cache =*/true); +} + } // namespace net::registry_controlled_domains
diff --git a/net/base/registry_controlled_domains/registry_controlled_domain.h b/net/base/registry_controlled_domains/registry_controlled_domain.h index c949266..7e0a2c0 100644 --- a/net/base/registry_controlled_domains/registry_controlled_domain.h +++ b/net/base/registry_controlled_domains/registry_controlled_domain.h
@@ -318,6 +318,9 @@ NET_EXPORT_PRIVATE void SetFindDomainGraphForTesting( base::span<const uint8_t> domains); +// Used for unit tests, so that each test has its own cache instance. +NET_EXPORT_PRIVATE void ResetGetDomainAndRegistryCacheForTesting(); + } // namespace net::registry_controlled_domains #endif // NET_BASE_REGISTRY_CONTROLLED_DOMAINS_REGISTRY_CONTROLLED_DOMAIN_H_
diff --git a/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc b/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc index 0e064c43..080eb51 100644 --- a/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc +++ b/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc
@@ -7,6 +7,7 @@ #include <cstdint> #include "base/containers/span.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/buildflags.h" @@ -88,6 +89,8 @@ class RegistryControlledDomainTest : public testing::Test { protected: + void SetUp() override { ResetGetDomainAndRegistryCacheForTesting(); } + void UseDomainData(base::span<const uint8_t> graph) { // This is undone in TearDown. SetFindDomainGraphForTesting(graph); @@ -207,6 +210,31 @@ EXPECT_EQ("", GetDomainFromHost(".localhost.")); } +// GetDomainAndRegistry is backed by a cache, so make sure that it's working +// correctly. +TEST_F(RegistryControlledDomainTest, TestGetDomainAndRegistryCaching) { + UseDomainData(test1::kDafsa); + + // Ask the same thing twice, should get the same result. + EXPECT_EQ("baz.jp", GetDomainFromHost("a.baz.jp")); + EXPECT_EQ("baz.jp", GetDomainFromHost("a.baz.jp")); + + // Asking 100 different things shouldn't cause any boundary issues. + for (int i = 0; i < 100; ++i) { + EXPECT_EQ("baz.jp", GetDomainFromHost(base::StringPrintf("%d.baz.jp", i))); + } + + // Ask a few more things multiple times, the results should be consistent. + for (int i = 0; i < 3; i++) { + EXPECT_EQ("baz.jp", GetDomainFromHost("a.baz.jp")); + EXPECT_EQ("baz.jp.", GetDomainFromHost("a.baz.jp.")); + EXPECT_EQ("", GetDomainFromHost("ac.jp")); + EXPECT_EQ("a.b.baz.bar.jp", GetDomainFromHost("a.b.baz.bar.jp")); + EXPECT_EQ("pref.bar.jp", GetDomainFromHost("baz.pref.bar.jp")); + EXPECT_EQ("b.bar.baz.com.", GetDomainFromHost("a.b.bar.baz.com.")); + } +} + TEST_F(RegistryControlledDomainTest, TestGetRegistryLength) { UseDomainData(test1::kDafsa); @@ -641,9 +669,28 @@ // Invalid characters at the beginning are OK if the suffix still matches. EXPECT_EQ(2U, PermissiveGetHostRegistryLength("*%00#?.Jp")); - // Escaped period, this will add new components. + // Escaped period, this will add new components (Www.Google.jp). EXPECT_EQ(4U, PermissiveGetHostRegistryLength("Www.Googl%45%2e%4Ap")); + // Escaped period, the last component is invalid (Www.Google.%p). + EXPECT_EQ(0U, PermissiveGetHostRegistryLength("Www.Googl%45%2e%25p")); + + // The last component is invalid (Www.Google.%p). + EXPECT_EQ(0U, PermissiveGetHostRegistryLength("Www.Google.%25p")); + + // Escaped period. er is a wildcard registry. + EXPECT_EQ(13U, PermissiveGetHostRegistryLength("Www.Googl%45%2eEr")); + + // Escaped period. The first component is invalid because of %FF%FE. + // er is a wildcard registry. + EXPECT_EQ(0U, PermissiveGetHostRegistryLength("%EF%2E%FF%FE.er")); + + // First component is invalid. Note that the RCD (test.er) doesn't fall into + // the middle of a component here, so this doesn't execute the brute search + // at the end of DoPermissiveGetHostRegistryLength, nor the is_canonical check + // right before the search. + EXPECT_EQ(7U, PermissiveGetHostRegistryLength("%EF%2E%FF%FE.test.er")); + // IDN cases (not supported when not linking ICU). #if !BUILDFLAG(USE_PLATFORM_ICU_ALTERNATIVES) EXPECT_EQ(10U, PermissiveGetHostRegistryLength("foo.xn--fiqs8s"));
diff --git a/net/base/sockaddr_storage.cc b/net/base/sockaddr_storage.cc index 21f6bf1..b43abf8 100644 --- a/net/base/sockaddr_storage.cc +++ b/net/base/sockaddr_storage.cc
@@ -6,22 +6,22 @@ #include <string.h> +#include "base/containers/span.h" + namespace net { -SockaddrStorage::SockaddrStorage() - : addr_len(sizeof(addr_storage)), - addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) {} +SockaddrStorage::SockaddrStorage() : addr_len(sizeof(addr_storage)) {} SockaddrStorage::SockaddrStorage(const SockaddrStorage& other) - : addr_len(other.addr_len), - addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) { - memcpy(addr, other.addr, addr_len); + : addr_len(other.addr_len) { + base::byte_span_from_ref(addr_storage) + .copy_from(base::byte_span_from_ref(other.addr_storage)); } void SockaddrStorage::operator=(const SockaddrStorage& other) { addr_len = other.addr_len; - // addr is already set to &this->addr_storage by default ctor. - memcpy(addr, other.addr, addr_len); + base::byte_span_from_ref(addr_storage) + .copy_from(base::byte_span_from_ref(other.addr_storage)); } } // namespace net
diff --git a/net/base/sockaddr_storage.h b/net/base/sockaddr_storage.h index 0c5f5a32..e4d26b4 100644 --- a/net/base/sockaddr_storage.h +++ b/net/base/sockaddr_storage.h
@@ -28,9 +28,12 @@ struct sockaddr_storage addr_storage; socklen_t addr_len; - // This field is not a raw_ptr<> because of a rewriter issue not adding .get() - // in reinterpret_cast. - RAW_PTR_EXCLUSION struct sockaddr* const addr; + + const sockaddr* addr() const { + return reinterpret_cast<const sockaddr*>(&addr_storage); + } + + sockaddr* addr() { return reinterpret_cast<sockaddr*>(&addr_storage); } }; } // namespace net
diff --git a/net/base/sockaddr_util_posix.cc b/net/base/sockaddr_util_posix.cc index 13d5f53b..e2ee55b1 100644 --- a/net/base/sockaddr_util_posix.cc +++ b/net/base/sockaddr_util_posix.cc
@@ -31,7 +31,7 @@ return false; struct sockaddr_un* socket_addr = - reinterpret_cast<struct sockaddr_un*>(address->addr); + reinterpret_cast<struct sockaddr_un*>(address->addr()); memset(socket_addr, 0, address->addr_len); socket_addr->sun_family = AF_UNIX; address->addr_len = path_size + offsetof(struct sockaddr_un, sun_path);
diff --git a/net/base/sockaddr_util_posix_unittest.cc b/net/base/sockaddr_util_posix_unittest.cc index d9bd02c..df43ed11a 100644 --- a/net/base/sockaddr_util_posix_unittest.cc +++ b/net/base/sockaddr_util_posix_unittest.cc
@@ -45,7 +45,7 @@ (unsigned int)storage.addr_len); struct sockaddr_un* socket_addr = - reinterpret_cast<struct sockaddr_un*>(storage.addr); + reinterpret_cast<struct sockaddr_un*>(storage.addr()); EXPECT_EQ(socket_addr->sun_family, AF_UNIX); // Implicit conversion to std::string for comparison is fine since the path @@ -69,7 +69,7 @@ FillUnixAddress(path, /*use_abstract_namespace=*/false, &storage)); struct sockaddr_un* socket_addr = - reinterpret_cast<struct sockaddr_un*>(storage.addr); + reinterpret_cast<struct sockaddr_un*>(storage.addr()); EXPECT_EQ(socket_addr->sun_family, AF_UNIX); EXPECT_EQ(socket_addr->sun_path, path); } @@ -95,7 +95,7 @@ (unsigned int)storage.addr_len); struct sockaddr_un* socket_addr = - reinterpret_cast<struct sockaddr_un*>(storage.addr); + reinterpret_cast<struct sockaddr_un*>(storage.addr()); EXPECT_EQ(socket_addr->sun_family, AF_UNIX); // The path buffer is preceded by a NUL character for abstract Linux
diff --git a/net/device_bound_sessions/registration_fetcher.cc b/net/device_bound_sessions/registration_fetcher.cc index a17ea11..5520a54 100644 --- a/net/device_bound_sessions/registration_fetcher.cc +++ b/net/device_bound_sessions/registration_fetcher.cc
@@ -290,7 +290,7 @@ void OnResponseCompleted() { if (!data_received_.empty()) { - std::optional<SessionParams> params = + std::optional<ParsedSessionParams> params = ParseSessionInstructionJson(data_received_); if (params) { RunCallbackAndDeleteSelf( @@ -331,7 +331,7 @@ } // namespace RegistrationFetcher::RegistrationCompleteParams::RegistrationCompleteParams( - SessionParams params, + ParsedSessionParams params, unexportable_keys::UnexportableKeyId key_id, const GURL& url) : params(std::move(params)), key_id(std::move(key_id)), url(url) {}
diff --git a/net/device_bound_sessions/registration_fetcher.h b/net/device_bound_sessions/registration_fetcher.h index f3549b5..0137367 100644 --- a/net/device_bound_sessions/registration_fetcher.h +++ b/net/device_bound_sessions/registration_fetcher.h
@@ -37,7 +37,7 @@ class NET_EXPORT RegistrationFetcher { public: struct NET_EXPORT RegistrationCompleteParams { - RegistrationCompleteParams(SessionParams params, + RegistrationCompleteParams(ParsedSessionParams params, unexportable_keys::UnexportableKeyId key_id, const GURL& url); RegistrationCompleteParams(RegistrationCompleteParams&& other) noexcept; @@ -46,7 +46,7 @@ ~RegistrationCompleteParams(); - SessionParams params; + ParsedSessionParams params; unexportable_keys::UnexportableKeyId key_id; GURL url; };
diff --git a/net/device_bound_sessions/registration_fetcher_unittest.cc b/net/device_bound_sessions/registration_fetcher_unittest.cc index f8f7680..f9542c97 100644 --- a/net/device_bound_sessions/registration_fetcher_unittest.cc +++ b/net/device_bound_sessions/registration_fetcher_unittest.cc
@@ -230,13 +230,16 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kInclude, "trusted.example.com", "/only_trusted_path"))); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -264,10 +267,13 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_FALSE(out_params->params.scope.include_site); - EXPECT_TRUE(out_params->params.scope.specifications.empty()); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_FALSE(session_params->scope.include_site); + EXPECT_TRUE(session_params->scope.specifications.empty()); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -326,10 +332,13 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_TRUE(out_params->params.scope.specifications.empty()); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_TRUE(session_params->scope.specifications.empty()); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -372,14 +381,17 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kExclude, "new.example.com", "/only_trusted_path"))); - EXPECT_THAT(out_params->params.credentials, + EXPECT_THAT(session_params->credentials, ElementsAre(SessionParams::Credential( "other_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); @@ -424,15 +436,18 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kExclude, "new.example.com", "/only_trusted_path"))); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -465,8 +480,11 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_TRUE(out_params->params.scope.specifications.empty()); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_TRUE(session_params->scope.specifications.empty()); } TEST_F(RegistrationTest, TypeIsNotCookie) { @@ -526,8 +544,11 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -563,8 +584,11 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -594,8 +618,11 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -712,13 +739,16 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kInclude, "trusted.example.com", "/only_trusted_path"))); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -853,13 +883,16 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kInclude, "trusted.example.com", "/only_trusted_path"))); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } @@ -883,18 +916,21 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kInclude, "trusted.example.com", "/only_trusted_path"))); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } -TEST_F(RegistrationTest, FetchRegitrationAndChallengeRequired) { +TEST_F(RegistrationTest, FetchRegistrationAndChallengeRequired) { crypto::ScopedMockUnexportableKeyProvider scoped_mock_key_provider_; server_.RegisterRequestHandler( base::BindRepeating(&ReturnResponseForRefreshRequest)); @@ -913,17 +949,45 @@ std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = callback.outcome(); ASSERT_TRUE(out_params); - EXPECT_TRUE(out_params->params.scope.include_site); - EXPECT_THAT(out_params->params.scope.specifications, + const SessionParams* session_params = + std::get_if<SessionParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_TRUE(session_params->scope.include_site); + EXPECT_THAT(session_params->scope.specifications, ElementsAre(SessionParams::Scope::Specification( SessionParams::Scope::Specification::Type::kInclude, "trusted.example.com", "/only_trusted_path"))); EXPECT_THAT( - out_params->params.credentials, + session_params->credentials, ElementsAre(SessionParams::Credential( "auth_cookie", "Domain=example.com; Path=/; Secure; SameSite=None"))); } +TEST_F(RegistrationTest, ContinueFalse) { + constexpr char kTestingJson[] = + R"({ + "session_identifier": "session_id", + "continue": false +})"; + crypto::ScopedMockUnexportableKeyProvider scoped_mock_key_provider_; + server_.RegisterRequestHandler( + base::BindRepeating(&ReturnResponse, HTTP_OK, kTestingJson)); + ASSERT_TRUE(server_.Start()); + + TestRegistrationCallback callback; + RegistrationFetcher::StartCreateTokenAndFetch( + GetBasicParam(), unexportable_key_service(), context_.get(), + IsolationInfo::CreateTransient(), callback.callback()); + callback.WaitForCall(); + std::optional<RegistrationFetcher::RegistrationCompleteParams> out_params = + callback.outcome(); + ASSERT_TRUE(out_params); + const SessionTerminationParams* session_params = + std::get_if<SessionTerminationParams>(&out_params->params); + ASSERT_TRUE(session_params); + EXPECT_EQ(session_params->session_id, "session_id"); +} + class RegistrationTokenHelperTest : public testing::Test { public: RegistrationTokenHelperTest() : unexportable_key_service_(task_manager_) {}
diff --git a/net/device_bound_sessions/session_json_utils.cc b/net/device_bound_sessions/session_json_utils.cc index 6047107..2e77b53e 100644 --- a/net/device_bound_sessions/session_json_utils.cc +++ b/net/device_bound_sessions/session_json_utils.cc
@@ -73,7 +73,7 @@ } // namespace -std::optional<SessionParams> ParseSessionInstructionJson( +std::optional<ParsedSessionParams> ParseSessionInstructionJson( std::string_view response_json) { // TODO(kristianm): Skip XSSI-escapes, see for example: // https://hg.mozilla.org/mozilla-central/rev/4cee9ec9155e @@ -96,10 +96,16 @@ return std::nullopt; } + std::optional<bool> continue_value = maybe_root->FindBool("continue"); + if (continue_value.has_value() && *continue_value == false) { + return SessionTerminationParams(*session_id); + } + std::string* refresh_url = maybe_root->FindString("refresh_url"); std::vector<SessionParams::Credential> credentials; base::Value::List* credentials_list = maybe_root->FindList("credentials"); + if (credentials_list) { credentials = ParseCredentials(*credentials_list); }
diff --git a/net/device_bound_sessions/session_json_utils.h b/net/device_bound_sessions/session_json_utils.h index 5a024db..f8b715d 100644 --- a/net/device_bound_sessions/session_json_utils.h +++ b/net/device_bound_sessions/session_json_utils.h
@@ -15,8 +15,12 @@ // Utilities for parsing the JSON session specification // https://github.com/WICG/dbsc/blob/main/README.md#session-registration-instructions-json -// Parse the full JSON as a string -std::optional<SessionParams> ParseSessionInstructionJson( +// Parse the full JSON as a string. Returns: +// - A SessionParams describing the session to be created on success +// - A SessionTerminationParams describing the session to be terminated +// when the JSON contains "continue": false +// - std::nullopt if parsing fails (e.g. invalid JSON) +std::optional<ParsedSessionParams> ParseSessionInstructionJson( std::string_view response_json); } // namespace net::device_bound_sessions
diff --git a/net/device_bound_sessions/session_params.h b/net/device_bound_sessions/session_params.h index e040f148..69e894fa 100644 --- a/net/device_bound_sessions/session_params.h +++ b/net/device_bound_sessions/session_params.h
@@ -6,6 +6,7 @@ #define NET_DEVICE_BOUND_SESSIONS_SESSION_PARAMS_H_ #include <string> +#include <variant> #include <vector> #include "net/base/net_export.h" @@ -59,6 +60,13 @@ std::vector<Credential> credentials; }; +struct SessionTerminationParams { + std::string session_id; +}; + +using ParsedSessionParams = + std::variant<SessionParams, SessionTerminationParams>; + } // namespace net::device_bound_sessions #endif // NET_DEVICE_BOUND_SESSIONS_SESSION_PARAMS_H_
diff --git a/net/device_bound_sessions/session_service_impl.cc b/net/device_bound_sessions/session_service_impl.cc index 848b330..935dbbe 100644 --- a/net/device_bound_sessions/session_service_impl.cc +++ b/net/device_bound_sessions/session_service_impl.cc
@@ -21,12 +21,12 @@ void NotifySessionAccess(SessionService::OnAccessCallback callback, const SchemefulSite& site, - const Session& session) { + const Session::Id& session_id) { if (callback.is_null()) { return; } - callback.Run({site, session.id()}); + callback.Run({site, session_id}); } bool SessionMatchesFilter( @@ -120,15 +120,26 @@ return; } - auto session = Session::CreateIfValid(std::move(params->params), params->url); + const SchemefulSite site(url::Origin::Create(params->url)); + + if (std::holds_alternative<SessionTerminationParams>(params->params)) { + const SessionTerminationParams& termination_params = + std::get<SessionTerminationParams>(params->params); + Session::Id session_id(termination_params.session_id); + DeleteSession(site, session_id); + NotifySessionAccess(on_access_callback, site, session_id); + return; + } + + CHECK(std::holds_alternative<SessionParams>(params->params)); + auto session = Session::CreateIfValid( + std::move(std::get<SessionParams>(params->params)), params->url); if (!session) { return; } session->set_unexportable_key_id(std::move(params->key_id)); - const SchemefulSite site(url::Origin::Create(params->url)); - - NotifySessionAccess(on_access_callback, site, *session); + NotifySessionAccess(on_access_callback, site, session->id()); AddSession(site, std::move(session)); } @@ -157,7 +168,7 @@ for (auto it = range.first; it != range.second; ++it) { if (it->second->ShouldDeferRequest(request)) { NotifySessionAccess(request->device_bound_session_access_callback(), site, - *it->second); + it->second->id()); return it->second->id(); } } @@ -195,7 +206,7 @@ } // Notify the request that it has been deferred for refreshed cookies. NotifySessionAccess(request->device_bound_session_access_callback(), site, - *session); + session->id()); // Do refresh the session. if (needs_refresh) { const Session::KeyIdOrError& key_id = session->unexportable_key_id(); @@ -205,7 +216,9 @@ } auto callback = base::BindOnce(&SessionServiceImpl::OnRefreshRequestCompletion, - weak_factory_.GetWeakPtr(), std::move(site), session_id); + weak_factory_.GetWeakPtr(), + request->device_bound_session_access_callback(), + std::move(site), session_id); RegistrationFetcher::StartFetchWithExistingKey( RegistrationRequestParam::Create(*session), key_service_.get(), context_.get(), request->isolation_info(), std::move(callback), @@ -214,6 +227,7 @@ } void SessionServiceImpl::OnRefreshRequestCompletion( + OnAccessCallback on_access_callback, SchemefulSite site, Session::Id session_id, std::optional<RegistrationFetcher::RegistrationCompleteParams> @@ -221,20 +235,41 @@ // Refresh succeeded: // 1. update the session by adding a new session and deleting the old one // 2. restart the deferred requests. + // + // Note that we notified `on_access_callback` about `session_id` already, so + // we only need to notify the callback about other sessions. + // // TODO(crbug.com/353766139): check if add/delete update will cause some race, // for example, if the the old session_id is still in use while deleting it. // Is it service's responsibility to keep the session_id same with the one in // received JSON which parsed as result_result->params? if (refresh_result) { - auto new_session = Session::CreateIfValid(std::move(refresh_result->params), - refresh_result->url); + if (std::holds_alternative<SessionTerminationParams>( + refresh_result->params)) { + const SessionTerminationParams& termination_params = + std::get<SessionTerminationParams>(refresh_result->params); + Session::Id new_session_id(termination_params.session_id); + + // Only delete the session requested by the server. + DeleteSession(site, new_session_id); + NotifySessionAccess(on_access_callback, site, new_session_id); + return; + } + + CHECK(std::holds_alternative<SessionParams>(refresh_result->params)); + auto new_session = Session::CreateIfValid( + std::move(std::get<SessionParams>(refresh_result->params)), + refresh_result->url); if (new_session) { new_session->set_unexportable_key_id(std::move(refresh_result->key_id)); // Delete old session. DeleteSession(site, session_id); // Add the new session. - AddSession(SchemefulSite(url::Origin::Create(refresh_result->url)), - std::move(new_session)); + SchemefulSite new_site(url::Origin::Create(refresh_result->url)); + if (new_session->id() != session_id) { + NotifySessionAccess(on_access_callback, new_site, new_session->id()); + } + AddSession(new_site, std::move(new_session)); // The session has been refreshed, restart the request. UnblockDeferredRequests(session_id, /*is_cookie_refreshed=*/true); return; @@ -282,7 +317,7 @@ auto range = GetSessionsForSite(site); for (auto it = range.first; it != range.second; ++it) { if (it->second->id().value() == param.session_id()) { - NotifySessionAccess(on_access_callback, site, *it->second); + NotifySessionAccess(on_access_callback, site, it->second->id()); it->second->set_cached_challenge(param.challenge()); return; }
diff --git a/net/device_bound_sessions/session_service_impl.h b/net/device_bound_sessions/session_service_impl.h index 891d5c5..a45bae5 100644 --- a/net/device_bound_sessions/session_service_impl.h +++ b/net/device_bound_sessions/session_service_impl.h
@@ -104,6 +104,7 @@ OnAccessCallback on_access_callback, std::optional<RegistrationFetcher::RegistrationCompleteParams> params); void OnRefreshRequestCompletion( + OnAccessCallback on_access_callback, SchemefulSite site, Session::Id session_id, std::optional<RegistrationFetcher::RegistrationCompleteParams> result);
diff --git a/net/device_bound_sessions/session_service_impl_unittest.cc b/net/device_bound_sessions/session_service_impl_unittest.cc index 7fd487d3..a79796c 100644 --- a/net/device_bound_sessions/session_service_impl_unittest.cc +++ b/net/device_bound_sessions/session_service_impl_unittest.cc
@@ -15,6 +15,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +using ::testing::ElementsAre; using ::testing::InSequence; using ::testing::Invoke; using ::testing::StrictMock; @@ -62,6 +63,13 @@ return std::nullopt; } +std::optional<RegistrationFetcher::RegistrationCompleteParams> +ContinueFalseFetcher() { + unexportable_keys::UnexportableKeyId key_id; + return std::make_optional<RegistrationFetcher::RegistrationCompleteParams>( + SessionTerminationParams{kSessionId}, std::move(key_id), kTestUrl); +} + RegistrationFetcher::FetcherType TestFetcherFactory(std::string session_id, std::string url_string) { static std::string g_session_id; @@ -92,6 +100,17 @@ ~ScopedNullFetcher() { RegistrationFetcher::SetFetcherForTesting(nullptr); } }; +class ScopedContinueFalseFetcher { + public: + ScopedContinueFalseFetcher() { + RegistrationFetcher::SetFetcherForTesting(ContinueFalseFetcher); + } + + ~ScopedContinueFalseFetcher() { + RegistrationFetcher::SetFetcherForTesting(nullptr); + } +}; + class TestDeferCompletion { public: enum class CallbackType { kRestart, kContinue }; @@ -122,6 +141,28 @@ base::WeakPtrFactory<TestDeferCompletion> weak_factory_{this}; }; +class FakeDeviceBoundSessionObserver { + public: + const std::vector<SessionKey>& notifications() const { + return notifications_; + } + + void ClearNotifications() { notifications_.clear(); } + + void OnSessionAccessed(const SessionKey& session_key) { + notifications_.push_back(session_key); + } + + SessionService::OnAccessCallback GetCallback() { + return base::BindRepeating( + &FakeDeviceBoundSessionObserver::OnSessionAccessed, + base::Unretained(this)); + } + + private: + std::vector<SessionKey> notifications_; +}; + class SessionServiceImplTest : public TestWithTaskEnvironment { public: SessionServiceImplTest() @@ -417,14 +458,13 @@ // Defer the request. // Set AccessCallback for DeferRequestForRefresh(). - base::test::TestFuture<SessionKey> future_2; - request->SetDeviceBoundSessionAccessCallback( - future_2.GetRepeatingCallback<const SessionKey&>()); + FakeDeviceBoundSessionObserver observer; + request->SetDeviceBoundSessionAccessCallback(observer.GetCallback()); // Set RestartCallback and ContinueCallback. - base::test::TestFuture<TestDeferCompletion::CallbackType> future_3; + base::test::TestFuture<TestDeferCompletion::CallbackType> future; TestDeferCompletion defer_completion( - future_3.GetCallback<TestDeferCompletion::CallbackType>()); + future.GetCallback<TestDeferCompletion::CallbackType>()); // Set up the fetcher for a successful refresh. ScopedTestFetcher scoped_test_fetcher(kSessionId, kUrlString); @@ -433,12 +473,11 @@ defer_completion.GetContinueCb()); // Check access callback triggered by DeferRequestForRefresh. - SessionKey session_key = future_2.Take(); - EXPECT_EQ(session_key.site, site); - EXPECT_EQ(session_key.id.value(), kSessionId); + ASSERT_THAT(observer.notifications(), + ElementsAre(SessionKey(site, Session::Id(kSessionId)))); // Check the restart callback is called for successful fetcher. - EXPECT_EQ(future_3.Take(), TestDeferCompletion::CallbackType::kRestart); + EXPECT_EQ(future.Take(), TestDeferCompletion::CallbackType::kRestart); } TEST_F(SessionServiceImplTest, TestDeferWithRequestContinue) { @@ -550,14 +589,13 @@ // Defer the request. // Set AccessCallback for DeferRequestForRefresh(). - base::test::TestFuture<SessionKey> future_2; - request->SetDeviceBoundSessionAccessCallback( - future_2.GetRepeatingCallback<const SessionKey&>()); + FakeDeviceBoundSessionObserver observer; + request->SetDeviceBoundSessionAccessCallback(observer.GetCallback()); // Set RestartCallback and ContinueCallback. - base::test::TestFuture<TestDeferCompletion::CallbackType> future_3; + base::test::TestFuture<TestDeferCompletion::CallbackType> future; TestDeferCompletion defer_completion( - future_3.GetCallback<TestDeferCompletion::CallbackType>()); + future.GetCallback<TestDeferCompletion::CallbackType>()); // Set up the fetcher for a successful refresh with a new session ID // which doesn't equal to the refreshing one. @@ -567,17 +605,36 @@ defer_completion.GetContinueCb()); // Check access callback triggered by DeferRequestForRefresh. - SessionKey session_key = future_2.Take(); - EXPECT_EQ(session_key.site, site); - EXPECT_EQ(session_key.id.value(), kSessionId); + EXPECT_THAT(observer.notifications(), + ElementsAre(SessionKey(site, Session::Id(kSessionId)), + SessionKey(site, Session::Id(kSessionId2)))); // Check the restart callback is called for successful fetcher. - EXPECT_EQ(future_3.Take(), TestDeferCompletion::CallbackType::kRestart); + EXPECT_EQ(future.Take(), TestDeferCompletion::CallbackType::kRestart); ASSERT_TRUE(service().GetSession(site, Session::Id(kSessionId2))); ASSERT_FALSE(service().GetSession(site, Session::Id(kSessionId))); } +TEST_F(SessionServiceImplTest, SessionTerminationFromContinueFalse) { + AddSessionsForTesting({{kSessionId, kUrlString}}); + + ASSERT_TRUE( + service().GetSession(SchemefulSite(kTestUrl), Session::Id(kSessionId))); + + { + ScopedContinueFalseFetcher scoped_fetcher; + auto fetch_param = RegistrationFetcherParam::CreateInstanceForTesting( + kTestUrl, {crypto::SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256}, + "challenge", /*authorization=*/std::nullopt); + service().RegisterBoundSession(base::DoNothing(), std::move(fetch_param), + IsolationInfo::CreateTransient()); + } + + EXPECT_FALSE( + service().GetSession(SchemefulSite(kTestUrl), Session::Id(kSessionId))); +} + } // namespace class SessionServiceImplWithStoreTest : public TestWithTaskEnvironment {
diff --git a/net/http/http_stream_pool_attempt_manager.cc b/net/http/http_stream_pool_attempt_manager.cc index c45ee632..e4def74 100644 --- a/net/http/http_stream_pool_attempt_manager.cc +++ b/net/http/http_stream_pool_attempt_manager.cc
@@ -4,6 +4,7 @@ #include "net/http/http_stream_pool_attempt_manager.h" +#include <map> #include <memory> #include <utility> @@ -499,6 +500,17 @@ pool()->DecrementTotalConnectingStreamCount(in_flight_attempts_.size()); in_flight_attempts_.clear(); slow_attempt_count_ = 0; + + std::erase_if(ip_endpoint_states_, [](const auto& it) { + return it.second == IPEndPointState::kSlowAttempting; + }); + + // If possible, try to complete asynchronously to avoid accessing deleted + // `this` and `group_`. `this` and/or `group_` can be accessed after leaving + // this method. Also, HttpStreamPool::OnSSLConfigChanged() calls this method + // when walking through all groups. If we destroy `this` here, we will break + // the loop. + MaybeCompleteLater(); } void HttpStreamPool::AttemptManager::OnJobComplete(Job* job) { @@ -718,9 +730,7 @@ stream_attempt_delay_timer_.Stop(); MaybeAttemptConnection(); } else { - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&AttemptManager::MaybeComplete, - weak_ptr_factory_.GetWeakPtr())); + MaybeCompleteLater(); } } @@ -1407,9 +1417,7 @@ base::SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(std::move(entry->callback), rv)); } - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&AttemptManager::MaybeComplete, - weak_ptr_factory_.GetWeakPtr())); + MaybeCompleteLater(); } void HttpStreamPool::AttemptManager::ProcessPreconnectsAfterAttemptComplete( @@ -1435,9 +1443,7 @@ FROM_HERE, base::BindOnce(std::move(entry->callback), entry->result)); } if (preconnects_.empty()) { - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&AttemptManager::MaybeComplete, - weak_ptr_factory_.GetWeakPtr())); + MaybeCompleteLater(); } } @@ -1936,4 +1942,12 @@ // `this` is deleted. } +void HttpStreamPool::AttemptManager::MaybeCompleteLater() { + if (CanComplete()) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&AttemptManager::MaybeComplete, + weak_ptr_factory_.GetWeakPtr())); + } +} + } // namespace net
diff --git a/net/http/http_stream_pool_attempt_manager.h b/net/http/http_stream_pool_attempt_manager.h index 46f4014..857c3f31 100644 --- a/net/http/http_stream_pool_attempt_manager.h +++ b/net/http/http_stream_pool_attempt_manager.h
@@ -133,9 +133,14 @@ // Tries to process a single pending request/preconnect. void ProcessPendingJob(); - // Returns the number of total jobs in this manager. + // Returns the number of jobs that haven't yet been notified success or + // failure. size_t JobCount() const { return jobs_.size(); } + // Returns the number of jobs that have already been notified success or + // failure. + size_t NotifiedJobCount() const { return notified_jobs_.size(); } + // Returns the number of in-flight attempts. size_t InFlightAttemptCount() const { return in_flight_attempts_.size(); } @@ -417,10 +422,15 @@ base::Value::Dict GetStatesAsNetLogParams(); + // Returns true when this can complete. bool CanComplete() const; + // Notifies `group_` that `this` has completed and can be destroyed. void MaybeComplete(); + // If `this` is ready to complete, posts a task to call MaybeComplete(). + void MaybeCompleteLater(); + const raw_ptr<Group> group_; const NetLogWithSource net_log_;
diff --git a/net/http/http_stream_pool_attempt_manager_unittest.cc b/net/http/http_stream_pool_attempt_manager_unittest.cc index f373821..71bce577 100644 --- a/net/http/http_stream_pool_attempt_manager_unittest.cc +++ b/net/http/http_stream_pool_attempt_manager_unittest.cc
@@ -1419,7 +1419,7 @@ EXPECT_EQ(get_remote_ip_endpoint(requester2), ip_endpoint_v4); // The third attempt triggered by the third request uses the IPv4 endpoint, - // wwhich was not slow. + // which was not slow. StreamRequester requester3; requester3.RequestStream(pool()); completer3.Complete(OK); @@ -2251,6 +2251,77 @@ ASSERT_FALSE(pool().GetGroupForTesting(requester.GetStreamKey())); } +// Tests that a group and corresponding attempt manager are destroyed after +// cancelling in-flight attempts due to an SSLConfig change when there are no +// jobs. +TEST_F(HttpStreamPoolAttemptManagerTest, CancelAttemptOnSSLConfigChangeNoJobs) { + constexpr size_t kNumRequest = 2; + + resolver() + ->AddFakeRequest() + ->add_endpoint(ServiceEndpointBuilder().add_v4("192.0.2.1").endpoint()) + .CompleteStartSynchronously(OK); + + const HttpStreamKey stream_key = StreamKeyBuilder().Build(); + std::vector<std::unique_ptr<MockConnectCompleter>> completers; + std::vector<std::unique_ptr<SequencedSocketData>> datas; + std::vector<std::unique_ptr<StreamRequester>> requesters; + for (size_t i = 0; i < kNumRequest; ++i) { + auto completer = std::make_unique<MockConnectCompleter>(); + auto data = std::make_unique<SequencedSocketData>(); + data->set_connect_data(MockConnect(completer.get())); + socket_factory()->AddSocketDataProvider(data.get()); + completers.emplace_back(std::move(completer)); + datas.emplace_back(std::move(data)); + + auto requester = std::make_unique<StreamRequester>(stream_key); + StreamRequester* raw_requester = requester.get(); + requesters.emplace_back(std::move(requester)); + raw_requester->RequestStream(pool()); + ASSERT_FALSE(raw_requester->result().has_value()); + } + AttemptManager* manager = + pool().GetGroupForTesting(stream_key)->GetAttemptManagerForTesting(); + ASSERT_EQ(manager->JobCount(), 2u); + ASSERT_EQ(manager->NotifiedJobCount(), 0u); + ASSERT_EQ(manager->InFlightAttemptCount(), 2u); + + auto count_slow_attempt_endpoints = [&]() { + size_t count = 0; + for (const auto& [_, state] : manager->ip_endpoint_states_for_testing()) { + if (state == AttemptManager::IPEndPointState::kSlowAttempting) { + ++count; + } + } + return count; + }; + + // Trigger slow timers. + FastForwardBy(HttpStreamPool::GetConnectionAttemptDelay()); + ASSERT_EQ(count_slow_attempt_endpoints(), 1u); + + // Cancel requests. This should remove all jobs from the corresponding group. + // Ensure that the job and attempt manager are still alive since there are + // in-flight attempts. + requesters.clear(); + manager = + pool().GetGroupForTesting(stream_key)->GetAttemptManagerForTesting(); + ASSERT_TRUE(manager); + ASSERT_EQ(manager->JobCount(), 0u); + ASSERT_EQ(manager->NotifiedJobCount(), 0u); + ASSERT_EQ(manager->InFlightAttemptCount(), 2u); + + // Trigger an SSLConfig change. This should cancel in-flight attempts. + ssl_config_service()->NotifySSLContextConfigChange(); + // Ensure IP endpoint states has been updated. + ASSERT_EQ(count_slow_attempt_endpoints(), 0u); + + // Run the cleanup task. The corresponding group and attempt manager should be + // destroyed. + FastForwardUntilNoTasksRemain(); + ASSERT_FALSE(pool().GetGroupForTesting(stream_key)); +} + TEST_F(HttpStreamPoolAttemptManagerTest, SSLConfigForServersChanged) { // Create idle streams in group A and group B. StreamRequester requester_a;
diff --git a/net/ntlm/ntlm_client.cc b/net/ntlm/ntlm_client.cc index d63407d..99c40cf 100644 --- a/net/ntlm/ntlm_client.cc +++ b/net/ntlm/ntlm_client.cc
@@ -340,8 +340,7 @@ // set to zeros. DCHECK_LT(kMicOffsetV2 + kMicLenV2, authenticate_message_len); - base::span<uint8_t, kMicLenV2> mic( - const_cast<uint8_t*>(auth_msg.data()) + kMicOffsetV2, kMicLenV2); + auto mic = base::span(auth_msg).subspan<kMicOffsetV2, kMicLenV2>(); GenerateMicV2(v2_session_key, negotiate_message_, server_challenge_message, auth_msg, mic); }
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc index 860f525..c7d4e75 100644 --- a/net/socket/socket_posix.cc +++ b/net/socket/socket_posix.cc
@@ -142,7 +142,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_NE(kInvalidSocket, socket_fd_); - int rv = bind(socket_fd_, address.addr, address.addr_len); + int rv = bind(socket_fd_, address.addr(), address.addr_len); if (rv < 0) { PLOG(ERROR) << "bind() failed"; return MapSystemError(errno); @@ -365,8 +365,9 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(address); - if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0) + if (getsockname(socket_fd_, address->addr(), &address->addr_len) < 0) { return MapSystemError(errno); + } return OK; } @@ -431,9 +432,8 @@ int SocketPosix::DoAccept(std::unique_ptr<SocketPosix>* socket) { SockaddrStorage new_peer_address; - int new_socket = HANDLE_EINTR(accept(socket_fd_, - new_peer_address.addr, - &new_peer_address.addr_len)); + int new_socket = HANDLE_EINTR( + accept(socket_fd_, new_peer_address.addr(), &new_peer_address.addr_len)); if (new_socket < 0) return MapAcceptError(errno); @@ -459,9 +459,8 @@ } int SocketPosix::DoConnect() { - int rv = HANDLE_EINTR(connect(socket_fd_, - peer_address_->addr, - peer_address_->addr_len)); + int rv = HANDLE_EINTR( + connect(socket_fd_, peer_address_->addr(), peer_address_->addr_len)); DCHECK_GE(0, rv); return rv == 0 ? OK : MapConnectError(errno); }
diff --git a/net/socket/socket_tag_unittest.cc b/net/socket/socket_tag_unittest.cc index 91e129a..1012279 100644 --- a/net/socket/socket_tag_unittest.cc +++ b/net/socket/socket_tag_unittest.cc
@@ -70,7 +70,7 @@ AddressList addr_list; ASSERT_TRUE(test_server.GetAddressList(&addr_list)); SockaddrStorage addr; - ASSERT_TRUE(addr_list[0].ToSockAddr(addr.addr, &addr.addr_len)); + ASSERT_TRUE(addr_list[0].ToSockAddr(addr.addr(), &addr.addr_len)); // Create socket. int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -81,7 +81,7 @@ uint64_t old_traffic = GetTaggedBytes(tag_val1); SocketTag tag1(SocketTag::UNSET_UID, tag_val1); tag1.Apply(s); - ASSERT_EQ(connect(s, addr.addr, addr.addr_len), 0); + ASSERT_EQ(connect(s, addr.addr(), addr.addr_len), 0); EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic); // Verify socket can be retagged with a new value and the current process's
diff --git a/net/socket/tcp_socket_posix.cc b/net/socket/tcp_socket_posix.cc index 6b0ddde..ed5b2b28 100644 --- a/net/socket/tcp_socket_posix.cc +++ b/net/socket/tcp_socket_posix.cc
@@ -209,7 +209,7 @@ DCHECK(!socket_); SockaddrStorage storage; - if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len) && + if (!peer_address.ToSockAddr(storage.addr(), &storage.addr_len) && // For backward compatibility, allows the empty address. !(peer_address == IPEndPoint())) { return ERR_ADDRESS_INVALID; @@ -240,8 +240,9 @@ DCHECK(socket_); SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; + } return socket_->Bind(storage); } @@ -281,8 +282,9 @@ [&] { return CreateNetLogIPEndPointParams(&address); }); SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; + } int rv = socket_->Connect( storage, base::BindOnce(&TCPSocketPosix::ConnectCompleted, @@ -379,8 +381,9 @@ if (rv != OK) return rv; - if (!address->FromSockAddr(storage.addr, storage.addr_len)) + if (!address->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } return OK; } @@ -396,8 +399,9 @@ if (rv != OK) return rv; - if (!address->FromSockAddr(storage.addr, storage.addr_len)) + if (!address->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } return OK; } @@ -553,7 +557,7 @@ SockaddrStorage storage; if (accept_socket_->GetPeerAddress(&storage) != OK || - !address->FromSockAddr(storage.addr, storage.addr_len)) { + !address->FromSockAddr(storage.addr(), storage.addr_len)) { accept_socket_.reset(); return ERR_ADDRESS_INVALID; }
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc index 941edc8..c6c7c26 100644 --- a/net/socket/tcp_socket_unittest.cc +++ b/net/socket/tcp_socket_unittest.cc
@@ -428,8 +428,8 @@ IPEndPoint address(IPAddress::IPv4Localhost(), 0); SockaddrStorage storage; - ASSERT_TRUE(address.ToSockAddr(storage.addr, &storage.addr_len)); - ASSERT_EQ(0, bind(existing_socket, storage.addr, storage.addr_len)); + ASSERT_TRUE(address.ToSockAddr(storage.addr(), &storage.addr_len)); + ASSERT_EQ(0, bind(existing_socket, storage.addr(), storage.addr_len)); ASSERT_THAT(socket_->Listen(kListenBacklog), IsOk()); ASSERT_THAT(socket_->GetLocalAddress(&local_address_), IsOk());
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index 2865722..79505e9 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc
@@ -448,10 +448,11 @@ DCHECK_NE(socket_, INVALID_SOCKET); SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; + } - int result = bind(socket_, storage.addr, storage.addr_len); + int result = bind(socket_, storage.addr(), storage.addr_len); int os_error = WSAGetLastError(); if (result < 0) { PLOG(ERROR) << "bind() returned an error"; @@ -715,12 +716,13 @@ DCHECK(address); SockaddrStorage storage; - if (getsockname(socket_, storage.addr, &storage.addr_len)) { + if (getsockname(socket_, storage.addr(), &storage.addr_len)) { int os_error = WSAGetLastError(); return MapSystemError(os_error); } - if (!address->FromSockAddr(storage.addr, storage.addr_len)) + if (!address->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } return OK; } @@ -893,7 +895,7 @@ int TCPSocketWin::AcceptInternal(std::unique_ptr<TCPSocketWin>* socket, IPEndPoint* address) { SockaddrStorage storage; - int new_socket = accept(socket_, storage.addr, &storage.addr_len); + int new_socket = accept(socket_, storage.addr(), &storage.addr_len); int os_error = WSAGetLastError(); if (new_socket < 0) { int net_error = MapSystemError(os_error); @@ -903,7 +905,7 @@ } IPEndPoint ip_end_point; - if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) { + if (!ip_end_point.FromSockAddr(storage.addr(), storage.addr_len)) { NOTREACHED(); } auto tcp_socket = @@ -962,8 +964,9 @@ WSAEventSelect(socket_, core_->GetConnectEvent(), FD_CONNECT); SockaddrStorage storage; - if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len)) + if (!peer_address_->ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; + } // Set option to choose a random port, if the socket is not already bound. // Ignore failures, which may happen if the socket was already bound. @@ -975,7 +978,7 @@ sizeof(randomize_port)); } - if (!connect(socket_, storage.addr, storage.addr_len)) { + if (!connect(socket_, storage.addr(), storage.addr_len)) { // Connected without waiting! // // The MSDN page for connect says:
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc index 62d4f64d..fda2d31 100644 --- a/net/socket/udp_socket_posix.cc +++ b/net/socket/udp_socket_posix.cc
@@ -238,11 +238,13 @@ if (!remote_address_.get()) { SockaddrStorage storage; - if (getpeername(socket_, storage.addr, &storage.addr_len)) + if (getpeername(socket_, storage.addr(), &storage.addr_len)) { return MapSystemError(errno); + } auto endpoint = std::make_unique<IPEndPoint>(); - if (!endpoint->FromSockAddr(storage.addr, storage.addr_len)) + if (!endpoint->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } remote_address_ = std::move(endpoint); } @@ -258,11 +260,13 @@ if (!local_address_.get()) { SockaddrStorage storage; - if (getsockname(socket_, storage.addr, &storage.addr_len)) + if (getsockname(socket_, storage.addr(), &storage.addr_len)) { return MapSystemError(errno); + } auto endpoint = std::make_unique<IPEndPoint>(); - if (!endpoint->FromSockAddr(storage.addr, storage.addr_len)) + if (!endpoint->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } local_address_ = std::move(endpoint); net_log_.AddEvent(NetLogEventType::UDP_LOCAL_ADDRESS, [&] { return CreateNetLogUDPConnectParams(*local_address_, bound_network_); @@ -396,10 +400,11 @@ } SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; + } - rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len)); + rv = HANDLE_EINTR(connect(socket_, storage.addr(), storage.addr_len)); if (rv < 0) return MapSystemError(errno); @@ -723,9 +728,9 @@ SockaddrStorage sock_addr; bool success = - remote_address_->ToSockAddr(sock_addr.addr, &sock_addr.addr_len); - DCHECK(success); - LogRead(result, buf->data(), sock_addr.addr_len, sock_addr.addr); + remote_address_->ToSockAddr(sock_addr.addr(), &sock_addr.addr_len); + DCHECK(success); + LogRead(result, buf->data(), sock_addr.addr_len, sock_addr.addr()); return result; } @@ -742,7 +747,7 @@ // 512 Bytes, re-used here. char control_buffer[512]; struct msghdr msg = { - .msg_name = storage.addr, + .msg_name = storage.addr(), .msg_namelen = storage.addr_len, .msg_iov = &iov, .msg_iovlen = 1, @@ -763,7 +768,7 @@ // Linux, but isn't supported by POSIX. result = ERR_MSG_TOO_BIG; } else if (address && - !address->FromSockAddr(storage.addr, storage.addr_len)) { + !address->FromSockAddr(storage.addr(), storage.addr_len)) { result = ERR_ADDRESS_INVALID; } else { result = bytes_transferred; @@ -787,7 +792,7 @@ } } - LogRead(result, buf->data(), storage.addr_len, storage.addr); + LogRead(result, buf->data(), storage.addr_len, storage.addr()); return result; } @@ -795,12 +800,12 @@ int buf_len, const IPEndPoint* address) { SockaddrStorage storage; - struct sockaddr* addr = storage.addr; + struct sockaddr* addr = storage.addr(); if (!address) { addr = nullptr; storage.addr_len = 0; } else { - if (!address->ToSockAddr(storage.addr, &storage.addr_len)) { + if (!address->ToSockAddr(storage.addr(), &storage.addr_len)) { int result = ERR_ADDRESS_INVALID; LogWrite(result, nullptr, nullptr); return result; @@ -876,9 +881,10 @@ int UDPSocketPosix::DoBind(const IPEndPoint& address) { SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; - int rv = bind(socket_, storage.addr, storage.addr_len); + } + int rv = bind(socket_, storage.addr(), storage.addr_len); if (rv == 0) return OK; int last_error = errno;
diff --git a/net/socket/udp_socket_win.cc b/net/socket/udp_socket_win.cc index 2d3f2490..8e6f516 100644 --- a/net/socket/udp_socket_win.cc +++ b/net/socket/udp_socket_win.cc
@@ -369,11 +369,13 @@ // TODO(szym): Simplify. http://crbug.com/126152 if (!remote_address_.get()) { SockaddrStorage storage; - if (getpeername(socket_, storage.addr, &storage.addr_len)) + if (getpeername(socket_, storage.addr(), &storage.addr_len)) { return MapSystemError(WSAGetLastError()); + } auto remote_address = std::make_unique<IPEndPoint>(); - if (!remote_address->FromSockAddr(storage.addr, storage.addr_len)) + if (!remote_address->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } remote_address_ = std::move(remote_address); } @@ -390,11 +392,13 @@ // TODO(szym): Simplify. http://crbug.com/126152 if (!local_address_.get()) { SockaddrStorage storage; - if (getsockname(socket_, storage.addr, &storage.addr_len)) + if (getsockname(socket_, storage.addr(), &storage.addr_len)) { return MapSystemError(WSAGetLastError()); + } auto local_address = std::make_unique<IPEndPoint>(); - if (!local_address->FromSockAddr(storage.addr, storage.addr_len)) + if (!local_address->FromSockAddr(storage.addr(), storage.addr_len)) { return ERR_ADDRESS_INVALID; + } local_address_ = std::move(local_address); net_log_.AddEvent(NetLogEventType::UDP_LOCAL_ADDRESS, [&] { return CreateNetLogUDPConnectParams(*local_address_, @@ -505,10 +509,11 @@ sizeof(randomize_port_value)); SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; + } - int rv = connect(socket_, storage.addr, storage.addr_len); + int rv = connect(socket_, storage.addr(), storage.addr_len); if (rv < 0) return MapSystemError(WSAGetLastError()); @@ -734,7 +739,7 @@ IPEndPoint address; IPEndPoint* address_to_log = nullptr; if (result >= 0) { - if (address.FromSockAddr(core_->recv_addr_storage_.addr, + if (address.FromSockAddr(core_->recv_addr_storage_.addr(), core_->recv_addr_storage_.addr_len)) { if (recv_from_address_) { *recv_from_address_ = address; @@ -892,7 +897,7 @@ } else { is_ipv6 = (addr_family_ == AF_INET6); } - message.name = storage.addr; + message.name = storage.addr(); message.namelen = storage.addr_len; message.lpBuffers = data_buffer; message.dwBufferCount = 1; @@ -957,7 +962,7 @@ SetLastTosFromWSAMSG(*message); } } else { - rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr, + rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr(), &storage.addr_len, &core_->read_overlapped_, nullptr); } if (rv == 0) { @@ -967,7 +972,7 @@ IPEndPoint address_storage; IPEndPoint* address_to_log = nullptr; if (result >= 0) { - if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr, + if (address_storage.FromSockAddr(core_->recv_addr_storage_.addr(), core_->recv_addr_storage_.addr_len)) { if (address) { *address = address_storage; @@ -999,7 +1004,7 @@ const IPEndPoint* address) { DCHECK(!core_->write_iobuffer_.get()); SockaddrStorage storage; - struct sockaddr* addr = storage.addr; + struct sockaddr* addr = storage.addr(); // Convert address. if (!address) { addr = nullptr; @@ -1087,7 +1092,7 @@ // returns the number of bytes received. } } else { - rv = recvfrom(socket_, buf->data(), buf_len, 0, storage.addr, + rv = recvfrom(socket_, buf->data(), buf_len, 0, storage.addr(), &storage.addr_len); } if (rv == SOCKET_ERROR) { @@ -1105,7 +1110,7 @@ IPEndPoint address_storage; IPEndPoint* address_to_log = nullptr; if (rv >= 0) { - if (address_storage.FromSockAddr(storage.addr, storage.addr_len)) { + if (address_storage.FromSockAddr(storage.addr(), storage.addr_len)) { if (address) { *address = address_storage; } @@ -1123,7 +1128,7 @@ const IPEndPoint* address) { DCHECK(!write_iobuffer_ || write_iobuffer_.get() == buf); SockaddrStorage storage; - struct sockaddr* addr = storage.addr; + struct sockaddr* addr = storage.addr(); // Convert address. if (address) { if (!address->ToSockAddr(addr, &storage.addr_len)) { @@ -1226,10 +1231,10 @@ int UDPSocketWin::DoBind(const IPEndPoint& address) { SockaddrStorage storage; - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { + if (!address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; } - int rv = bind(socket_, storage.addr, storage.addr_len); + int rv = bind(socket_, storage.addr(), storage.addr_len); if (rv == 0) { return OK; } @@ -1525,7 +1530,7 @@ } SockaddrStorage storage; - if (!remote_address.ToSockAddr(storage.addr, &storage.addr_len)) { + if (!remote_address.ToSockAddr(storage.addr(), &storage.addr_len)) { return ERR_ADDRESS_INVALID; } @@ -1537,7 +1542,7 @@ const QOS_TRAFFIC_TYPE traffic_type = DscpToTrafficType(dscp_value_); - if (!api_->AddSocketToFlow(qos_handle_, socket_, storage.addr, traffic_type, + if (!api_->AddSocketToFlow(qos_handle_, socket_, storage.addr(), traffic_type, QOS_NON_ADAPTIVE_FLOW, &flow_id_)) { DWORD err = ::GetLastError(); if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) {
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn index 79e93ad..16f2317 100644 --- a/remoting/host/linux/BUILD.gn +++ b/remoting/host/linux/BUILD.gn
@@ -67,6 +67,12 @@ deps = [ "//remoting/host/crash:remoting_crash_uploader" ] } + copy("remoting_me2me_host_copy_libremoting_core") { + sources = [ "$root_build_dir/libremoting_core.so" ] + outputs = [ "$root_build_dir/remoting/libremoting_core.so" ] + deps = [ "//remoting/host:remoting_core" ] + } + remoting_localize("url_forwarder_desktop_entry") { sources = [ "crd-url-forwarder.desktop.jinja2" ] locale_list = remoting_locales_without_pseudolocales @@ -83,6 +89,7 @@ deps = [ ":remoting_me2me_host_copy_crash_uploader", ":remoting_me2me_host_copy_host_wrapper", + ":remoting_me2me_host_copy_libremoting_core", ":remoting_me2me_host_copy_pipewire_templates", ":remoting_me2me_host_copy_script", ":remoting_me2me_host_copy_setup_url_forwarder_script",
diff --git a/remoting/host/linux/ei_event_watcher_glib.cc b/remoting/host/linux/ei_event_watcher_glib.cc index 0797c1a..9f848a1 100644 --- a/remoting/host/linux/ei_event_watcher_glib.cc +++ b/remoting/host/linux/ei_event_watcher_glib.cc
@@ -8,7 +8,7 @@ #include "base/check.h" #include "base/memory/raw_ptr.h" -#include "third_party/libei/cipd/include/libei.h" +#include "third_party/libei/cipd/include/libei-1.0/libei.h" namespace remoting {
diff --git a/remoting/host/linux/remote_desktop_portal_injector.cc b/remoting/host/linux/remote_desktop_portal_injector.cc index 3b3a40e..c330dd2 100644 --- a/remoting/host/linux/remote_desktop_portal_injector.cc +++ b/remoting/host/linux/remote_desktop_portal_injector.cc
@@ -17,7 +17,7 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "remoting/base/logging.h" -#include "third_party/libei/cipd/include/libei.h" +#include "third_party/libei/cipd/include/libei-1.0/libei.h" #include "third_party/webrtc/modules/portal/portal_request_response.h" #include "third_party/webrtc/modules/portal/scoped_glib.h" #include "third_party/webrtc/modules/portal/xdg_desktop_portal_utils.h" @@ -123,8 +123,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (use_ei_) { if (ei_pointer_enabled_) { - ei_device_pointer_button(ei_pointer_, EvdevCodeToMouseButton(code), - pressed); + ei_device_button_button(ei_pointer_, EvdevCodeToMouseButton(code), + pressed); ei_device_frame(ei_pointer_, ei_now(ei_)); } else { // Non-ei injection is blocked by portal when EI has been enabled @@ -153,13 +153,13 @@ if (use_ei_) { if (ei_absolute_pointer_enabled_) { if (axis == ScrollType::VERTICAL_SCROLL) { - ei_device_pointer_scroll_discrete(ei_absolute_pointer_, 0, - steps * EI_SCROLL_FACTOR); + ei_device_scroll_discrete(ei_absolute_pointer_, 0, + steps * EI_SCROLL_FACTOR); } else { - ei_device_pointer_scroll_discrete(ei_absolute_pointer_, - steps * EI_SCROLL_FACTOR, 0); + ei_device_scroll_discrete(ei_absolute_pointer_, + steps * EI_SCROLL_FACTOR, 0); } - ei_device_pointer_scroll_stop(ei_absolute_pointer_, true, true); + ei_device_scroll_stop(ei_absolute_pointer_, true, true); ei_device_frame(ei_absolute_pointer_, ei_now(ei_)); } else { LOG(ERROR) << "Unable to scroll mouse since EI pointer is disabled"; @@ -376,9 +376,10 @@ ei_seat_ = ei_seat_ref(ei_event_get_seat(event)); HOST_LOG << "EI seat added: " << ei_seat_get_name(ei_seat_); - ei_seat_bind_capability(ei_seat_, EI_DEVICE_CAP_POINTER); - ei_seat_bind_capability(ei_seat_, EI_DEVICE_CAP_KEYBOARD); - ei_seat_bind_capability(ei_seat_, EI_DEVICE_CAP_POINTER_ABSOLUTE); + ei_seat_bind_capabilities( + ei_seat_, EI_DEVICE_CAP_POINTER, EI_DEVICE_CAP_KEYBOARD, + EI_DEVICE_CAP_POINTER_ABSOLUTE, EI_DEVICE_CAP_BUTTON, + EI_DEVICE_CAP_SCROLL, nullptr); } void RemoteDesktopPortalInjector::OnEiSeatRemovedEvent(struct ei_event* event) { @@ -535,9 +536,9 @@ case EI_EVENT_DEVICE_STOP_EMULATING: case EI_EVENT_POINTER_MOTION: case EI_EVENT_POINTER_MOTION_ABSOLUTE: - case EI_EVENT_POINTER_BUTTON: - case EI_EVENT_POINTER_SCROLL: - case EI_EVENT_POINTER_SCROLL_DISCRETE: + case EI_EVENT_BUTTON_BUTTON: + case EI_EVENT_SCROLL_DELTA: + case EI_EVENT_SCROLL_DISCRETE: case EI_EVENT_KEYBOARD_KEY: break; default:
diff --git a/remoting/host/linux/remote_desktop_portal_injector.h b/remoting/host/linux/remote_desktop_portal_injector.h index e957986e..f1805bb 100644 --- a/remoting/host/linux/remote_desktop_portal_injector.h +++ b/remoting/host/linux/remote_desktop_portal_injector.h
@@ -15,7 +15,7 @@ #include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" #include "remoting/host/linux/ei_event_watcher_glib.h" -#include "third_party/libei/cipd/include/libei.h" +#include "third_party/libei/cipd/include/libei-1.0/libei.h" #include "third_party/webrtc/modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h" #include "third_party/webrtc/modules/desktop_capture/linux/wayland/screencast_portal.h" #include "third_party/webrtc/modules/portal/xdg_desktop_portal_utils.h"
diff --git a/sandbox/policy/features.cc b/sandbox/policy/features.cc index 8029438..a19dd78 100644 --- a/sandbox/policy/features.cc +++ b/sandbox/policy/features.cc
@@ -111,6 +111,12 @@ BASE_FEATURE(kWinSboxParallelProcessLaunch, "WinSboxParallelProcessLaunch", base::FEATURE_DISABLED_BY_DEFAULT); + +// Enables Csrss lockdown in supported processes by closing all ALPC +// ports before sandbox lockdown. See crbug.com/40408399 for details. +BASE_FEATURE(kEnableCsrssLockdown, + "EnableCsrssLockdown", + base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/sandbox/policy/features.h b/sandbox/policy/features.h index f50a762..78bea56 100644 --- a/sandbox/policy/features.h +++ b/sandbox/policy/features.h
@@ -37,6 +37,7 @@ SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE( kWinSboxRestrictCoreSharingOnRenderer); SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxParallelProcessLaunch); +SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kEnableCsrssLockdown); #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc index 6171038..1c3ead1 100644 --- a/sandbox/policy/win/sandbox_win.cc +++ b/sandbox/policy/win/sandbox_win.cc
@@ -92,11 +92,6 @@ L"rpchromebrowserrecordhelper.dll", // RealPlayer. }; -// This is for finch. See also crbug.com/464430 for details. -BASE_FEATURE(kEnableCsrssLockdownFeature, - "EnableCsrssLockdown", - base::FEATURE_DISABLED_BY_DEFAULT); - // Return a mapping between the long and short names for all loaded modules in // the current process. The mapping excludes modules which don't have a typical // short name, e.g. EXAMPL~1.DLL. @@ -690,7 +685,7 @@ void SandboxWin::AddBaseHandleClosePolicy(TargetConfig* config) { DCHECK(!config->IsConfigured()); - if (base::FeatureList::IsEnabled(kEnableCsrssLockdownFeature)) { + if (base::FeatureList::IsEnabled(features::kEnableCsrssLockdown)) { // Close all ALPC ports. config->SetDisconnectCsrss(); }
diff --git a/services/on_device_model/fake/fake_chrome_ml_api.cc b/services/on_device_model/fake/fake_chrome_ml_api.cc index 7c2f4011..9fb3ce52 100644 --- a/services/on_device_model/fake/fake_chrome_ml_api.cc +++ b/services/on_device_model/fake/fake_chrome_ml_api.cc
@@ -65,7 +65,8 @@ } struct FakeModelInstance { - ModelBackendType backend_type_; + ml::ModelBackendType backend_type_; + ml::ModelPerformanceHint performance_hint; std::string model_data_; }; @@ -97,8 +98,10 @@ ChromeMLModel SessionCreateModel(const ChromeMLModelDescriptor* descriptor, uintptr_t context, ChromeMLScheduleFn schedule) { - return reinterpret_cast<ChromeMLModel>( - new FakeModelInstance{.backend_type_ = descriptor->backend_type}); + return reinterpret_cast<ChromeMLModel>(new FakeModelInstance{ + .backend_type_ = descriptor->backend_type, + .performance_hint = descriptor->performance_hint, + }); } void DestroyModel(ChromeMLModel model) { @@ -121,11 +124,11 @@ if (descriptor) { instance->enable_image_input = descriptor->enable_image_input; if (descriptor->model_data) { - if (model_instance->backend_type_ == ModelBackendType::kGpuBackend) { + if (model_instance->backend_type_ == ml::ModelBackendType::kGpuBackend) { instance->adaptation_data_ = ReadFile(descriptor->model_data->weights_file); } else if (model_instance->backend_type_ == - ModelBackendType::kApuBackend) { + ml::ModelBackendType::kApuBackend) { base::ReadFileToString( base::FilePath::FromUTF8Unsafe(descriptor->model_data->model_path), &instance->adaptation_data_); @@ -206,6 +209,10 @@ output_fn(&output); }; + if (reinterpret_cast<FakeModelInstance*>(model)->performance_hint == + ml::ModelPerformanceHint::kFastestInference) { + OutputChunk("Fastest inference\n"); + } if (!instance->adaptation_data_.empty()) { OutputChunk("Adaptation: " + instance->adaptation_data_ + "\n"); }
diff --git a/services/on_device_model/ml/chrome_ml_api.h b/services/on_device_model/ml/chrome_ml_api.h index 23c3543..7b9108c 100644 --- a/services/on_device_model/ml/chrome_ml_api.h +++ b/services/on_device_model/ml/chrome_ml_api.h
@@ -15,6 +15,9 @@ // This header defines the public interface to the ChromeML shared library. +// TODO: crbug.com/379723772 - Remove this when internal code migrates. +using ::ml::ModelBackendType; + extern "C" { // A function used to handle fatal errors. @@ -43,15 +46,6 @@ // Opaque handle to a video-frame-specific ML inference engine. using ChromeMLInferenceEngine = uintptr_t; -// Type of the backend to run the model. -enum ModelBackendType { - // The default WebGPU backend. - kGpuBackend = 0, - // The APU accelerator backend. Only available on devices with APU, and need - // special APU model files. - kApuBackend = 1, -}; - // A contiguous byte span. struct ChromeMLByteSpan { uint8_t* data; @@ -79,7 +73,7 @@ // Describes a model to use with ChromeML. struct ChromeMLModelDescriptor { // The backend to run this model. - ModelBackendType backend_type; + ml::ModelBackendType backend_type; // The model data to use. const ChromeMLModelData* model_data; @@ -105,6 +99,8 @@ bool enable_host_mapped_pointer; bool use_low_power; bool allow_fp16; + + ml::ModelPerformanceHint performance_hint; }; // Describes an adaptation for a model.
diff --git a/services/on_device_model/ml/chrome_ml_types.h b/services/on_device_model/ml/chrome_ml_types.h index 2a0135d..d929ecbd 100644 --- a/services/on_device_model/ml/chrome_ml_types.h +++ b/services/on_device_model/ml/chrome_ml_types.h
@@ -28,6 +28,21 @@ // current library version. using InputPiece = std::variant<Token, std::string, SkBitmap, bool>; +// Options for specifying the performance characteristics of the model to load. +enum class ModelPerformanceHint { + kHighestQuality, + kFastestInference, +}; + +// Type of the backend to run the model. +enum ModelBackendType { + // The default WebGPU backend. + kGpuBackend = 0, + // The APU accelerator backend. Only available on devices with APU, and need + // special APU model files. + kApuBackend = 1, +}; + } // namespace ml #endif // SERVICES_ON_DEVICE_MODEL_ML_CHROME_ML_TYPES_H_
diff --git a/services/on_device_model/ml/chrome_ml_types_traits.cc b/services/on_device_model/ml/chrome_ml_types_traits.cc index 0fd4846a..e8acfec 100644 --- a/services/on_device_model/ml/chrome_ml_types_traits.cc +++ b/services/on_device_model/ml/chrome_ml_types_traits.cc
@@ -98,4 +98,62 @@ return false; } +// static +on_device_model::mojom::ModelBackendType +EnumTraits<on_device_model::mojom::ModelBackendType, + ml::ModelBackendType>::ToMojom(ml::ModelBackendType input) { + switch (input) { + case ml::ModelBackendType::kGpuBackend: + return on_device_model::mojom::ModelBackendType::kGpu; + case ml::ModelBackendType::kApuBackend: + return on_device_model::mojom::ModelBackendType::kApu; + } + NOTREACHED(); +} + +// static +bool EnumTraits<on_device_model::mojom::ModelBackendType, + ml::ModelBackendType>:: + FromMojom(on_device_model::mojom::ModelBackendType input, + ml::ModelBackendType* output) { + switch (input) { + case on_device_model::mojom::ModelBackendType::kGpu: + *output = ml::ModelBackendType::kGpuBackend; + return true; + case on_device_model::mojom::ModelBackendType::kApu: + *output = ml::ModelBackendType::kApuBackend; + return true; + } + return false; +} + +// static +on_device_model::mojom::ModelPerformanceHint +EnumTraits<on_device_model::mojom::ModelPerformanceHint, + ml::ModelPerformanceHint>::ToMojom(ml::ModelPerformanceHint input) { + switch (input) { + case ml::ModelPerformanceHint::kHighestQuality: + return on_device_model::mojom::ModelPerformanceHint::kHighestQuality; + case ml::ModelPerformanceHint::kFastestInference: + return on_device_model::mojom::ModelPerformanceHint::kFastestInference; + } + NOTREACHED(); +} + +// static +bool EnumTraits<on_device_model::mojom::ModelPerformanceHint, + ml::ModelPerformanceHint>:: + FromMojom(on_device_model::mojom::ModelPerformanceHint input, + ml::ModelPerformanceHint* output) { + switch (input) { + case on_device_model::mojom::ModelPerformanceHint::kHighestQuality: + *output = ml::ModelPerformanceHint::kHighestQuality; + return true; + case on_device_model::mojom::ModelPerformanceHint::kFastestInference: + *output = ml::ModelPerformanceHint::kFastestInference; + return true; + } + return false; +} + } // namespace mojo
diff --git a/services/on_device_model/ml/chrome_ml_types_traits.h b/services/on_device_model/ml/chrome_ml_types_traits.h index bc83eb8..657db6a4 100644 --- a/services/on_device_model/ml/chrome_ml_types_traits.h +++ b/services/on_device_model/ml/chrome_ml_types_traits.h
@@ -43,6 +43,24 @@ ml::InputPiece* out); }; +template <> +struct EnumTraits<on_device_model::mojom::ModelBackendType, + ml::ModelBackendType> { + static on_device_model::mojom::ModelBackendType ToMojom( + ml::ModelBackendType input); + static bool FromMojom(on_device_model::mojom::ModelBackendType input, + ml::ModelBackendType* output); +}; + +template <> +struct EnumTraits<on_device_model::mojom::ModelPerformanceHint, + ml::ModelPerformanceHint> { + static on_device_model::mojom::ModelPerformanceHint ToMojom( + ml::ModelPerformanceHint input); + static bool FromMojom(on_device_model::mojom::ModelPerformanceHint input, + ml::ModelPerformanceHint* output); +}; + } // namespace mojo #endif // SERVICES_ON_DEVICE_MODEL_ML_CHROME_ML_TYPES_TRAITS_H_
diff --git a/services/on_device_model/ml/gpu_blocklist.cc b/services/on_device_model/ml/gpu_blocklist.cc index e35c509e..24be686 100644 --- a/services/on_device_model/ml/gpu_blocklist.cc +++ b/services/on_device_model/ml/gpu_blocklist.cc
@@ -16,7 +16,7 @@ namespace { const base::FeatureParam<std::string> kGpuBlockList{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_model_gpu_block_list", // These devices are nearly always crashing or have very low performance. "8086:412|8086:a16|8086:41e|8086:416|8086:402|8086:166|8086:1616|8086:22b1|"
diff --git a/services/on_device_model/ml/on_device_model_executor.cc b/services/on_device_model/ml/on_device_model_executor.cc index 7641616..a433736 100644 --- a/services/on_device_model/ml/on_device_model_executor.cc +++ b/services/on_device_model/ml/on_device_model_executor.cc
@@ -105,18 +105,6 @@ std::max(1u, top_k.value_or(1))); } -std::optional<ModelBackendType> ModelBackendTypeFromMojom( - on_device_model::mojom::ModelBackendType backend) { - switch (backend) { - case on_device_model::mojom::ModelBackendType::kGpu: - return ModelBackendType::kGpuBackend; - case on_device_model::mojom::ModelBackendType::kApu: - return ModelBackendType::kApuBackend; - default: - return std::nullopt; - } -} - } // namespace // Handles sending and canceling responses. @@ -466,24 +454,17 @@ max_tokens_ = std::max(params->max_tokens, kReserveTokensForSafety); - std::optional<ModelBackendType> backend_type = - ModelBackendTypeFromMojom(params->backend_type); - if (!backend_type.has_value()) { - LOG(ERROR) << "Failed to parse model backend type"; - return LoadModelResult::kFailedToLoadLibrary; - } - ChromeMLModelData data; std::string weights_path_str = assets.weights_path.AsUTF8Unsafe(); std::string sp_model_path_str = assets.sp_model_path.AsUTF8Unsafe(); - if (*backend_type == ModelBackendType::kGpuBackend) { + if (params->backend_type == ml::ModelBackendType::kGpuBackend) { data.weights_file = assets.weights.TakePlatformFile(); } else { data.model_path = weights_path_str.data(); data.sentencepiece_model_path = sp_model_path_str.data(); } ChromeMLModelDescriptor descriptor = { - .backend_type = *backend_type, + .backend_type = params->backend_type, .model_data = &data, .max_tokens = max_tokens_, .temperature = 0.0f, @@ -494,6 +475,7 @@ .enable_host_mapped_pointer = kEnableHostMappedPointer.Get(), .use_low_power = kUseLowPower.Get(), .allow_fp16 = kAllowFp16.Get(), + .performance_hint = params->performance_hint, }; model_ = chrome_ml_->api().SessionCreateModel( &descriptor, reinterpret_cast<uintptr_t>(this),
diff --git a/services/on_device_model/ml/performance_class.cc b/services/on_device_model/ml/performance_class.cc index eff15fa..b29cea0a 100644 --- a/services/on_device_model/ml/performance_class.cc +++ b/services/on_device_model/ml/performance_class.cc
@@ -18,30 +18,30 @@ // The threshold for GPU RAM below which the device is considered VeryLow. const base::FeatureParam<int> kLowRAMThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_low_ram_threshold_mb", 3000}; // RAM threshold necessary to be considered High or better. const base::FeatureParam<int> kHighRAMThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_high_ram_threshold_mb", 5500}; // Output threshold to be considered Low or better. const base::FeatureParam<int> kLowOutputThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_low_output_threshold", 5}; // Input speed min thresholds or each device class. const base::FeatureParam<int> kLowThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_low_threshold", 50}; const base::FeatureParam<int> kMediumThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_medium_threshold", 75}; const base::FeatureParam<int> kHighThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_high_threshold", 150}; const base::FeatureParam<int> kVeryHighThreshold{ - &optimization_guide::features::kOptimizationGuideOnDeviceModel, + &optimization_guide::features::kOnDeviceModelPerformanceParams, "on_device_very_high_threshold", 500}; // These values are persisted to logs. Entries should not be renumbered and
diff --git a/services/on_device_model/on_device_model_service_unittest.cc b/services/on_device_model/on_device_model_service_unittest.cc index 413c6359..cce46101 100644 --- a/services/on_device_model/on_device_model_service_unittest.cc +++ b/services/on_device_model/on_device_model_service_unittest.cc
@@ -81,11 +81,14 @@ mojo::Remote<mojom::OnDeviceModelService>& service() { return service_; } mojo::Remote<mojom::OnDeviceModel> LoadModel( - mojom::ModelBackendType backend_type = mojom::ModelBackendType::kGpu) { + ml::ModelBackendType backend_type = ml::ModelBackendType::kGpuBackend, + ml::ModelPerformanceHint performance_hint = + ml::ModelPerformanceHint::kHighestQuality) { base::RunLoop run_loop; mojo::Remote<mojom::OnDeviceModel> remote; auto params = mojom::LoadModelParams::New(); params->backend_type = backend_type; + params->performance_hint = performance_hint; params->max_tokens = 8000; service()->LoadModel( std::move(params), remote.BindNewPipeAndPassReceiver(), @@ -452,7 +455,7 @@ TEST_F(OnDeviceModelServiceTest, LoadsAdaptationWithPath) { FakeFile weights1("Adapt1"); FakeFile weights2("Adapt2"); - auto model = LoadModel(mojom::ModelBackendType::kApu); + auto model = LoadModel(ml::ModelBackendType::kApuBackend); auto adaptation1 = LoadAdaptation(*model, weights1.Path()); EXPECT_THAT(GetResponses(*model, "foo"), ElementsAre("Input: foo\n")); EXPECT_THAT(GetResponses(*adaptation1, "foo"), @@ -633,5 +636,12 @@ EXPECT_THAT(resp2->class_scores, ElementsAre(0.2, 0.2)); } +TEST_F(OnDeviceModelServiceTest, PerformanceHint) { + auto model = LoadModel(ml::ModelBackendType::kGpuBackend, + ml::ModelPerformanceHint::kFastestInference); + EXPECT_THAT(GetResponses(*model, "foo"), + ElementsAre("Fastest inference\n", "Input: foo\n")); +} + } // namespace } // namespace on_device_model
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.cc b/services/on_device_model/public/cpp/test_support/fake_service.cc index 5220cf2..f493200 100644 --- a/services/on_device_model/public/cpp/test_support/fake_service.cc +++ b/services/on_device_model/public/cpp/test_support/fake_service.cc
@@ -130,6 +130,12 @@ mojom::InputOptionsPtr input, mojo::PendingRemote<mojom::StreamingResponder> response) { mojo::Remote<mojom::StreamingResponder> remote(std::move(response)); + if (model_->performance_hint() == + ml::ModelPerformanceHint::kFastestInference) { + auto chunk = mojom::ResponseChunk::New(); + chunk->text = "Fastest inference\n"; + remote->OnResponse(std::move(chunk)); + } if (model_->data().base_weight != "0") { auto chunk = mojom::ResponseChunk::New(); chunk->text = "Base model: " + model_->data().base_weight + "\n"; @@ -184,8 +190,11 @@ } FakeOnDeviceModel::FakeOnDeviceModel(FakeOnDeviceServiceSettings* settings, - FakeOnDeviceModel::Data&& data) - : settings_(settings), data_(std::move(data)) {} + FakeOnDeviceModel::Data&& data, + ml::ModelPerformanceHint performance_hint) + : settings_(settings), + data_(std::move(data)), + performance_hint_(performance_hint) {} FakeOnDeviceModel::~FakeOnDeviceModel() = default; @@ -221,8 +230,8 @@ LoadAdaptationCallback callback) { Data data = data_; data.adaptation_model_weight = ReadFile(params->assets.weights); - auto test_model = - std::make_unique<FakeOnDeviceModel>(settings_, std::move(data)); + auto test_model = std::make_unique<FakeOnDeviceModel>( + settings_, std::move(data), ml::ModelPerformanceHint::kHighestQuality); model_adaptation_receivers_.Add(std::move(test_model), std::move(model)); std::move(callback).Run(mojom::LoadModelResult::kSuccess); } @@ -292,8 +301,8 @@ } FakeOnDeviceModel::Data data; data.base_weight = ReadFile(params->assets.weights); - auto test_model = - std::make_unique<FakeOnDeviceModel>(settings_, std::move(data)); + auto test_model = std::make_unique<FakeOnDeviceModel>( + settings_, std::move(data), params->performance_hint); model_receivers_.Add(std::move(test_model), std::move(model)); std::move(callback).Run(mojom::LoadModelResult::kSuccess); }
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.h b/services/on_device_model/public/cpp/test_support/fake_service.h index 0b1bb12..86bd468 100644 --- a/services/on_device_model/public/cpp/test_support/fake_service.h +++ b/services/on_device_model/public/cpp/test_support/fake_service.h
@@ -112,7 +112,8 @@ std::string adaptation_model_weight = ""; }; explicit FakeOnDeviceModel(FakeOnDeviceServiceSettings* settings, - Data&& data); + Data&& data, + ml::ModelPerformanceHint performance_hint); ~FakeOnDeviceModel() override; // mojom::OnDeviceModel: @@ -134,9 +135,14 @@ const Data& data() const { return data_; } + ml::ModelPerformanceHint performance_hint() const { + return performance_hint_; + } + private: raw_ptr<FakeOnDeviceServiceSettings> settings_; Data data_; + ml::ModelPerformanceHint performance_hint_; mojo::UniqueReceiverSet<mojom::Session> receivers_; mojo::UniqueReceiverSet<mojom::OnDeviceModel> model_adaptation_receivers_;
diff --git a/services/on_device_model/public/mojom/BUILD.gn b/services/on_device_model/public/mojom/BUILD.gn index 5cbd4c46..27c5d345 100644 --- a/services/on_device_model/public/mojom/BUILD.gn +++ b/services/on_device_model/public/mojom/BUILD.gn
@@ -37,6 +37,14 @@ mojom = "on_device_model.mojom.InputPiece" cpp = "::ml::InputPiece" }, + { + mojom = "on_device_model.mojom.ModelBackendType" + cpp = "::ml::ModelBackendType" + }, + { + mojom = "on_device_model.mojom.ModelPerformanceHint" + cpp = "::ml::ModelPerformanceHint" + }, ] traits_headers = [ "//services/on_device_model/public/cpp/adaptation_assets_mojom_traits.h",
diff --git a/services/on_device_model/public/mojom/on_device_model_service.mojom b/services/on_device_model/public/mojom/on_device_model_service.mojom index 0c5f5e6..cfa2f673 100644 --- a/services/on_device_model/public/mojom/on_device_model_service.mojom +++ b/services/on_device_model/public/mojom/on_device_model_service.mojom
@@ -36,6 +36,12 @@ kApu, }; +// Options for specifying the performance characteristics of the model to load. +enum ModelPerformanceHint { + kHighestQuality, + kFastestInference, +}; + // Params to describe the model to load. struct LoadModelParams { // Backend type of the model. @@ -50,6 +56,10 @@ // List of adaptation ranks the model should support. array<uint32> adaptation_ranks; + + // Chooses the performance characteristics of the model loaded. If only a + // single model is available, this field will do nothing. + ModelPerformanceHint performance_hint = kHighestQuality; }; struct TextSafetyModelAssets {
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc index a1786a07..047be7f 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc
@@ -26,7 +26,6 @@ perfetto::DataSourceDescriptor dsd; dsd.set_name(name()); DataSourceProxy::Register(dsd, this); - tracing::PerfettoTracedProcess::Get()->AddDataSource(this); } TracingObserver::~TracingObserver() = default;
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn index 35be031..d01ffc2 100644 --- a/services/tracing/BUILD.gn +++ b/services/tracing/BUILD.gn
@@ -89,7 +89,6 @@ sources = [ "perfetto/consumer_host_unittest.cc", - "perfetto/perfetto_integration_unittest.cc", "perfetto/privacy_filtering_check_unittest.cc", "public/cpp/perfetto/perfetto_config_unittest.cc", "public/cpp/perfetto/trace_packet_tokenizer_unittest.cc",
diff --git a/services/tracing/perfetto/consumer_host_unittest.cc b/services/tracing/perfetto/consumer_host_unittest.cc index c87269e..29a5a19d 100644 --- a/services/tracing/perfetto/consumer_host_unittest.cc +++ b/services/tracing/perfetto/consumer_host_unittest.cc
@@ -21,6 +21,7 @@ #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool.h" #include "base/test/bind.h" +#include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" #include "base/trace_event/trace_config.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -41,6 +42,8 @@ constexpr base::ProcessId kProducerPid = 1234; +using testing::_; + // This is here so we can properly simulate this running on three // different sequences (ProducerClient side, Service side, and // whatever connects via Mojo to the Producer). This is needed @@ -113,33 +116,107 @@ void OnTracingDisabled(bool) override {} - void CreateProducer(const std::string& data_source_name, - size_t num_packets, - base::OnceClosure on_tracing_started) { - base::RunLoop wait_for_datasource_registration; + void CreateProducer() { + base::RunLoop wait_for_producer; task_runner_->PostTask( FROM_HERE, base::BindOnce(&ThreadedPerfettoService::CreateProducerOnSequence, + base::Unretained(this), + wait_for_producer.QuitClosure())); + wait_for_producer.Run(); + } + + std::unique_ptr<perfetto::TraceWriter> RegisterDataSource( + const std::string& data_source_name) { + base::RunLoop wait_for_datasource; + std::unique_ptr<perfetto::TraceWriter> trace_writer; + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&ThreadedPerfettoService::RegisterDataSourceOnSequence, base::Unretained(this), data_source_name, - wait_for_datasource_registration.QuitClosure(), - std::move(on_tracing_started), num_packets)); - wait_for_datasource_registration.Run(); + wait_for_datasource.QuitClosure())); + wait_for_datasource.Run(); + return trace_writer; + } + + std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter( + const std::string& data_source_name) { + base::RunLoop wait_for_datasource; + std::unique_ptr<perfetto::TraceWriter> trace_writer; + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&ThreadedPerfettoService::CreateTraceWriterOnSequence, + base::Unretained(this), data_source_name, + base::BindLambdaForTesting( + [&](std::unique_ptr<perfetto::TraceWriter> writer) { + trace_writer = std::move(writer); + wait_for_datasource.Quit(); + }))); + wait_for_datasource.Run(); + return trace_writer; + } + + perfetto::DataSourceConfig GetDataSourceConfig( + const std::string& data_source_name) { + base::RunLoop wait_for_datasource; + perfetto::DataSourceConfig ds_config; + task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &ThreadedPerfettoService::GetDataSourceConfigOnSequence, + base::Unretained(this), data_source_name, + base::BindLambdaForTesting([&](perfetto::DataSourceConfig config) { + ds_config = config; + wait_for_datasource.Quit(); + }))); + wait_for_datasource.Run(); + return ds_config; } void CreateConsumerOnSequence() { consumer_ = std::make_unique<ConsumerHost>(perfetto_service_.get()); } - void CreateProducerOnSequence(const std::string& data_source_name, - base::OnceClosure on_datasource_registered, - base::OnceClosure on_tracing_started, - size_t num_packets) { - producer_ = std::make_unique<MockProducer>( - base::StrCat({mojom::kPerfettoProducerNamePrefix, - base::NumberToString(kProducerPid)}), - data_source_name, perfetto_service_.get(), - std::move(on_datasource_registered), std::move(on_tracing_started), - num_packets); + void CreateProducerOnSequence(base::OnceClosure on_producer_connected) { + producer_ = std::make_unique<MockProducer>(); + producer_->Connect(perfetto_service_.get(), + base::StrCat({mojom::kPerfettoProducerNamePrefix, + base::NumberToString(kProducerPid)})); + EXPECT_CALL(*producer_, OnConnect()) + .WillOnce(base::test::RunOnceClosure(std::move(on_producer_connected))); + } + + void RegisterDataSourceOnSequence(const std::string& data_source_name, + base::OnceClosure on_data_source_start) { + producer_->RegisterDataSource(data_source_name); + EXPECT_CALL(*producer_, OnStartDataSource(data_source_name, _)) + .WillOnce(base::test::RunOnceClosure(std::move(on_data_source_start))); + } + + void CreateTraceWriterOnSequence( + const std::string& data_source_name, + base::RepeatingCallback<void(std::unique_ptr<perfetto::TraceWriter>)> + on_data_source_start) { + producer_->RegisterDataSource(data_source_name); + EXPECT_CALL(*producer_, OnStartDataSource(data_source_name, _)) + .WillOnce( + [on_data_source_start, this](const std::string& name, + perfetto::DataSourceInstanceID ds_id) { + on_data_source_start.Run(producer_->CreateTraceWriter(ds_id)); + }); + } + + void GetDataSourceConfigOnSequence( + const std::string& data_source_name, + base::RepeatingCallback<void(perfetto::DataSourceConfig)> + on_data_source_start) { + producer_->RegisterDataSource(data_source_name); + EXPECT_CALL(*producer_, OnStartDataSource(data_source_name, _)) + .WillOnce( + [on_data_source_start, this](const std::string& name, + perfetto::DataSourceInstanceID ds_id) { + on_data_source_start.Run(producer_->GetDataSourceConfig(ds_id)); + }); } void EnableTracingWithConfig(const perfetto::TraceConfig& config) { @@ -200,16 +277,11 @@ wait_for_call.Run(); } - void WritePacketBigly() { - base::RunLoop wait_for_call; - task_runner_->PostTask(FROM_HERE, - base::BindOnce(&MockProducer::WritePacketBigly, - base::Unretained(producer_.get()), - wait_for_call.QuitClosure())); - wait_for_call.Run(); - } - - void Flush(base::OnceClosure on_flush_complete) { + void Flush(perfetto::TraceWriter& writer_to_flush, + base::OnceClosure on_flush_complete) { + EXPECT_CALL(*producer_, OnFlush()).WillOnce([&]() { + writer_to_flush.Flush(); + }); task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -270,18 +342,6 @@ *tracing_enabled = tracing_enabled_; } - perfetto::DataSourceConfig GetProducerClientConfig() { - perfetto::DataSourceConfig config; - base::RunLoop wait_loop; - task_runner_->PostTaskAndReply(FROM_HERE, base::BindLambdaForTesting([&]() { - config = - producer_->data_source()->config(); - }), - wait_loop.QuitClosure()); - wait_loop.Run(); - return config; - } - void ClearConsumer() { base::RunLoop wait_loop; task_runner_->PostTaskAndReply( @@ -304,16 +364,11 @@ }; // TODO(crbug.com/42050015): Switch this to use TracingUnitTest. -class TracingConsumerTest : public testing::Test, +class TracingConsumerTest : public TracingUnitTest, public mojo::DataPipeDrainer::Client { public: void SetUp() override { - task_environment_ = std::make_unique<base::test::TaskEnvironment>( - base::test::TaskEnvironment::MainThreadType::IO); - tracing_environment_ = std::make_unique<base::test::TracingEnvironment>( - *task_environment_, base::SingleThreadTaskRunner::GetCurrentDefault()); - test_handle_ = tracing::PerfettoTracedProcess::SetupForTesting(); - PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); + TracingUnitTest::SetUp(); threaded_service_ = std::make_unique<ThreadedPerfettoService>(); matching_packet_count_ = 0; @@ -321,11 +376,8 @@ } void TearDown() override { - tracing_environment_.reset(); threaded_service_.reset(); - task_environment_->RunUntilIdle(); - test_handle_.reset(); - task_environment_.reset(); + TracingUnitTest::TearDown(); } // mojo::DataPipeDrainer::Client @@ -434,7 +486,7 @@ bool IsTracingEnabled() { // Flush any other pending tasks on the perfetto task runner to ensure that // any pending data source start callbacks have propagated. - task_environment_->RunUntilIdle(); + RunUntilIdle(); return threaded_service_->IsTracingEnabled(); } @@ -447,9 +499,6 @@ private: std::unique_ptr<ThreadedPerfettoService> threaded_service_; - std::unique_ptr<base::test::TaskEnvironment> task_environment_; - std::unique_ptr<base::test::TracingEnvironment> tracing_environment_; - std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_; base::OnceClosure on_data_complete_; std::unique_ptr<mojo::DataPipeDrainer> drainer_; std::vector<uint8_t> received_data_; @@ -476,11 +525,9 @@ TEST_F(TracingConsumerTest, ReceiveTestPackets) { EnableTracingWithDataSourceName(kDataSourceName); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 10u, wait_for_tracing_start.QuitClosure()); - - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + auto writer = threaded_perfetto_service()->CreateTraceWriter(kDataSourceName); + MockProducer::WritePackets(*writer, 10); base::RunLoop no_more_data; ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure()); @@ -496,11 +543,9 @@ TEST_F(TracingConsumerTest, DeleteConsumerWhenReceiving) { EnableTracingWithDataSourceName(kDataSourceName); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 100u, wait_for_tracing_start.QuitClosure()); - - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + auto writer = threaded_perfetto_service()->CreateTraceWriter(kDataSourceName); + MockProducer::WritePackets(*writer, 100u); base::RunLoop no_more_data; ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure()); @@ -515,17 +560,16 @@ TEST_F(TracingConsumerTest, FlushProducers) { EnableTracingWithDataSourceName(kDataSourceName); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 10u, wait_for_tracing_start.QuitClosure()); - - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + auto writer = threaded_perfetto_service()->CreateTraceWriter(kDataSourceName); + MockProducer::WritePackets(*writer, 10); base::RunLoop wait_for_packets; ExpectPackets(kPerfettoTestString, wait_for_packets.QuitClosure()); base::RunLoop wait_for_flush; - threaded_perfetto_service()->Flush(wait_for_flush.QuitClosure()); + + threaded_perfetto_service()->Flush(*writer, wait_for_flush.QuitClosure()); ReadBuffers(); wait_for_flush.Run(); @@ -537,17 +581,13 @@ TEST_F(TracingConsumerTest, LargeDataSize) { EnableTracingWithDataSourceName(kDataSourceName); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 0u, wait_for_tracing_start.QuitClosure()); - - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + auto writer = threaded_perfetto_service()->CreateTraceWriter(kDataSourceName); + MockProducer::WritePacketBigly(*writer); base::RunLoop no_more_data; ExpectPackets(kPerfettoTestString, no_more_data.QuitClosure()); - threaded_perfetto_service()->WritePacketBigly(); - threaded_perfetto_service()->DisableTracing(); ReadBuffers(); @@ -573,10 +613,8 @@ // its data source has started. EXPECT_FALSE(IsTracingEnabled()); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 0u, wait_for_tracing_start.QuitClosure()); - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + threaded_perfetto_service()->RegisterDataSource(kDataSourceName); EXPECT_TRUE(IsTracingEnabled()); } @@ -596,10 +634,8 @@ // its data source has started. EXPECT_FALSE(IsTracingEnabled()); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 0u, wait_for_tracing_start.QuitClosure()); - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + threaded_perfetto_service()->RegisterDataSource(kDataSourceName); EXPECT_TRUE(IsTracingEnabled()); } @@ -632,10 +668,8 @@ // its data source has started and once the PIDs are initialized. EXPECT_FALSE(IsTracingEnabled()); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 0u, wait_for_tracing_start.QuitClosure()); - wait_for_tracing_start.Run(); + threaded_perfetto_service()->CreateProducer(); + threaded_perfetto_service()->RegisterDataSource(kDataSourceName); EXPECT_FALSE(IsTracingEnabled()); @@ -648,19 +682,13 @@ /* enable_privacy_filtering =*/true, /* convert_to_legacy_json =*/false); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 10u, wait_for_tracing_start.QuitClosure()); + threaded_perfetto_service()->CreateProducer(); - wait_for_tracing_start.Run(); - EXPECT_TRUE(threaded_perfetto_service() - ->GetProducerClientConfig() - .chrome_config() - .privacy_filtering_enabled()); - base::trace_event::TraceConfig base_config(threaded_perfetto_service() - ->GetProducerClientConfig() - .chrome_config() - .trace_config()); + auto config = + threaded_perfetto_service()->GetDataSourceConfig(kDataSourceName); + EXPECT_TRUE(config.chrome_config().privacy_filtering_enabled()); + base::trace_event::TraceConfig base_config( + config.chrome_config().trace_config()); EXPECT_FALSE(base_config.IsArgumentFilterEnabled()); } @@ -669,20 +697,13 @@ /* enable_privacy_filtering =*/false, /* convert_to_legacy_json =*/true); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 10u, wait_for_tracing_start.QuitClosure()); + threaded_perfetto_service()->CreateProducer(); - wait_for_tracing_start.Run(); - - EXPECT_FALSE(threaded_perfetto_service() - ->GetProducerClientConfig() - .chrome_config() - .privacy_filtering_enabled()); - base::trace_event::TraceConfig base_config(threaded_perfetto_service() - ->GetProducerClientConfig() - .chrome_config() - .trace_config()); + auto config = + threaded_perfetto_service()->GetDataSourceConfig(kDataSourceName); + EXPECT_FALSE(config.chrome_config().privacy_filtering_enabled()); + base::trace_event::TraceConfig base_config( + config.chrome_config().trace_config()); EXPECT_FALSE(base_config.IsArgumentFilterEnabled()); } @@ -691,20 +712,12 @@ /* enable_privacy_filtering =*/true, /* convert_to_legacy_json =*/true); - base::RunLoop wait_for_tracing_start; - threaded_perfetto_service()->CreateProducer( - kDataSourceName, 10u, wait_for_tracing_start.QuitClosure()); - - wait_for_tracing_start.Run(); - - EXPECT_FALSE(threaded_perfetto_service() - ->GetProducerClientConfig() - .chrome_config() - .privacy_filtering_enabled()); - base::trace_event::TraceConfig base_config(threaded_perfetto_service() - ->GetProducerClientConfig() - .chrome_config() - .trace_config()); + threaded_perfetto_service()->CreateProducer(); + auto config = + threaded_perfetto_service()->GetDataSourceConfig(kDataSourceName); + EXPECT_FALSE(config.chrome_config().privacy_filtering_enabled()); + base::trace_event::TraceConfig base_config( + config.chrome_config().trace_config()); EXPECT_TRUE(base_config.IsArgumentFilterEnabled()); base::RunLoop no_more_data; @@ -721,56 +734,4 @@ EXPECT_EQ(1u, matching_packet_count()); } -class MockConsumerHost : public mojom::TracingSessionClient { - public: - explicit MockConsumerHost(PerfettoService* service) - : consumer_host_(std::make_unique<ConsumerHost>(service)) {} - - void EnableTracing(const perfetto::TraceConfig& config) { - mojo::PendingRemote<tracing::mojom::TracingSessionClient> - tracing_session_client; - receiver_.Bind(tracing_session_client.InitWithNewPipeAndPassReceiver()); - - receiver_.set_disconnect_handler(base::BindOnce( - &MockConsumerHost::OnConnectionLost, base::Unretained(this))); - - consumer_host_->EnableTracing( - tracing_session_host_.BindNewPipeAndPassReceiver(), - std::move(tracing_session_client), config, base::File()); - tracing_session_host_.set_disconnect_handler(base::BindOnce( - &MockConsumerHost::OnConnectionLost, base::Unretained(this))); - } - - void DisableTracing() { tracing_session_host_->DisableTracing(); } - - void OnConnectionLost() { - CloseTracingSession(); - wait_for_connection_lost_.Quit(); - } - - void CloseTracingSession() { - tracing_session_host_.reset(); - receiver_.reset(); - } - - // mojom::TracingSessionClient implementation: - void OnTracingEnabled() override { wait_for_tracing_enabled_.Quit(); } - - void OnTracingDisabled(bool) override { wait_for_tracing_disabled_.Quit(); } - - void WaitForConnectionLost() { wait_for_connection_lost_.Run(); } - - void WaitForTracingEnabled() { wait_for_tracing_enabled_.Run(); } - - void WaitForTracingDisabled() { wait_for_tracing_disabled_.Run(); } - - private: - mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_; - mojo::Receiver<mojom::TracingSessionClient> receiver_{this}; - std::unique_ptr<ConsumerHost> consumer_host_; - base::RunLoop wait_for_connection_lost_; - base::RunLoop wait_for_tracing_enabled_; - base::RunLoop wait_for_tracing_disabled_; -}; - } // namespace tracing
diff --git a/services/tracing/perfetto/perfetto_integration_unittest.cc b/services/tracing/perfetto/perfetto_integration_unittest.cc deleted file mode 100644 index 176e57bd..0000000 --- a/services/tracing/perfetto/perfetto_integration_unittest.cc +++ /dev/null
@@ -1,457 +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. - -#include <memory> -#include <string> -#include <thread> -#include <utility> - -#include "base/functional/bind.h" -#include "base/run_loop.h" -#include "base/strings/strcat.h" -#include "base/test/bind.h" -#include "base/threading/thread.h" -#include "base/tracing/perfetto_platform.h" -#include "services/tracing/perfetto/perfetto_service.h" -#include "services/tracing/perfetto/producer_host.h" -#include "services/tracing/perfetto/test_utils.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/perfetto/include/perfetto/tracing/tracing.h" -#include "third_party/perfetto/protos/perfetto/common/commit_data_request.pb.h" - -// TODO(crbug.com/41457644): Fix memory leaks in tests and re-enable on LSAN. -#ifdef LEAK_SANITIZER -#define MAYBE_DifferentSharedMemoryBuffersForDifferentAgents \ - DISABLED_DifferentSharedMemoryBuffersForDifferentAgents -#else -#define MAYBE_DifferentSharedMemoryBuffersForDifferentAgents \ - DifferentSharedMemoryBuffersForDifferentAgents -#endif - -namespace tracing { - -namespace { - -const char kPerfettoTestDataSourceName[] = - "org.chromium.chrome_integration_unittest"; - -std::string GetPerfettoProducerName() { - return base::StrCat({mojom::kPerfettoProducerNamePrefix, "123"}); -} - -class PerfettoIntegrationTest : public TracingUnitTest { - public: - void SetUp() override { - TracingUnitTest::SetUp(); - data_source_ = TestDataSource::CreateAndRegisterDataSource( - kPerfettoTestDataSourceName, 0); - perfetto_service_ = std::make_unique<PerfettoService>(); - RunUntilIdle(); - } - - void TearDown() override { - perfetto_service_.reset(); - TracingUnitTest::TearDown(); - } - - PerfettoService* perfetto_service() const { return perfetto_service_.get(); } - - protected: - std::unique_ptr<TestDataSource> data_source_; - std::unique_ptr<PerfettoService> perfetto_service_; -}; - -TEST_F(PerfettoIntegrationTest, ProducerDatasourceInitialized) { - std::unique_ptr<MockProducerClient::Handle> dummy_client = - MockProducerClient::Create(); - - base::RunLoop producer_initialized_runloop; - auto new_producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **dummy_client, producer_initialized_runloop.QuitClosure()); - - producer_initialized_runloop.Run(); -} - -TEST_F(PerfettoIntegrationTest, ClientEnabledAndDisabled) { - base::RunLoop on_trace_packets; - MockConsumer consumer({kPerfettoTestDataSourceName}, - perfetto_service()->GetService(), - [&on_trace_packets](bool has_more) { - EXPECT_FALSE(has_more); - on_trace_packets.Quit(); - }); - - base::RunLoop client_enabled_callback; - base::RunLoop client_disabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 1, client_enabled_callback.QuitClosure(), - client_disabled_callback.QuitClosure()); - - auto producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client); - - client_enabled_callback.Run(); - - RunUntilIdle(); - - consumer.StopTracing(); - - client_disabled_callback.Run(); - - on_trace_packets.Run(); - EXPECT_EQ(0u, consumer.received_test_packets()); -} - -TEST_F(PerfettoIntegrationTest, PacketsEndToEndProducerFirst) { - const size_t kNumPackets = 10; - data_source_->set_send_packet_count(kNumPackets); - - base::RunLoop client_enabled_callback; - base::RunLoop client_disabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 1, client_enabled_callback.QuitClosure(), - client_disabled_callback.QuitClosure()); - - auto producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client); - - base::RunLoop no_more_packets_runloop; - MockConsumer consumer({kPerfettoTestDataSourceName}, - perfetto_service()->GetService(), - [&no_more_packets_runloop](bool has_more) { - if (!has_more) { - no_more_packets_runloop.Quit(); - } - }); - - client_enabled_callback.Run(); - - RunUntilIdle(); - - consumer.StopTracing(); - client_disabled_callback.Run(); - - no_more_packets_runloop.Run(); - - EXPECT_EQ(kNumPackets, consumer.received_test_packets()); -} - -TEST_F(PerfettoIntegrationTest, PacketsEndToEndConsumerFirst) { - const size_t kNumPackets = 10; - data_source_->set_send_packet_count(kNumPackets); - - base::RunLoop no_more_packets_runloop; - MockConsumer consumer({kPerfettoTestDataSourceName}, - perfetto_service()->GetService(), - [&no_more_packets_runloop](bool has_more) { - if (!has_more) { - no_more_packets_runloop.Quit(); - } - }); - - base::RunLoop client_enabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 1, client_enabled_callback.QuitClosure()); - - auto new_producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client); - - client_enabled_callback.Run(); - - RunUntilIdle(); - - consumer.StopTracing(); - - no_more_packets_runloop.Run(); - - EXPECT_EQ(kNumPackets, consumer.received_test_packets()); -} - -TEST_F(PerfettoIntegrationTest, CloneSession) { - const size_t kNumPackets = 100; - data_source_->set_send_packet_count(kNumPackets); - - perfetto::TraceConfig trace_config; - auto uuid = base::UnguessableToken::Create(); - trace_config.set_unique_session_name(uuid.ToString()); - trace_config.add_buffers()->set_size_kb(1024 * 32); - { - auto* ds_config = trace_config.add_data_sources()->mutable_config(); - ds_config->set_name(kPerfettoTestDataSourceName); - ds_config->set_target_buffer(0); - } - - MockConsumer consumer( - {kPerfettoTestDataSourceName}, perfetto_service()->GetService(), - [](bool has_more) {}, trace_config); - - base::RunLoop client_enabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 1, client_enabled_callback.QuitClosure()); - - auto new_producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, - perfetto_service(), **client); - - client_enabled_callback.Run(); - - class ClonedConsumer : public MockConsumerBase { - public: - ClonedConsumer(perfetto::TracingService* service, - PacketReceivedCallback packet_received_callback) - : MockConsumerBase(service, std::move(packet_received_callback)) {} - - // perfetto::Consumer implementation - void OnSessionCloned(const OnSessionClonedArgs& args) override { - on_session_cloned_runloop_.Quit(); - } - - void WaitForSessionCloned() { on_session_cloned_runloop_.Run(); } - - private: - base::RunLoop on_session_cloned_runloop_; - }; - - base::RunLoop no_more_packets_runloop; - ClonedConsumer cloned_consumer(perfetto_service()->GetService(), - [&no_more_packets_runloop](bool has_more) { - if (!has_more) { - no_more_packets_runloop.Quit(); - } - }); - cloned_consumer.CloneSession(uuid.ToString()); - cloned_consumer.WaitForSessionCloned(); - cloned_consumer.ReadBuffers(); - no_more_packets_runloop.Run(); - EXPECT_EQ(kNumPackets, cloned_consumer.received_test_packets()); - - consumer.StopTracing(); -} - -TEST_F(PerfettoIntegrationTest, CommitDataRequestIsMaybeComplete) { - const size_t kNumPackets = 100; - data_source_->set_send_packet_count(kNumPackets); - - base::RunLoop no_more_packets_runloop; - MockConsumer consumer({kPerfettoTestDataSourceName}, - perfetto_service()->GetService(), - [&no_more_packets_runloop](bool has_more) { - if (!has_more) { - no_more_packets_runloop.Quit(); - } - }); - - base::RunLoop client_enabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 1, client_enabled_callback.QuitClosure()); - auto new_producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client); - - client_enabled_callback.Run(); - - base::RunLoop wait_for_packet_write; - PerfettoTracedProcess::Get() - ->GetTaskRunner() - ->GetOrCreateTaskRunner() - ->PostTaskAndReply(FROM_HERE, - base::BindOnce(&TestDataSource::WritePacketBigly, - base::Unretained(data_source_.get())), - wait_for_packet_write.QuitClosure()); - wait_for_packet_write.Run(); - - RunUntilIdle(); - - consumer.StopTracing(); - - no_more_packets_runloop.Run(); - - // {cli,host}_reqs are a std::vector<std::string>. Each entry of the vector - // is a proto-serialized CommitDataRequest. - const auto& cli_reqs = (*client)->all_client_commit_data_requests(); - const auto& host_reqs = new_producer->all_host_commit_data_requests(); - ASSERT_EQ(cli_reqs.size(), host_reqs.size()); - for (size_t i = 0; i < cli_reqs.size(); i++) { - // Note that the proto-encoded strings are not identical. This is because - // perfetto doesn't emit unset fields. But then when going over mojo these - // unset fields get copied as 0-value (it's fine), so on the host side we - // see extra fields being explicitly zero-initialized. Here we force a - // re-encode using the libprotobuf message for the sake of the comparison. - // libprotobuf will re-normalize messages before serializing. - perfetto::protos::CommitDataRequest cli_req; - ASSERT_TRUE(cli_req.ParseFromString(cli_reqs[i])); - perfetto::protos::CommitDataRequest host_req; - ASSERT_TRUE(host_req.ParseFromString(cli_reqs[i])); - ASSERT_EQ(cli_req.SerializeAsString(), host_req.SerializeAsString()); - } -} - -TEST_F(PerfettoIntegrationTest, TracingRestarted) { - const size_t kNumPackets = 10; - data_source_->set_send_packet_count(kNumPackets); - - base::RunLoop no_more_packets_runloop; - MockConsumer consumer({kPerfettoTestDataSourceName}, - perfetto_service()->GetService(), - [&no_more_packets_runloop](bool has_more) { - if (!has_more) { - no_more_packets_runloop.Quit(); - } - }); - - base::RunLoop client_enabled_callback; - base::RunLoop client_disabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 1, client_enabled_callback.QuitClosure(), - client_disabled_callback.QuitClosure()); - - auto new_producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client); - - client_enabled_callback.Run(); - - RunUntilIdle(); - - perfetto::SharedMemory* first_session_shm = - (*client)->shared_memory_for_testing(); - consumer.StopTracing(); - - client_disabled_callback.Run(); - no_more_packets_runloop.Run(); - EXPECT_EQ(kNumPackets, consumer.received_test_packets()); - - consumer.FreeBuffers(); - - base::RunLoop client_reenabled_callback; - (*client)->SetAgentEnabledCallback(client_reenabled_callback.QuitClosure()); - - consumer.StartTracing(); - client_reenabled_callback.Run(); - - RunUntilIdle(); - - // We should still be using the same shared memory. - EXPECT_EQ(first_session_shm, (*client)->shared_memory_for_testing()); - - base::RunLoop client_redisabled_callback; - (*client)->SetAgentDisabledCallback(client_redisabled_callback.QuitClosure()); - - consumer.StopTracing(); - client_redisabled_callback.Run(); - - EXPECT_EQ(kNumPackets * 2, consumer.received_test_packets()); -} - -TEST_F(PerfettoIntegrationTest, NoPacketsReceivedOnWrongSourceName) { - const size_t kNumPackets = 10; - data_source_->set_send_packet_count(kNumPackets); - - base::RunLoop client_enabled_callback; - base::RunLoop client_disabled_callback; - std::unique_ptr<MockProducerClient::Handle> client = - MockProducerClient::Create( - /* num_data_sources = */ 0, client_enabled_callback.QuitClosure(), - client_disabled_callback.QuitClosure()); - - base::RunLoop producer_initialized_runloop; - auto new_producer = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), "fake_data_source", perfetto_service(), **client); - - base::RunLoop no_more_packets_runloop; - MockConsumer consumer({"fake_data_source"}, perfetto_service()->GetService(), - [&no_more_packets_runloop](bool has_more) { - if (!has_more) { - no_more_packets_runloop.Quit(); - } - }); - - RunUntilIdle(); - - consumer.StopTracing(); - - no_more_packets_runloop.Run(); - - EXPECT_EQ(0u, consumer.received_test_packets()); -} - -TEST_F(PerfettoIntegrationTest, - MAYBE_DifferentSharedMemoryBuffersForDifferentAgents) { - base::RunLoop client1_enabled_callback; - base::RunLoop client2_enabled_callback; - std::unique_ptr<MockProducerClient::Handle> client1 = - MockProducerClient::Create( - /* num_data_sources = */ 1, client1_enabled_callback.QuitClosure()); - auto producer1 = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client1); - - // Start the trace here, this is because we need to send the EnableTracing - // call to client1, but constructing client2 will override the - // |producer_client_| pointer in PerfettoTracedProcess::Get() so we wait until - // client1 has been enabled before constructing the second producer client. - MockConsumer consumer({kPerfettoTestDataSourceName}, - perfetto_service()->GetService(), nullptr); - - client1_enabled_callback.Run(); - - // client2 will trigger a StartTracing call without shutting down the data - // source first, to prevent this hitting a DCHECK set the previous producer to - // null. - data_source_->ClearProducerForTesting(); - - std::unique_ptr<MockProducerClient::Handle> client2 = - MockProducerClient::Create( - /* num_data_sources = */ 1, client2_enabled_callback.QuitClosure()); - - auto producer2 = std::make_unique<MockProducerHost>( - GetPerfettoProducerName(), kPerfettoTestDataSourceName, perfetto_service(), - **client2); - - client2_enabled_callback.Run(); - - EXPECT_TRUE((*client1)->shared_memory_for_testing()); - EXPECT_TRUE((*client2)->shared_memory_for_testing()); - EXPECT_NE((*client1)->shared_memory_for_testing(), - (*client2)->shared_memory_for_testing()); -} - -TEST_F(PerfettoIntegrationTest, PerfettoPlatformTest) { - auto* platform = - PerfettoTracedProcess::Get()->perfetto_platform_for_testing(); - auto* tls = platform->GetOrCreateThreadLocalObject(); - EXPECT_TRUE(tls); - EXPECT_EQ(tls, platform->GetOrCreateThreadLocalObject()); - - base::Thread thread("TestThread"); - thread.Start(); - thread.task_runner()->PostTask( - FROM_HERE, base::BindLambdaForTesting([&platform, &tls] { - auto* thread_tls = platform->GetOrCreateThreadLocalObject(); - EXPECT_TRUE(thread_tls); - EXPECT_NE(tls, thread_tls); - })); - thread.Stop(); -} - -TEST_F(PerfettoIntegrationTest, PerfettoClientLibraryTest) { - // Check that PerfettoTracedProcess initialized the client library. Functional - // client library tests are in TracingServiceTest. - EXPECT_TRUE(perfetto::Tracing::IsInitialized()); -} - -} // namespace - -} // namespace tracing
diff --git a/services/tracing/perfetto/producer_host.cc b/services/tracing/perfetto/producer_host.cc index 489bd76..4811b34 100644 --- a/services/tracing/perfetto/producer_host.cc +++ b/services/tracing/perfetto/producer_host.cc
@@ -15,7 +15,6 @@ #include "base/process/process.h" #include "build/build_config.h" #include "services/tracing/perfetto/perfetto_service.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" #include "services/tracing/public/cpp/perfetto/shared_memory.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/client_identity.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h"
diff --git a/services/tracing/perfetto/test_utils.cc b/services/tracing/perfetto/test_utils.cc index 59a651d..34f23a2 100644 --- a/services/tracing/perfetto/test_utils.cc +++ b/services/tracing/perfetto/test_utils.cc
@@ -12,6 +12,7 @@ #include "base/tracing/perfetto_platform.h" #include "services/tracing/public/cpp/perfetto/shared_memory.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/perfetto/include/perfetto/ext/tracing/core/client_identity.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" @@ -23,6 +24,58 @@ namespace tracing { namespace { +// A proxy task runner which can be dynamically pointed to route tasks into a +// different task runner. +class RebindableTaskRunner : public base::SequencedTaskRunner { + public: + RebindableTaskRunner(); + + void set_task_runner(scoped_refptr<base::SequencedTaskRunner> task_runner) { + task_runner_ = task_runner; + } + + // base::SequencedTaskRunner implementation. + bool PostDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) override; + bool PostNonNestableDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) override; + bool RunsTasksInCurrentSequence() const override; + + private: + ~RebindableTaskRunner() override; + + scoped_refptr<base::SequencedTaskRunner> task_runner_; +}; + +RebindableTaskRunner::RebindableTaskRunner() = default; +RebindableTaskRunner::~RebindableTaskRunner() = default; + +bool RebindableTaskRunner::PostDelayedTask(const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) { + return task_runner_->PostDelayedTask(from_here, std::move(task), delay); +} + +bool RebindableTaskRunner::PostNonNestableDelayedTask( + const base::Location& from_here, + base::OnceClosure task, + base::TimeDelta delay) { + return task_runner_->PostNonNestableDelayedTask(from_here, std::move(task), + delay); +} + +bool RebindableTaskRunner::RunsTasksInCurrentSequence() const { + return task_runner_->RunsTasksInCurrentSequence(); +} + +RebindableTaskRunner* GetClientLibTaskRunner() { + static base::NoDestructor<scoped_refptr<RebindableTaskRunner>> task_runner( + base::MakeRefCounted<RebindableTaskRunner>()); + return task_runner.get()->get(); +} + perfetto::TraceConfig GetDefaultTraceConfig( const std::vector<std::string>& data_sources) { perfetto::TraceConfig trace_config; @@ -37,174 +90,91 @@ } // namespace -// static -std::unique_ptr<TestDataSource> TestDataSource::CreateAndRegisterDataSource( - const std::string& data_source_name, - size_t send_packet_count) { - auto data_source = std::unique_ptr<TestDataSource>( - new TestDataSource(data_source_name, send_packet_count)); - PerfettoTracedProcess::Get()->AddDataSource(data_source.get()); - return data_source; +MockProducer::MockProducer() = default; +MockProducer::~MockProducer() = default; + +void MockProducer::Connect(PerfettoService* service, + const std::string& producer_name, + uid_t uid, + pid_t pid) { + producer_name_ = producer_name; + service_endpoint_ = service->GetService()->ConnectProducer( + this, perfetto::ClientIdentity(uid, pid), producer_name, 0, + /*in_process=*/true, + perfetto::TracingService::ProducerSMBScrapingMode::kDefault, 0, nullptr); +} +void MockProducer::RegisterDataSource(const std::string& name) { + perfetto::DataSourceDescriptor ds_desc; + ds_desc.set_name(name); + service_endpoint_->RegisterDataSource(ds_desc); } -TestDataSource::TestDataSource(const std::string& data_source_name, - size_t send_packet_count) - : DataSourceBase(data_source_name), send_packet_count_(send_packet_count) { +void MockProducer::UnregisterDataSource(const std::string& name) { + service_endpoint_->UnregisterDataSource(name); } -TestDataSource::~TestDataSource() = default; +void MockProducer::SetupDataSource(perfetto::DataSourceInstanceID ds_id, + const perfetto::DataSourceConfig& cfg) { + EXPECT_FALSE(data_source_instances_.count(ds_id)); + data_source_instances_.emplace(ds_id, cfg); + OnSetupDataSource(cfg.name(), ds_id); +} -void TestDataSource::WritePacketBigly() { +void MockProducer::StartDataSource(perfetto::DataSourceInstanceID ds_id, + const perfetto::DataSourceConfig& cfg) { + // The data source might have been seen already through + // WaitForDataSourceSetup(). + if (data_source_instances_.count(ds_id) == 0) { + data_source_instances_.emplace(ds_id, cfg); + } + OnStartDataSource(cfg.name(), ds_id); +} + +void MockProducer::StopDataSource(perfetto::DataSourceInstanceID ds_id) { + ASSERT_EQ(1u, data_source_instances_.count(ds_id)); + std::string name = data_source_instances_[ds_id].name(); + data_source_instances_.erase(ds_id); + OnStopDataSource(name, ds_id); +} + +std::unique_ptr<perfetto::TraceWriter> MockProducer::CreateTraceWriter( + perfetto::DataSourceInstanceID ds_id, + perfetto::BufferExhaustedPolicy buffer_exhausted_policy) { + PERFETTO_DCHECK(data_source_instances_.count(ds_id)); + perfetto::BufferID buf_id = static_cast<perfetto::BufferID>( + data_source_instances_[ds_id].target_buffer()); + return service_endpoint_->CreateTraceWriter(buf_id, buffer_exhausted_policy); +} + +perfetto::DataSourceConfig MockProducer::GetDataSourceConfig( + perfetto::DataSourceInstanceID ds_id) { + PERFETTO_DCHECK(data_source_instances_.count(ds_id)); + return data_source_instances_.at(ds_id); +} + +void MockProducer::WritePackets(perfetto::TraceWriter& writer, + size_t num_packets) { + for (size_t i = 0; i < 10; i++) { + auto tp = writer.NewTracePacket(); + tp->set_for_testing()->set_str(kPerfettoTestString); + } +} + +void MockProducer::WritePacketBigly(perfetto::TraceWriter& writer) { auto payload = base::HeapArray<char>::Uninit(kLargeMessageSize); std::ranges::fill(payload, '.'); payload.as_span().back() = 0; - std::unique_ptr<perfetto::TraceWriter> writer = - producer_->CreateTraceWriter(config_.target_buffer()); - CHECK(writer); - - writer->NewTracePacket()->set_for_testing()->set_str(payload.data(), - payload.size()); + writer.NewTracePacket()->set_for_testing()->set_str(payload.data(), + payload.size()); } -void TestDataSource::StartTracingImpl( - PerfettoProducer* producer, - const perfetto::DataSourceConfig& data_source_config) { - producer_ = producer; - config_ = data_source_config; - - if (send_packet_count_ > 0) { - std::unique_ptr<perfetto::TraceWriter> writer = - producer_->CreateTraceWriter(config_.target_buffer()); - CHECK(writer); - - for (size_t i = 0; i < send_packet_count_; i++) { - writer->NewTracePacket()->set_for_testing()->set_str(kPerfettoTestString); - } - } - if (!start_tracing_callback_.is_null()) { - std::move(start_tracing_callback_).Run(); - } -} - -void TestDataSource::StopTracingImpl(base::OnceClosure stop_complete_callback) { - CHECK(producer_); - producer_ = nullptr; - std::move(stop_complete_callback).Run(); -} - -void TestDataSource::Flush(base::RepeatingClosure flush_complete_callback) { - if (flush_complete_callback) { - flush_complete_callback.Run(); - } -} -void TestDataSource::set_start_tracing_callback( - base::OnceClosure start_tracing_callback) { - start_tracing_callback_ = std::move(start_tracing_callback); -} - -MockProducerClient::MockProducerClient( - uint32_t num_data_sources, - base::OnceClosure client_enabled_callback, - base::OnceClosure client_disabled_callback) - : ProducerClient(PerfettoTracedProcess::Get()->GetTaskRunner()), - num_data_sources_expected_(num_data_sources), - client_enabled_callback_(std::move(client_enabled_callback)), - client_disabled_callback_(std::move(client_disabled_callback)) { - // Create SMB immediately since we never call ProducerClient's Connect(). - CHECK(InitSharedMemoryIfNeeded()); -} - -MockProducerClient::~MockProducerClient() = default; - -// static -std::unique_ptr<MockProducerClient::Handle> MockProducerClient::Create( - uint32_t num_data_sources, - base::OnceClosure client_enabled_callback, - base::OnceClosure client_disabled_callback) { - std::unique_ptr<MockProducerClient> client(new MockProducerClient( - num_data_sources, std::move(client_enabled_callback), - std::move(client_disabled_callback))); - auto handle = std::make_unique<Handle>(client.get()); - - // Transfer ownership of the client to PerfettoTracedProcess. - PerfettoTracedProcess::Get() - ->GetTaskRunner() - ->GetOrCreateTaskRunner() - ->PostTask( - FROM_HERE, - base::BindOnce( - [](std::unique_ptr<MockProducerClient> client) { - auto* raw_client = client.get(); - raw_client->old_producer_ = - PerfettoTracedProcess::Get()->SetProducerClientForTesting( - std::move(client)); - }, - std::move(client))); - return handle; -} - -MockProducerClient::Handle::~Handle() { - // Replace the previous client in PerfettoTracedProcess, deleting the mock - // as a side-effect. - PerfettoTracedProcess::Get() - ->GetTaskRunner() - ->GetOrCreateTaskRunner() - ->PostTask( - FROM_HERE, - base::BindOnce( - [](std::unique_ptr<ProducerClient> old_producer) { - PerfettoTracedProcess::Get()->SetProducerClientForTesting( - std::move(old_producer)); - }, - std::move(client_->old_producer_))); -} - -void MockProducerClient::SetupDataSource(const std::string& data_source_name) {} - -void MockProducerClient::StartDataSource( - uint64_t id, - const perfetto::DataSourceConfig& data_source_config, - StartDataSourceCallback callback) { - ProducerClient::StartDataSource(id, std::move(data_source_config), - std::move(callback)); - - CHECK_LT(num_data_sources_active_, num_data_sources_expected_); - if (++num_data_sources_active_ == num_data_sources_expected_ && - client_enabled_callback_) { - std::move(client_enabled_callback_).Run(); - } -} - -void MockProducerClient::StopDataSource(uint64_t id, - StopDataSourceCallback callback) { - ProducerClient::StopDataSource(id, std::move(callback)); - - CHECK_GT(num_data_sources_active_, 0u); - if (--num_data_sources_active_ == 0 && client_disabled_callback_) { - std::move(client_disabled_callback_).Run(); - } -} - -void MockProducerClient::CommitData(const perfetto::CommitDataRequest& commit, - CommitDataCallback callback) { - // Only write out commits that have actual data in it; Perfetto - // might send two commits from different threads (one always empty), - // which causes TSan to complain. - if (commit.chunks_to_patch_size() || commit.chunks_to_move_size()) { - all_client_commit_data_requests_.push_back(commit.SerializeAsString()); - } - ProducerClient::CommitData(commit, callback); -} - -void MockProducerClient::SetAgentEnabledCallback( - base::OnceClosure client_enabled_callback) { - client_enabled_callback_ = std::move(client_enabled_callback); -} - -void MockProducerClient::SetAgentDisabledCallback( - base::OnceClosure client_disabled_callback) { - client_disabled_callback_ = std::move(client_disabled_callback); +void MockProducer::Flush(perfetto::FlushRequestID flush_req_id, + const perfetto::DataSourceInstanceID* ds_id, + size_t, + perfetto::FlushFlags) { + OnFlush(); + service_endpoint_->NotifyFlushComplete(flush_req_id); } MockConsumerBase::MockConsumerBase( @@ -364,99 +334,15 @@ } } -MockProducerHost::MockProducerHost( - const std::string& producer_name, - const std::string& data_source_name, - PerfettoService* service, - MockProducerClient* producer_client, - base::OnceClosure datasource_registered_callback) - : producer_name_(producer_name), - datasource_registered_callback_( - std::move(datasource_registered_callback)) { - mojo::PendingRemote<mojom::ProducerClient> client; - mojo::PendingRemote<mojom::ProducerHost> host_remote; - auto client_receiver = client.InitWithNewPipeAndPassReceiver(); - Initialize(std::move(client), service->GetService(), producer_name_, - static_cast<ChromeBaseSharedMemory*>( - producer_client->shared_memory_for_testing()) - ->CloneRegion(), - PerfettoProducer::kSMBPageSizeBytes); - receiver_.Bind(host_remote.InitWithNewPipeAndPassReceiver()); - producer_client->BindClientAndHostPipesForTesting(std::move(client_receiver), - std::move(host_remote)); - producer_client->SetupDataSource(data_source_name); -} - -MockProducerHost::~MockProducerHost() = default; - -void MockProducerHost::RegisterDataSource( - const perfetto::DataSourceDescriptor& registration_info) { - ProducerHost::RegisterDataSource(registration_info); - - on_commit_callback_for_testing_ = - base::BindRepeating(&MockProducerHost::OnCommit, base::Unretained(this)); - - if (datasource_registered_callback_) { - std::move(datasource_registered_callback_).Run(); - } -} - -void MockProducerHost::OnConnect() {} - -void MockProducerHost::OnCommit( - const perfetto::CommitDataRequest& commit_data_request) { - if (!commit_data_request.chunks_to_patch_size() && - !commit_data_request.chunks_to_move_size()) { - return; - } - - all_host_commit_data_requests_.push_back( - commit_data_request.SerializeAsString()); -} - -MockProducer::MockProducer(const std::string& producer_name, - const std::string& data_source_name, - PerfettoService* service, - base::OnceClosure on_datasource_registered, - base::OnceClosure on_tracing_started, - size_t num_packets) { - // Construct MockProducerClient before TestDataSource to avoid a race. - // - // TestDataSource calls AddDataSource on the global PerfettoTracedProcess, - // which PostTasks to the threadpool in the task it will access the - // |producer_client_| pointer that the PerfettoTracedProcess owns. However in - // the constructor for MockProducerClient we will set the |producer_client_| - // from the real client to the mock, however this is done on a different - // sequence and thus we have a race. By setting the pointer before we - // construct the data source the TestDataSource can not race. - producer_client_ = MockProducerClient::Create( - /* num_data_sources = */ 1, std::move(on_tracing_started)); - data_source_ = TestDataSource::CreateAndRegisterDataSource(data_source_name, - num_packets); - - producer_host_ = std::make_unique<MockProducerHost>( - producer_name, data_source_name, service, **producer_client_, - std::move(on_datasource_registered)); -} - -MockProducer::~MockProducer() = default; - -void MockProducer::WritePacketBigly(base::OnceClosure on_write_complete) { - PerfettoTracedProcess::Get() - ->GetTaskRunner() - ->GetOrCreateTaskRunner() - ->PostTaskAndReply(FROM_HERE, - base::BindOnce(&TestDataSource::WritePacketBigly, - base::Unretained(data_source())), - std::move(on_write_complete)); -} - TracingUnitTest::TracingUnitTest() : task_environment_(std::make_unique<base::test::TaskEnvironment>( - base::test::TaskEnvironment::MainThreadType::IO)), - tracing_environment_(std::make_unique<base::test::TracingEnvironment>( - *task_environment_, - base::SingleThreadTaskRunner::GetCurrentDefault())) {} + base::test::TaskEnvironment::MainThreadType::IO)) { + // Also tell PerfettoTracedProcess to use the current task environment. + auto* client_lib_task_runner = GetClientLibTaskRunner(); + client_lib_task_runner->set_task_runner( + base::SingleThreadTaskRunner::GetCurrentDefault()); + test_handle_ = PerfettoTracedProcess::SetupForTesting(client_lib_task_runner); +} TracingUnitTest::~TracingUnitTest() { CHECK(setup_called_ && teardown_called_); @@ -465,30 +351,19 @@ void TracingUnitTest::SetUp() { setup_called_ = true; - // Also tell PerfettoTracedProcess to use the current task environment. - test_handle_ = PerfettoTracedProcess::SetupForTesting( - base::SingleThreadTaskRunner::GetCurrentDefault()); - PerfettoTracedProcess::Get()->OnThreadPoolAvailable( - /* enable_consumer */ true); - // Wait for any posted construction tasks to execute. RunUntilIdle(); } void TracingUnitTest::TearDown() { teardown_called_ = true; - tracing_environment_.reset(); // Wait for any posted destruction tasks to execute. RunUntilIdle(); - // From here on, no more tasks should be posted. - task_environment_.reset(); - // Clear task runner and data sources. PerfettoTracedProcess::Get()->GetTaskRunner()->ResetTaskRunnerForTesting( nullptr); - PerfettoTracedProcess::Get()->ClearDataSourcesForTesting(); test_handle_.reset(); }
diff --git a/services/tracing/perfetto/test_utils.h b/services/tracing/perfetto/test_utils.h index 6e6cd9a60..cff53a0 100644 --- a/services/tracing/perfetto/test_utils.h +++ b/services/tracing/perfetto/test_utils.h
@@ -12,14 +12,14 @@ #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/test/task_environment.h" -#include "base/test/trace_test_utils.h" #include "mojo/public/cpp/bindings/receiver.h" #include "services/tracing/perfetto/perfetto_service.h" -#include "services/tracing/perfetto/producer_host.h" #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h" +#include "third_party/perfetto/include/perfetto/ext/tracing/core/producer.h" +#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" #include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h" #include "third_party/perfetto/protos/perfetto/common/observable_events.pb.h" @@ -32,92 +32,72 @@ const char kPerfettoTestString[] = "d00df00d"; const size_t kLargeMessageSize = 1 * 1024 * 1024; -class TestDataSource : public PerfettoTracedProcess::DataSourceBase { +// third_party/perfetto/src/tracing/test/mock_producer.h +class MockProducer : public perfetto::Producer { public: - static std::unique_ptr<TestDataSource> CreateAndRegisterDataSource( - const std::string& data_source_name, - size_t send_packet_count); - ~TestDataSource() override; + MockProducer(); + ~MockProducer() override; - void WritePacketBigly(); + void Connect(PerfettoService* service, + const std::string& producer_name, + uid_t uid = 42, + pid_t pid = 1025); + void RegisterDataSource(const std::string& name); + void UnregisterDataSource(const std::string& name); - // DataSourceBase implementation - void StartTracingImpl( - PerfettoProducer* producer, - const perfetto::DataSourceConfig& data_source_config) override; - void StopTracingImpl( - base::OnceClosure stop_complete_callback = base::OnceClosure()) override; - void Flush(base::RepeatingClosure flush_complete_callback) override; - - const perfetto::DataSourceConfig& config() { return config_; } - - void set_send_packet_count(size_t count) { send_packet_count_ = count; } - - void set_start_tracing_callback(base::OnceClosure start_tracing_callback); - - private: - TestDataSource(const std::string& data_source_name, size_t send_packet_count); - - size_t send_packet_count_; - raw_ptr<tracing::PerfettoProducer, AcrossTasksDanglingUntriaged> producer_ = - nullptr; - perfetto::DataSourceConfig config_; - base::OnceClosure start_tracing_callback_ = base::OnceClosure(); -}; - -// This class is owned by PerfettoTracedProcess, and its lifetime is indirectly -// controlled by the handle returned from Create(). -class MockProducerClient : public ProducerClient { - public: - class Handle { - public: - explicit Handle(MockProducerClient* client) : client_(client) {} - ~Handle(); - - MockProducerClient* operator->() { return client_; } - MockProducerClient* operator*() { return client_; } - - private: - const raw_ptr<MockProducerClient, AcrossTasksDanglingUntriaged> client_; - }; - - ~MockProducerClient() override; - - static std::unique_ptr<Handle> Create( - uint32_t num_data_sources = 0, - base::OnceClosure client_enabled_callback = base::OnceClosure(), - base::OnceClosure client_disabled_callback = base::OnceClosure()); - - void SetupDataSource(const std::string& data_source_name); - - void StartDataSource(uint64_t id, - const perfetto::DataSourceConfig& data_source_config, - StartDataSourceCallback callback) override; - - void StopDataSource(uint64_t id, StopDataSourceCallback callback) override; - - void CommitData(const perfetto::CommitDataRequest& commit, - CommitDataCallback callback = {}) override; - - void SetAgentEnabledCallback(base::OnceClosure client_enabled_callback); - - void SetAgentDisabledCallback(base::OnceClosure client_disabled_callback); - - const std::vector<std::string>& all_client_commit_data_requests() const { - return all_client_commit_data_requests_; + perfetto::TracingService::ProducerEndpoint* endpoint() { + return service_endpoint_.get(); } - private: - MockProducerClient(uint32_t num_data_sources, - base::OnceClosure client_enabled_callback, - base::OnceClosure client_disabled_callback); + std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter( + perfetto::DataSourceInstanceID, + perfetto::BufferExhaustedPolicy buffer_exhausted_policy = + perfetto::BufferExhaustedPolicy::kDefault); - uint32_t num_data_sources_active_ = 0; - uint32_t num_data_sources_expected_; - base::OnceClosure client_enabled_callback_; - base::OnceClosure client_disabled_callback_; - std::vector<std::string> all_client_commit_data_requests_; - std::unique_ptr<ProducerClient> old_producer_; + perfetto::DataSourceConfig GetDataSourceConfig( + perfetto::DataSourceInstanceID); + + static void WritePackets(perfetto::TraceWriter&, size_t num_packets); + static void WritePacketBigly(perfetto::TraceWriter&); + + MOCK_METHOD(void, + OnSetupDataSource, + (const std::string& name, perfetto::DataSourceInstanceID), + ()); + MOCK_METHOD(void, + OnStartDataSource, + (const std::string& name, perfetto::DataSourceInstanceID), + ()); + MOCK_METHOD(void, + OnStopDataSource, + (const std::string& name, perfetto::DataSourceInstanceID), + ()); + MOCK_METHOD(void, OnFlush, (), ()); + + // perfetto::Producer + MOCK_METHOD(void, OnConnect, (), (override)); + MOCK_METHOD(void, OnDisconnect, (), (override)); + MOCK_METHOD(void, OnTracingSetup, (), (override)); + void SetupDataSource(perfetto::DataSourceInstanceID, + const perfetto::DataSourceConfig&) override; + void StartDataSource(perfetto::DataSourceInstanceID, + const perfetto::DataSourceConfig&) override; + void StopDataSource(perfetto::DataSourceInstanceID) override; + void Flush(perfetto::FlushRequestID, + const perfetto::DataSourceInstanceID*, + size_t, + perfetto::FlushFlags) override; + MOCK_METHOD(void, + ClearIncrementalState, + (const perfetto::DataSourceInstanceID*, size_t), + (override)); + + private: + scoped_refptr<base::SequencedTaskRunner> task_runner_; + std::string producer_name_; + std::unique_ptr<perfetto::TracingService::ProducerEndpoint> service_endpoint_; + std::map<perfetto::DataSourceInstanceID, perfetto::DataSourceConfig> + data_source_instances_; }; class MockConsumerBase : public perfetto::Consumer { @@ -200,56 +180,6 @@ perfetto::TraceConfig trace_config_; }; -class MockProducerHost : public ProducerHost { - public: - MockProducerHost( - const std::string& producer_name, - const std::string& data_source_name, - PerfettoService* service, - MockProducerClient* producer_client, - base::OnceClosure datasource_registered_callback = base::OnceClosure()); - ~MockProducerHost() override; - - void RegisterDataSource( - const perfetto::DataSourceDescriptor& registration_info) override; - - void OnConnect() override; - - void OnCommit(const perfetto::CommitDataRequest& commit_data_request); - - const std::vector<std::string>& all_host_commit_data_requests() const { - return all_host_commit_data_requests_; - } - - protected: - const std::string producer_name_; - base::OnceClosure datasource_registered_callback_; - std::vector<std::string> all_host_commit_data_requests_; - mojo::Receiver<mojom::ProducerHost> receiver_{this}; -}; - -class MockProducer { - public: - MockProducer(const std::string& producer_name, - const std::string& data_source_name, - PerfettoService* service, - base::OnceClosure on_datasource_registered, - base::OnceClosure on_tracing_started, - size_t num_packets = 10); - virtual ~MockProducer(); - - void WritePacketBigly(base::OnceClosure on_write_complete); - - MockProducerClient* producer_client() { return **producer_client_; } - - TestDataSource* data_source() { return data_source_.get(); } - - private: - std::unique_ptr<TestDataSource> data_source_; - std::unique_ptr<MockProducerClient::Handle> producer_client_; - std::unique_ptr<MockProducerHost> producer_host_; -}; - // Base class for various tracing unit tests, ensuring cleanup of // PerfettoTracedProcess. Tracing tasks are run on the test thread. class TracingUnitTest : public testing::Test { @@ -265,7 +195,6 @@ private: std::unique_ptr<base::test::TaskEnvironment> task_environment_; - std::unique_ptr<base::test::TracingEnvironment> tracing_environment_; std::unique_ptr<PerfettoTracedProcess::TestHandle> test_handle_; bool setup_called_ = false; bool teardown_called_ = false;
diff --git a/services/tracing/public/cpp/BUILD.gn b/services/tracing/public/cpp/BUILD.gn index 0b0b372..e9719d4 100644 --- a/services/tracing/public/cpp/BUILD.gn +++ b/services/tracing/public/cpp/BUILD.gn
@@ -75,8 +75,6 @@ "perfetto/perfetto_traced_process.h", "perfetto/perfetto_tracing_backend.cc", "perfetto/perfetto_tracing_backend.h", - "perfetto/producer_client.cc", - "perfetto/producer_client.h", "perfetto/shared_memory.cc", "perfetto/shared_memory.h", "perfetto/system_trace_writer.h",
diff --git a/services/tracing/public/cpp/perfetto/perfetto_producer.cc b/services/tracing/public/cpp/perfetto/perfetto_producer.cc index ec6c95e6..a4c3ae17 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_producer.cc +++ b/services/tracing/public/cpp/perfetto/perfetto_producer.cc
@@ -39,16 +39,6 @@ buffer_exhausted_policy); } -void PerfettoProducer::DeleteSoonForTesting( - std::unique_ptr<PerfettoProducer> perfetto_producer) { - PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->DeleteSoon( - FROM_HERE, std::move(perfetto_producer)); -} - -void PerfettoProducer::ResetSequenceForTesting() { - DETACH_FROM_SEQUENCE(sequence_checker_); -} - base::tracing::PerfettoTaskRunner* PerfettoProducer::task_runner() { return task_runner_; }
diff --git a/services/tracing/public/cpp/perfetto/perfetto_producer.h b/services/tracing/public/cpp/perfetto/perfetto_producer.h index 45b138e..a383c74 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_producer.h +++ b/services/tracing/public/cpp/perfetto/perfetto_producer.h
@@ -56,18 +56,6 @@ virtual void NewDataSourceAdded( const PerfettoTracedProcess::DataSourceBase* const data_source) = 0; - static void DeleteSoonForTesting( - std::unique_ptr<PerfettoProducer> perfetto_producer); - - // In tests, PerfettoProducers may leak between tests, but their task sequence - // may become invalid (e.g. TaskEnvironment is destroyed). This resets the - // PerfettoProducer's sequence checker, so that it can later be rebound to a - // new test's sequence. Note that this only resets the producer's sequence - // checker - and there may be other sequence checkers elsewhere, e.g. in - // PosixSystemProducer's socket (which would fail on disconnect if the system - // producer's sequence is reset while it is connected). - void ResetSequenceForTesting(); - protected: friend class MockProducerHost; @@ -107,9 +95,6 @@ private: const raw_ptr<base::tracing::PerfettoTaskRunner, DanglingUntriaged> task_runner_; - - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<PerfettoProducer> weak_ptr_factory_{this}; }; } // namespace tracing #endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PRODUCER_H_
diff --git a/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc b/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc index 94d43c5..f893695 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc +++ b/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
@@ -8,16 +8,13 @@ #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/no_destructor.h" -#include "base/run_loop.h" #include "base/task/sequenced_task_runner.h" #include "base/trace_event/trace_config.h" -#include "base/trace_event/trace_log.h" #include "base/tracing/perfetto_platform.h" #include "build/build_config.h" #include "services/tracing/public/cpp/perfetto/custom_event_recorder.h" #include "services/tracing/public/cpp/perfetto/metadata_data_source.h" #include "services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" #include "services/tracing/public/cpp/perfetto/track_name_recorder.h" #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h" #include "services/tracing/public/cpp/system_metrics_sampler.h" @@ -170,8 +167,7 @@ } PerfettoTracedProcess::PerfettoTracedProcess() - : producer_client_(std::make_unique<ProducerClient>(GetTaskRunner())), - platform_( + : platform_( std::make_unique<base::tracing::PerfettoPlatform>(GetTaskRunner())), tracing_backend_(std::make_unique<PerfettoTracingBackend>()) { DETACH_FROM_SEQUENCE(sequence_checker_); @@ -190,20 +186,6 @@ tracing_backend_->OnProducerConnected(std::move(perfetto_service)); } -void PerfettoTracedProcess::ClearDataSourcesForTesting() { - base::AutoLock lock(data_sources_lock_); - data_sources_.clear(); -} - -std::unique_ptr<ProducerClient> -PerfettoTracedProcess::SetProducerClientForTesting( - std::unique_ptr<ProducerClient> client) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto old_producer_client_for_testing = std::move(producer_client_); - producer_client_ = std::move(client); - return old_producer_client_for_testing; -} - // We never destroy the taskrunner as we may need it for cleanup // of TraceWriters in TLS, which could happen after the PerfettoTracedProcess // is deleted. @@ -221,53 +203,15 @@ // Make sure Perfetto was properly torn down in any prior tests. DCHECK(!perfetto::Tracing::IsInitialized()); GetTaskRunner()->ResetTaskRunnerForTesting(task_runner); - Get()->ClearDataSourcesForTesting(); // IN-TEST - // On the first call within the process's lifetime, this will call - // PerfettoTracedProcess::Get(), ensuring PerfettoTracedProcess is created. - InitTracingPostThreadPoolStartAndFeatureList( + PerfettoTracedProcess::Get()->tracing_backend_ = + std::make_unique<PerfettoTracingBackend>(); + PerfettoTracedProcess::Get()->OnThreadPoolAvailable( /* enable_consumer */ true); // Disassociate the PerfettoTracedProcess from any prior task runner. DETACH_FROM_SEQUENCE(PerfettoTracedProcess::Get()->sequence_checker_); - PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask( - FROM_HERE, base::BindOnce([]() { - // Lock the sequence checker onto the new task runner. - DCHECK_CALLED_ON_VALID_SEQUENCE( - PerfettoTracedProcess::Get()->sequence_checker_); - PerfettoTracedProcess::Get() - ->producer_client() - ->ResetSequenceForTesting(); - })); return std::make_unique<TestHandle>(); } -void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) { - bool inserted; - { - base::AutoLock lock(data_sources_lock_); - inserted = data_sources_.insert(data_source).second; - } - - // Before the thread pool is up, the producers are not yet connected to the - // service, so don't need to be notified about new data source registrations. - if (inserted && GetTaskRunner()->HasTaskRunner()) { - GetTaskRunner()->GetOrCreateTaskRunner()->PostTask( - FROM_HERE, base::BindOnce( - [](DataSourceBase* data_source) { - PerfettoTracedProcess* traced_process = - PerfettoTracedProcess::Get(); - traced_process->producer_client()->NewDataSourceAdded( - data_source); - }, - base::Unretained(data_source))); - } -} - -std::set<raw_ptr<PerfettoTracedProcess::DataSourceBase, SetExperimental>> -PerfettoTracedProcess::data_sources() { - base::AutoLock lock(data_sources_lock_); - return data_sources_; -} - void PerfettoTracedProcess::RequestStartupTracing( const perfetto::TraceConfig& config, const perfetto::Tracing::SetupStartupTracingOpts& opts) { @@ -395,33 +339,11 @@ result_callback(result); } -bool PerfettoTracedProcess::CanStartTracing( - PerfettoProducer* producer, - base::OnceCallback<void()> start_tracing) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(producer); - if (producer != producer_client_.get()) { - // In tests this is possible due to the periodic polling of CanStartTracing - // by the PosixSystemProducer, when we swap it out for a - // MockSystemProducer there can be three PerfettoProducers calling this - // function. In production nothing ever calls the - // |Set.*ProducerForTesting()| functions so this should never be reached. - return false; - } - if (!start_tracing.is_null()) { - std::move(start_tracing).Run(); - } - return true; -} - -ProducerClient* PerfettoTracedProcess::producer_client() const { - return producer_client_.get(); -} - PerfettoTracedProcess::TestHandle::~TestHandle() { // TODO(skyostil): We only uninitialize Perfetto for now, but there may also // be other tracing-related state which should not leak between tests. perfetto::Tracing::ResetForTesting(); + PerfettoTracedProcess::Get()->tracing_backend_ = nullptr; } } // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/perfetto_traced_process.h b/services/tracing/public/cpp/perfetto/perfetto_traced_process.h index e87d66ae..2a1a219 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_traced_process.h +++ b/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
@@ -35,8 +35,6 @@ } // namespace mojom class PerfettoProducer; -class ProducerClient; -class SystemProducer; // This represents global process level state that the Perfetto tracing system // expects to exist. This includes a single base implementation of DataSources @@ -183,23 +181,12 @@ // legacy TraceLog to become the trace producer for this process. void ConnectProducer(mojo::PendingRemote<mojom::PerfettoService>); - ProducerClient* producer_client() const; - ~PerfettoTracedProcess() override; // Returns the task runner used by any Perfetto service. Can be called on any // thread. static base::tracing::PerfettoTaskRunner* GetTaskRunner(); - // Add a new data source to the PerfettoTracedProcess; the caller retains - // ownership and is responsible for making sure the data source outlives the - // PerfettoTracedProcess. Except for tests, this means the data source should - // never be destroyed. Can be called on any thread. - void AddDataSource(DataSourceBase*); - // Returns a copy of the set of currently registered data sources. Can be - // called on any thread. - std::set<raw_ptr<DataSourceBase, SetExperimental>> data_sources(); - // Attempt to enable startup tracing for the current process and given // producer. Returns false on failure, e.g. because another concurrent tracing // session is already active. Can be called on any thread. @@ -219,18 +206,6 @@ // Overrides SetAllowSystemTracingConsumerCallback() for testing. void SetAllowSystemTracingConsumerForTesting(bool allow); - // If the provided |producer| can begin tracing then |start_tracing| will be - // invoked (unless cancelled by the Perfetto service) at some point later - // using the GetTaskRunner()'s sequence and this function will return true. - // Otherwise the return value will be false and start_tracing will not be - // invoked at all. This function must be called on GetTaskRunners()'s - // sequence. - bool CanStartTracing(PerfettoProducer* producer, - base::OnceCallback<void()> start_tracing); - - // Can be called on any thread, but only after OnThreadPoolAvailable(). - void ActivateSystemTriggers(const std::vector<std::string>& triggers); - // Sets the task runner used by the tracing infrastructure in this process. // The returned handle will automatically tear down tracing when destroyed, so // it should be kept valid until the test terminates. @@ -249,16 +224,6 @@ static std::unique_ptr<TestHandle> SetupForTesting( scoped_refptr<base::SequencedTaskRunner> task_runner = nullptr); - // Sets the ProducerClient (or SystemProducer) and returns the old pointer. If - // tests want to restore the state of the world they should store the pointer - // and call this method again with it as the parameter when finished. - std::unique_ptr<ProducerClient> SetProducerClientForTesting( - std::unique_ptr<ProducerClient> client); - std::unique_ptr<SystemProducer> SetSystemProducerForTesting( - std::unique_ptr<SystemProducer> producer); - - void ClearDataSourcesForTesting(); - base::tracing::PerfettoPlatform* perfetto_platform_for_testing() const { return platform_.get(); } @@ -301,15 +266,6 @@ bool system_consumer_enabled_for_testing_ GUARDED_BY(allow_system_consumer_lock_) = false; - base::Lock data_sources_lock_; - // The canonical set of DataSourceBases alive in this process. These will be - // registered with the tracing service. - std::set<raw_ptr<DataSourceBase, SetExperimental>> data_sources_; - - // A PerfettoProducer that connects to the chrome Perfetto service through - // mojo. - std::unique_ptr<ProducerClient> producer_client_; - // Platform implementation for the Perfetto client library. std::unique_ptr<base::tracing::PerfettoPlatform> platform_; std::unique_ptr<PerfettoTracingBackend> tracing_backend_;
diff --git a/services/tracing/public/cpp/perfetto/producer_client.cc b/services/tracing/public/cpp/perfetto/producer_client.cc deleted file mode 100644 index a7210c9..0000000 --- a/services/tracing/public/cpp/perfetto/producer_client.cc +++ /dev/null
@@ -1,388 +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. - -#include "services/tracing/public/cpp/perfetto/producer_client.h" - -#include <utility> - -#include "base/auto_reset.h" -#include "base/containers/adapters.h" -#include "base/containers/contains.h" -#include "base/functional/bind.h" -#include "base/memory/unsafe_shared_memory_region.h" -#include "base/metrics/histogram_functions.h" -#include "base/process/process.h" -#include "base/tracing/tracing_tls.h" -#include "build/build_config.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/tracing/public/cpp/perfetto/shared_memory.h" -#include "services/tracing/public/cpp/traced_process_impl.h" -#include "services/tracing/public/mojom/constants.mojom.h" -#include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h" -#include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h" -#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" -#include "third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h" -#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h" -#include "third_party/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.h" - -namespace { -// Result for getting the shared buffer in InitSharedMemoryIfNeeded. -constexpr char kSharedBufferIsValidMetricName[] = "Tracing.SharedBufferIsValid"; -} // namespace - -using ShmemMode = perfetto::SharedMemoryArbiter::ShmemMode; - -namespace tracing { - -ProducerClient::ProducerClient(base::tracing::PerfettoTaskRunner* task_runner) - : PerfettoProducer(task_runner) { - DETACH_FROM_SEQUENCE(sequence_checker_); -} - -ProducerClient::~ProducerClient() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -void ProducerClient::Disconnect() { - LOG(DFATAL) << "Not implemented yet"; -} - -perfetto::SharedMemoryArbiter* ProducerClient::MaybeSharedMemoryArbiter() { - base::AutoLock lock(lock_); - // |shared_memory_arbiter_| is never destroyed, thus OK to return a - // reference here. - return shared_memory_arbiter_.get(); -} - -void ProducerClient::NewDataSourceAdded( - const PerfettoTracedProcess::DataSourceBase* const data_source) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!producer_host_) { - return; - } - perfetto::DataSourceDescriptor new_registration; - new_registration.set_name(data_source->name()); - new_registration.set_will_notify_on_start(true); - new_registration.set_will_notify_on_stop(true); - new_registration.set_handles_incremental_state_clear(true); - - // Add categories to the DataSourceDescriptor. - std::set<std::string> category_set; - tracing::TracedProcessImpl::GetInstance()->GetCategories(&category_set); - protozero::HeapBuffered<perfetto::protos::pbzero::TrackEventDescriptor> proto; - for (const std::string& s : category_set) { - auto* cat = proto->add_available_categories(); - cat->set_name(s); - if (s.find(TRACE_DISABLED_BY_DEFAULT("")) == 0) { - cat->add_tags("slow"); - } - } - new_registration.set_track_event_descriptor_raw(proto.SerializeAsString()); - - producer_host_->RegisterDataSource(std::move(new_registration)); -} - -void ProducerClient::OnTracingStart() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(producer_host_); - - perfetto::SharedMemoryArbiter* arbiter; - { - base::AutoLock lock(lock_); - // |shared_memory_arbiter_| is never destroyed, thus OK to call - // BindToProducerEndpoint() without holding the lock. - arbiter = shared_memory_arbiter_.get(); - } - DCHECK(arbiter); - arbiter->BindToProducerEndpoint(this, task_runner()); -} - -void ProducerClient::StartDataSource( - uint64_t id, - const perfetto::DataSourceConfig& data_source_config, - StartDataSourceCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // TODO(oysteine): Support concurrent tracing sessions. - for (PerfettoTracedProcess::DataSourceBase* data_source : - PerfettoTracedProcess::Get()->data_sources()) { - if (data_source->name() == data_source_config.name()) { - { - base::AutoLock lock(lock_); - ++data_sources_tracing_; - } - // ProducerClient should never be denied permission to start, but it will - // only start tracing once the callback passed below is called. - bool result = PerfettoTracedProcess::Get()->CanStartTracing( - this, - base::BindOnce( - [](base::WeakPtr<ProducerClient> weak_ptr, - PerfettoTracedProcess::DataSourceBase* data_source, - perfetto::DataSourceInstanceID id, - const perfetto::DataSourceConfig& data_source_config, - StartDataSourceCallback callback) { - if (!weak_ptr) { - return; - } - - DCHECK_CALLED_ON_VALID_SEQUENCE(weak_ptr->sequence_checker_); - data_source->StartTracing(id, weak_ptr.get(), - data_source_config); - - // TODO(eseckler): Consider plumbing this callback through - // |data_source|. - std::move(callback).Run(); - }, - weak_ptr_factory_.GetWeakPtr(), data_source, id, - data_source_config, std::move(callback))); - DCHECK(result); - return; - } - } -} - -void ProducerClient::StopDataSource(uint64_t id, - StopDataSourceCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - for (PerfettoTracedProcess::DataSourceBase* data_source : - PerfettoTracedProcess::Get()->data_sources()) { - if (data_source->data_source_id() == id && - data_source->producer() == this) { - data_source->StopTracing(base::BindOnce( - [](base::WeakPtr<ProducerClient> weak_ptr, - StopDataSourceCallback callback, uint64_t id) { - if (!weak_ptr) { - std::move(callback).Run(); - return; - } - DCHECK_CALLED_ON_VALID_SEQUENCE(weak_ptr->sequence_checker_); - // Flush any commits that might have been batched by - // SharedMemoryArbiter. - weak_ptr->MaybeSharedMemoryArbiter() - ->FlushPendingCommitDataRequests(); - std::move(callback).Run(); - base::AutoLock lock(weak_ptr->lock_); - --weak_ptr->data_sources_tracing_; - }, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), id)); - return; - } - } - - DLOG(ERROR) << "Invalid data source ID."; -} - -void ProducerClient::Flush(uint64_t flush_request_id, - const std::vector<uint64_t>& data_source_ids) { - pending_replies_for_latest_flush_ = {flush_request_id, - data_source_ids.size()}; - - // N^2, optimize once there's more than a couple of possible data sources. - for (PerfettoTracedProcess::DataSourceBase* data_source : - PerfettoTracedProcess::Get()->data_sources()) { - if (base::Contains(data_source_ids, data_source->data_source_id())) { - data_source->Flush(base::BindRepeating( - [](base::WeakPtr<ProducerClient> weak_ptr, uint64_t id) { - if (weak_ptr) { - weak_ptr->NotifyDataSourceFlushComplete(id); - } - }, - weak_ptr_factory_.GetWeakPtr(), flush_request_id)); - } - } -} - -void ProducerClient::ClearIncrementalState() { - for (PerfettoTracedProcess::DataSourceBase* data_source : - PerfettoTracedProcess::Get()->data_sources()) { - data_source->ClearIncrementalState(); - } -} - -std::unique_ptr<perfetto::TraceWriter> ProducerClient::CreateTraceWriter( - perfetto::BufferID target_buffer, - perfetto::BufferExhaustedPolicy buffer_exhausted_policy) { - return PerfettoProducer::CreateTraceWriter(target_buffer, - buffer_exhausted_policy); -} - -void ProducerClient::CommitData(const perfetto::CommitDataRequest& commit, - CommitDataCallback callback) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto commit_callback = - callback ? base::BindOnce([](CommitDataCallback callback) { callback(); }, - callback) - : mojom::ProducerHost::CommitDataCallback(); - - // We need to make sure the CommitData IPC is sent off without triggering any - // trace events, as that could stall waiting for SMB chunks to be freed up - // which requires the tracing service to receive the IPC. - if (!*base::tracing::GetThreadIsInTraceEvent()) { - const base::AutoReset<bool> resetter( - base::tracing::GetThreadIsInTraceEvent(), true); - - producer_host_->CommitData(commit, std::move(commit_callback)); - return; - } - - producer_host_->CommitData(commit, std::move(commit_callback)); -} - -void ProducerClient::RegisterTraceWriter(uint32_t writer_id, - uint32_t target_buffer) { - producer_host_->RegisterTraceWriter(writer_id, target_buffer); -} - -void ProducerClient::UnregisterTraceWriter(uint32_t writer_id) { - producer_host_->UnregisterTraceWriter(writer_id); -} - -perfetto::SharedMemory* ProducerClient::shared_memory() const { - NOTREACHED(); -} - -void ProducerClient::NotifyFlushComplete(perfetto::FlushRequestID id) { - NOTREACHED(); -} - -void ProducerClient::RegisterDataSource(const perfetto::DataSourceDescriptor&) { - NOTREACHED(); -} - -void ProducerClient::UpdateDataSource(const perfetto::DataSourceDescriptor&) { - NOTREACHED(); -} - -void ProducerClient::UnregisterDataSource(const std::string& name) { - NOTREACHED(); -} - -void ProducerClient::NotifyDataSourceStopped( - perfetto::DataSourceInstanceID id) { - NOTREACHED(); -} - -void ProducerClient::NotifyDataSourceStarted( - perfetto::DataSourceInstanceID id) { - NOTREACHED(); -} - -void ProducerClient::ActivateTriggers(const std::vector<std::string>&) { - NOTREACHED(); -} - -size_t ProducerClient::shared_buffer_page_size_kb() const { - NOTREACHED(); -} - -bool ProducerClient::IsShmemProvidedByProducer() const { - NOTREACHED(); -} - -void ProducerClient::Sync(std::function<void()>) { - NOTREACHED(); -} - -void ProducerClient::BindClientAndHostPipesForTesting( - mojo::PendingReceiver<mojom::ProducerClient> producer_client_receiver, - mojo::PendingRemote<mojom::ProducerHost> producer_host_remote) { - task_runner()->GetOrCreateTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&ProducerClient::BindClientAndHostPipesOnSequence, - base::Unretained(this), - std::move(producer_client_receiver), - std::move(producer_host_remote))); -} - -perfetto::SharedMemory* ProducerClient::shared_memory_for_testing() { - base::AutoLock lock(lock_); - // |shared_memory_| is never destroyed except in tests, thus OK to return a - // reference here. - return shared_memory_.get(); -} - -bool ProducerClient::InitSharedMemoryIfNeeded() { - base::AutoLock lock(lock_); - if (shared_memory_) { - return true; - } - - // The shared memory buffer is always provided by the ProducerClient, but only - // created upon the first tracing request. - shared_memory_ = - std::make_unique<ChromeBaseSharedMemory>(GetPreferredSmbSizeBytes()); - - // TODO(crbug.com/40677516): We see shared memory region creation fail on - // windows in the field. Investigate why this can happen. Gather statistics on - // failure rates. - bool valid = shared_memory_->region().IsValid(); - base::UmaHistogramBoolean(kSharedBufferIsValidMetricName, valid); - - if (!valid) { - LOG(ERROR) << "Failed to create tracing SMB"; - shared_memory_.reset(); - return false; - } - - shared_memory_arbiter_ = perfetto::SharedMemoryArbiter::CreateUnboundInstance( - shared_memory_.get(), kSMBPageSizeBytes, ShmemMode::kDefault); - shared_memory_arbiter_->SetDirectSMBPatchingSupportedByService(); - shared_memory_arbiter_->EnableDirectSMBPatching(); - shared_memory_arbiter_->SetBatchCommitsDuration( - kShmArbiterBatchCommitDurationMs); - return true; -} - -bool ProducerClient::SetupSharedMemoryForStartupTracing() { - return InitSharedMemoryIfNeeded(); -} - -// The Mojo binding should run on the same sequence as the one we get -// callbacks from Perfetto on, to avoid additional PostTasks. -void ProducerClient::BindClientAndHostPipesOnSequence( - mojo::PendingReceiver<mojom::ProducerClient> producer_client_receiver, - mojo::PendingRemote<mojom::ProducerHost> producer_host_info) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - CHECK(!receiver_ || !receiver_->is_bound()); - - receiver_ = std::make_unique<mojo::Receiver<mojom::ProducerClient>>( - this, std::move(producer_client_receiver)); - receiver_->set_disconnect_handler(base::BindOnce( - [](ProducerClient* producer_client) { - producer_client->receiver_->reset(); - }, - base::Unretained(this))); - - producer_host_.Bind(std::move(producer_host_info)); - - // TODO(oysteine) We register the data sources in reverse as a temporary - // workaround to make sure that the TraceEventDataSource is registered - // *after* the MetadataSource, as the logic which waits for trace clients - // to be "ready" (in the tracing coordinator) waits for the TraceLog to - // be enabled, which is done by the TraceEventDataSource. We need to register - // the MetadataSource first to ensure that it's also ready. Once the - // Perfetto Observer interface is ready, we can remove this. - const auto& data_sources = PerfettoTracedProcess::Get()->data_sources(); - for (const PerfettoTracedProcess::DataSourceBase* data_source : - base::Reversed(data_sources)) { - NewDataSourceAdded(data_source); - } -} - -void ProducerClient::NotifyDataSourceFlushComplete( - perfetto::FlushRequestID id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (pending_replies_for_latest_flush_.first != id) { - // Ignore; completed flush was for an earlier request. - return; - } - - DCHECK_NE(pending_replies_for_latest_flush_.second, 0u); - if (--pending_replies_for_latest_flush_.second == 0) { - MaybeSharedMemoryArbiter()->NotifyFlushComplete(id); - } -} - -} // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/producer_client.h b/services/tracing/public/cpp/perfetto/producer_client.h deleted file mode 100644 index c28cbdeb..0000000 --- a/services/tracing/public/cpp/perfetto/producer_client.h +++ /dev/null
@@ -1,148 +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. - -#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_CLIENT_H_ -#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_CLIENT_H_ - -#include <memory> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "base/atomicops.h" -#include "base/component_export.h" -#include "base/functional/callback_forward.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/no_destructor.h" -#include "base/sequence_checker.h" -#include "base/synchronization/lock.h" -#include "base/tracing/perfetto_task_runner.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/tracing/public/cpp/perfetto/perfetto_producer.h" -#include "services/tracing/public/mojom/perfetto_service.mojom.h" -#include "third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h" - -namespace perfetto { -class SharedMemoryArbiter; -} // namespace perfetto - -namespace tracing { - -class ChromeBaseSharedMemory; - -// This class is the per-process client side of the Perfetto -// producer, and is responsible for creating specific kinds -// of DataSources (like ChromeTracing) on demand, and provide -// them with TraceWriters and a configuration to start logging. -class COMPONENT_EXPORT(TRACING_CPP) ProducerClient - : public PerfettoProducer, - public perfetto::TracingService::ProducerEndpoint, - public mojom::ProducerClient { - public: - explicit ProducerClient(base::tracing::PerfettoTaskRunner*); - - ProducerClient(const ProducerClient&) = delete; - ProducerClient& operator=(const ProducerClient&) = delete; - - ~ProducerClient() override; - - void Disconnect() override; - - // PerfettoProducer implementation. - perfetto::SharedMemoryArbiter* MaybeSharedMemoryArbiter() override; - void NewDataSourceAdded( - const PerfettoTracedProcess::DataSourceBase* const data_source) override; - - // mojom::ProducerClient implementation. - // Called through Mojo by the ProducerHost on the service-side to control - // tracing and toggle specific DataSources. - void OnTracingStart() override; - void StartDataSource(uint64_t id, - const perfetto::DataSourceConfig& data_source_config, - StartDataSourceCallback callback) override; - - void StopDataSource(uint64_t id, StopDataSourceCallback callback) override; - void Flush(uint64_t flush_request_id, - const std::vector<uint64_t>& data_source_ids) override; - void ClearIncrementalState() override; - - // perfetto::TracingService::ProducerEndpoint implementation. - - // Called by DataSources to create trace writers. The returned trace writers - // are hooked up to our SharedMemoryArbiter directly. - std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter( - perfetto::BufferID target_buffer, - perfetto::BufferExhaustedPolicy = - perfetto::BufferExhaustedPolicy::kDefault) override; - - // Used by SharedMemoryArbiterImpl to register/unregister TraceWriters and - // send commit requests, which signal that shared memory chunks are ready - // for consumption. - void CommitData(const perfetto::CommitDataRequest& commit, - CommitDataCallback callback) override; - void RegisterTraceWriter(uint32_t writer_id, uint32_t target_buffer) override; - void UnregisterTraceWriter(uint32_t writer_id) override; - - // These ProducerEndpoint functions are only used on the service - // side and should not be called on the clients. - perfetto::SharedMemory* shared_memory() const override; - void NotifyFlushComplete(perfetto::FlushRequestID) override; - void RegisterDataSource(const perfetto::DataSourceDescriptor&) override; - void UpdateDataSource(const perfetto::DataSourceDescriptor&) override; - void UnregisterDataSource(const std::string& name) override; - void NotifyDataSourceStopped(perfetto::DataSourceInstanceID) override; - void NotifyDataSourceStarted(perfetto::DataSourceInstanceID) override; - void ActivateTriggers(const std::vector<std::string>&) override; - size_t shared_buffer_page_size_kb() const override; - bool IsShmemProvidedByProducer() const override; - void Sync(std::function<void()> callback) override; - - void BindClientAndHostPipesForTesting( - mojo::PendingReceiver<mojom::ProducerClient>, - mojo::PendingRemote<mojom::ProducerHost>); - perfetto::SharedMemory* shared_memory_for_testing(); - - protected: - // Protected for testing. Returns false if SMB creation failed. - bool InitSharedMemoryIfNeeded(); - - // PerfettoProducer implementation. - bool SetupSharedMemoryForStartupTracing() override; - - private: - friend class base::NoDestructor<ProducerClient>; - - void BindClientAndHostPipesOnSequence( - mojo::PendingReceiver<mojom::ProducerClient>, - mojo::PendingRemote<mojom::ProducerHost>); - - // Called after a data source has completed a flush. - void NotifyDataSourceFlushComplete(perfetto::FlushRequestID id); - - uint32_t data_sources_tracing_ = 0; - std::unique_ptr<mojo::Receiver<mojom::ProducerClient>> receiver_; - mojo::Remote<mojom::ProducerHost> producer_host_; - // First value is the flush ID, the second is the number of - // replies we're still waiting for. - std::pair<uint64_t, size_t> pending_replies_for_latest_flush_; - - // Guards initialization of SMB and startup tracing. - base::Lock lock_; - // TODO(eseckler): Consider accessing |shared_memory_| and - // |shared_memory_arbiter_| without locks after setup was completed, since we - // never destroy or unset them. - std::unique_ptr<ChromeBaseSharedMemory> shared_memory_ GUARDED_BY(lock_); - std::unique_ptr<perfetto::SharedMemoryArbiter> shared_memory_arbiter_ - GUARDED_BY(lock_); - - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<ProducerClient> weak_ptr_factory_{this}; -}; - -} // namespace tracing - -#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_CLIENT_H_
diff --git a/services/tracing/public/cpp/perfetto/producer_test_utils.cc b/services/tracing/public/cpp/perfetto/producer_test_utils.cc index b910952..59678ee 100644 --- a/services/tracing/public/cpp/perfetto/producer_test_utils.cc +++ b/services/tracing/public/cpp/perfetto/producer_test_utils.cc
@@ -10,10 +10,7 @@ #include <utility> #include "base/debug/leak_annotations.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" #include "base/run_loop.h" -#include "base/task/single_thread_task_runner.h" #include "services/tracing/public/cpp/tracing_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/include/perfetto/ext/base/utils.h" @@ -22,184 +19,6 @@ namespace tracing { -namespace { - -constexpr size_t kChunkSize = 4096; - -// For sequences/threads other than our own, we just want to ignore -// any events coming in. -class DummyTraceWriter : public perfetto::TraceWriter { - public: - DummyTraceWriter() - : delegate_(kChunkSize), stream_(&delegate_) {} - - perfetto::TraceWriter::TracePacketHandle NewTracePacket() override { - stream_.Reset(delegate_.GetNewBuffer()); - trace_packet_.Reset(&stream_); - - return perfetto::TraceWriter::TracePacketHandle(&trace_packet_); - } - - void FinishTracePacket() override { trace_packet_.Finalize(); } - - void Flush(std::function<void()> callback = {}) override {} - - perfetto::WriterID writer_id() const override { - return perfetto::WriterID(0); - } - - uint64_t written() const override { return 0u; } - - private: - protozero::RootMessage<perfetto::protos::pbzero::TracePacket> trace_packet_; - protozero::ScatteredStreamWriterNullDelegate delegate_; - protozero::ScatteredStreamWriter stream_; -}; - -} // namespace - -TestProducerClient::TestProducerClient( - std::unique_ptr<base::tracing::PerfettoTaskRunner> main_thread_task_runner, - bool log_only_main_thread) - : ProducerClient(main_thread_task_runner.get()), - delegate_(kChunkSize), - stream_(&delegate_), - main_thread_task_runner_(std::move(main_thread_task_runner)), - log_only_main_thread_(log_only_main_thread) {} - -TestProducerClient::~TestProducerClient() = default; - -std::unique_ptr<perfetto::TraceWriter> TestProducerClient::CreateTraceWriter( - perfetto::BufferID target_buffer, - perfetto::BufferExhaustedPolicy) { - // We attempt to destroy TraceWriters on thread shutdown in - // ThreadLocalStorage::Slot, by posting them to the ProducerClient taskrunner, - // but there's no guarantee that this will succeed if that taskrunner is also - // shut down. - ANNOTATE_SCOPED_MEMORY_LEAK; - if (!log_only_main_thread_ || - main_thread_task_runner_->GetOrCreateTaskRunner() - ->RunsTasksInCurrentSequence()) { - return std::make_unique<TestTraceWriter>(this); - } else { - return std::make_unique<DummyTraceWriter>(); - } -} - -void TestProducerClient::FlushPacketIfPossible() { - // GetNewBuffer() in ScatteredStreamWriterNullDelegate doesn't - // actually return a new buffer, but rather lets us access the buffer - // buffer already used by protozero to write the TracePacket into. - protozero::ContiguousMemoryRange buffer = delegate_.GetNewBuffer(); - - if (!trace_packet_) - return; - - trace_packet_->Finalize(); - uint32_t message_size = stream_.written() - trace_packet_written_start_; - EXPECT_GE(buffer.size(), message_size); - - auto proto = std::make_unique<perfetto::protos::TracePacket>(); - EXPECT_TRUE(proto->ParseFromArray(buffer.begin, message_size)); - if (proto->has_chrome_events() && - proto->chrome_events().metadata().size() > 0) { - legacy_metadata_packets_.push_back(std::move(proto)); - } else if (proto->has_chrome_metadata()) { - proto_metadata_packets_.push_back(std::move(proto)); - } else if (message_size > 0) { - finalized_packets_.push_back(std::move(proto)); - } else { - ++empty_finalized_packets_count_; - } - - stream_.Reset(buffer); - trace_packet_.reset(); -} - -perfetto::protos::pbzero::TracePacket* TestProducerClient::NewTracePacket() { - FlushPacketIfPossible(); - trace_packet_.emplace(); - trace_packet_->Reset(&stream_); - trace_packet_written_start_ = stream_.written(); - return &trace_packet_.value(); -} - -void TestProducerClient::FinishTracePacket() { - FlushPacketIfPossible(); -} - -size_t TestProducerClient::GetFinalizedPacketCount() { - FlushPacketIfPossible(); - return finalized_packets_.size(); -} - -const perfetto::protos::TracePacket* TestProducerClient::GetFinalizedPacket( - size_t packet_index) { - FlushPacketIfPossible(); - EXPECT_GT(finalized_packets_.size(), packet_index); - return finalized_packets_[packet_index].get(); -} - -const google::protobuf::RepeatedPtrField<perfetto::protos::ChromeMetadata>* -TestProducerClient::GetChromeMetadata(size_t packet_index) { - FlushPacketIfPossible(); - if (legacy_metadata_packets_.empty()) { - return nullptr; - } - EXPECT_GT(legacy_metadata_packets_.size(), packet_index); - - const auto& event_bundle = - legacy_metadata_packets_[packet_index]->chrome_events(); - return &event_bundle.metadata(); -} - -const perfetto::protos::ChromeMetadataPacket* -TestProducerClient::GetProtoChromeMetadata(size_t packet_index) { - FlushPacketIfPossible(); - EXPECT_GT(proto_metadata_packets_.size(), packet_index); - return &proto_metadata_packets_[packet_index]->chrome_metadata(); -} - -// static -void TestProducerClient::WriteTraceToFile( - const base::FilePath::StringType& filename, - const PacketVector& packets) { - auto&& raw_trace = TestProducerClient::SerializePacketsAsTrace(packets); - EXPECT_TRUE(base::WriteFile(base::FilePath(filename), raw_trace)); -} - -// static -std::string TestProducerClient::SerializePacketsAsTrace( - const PacketVector& finalized_packets) { - perfetto::protos::Trace trace; - for (auto& packet : finalized_packets) { - *trace.add_packet() = *packet; - } - std::string trace_bytes; - trace.SerializeToString(&trace_bytes); - return trace_bytes; -} - -TestTraceWriter::TestTraceWriter(TestProducerClient* producer_client) - : producer_client_(producer_client) {} - -perfetto::TraceWriter::TracePacketHandle TestTraceWriter::NewTracePacket() { - return perfetto::TraceWriter::TracePacketHandle( - producer_client_->NewTracePacket()); -} - -void TestTraceWriter::FinishTracePacket() { - producer_client_->FinishTracePacket(); -} - -perfetto::WriterID TestTraceWriter::writer_id() const { - return perfetto::WriterID(0); -} - -uint64_t TestTraceWriter::written() const { - return 0u; -} - DataSourceTester::DataSourceTester( tracing::PerfettoTracedProcess::DataSourceBase* data_source) { @@ -256,4 +75,30 @@ std::move(quit_closure).Run(); } +DummyTraceWriter::DummyTraceWriter() + : delegate_(kChunkSize), stream_(&delegate_) {} + +DummyTraceWriter::~DummyTraceWriter() = default; + +perfetto::TraceWriter::TracePacketHandle DummyTraceWriter::NewTracePacket() { + stream_.Reset(delegate_.GetNewBuffer()); + trace_packet_.Reset(&stream_); + + return perfetto::TraceWriter::TracePacketHandle(&trace_packet_); +} + +void DummyTraceWriter::FinishTracePacket() { + trace_packet_.Finalize(); +} + +void DummyTraceWriter::Flush(std::function<void()> callback) {} + +perfetto::WriterID DummyTraceWriter::writer_id() const { + return perfetto::WriterID(0); +} + +uint64_t DummyTraceWriter::written() const { + return 0u; +} + } // namespace tracing
diff --git a/services/tracing/public/cpp/perfetto/producer_test_utils.h b/services/tracing/public/cpp/perfetto/producer_test_utils.h index 92dea7c7..bcb3cb3 100644 --- a/services/tracing/public/cpp/perfetto/producer_test_utils.h +++ b/services/tracing/public/cpp/perfetto/producer_test_utils.h
@@ -9,14 +9,11 @@ #include <optional> #include <vector> -#include "base/files/file_path.h" #include "base/functional/callback_forward.h" -#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted_memory.h" #include "base/test/scoped_feature_list.h" -#include "base/tracing/perfetto_task_runner.h" #include "services/tracing/public/cpp/perfetto/perfetto_config.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" #include "third_party/perfetto/include/perfetto/protozero/root_message.h" #include "third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h" @@ -27,98 +24,6 @@ namespace tracing { -// Test producer client for data source tests. -class TestProducerClient : public ProducerClient { - public: - using PacketVector = - std::vector<std::unique_ptr<perfetto::protos::TracePacket>>; - explicit TestProducerClient(std::unique_ptr<base::tracing::PerfettoTaskRunner> - main_thread_task_runner, - bool log_only_main_thread = true); - ~TestProducerClient() override; - - // ProducerClient implementation: - std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter( - perfetto::BufferID target_buffer, - perfetto::BufferExhaustedPolicy = - perfetto::BufferExhaustedPolicy::kDefault) override; - - void FlushPacketIfPossible(); - - perfetto::protos::pbzero::TracePacket* NewTracePacket(); - - void FinishTracePacket(); - - size_t GetFinalizedPacketCount(); - - const perfetto::protos::TracePacket* GetFinalizedPacket( - size_t packet_index = 0); - - const google::protobuf::RepeatedPtrField<perfetto::protos::ChromeMetadata>* - GetChromeMetadata(size_t packet_index = 0); - - const perfetto::protos::ChromeMetadataPacket* GetProtoChromeMetadata( - size_t packet_index = 0); - - const PacketVector& finalized_packets() { - FlushPacketIfPossible(); - return finalized_packets_; - } - - // Serialize given trace packets and write the raw trace to the given file. - // Very handy for debugging when trace generated in a test needs to be - // exported, to understand it further with other tools. - // Sample usage : WriteTraceToFile("/tmp/trace.pb", finalized_packets()); - static void WriteTraceToFile(const base::FilePath::StringType& filename, - const PacketVector& packets); - - static std::string SerializePacketsAsTrace( - const PacketVector& finalized_packets); - - std::string GetSerializedTrace() const; - - int empty_finalized_packets_count() const { - return empty_finalized_packets_count_; - } - - TestProducerClient(TestProducerClient&&) = delete; - TestProducerClient& operator=(TestProducerClient&&) = delete; - - private: - PacketVector finalized_packets_; - // A count of finalized packets not added to |finalized_packets_| per being - // empty. - int empty_finalized_packets_count_ = 0; - PacketVector legacy_metadata_packets_; - PacketVector proto_metadata_packets_; - std::optional<protozero::RootMessage<perfetto::protos::pbzero::TracePacket>> - trace_packet_; - protozero::ScatteredStreamWriterNullDelegate delegate_; - protozero::ScatteredStreamWriter stream_; - size_t trace_packet_written_start_ = 0; - std::unique_ptr<base::tracing::PerfettoTaskRunner> main_thread_task_runner_; - bool log_only_main_thread_; -}; - -class TestTraceWriter : public perfetto::TraceWriter { - public: - using TracePacketCallback = base::RepeatingCallback<void( - std::unique_ptr<perfetto::protos::TracePacket>)>; - explicit TestTraceWriter(TestProducerClient* producer_client); - - perfetto::TraceWriter::TracePacketHandle NewTracePacket() override; - void FinishTracePacket() override; - void Flush(std::function<void()> callback = {}) override {} - perfetto::WriterID writer_id() const override; - uint64_t written() const override; - - TestTraceWriter(TestTraceWriter&&) = delete; - TestTraceWriter& operator=(TestTraceWriter&&) = delete; - - private: - raw_ptr<TestProducerClient, AcrossTasksDanglingUntriaged> producer_client_; -}; - // Wrapper class around TestProducerClient useful for testing a trace data // source. // @@ -152,6 +57,27 @@ finalized_packets_; }; +// For sequences/threads other than our own, we just want to ignore +// any events coming in. +class DummyTraceWriter : public perfetto::TraceWriter { + public: + static constexpr size_t kChunkSize = 4096; + + DummyTraceWriter(); + ~DummyTraceWriter() override; + + perfetto::TraceWriter::TracePacketHandle NewTracePacket() override; + void FinishTracePacket() override; + void Flush(std::function<void()> callback) override; + perfetto::WriterID writer_id() const override; + uint64_t written() const override; + + private: + protozero::RootMessage<perfetto::protos::pbzero::TracePacket> trace_packet_; + protozero::ScatteredStreamWriterNullDelegate delegate_; + protozero::ScatteredStreamWriter stream_; +}; + } // namespace tracing #endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_TEST_UTILS_H_
diff --git a/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc b/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc index 54e27890..9ae1569 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_metadata_source.cc
@@ -78,7 +78,6 @@ : DataSourceBase(mojom::kMetaDataSourceName), origin_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) { g_trace_event_metadata_source_for_testing = this; - PerfettoTracedProcess::Get()->AddDataSource(this); AddGeneratorFunction(base::BindRepeating( &TraceEventMetadataSource::WriteMetadataPacket, base::Unretained(this))); AddGeneratorFunction(base::BindRepeating(
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc index 1015ceb..071ea70 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
@@ -30,7 +30,6 @@ #include "build/build_config.h" #include "services/tracing/public/cpp/buildflags.h" #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" #include "third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/profiling/profile_packet.pbzero.h" @@ -224,7 +223,6 @@ TracingSamplerProfilerDataSource() : DataSourceBase(mojom::kSamplerProfilerSourceName) { - PerfettoTracedProcess::Get()->AddDataSource(this); g_sampler_profiler_ds_for_test = this; } @@ -743,8 +741,6 @@ // static void TracingSamplerProfiler::RegisterDataSource() { TracingSamplerProfilerDataSource::Get()->RegisterDataSource(); - PerfettoTracedProcess::Get()->AddDataSource( - TracingSamplerProfilerDataSource::Get()); } // static
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc index ef23c2c..98fbaf4 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
@@ -20,15 +20,22 @@ #include "base/profiler/unwinder.h" #include "base/run_loop.h" #include "base/task/single_thread_task_runner.h" +#include "base/test/gmock_callback_support.h" #include "base/test/test_simple_task_runner.h" +#include "base/test/trace_test_utils.h" #include "base/threading/thread.h" #include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_log.h" #include "build/build_config.h" +#include "services/tracing/perfetto/perfetto_service.h" #include "services/tracing/perfetto/test_utils.h" #include "services/tracing/public/cpp/buildflags.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" #include "services/tracing/public/cpp/perfetto/producer_test_utils.h" +#include "services/tracing/public/cpp/traced_process_impl.h" +#include "services/tracing/public/mojom/traced_process.mojom.h" +#include "services/tracing/tracing_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h" @@ -52,7 +59,8 @@ using ::testing::AtLeast; using ::testing::Invoke; using ::testing::Return; -using PacketVector = TestProducerClient::PacketVector; +using PacketVector = + std::vector<std::unique_ptr<perfetto::protos::TracePacket>>; std::unique_ptr<perfetto::TracingSession> g_tracing_session; @@ -494,43 +502,17 @@ #endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -class TracingProfileBuilderTest : public TracingUnitTest { - public: - void SetUp() override { - TracingUnitTest::SetUp(); - - auto perfetto_wrapper = std::make_unique<base::tracing::PerfettoTaskRunner>( - base::SingleThreadTaskRunner::GetCurrentDefault()); - producer_client_ = std::make_unique<TestProducerClient>( - std::move(perfetto_wrapper), /*log_only_main_thread=*/false); - } - - void TearDown() override { - producer_client_.reset(); - TracingUnitTest::TearDown(); - } - - TestProducerClient* producer() { return producer_client_.get(); } - - private: - std::unique_ptr<TestProducerClient> producer_client_; -}; - -TEST_F(TracingProfileBuilderTest, ValidModule) { +TEST(TracingProfileBuilderTest, ValidModule) { base::TestModule module; TracingSamplerProfiler::TracingProfileBuilder profile_builder( - base::PlatformThreadId(), - std::make_unique<TestTraceWriter>(producer()), - false); + base::PlatformThreadId(), std::make_unique<DummyTraceWriter>(), false); profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)}, base::TimeTicks()); } -TEST_F(TracingProfileBuilderTest, InvalidModule) { +TEST(TracingProfileBuilderTest, InvalidModule) { TracingSamplerProfiler::TracingProfileBuilder profile_builder( - base::PlatformThreadId(), - std::make_unique<TestTraceWriter>(producer()), - false); + base::PlatformThreadId(), std::make_unique<DummyTraceWriter>(), false); profile_builder.OnSampleCompleted({base::Frame(0x1010, nullptr)}, base::TimeTicks()); }
diff --git a/services/tracing/public/cpp/trace_startup.cc b/services/tracing/public/cpp/trace_startup.cc index 7026a5d..f36cd6b 100644 --- a/services/tracing/public/cpp/trace_startup.cc +++ b/services/tracing/public/cpp/trace_startup.cc
@@ -13,7 +13,7 @@ #include "components/tracing/common/trace_to_console.h" #include "components/tracing/common/tracing_switches.h" #include "services/tracing/public/cpp/perfetto/perfetto_config.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" #include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h" #include "services/tracing/public/cpp/trace_event_agent.h" #include "services/tracing/public/cpp/trace_event_args_allowlist.h"
diff --git a/services/tracing/public/cpp/traced_process_impl.cc b/services/tracing/public/cpp/traced_process_impl.cc index a65a41e9..65b928a 100644 --- a/services/tracing/public/cpp/traced_process_impl.cc +++ b/services/tracing/public/cpp/traced_process_impl.cc
@@ -11,7 +11,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "services/tracing/public/cpp/base_agent.h" -#include "services/tracing/public/cpp/perfetto/producer_client.h" +#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h" #include "services/tracing/public/cpp/trace_event_agent.h" #include "services/tracing/public/mojom/constants.mojom.h"
diff --git a/services/tracing/tracing_service_unittest.cc b/services/tracing/tracing_service_unittest.cc index 03bb186..1d494d5 100644 --- a/services/tracing/tracing_service_unittest.cc +++ b/services/tracing/tracing_service_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "services/tracing/tracing_service.h" + #include <memory> #include <utility> @@ -12,6 +14,7 @@ #include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/test/bind.h" +#include "base/test/gmock_callback_support.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" @@ -27,7 +30,6 @@ #include "services/tracing/public/mojom/perfetto_service.mojom.h" #include "services/tracing/public/mojom/traced_process.mojom.h" #include "services/tracing/public/mojom/tracing_service.mojom.h" -#include "services/tracing/tracing_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h" #include "third_party/perfetto/include/perfetto/tracing/data_source.h" @@ -40,6 +42,8 @@ namespace tracing { +using ::testing::_; + class TracingServiceTest : public TracingUnitTest { public: TracingServiceTest() : service_(&perfetto_service_) {} @@ -180,14 +184,15 @@ // Register a mock producer with an in-process Perfetto service. auto pid = 123; size_t kNumPackets = 10; - base::RunLoop wait_for_start; - base::RunLoop wait_for_registration; - std::unique_ptr<MockProducer> producer = std::make_unique<MockProducer>( - std::string("org.chromium-") + base::NumberToString(pid), - "com.example.mock_data_source", perfetto_service(), - wait_for_registration.QuitClosure(), wait_for_start.QuitClosure(), - kNumPackets); - wait_for_registration.Run(); + MockProducer producer; + base::RunLoop on_producer_connected; + producer.Connect(perfetto_service(), + std::string("org.chromium-") + base::NumberToString(pid)); + EXPECT_CALL(producer, OnConnect()) + .WillOnce( + base::test::RunOnceClosure(on_producer_connected.QuitClosure())); + on_producer_connected.Run(); + producer.RegisterDataSource("com.example.mock_data_source"); // Start a tracing session using the client API. auto session = @@ -197,9 +202,21 @@ auto* ds_cfg = perfetto_config.add_data_sources()->mutable_config(); ds_cfg->set_name("com.example.mock_data_source"); session->Setup(perfetto_config); + + base::RunLoop wait_for_start; + std::unique_ptr<perfetto::TraceWriter> writer; + EXPECT_CALL(producer, OnStartDataSource("com.example.mock_data_source", _)) + .WillOnce( + [&](const std::string& name, perfetto::DataSourceInstanceID ds_id) { + writer = producer.CreateTraceWriter(ds_id); + wait_for_start.Quit(); + }); + session->Start(); wait_for_start.Run(); + MockProducer::WritePackets(*writer, kNumPackets); + // Stop the session and wait for it to stop. Note that we can't use the // blocking API here because the service runs on the current sequence. base::RunLoop wait_for_stop_loop; @@ -240,6 +257,9 @@ base::trace_event::TraceConfig(), /*privacy_filtering_enabled=*/false, /*convert_to_legacy_json=*/true); session->Setup(perfetto_config); + base::RunLoop wait_for_start_loop; + session->SetOnStartCallback( + [&wait_for_start_loop] { wait_for_start_loop.Quit(); }); session->Start(); // Stop the session and wait for it to stop. Note that we can't use the @@ -374,14 +394,15 @@ // Register a mock producer with an in-process Perfetto service. auto pid = 123; size_t kNumPackets = 10; - base::RunLoop wait_for_start; - base::RunLoop wait_for_registration; - std::unique_ptr<MockProducer> producer = std::make_unique<MockProducer>( - std::string("org.chromium-") + base::NumberToString(pid), - "com.example.mock_data_source", perfetto_service(), - wait_for_registration.QuitClosure(), wait_for_start.QuitClosure(), - kNumPackets); - wait_for_registration.Run(); + MockProducer producer; + base::RunLoop on_producer_connected; + producer.Connect(perfetto_service(), + std::string("org.chromium-") + base::NumberToString(pid)); + EXPECT_CALL(producer, OnConnect()) + .WillOnce( + base::test::RunOnceClosure(on_producer_connected.QuitClosure())); + on_producer_connected.Run(); + producer.RegisterDataSource("com.example.mock_data_source"); base::FilePath output_file_path; ASSERT_TRUE(base::CreateTemporaryFile(&output_file_path)); @@ -398,9 +419,21 @@ auto* ds_cfg = perfetto_config.add_data_sources()->mutable_config(); ds_cfg->set_name("com.example.mock_data_source"); session->Setup(perfetto_config, output_file.TakePlatformFile()); + + base::RunLoop wait_for_start; + std::unique_ptr<perfetto::TraceWriter> writer; + EXPECT_CALL(producer, OnStartDataSource("com.example.mock_data_source", _)) + .WillOnce( + [&](const std::string& name, perfetto::DataSourceInstanceID ds_id) { + writer = producer.CreateTraceWriter(ds_id); + wait_for_start.Quit(); + }); + session->Start(); wait_for_start.Run(); + MockProducer::WritePackets(*writer, kNumPackets); + // Stop the session and wait for it to stop. Note that we can't use the // blocking API here because the service runs on the current sequence. base::RunLoop wait_for_stop_loop;
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc index 0b6cb8db..28d829e 100644 --- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc +++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -148,9 +148,9 @@ // GPU process. command_buffer_ = std::make_unique<gpu::CommandBufferProxyImpl>( channel_, stream_id_, default_task_runner_, buffer_mapper_); - bind_result_ = command_buffer_->Initialize( - gpu::kNullSurfaceHandle, /*shared_command_buffer=*/nullptr, - stream_priority_, attributes_, active_url_); + bind_result_ = + command_buffer_->Initialize(/*shared_command_buffer=*/nullptr, + stream_priority_, attributes_, active_url_); if (bind_result_ != gpu::ContextResult::kSuccess) { DLOG(ERROR) << "GpuChannelHost failed to create command buffer."; command_buffer_metrics::UmaRecordContextInitFailed(context_type_);
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 86af17c..c1da101 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -42,6 +42,7 @@ "rusty_png_feature.cc", "rusty_png_feature.h", ] + deps = [ ":skia" ] public_deps = [ ":buildflags", "//base",
diff --git a/skia/rusty_png_feature.cc b/skia/rusty_png_feature.cc index 7140050..45407c5 100644 --- a/skia/rusty_png_feature.cc +++ b/skia/rusty_png_feature.cc
@@ -5,9 +5,72 @@ #include "skia/rusty_png_feature.h" #include "base/feature_list.h" +#include "base/notreached.h" +#include "skia/buildflags.h" +#include "third_party/skia/include/encode/SkPngEncoder.h" + +#if BUILDFLAG(SKIA_BUILD_RUST_PNG) +#include "third_party/skia/experimental/rust_png/encoder/SkPngRustEncoder.h" +#endif namespace skia { +#if BUILDFLAG(SKIA_BUILD_RUST_PNG) +namespace { + +SkPngRustEncoder::Options ConvertToRustOptions( + const SkPngEncoder::Options& options) { + SkPngRustEncoder::Options rust_options; + if (options.fZLibLevel < 4) { + rust_options.fCompressionLevel = SkPngRustEncoder::CompressionLevel::kLow; + } else if (options.fZLibLevel < 7) { + rust_options.fCompressionLevel = + SkPngRustEncoder::CompressionLevel::kMedium; + } else { + rust_options.fCompressionLevel = SkPngRustEncoder::CompressionLevel::kHigh; + } + rust_options.fComments = options.fComments; + + // TODO(https://crbug.com/379312510): Translate other `options` (e.g. + // comments and/or ICC profile). + + return rust_options; +} + +} // namespace +#endif + BASE_FEATURE(kRustyPngFeature, "RustyPng", base::FEATURE_DISABLED_BY_DEFAULT); +bool EncodePng(SkWStream* dst, + const SkPixmap& src, + const SkPngEncoder::Options& options) { + if (IsRustyPngEnabled()) { +#if BUILDFLAG(SKIA_BUILD_RUST_PNG) + return SkPngRustEncoder::Encode(dst, src, ConvertToRustOptions(options)); +#else + // The `if` condition guarantees `SKIA_BUILD_RUST_PNG`. + NOTREACHED(); +#endif + } + + return SkPngEncoder::Encode(dst, src, options); +} + +std::unique_ptr<SkEncoder> MakePngEncoder( + SkWStream* dst, + const SkPixmap& src, + const SkPngEncoder::Options& options) { + if (IsRustyPngEnabled()) { +#if BUILDFLAG(SKIA_BUILD_RUST_PNG) + return SkPngRustEncoder::Make(dst, src, ConvertToRustOptions(options)); +#else + // The `if` condition guarantees `SKIA_BUILD_RUST_PNG`. + NOTREACHED(); +#endif + } + + return SkPngEncoder::Make(dst, src, options); +} + } // namespace skia
diff --git a/skia/rusty_png_feature.h b/skia/rusty_png_feature.h index 6c87d57..585fbf7 100644 --- a/skia/rusty_png_feature.h +++ b/skia/rusty_png_feature.h
@@ -5,9 +5,19 @@ #ifndef SKIA_RUSTY_PNG_FEATURE_H_ #define SKIA_RUSTY_PNG_FEATURE_H_ +#include <memory> + #include "base/component_export.h" #include "base/feature_list.h" #include "skia/buildflags.h" +#include "third_party/skia/include/encode/SkEncoder.h" + +class SkPixmap; +class SkWStream; + +namespace SkPngEncoder { +struct Options; +} // namespace SkPngEncoder namespace skia { @@ -31,6 +41,21 @@ #endif } +// A helper that will encode a PNG image using either the `libpng`-based +// `SkPngEncoder::Encode` API, or (if `kRustyPngFeature` is built and enabled) +// the Rust-based `SkPngRustEncoder::Encode` API. +COMPONENT_EXPORT(SKIA_RUSTY_PNG_FEATURE_DETECTION) +bool EncodePng(SkWStream* dst, + const SkPixmap& src, + const SkPngEncoder::Options& options); + +// A helper that will create either a `libpng`-based, or a Rust-based PNG +// encoder (depending on whether the `kRustyPngFeature` is built and enabled). +COMPONENT_EXPORT(SKIA_RUSTY_PNG_FEATURE_DETECTION) +std::unique_ptr<SkEncoder> MakePngEncoder(SkWStream* dst, + const SkPixmap& src, + const SkPngEncoder::Options& options); + } // namespace skia #endif // SKIA_RUSTY_PNG_FEATURE_H_
diff --git a/testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter b/testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter index 9a03d39..e69de29 100644 --- a/testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter +++ b/testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter
@@ -1,2 +0,0 @@ -# crbug.com/351017155 --org.chromium.android_webview.test.VariationsSeedLoaderTest.testFinchSeedExpirationAgeFlag
diff --git a/testing/buildbot/filters/android.device.content_shell_test_apk.filter b/testing/buildbot/filters/android.device.content_shell_test_apk.filter index 0ef6eb7..e69de29 100644 --- a/testing/buildbot/filters/android.device.content_shell_test_apk.filter +++ b/testing/buildbot/filters/android.device.content_shell_test_apk.filter
@@ -1,27 +0,0 @@ -# crbug.com/343821809 --org.chromium.net.AndroidProxySelectorTest.* - -# crbug.com/343808767 --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarInputCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarInputCut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarInputPaste --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPasswordCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPasswordCut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPasswordPaste --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPlainTextCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPlainTextCut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarTextAreaCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarTextAreaCut --org.chromium.content.browser.ContentTextSelectionTest.testCorrectPasteMenuItemsAddedWhenThereIsNoSelection --org.chromium.content.browser.ContentTextSelectionTest.testCorrectSelectionMenuItemsAddedForInputSelection - -# crbug.com/343821701 --org.chromium.content.browser.input.ImeTest.testImeCopy --org.chromium.content.browser.input.ImeTest.testImeCut --org.chromium.content.browser.input.ImeTest.testImePaste --org.chromium.content.browser.input.ImeTest.testKeyboardNotDismissedAfterCopySelection - -# crbug.com/1294427 --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_copy --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_cut --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_paste \ No newline at end of file
diff --git a/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter b/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter index 148c7c18..e69de29 100644 --- a/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter +++ b/testing/buildbot/filters/android.emulator_12.content_shell_test_apk.filter
@@ -1,7 +0,0 @@ -# https://crbug.com/1294427 --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_copy --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_cut --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_paste --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBar*Copy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBar*Cut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBar*Paste
diff --git a/testing/buildbot/filters/android.emulator_12l.content_shell_test_apk.filter b/testing/buildbot/filters/android.emulator_12l.content_shell_test_apk.filter index 2a3cf92..26f65fdf 100644 --- a/testing/buildbot/filters/android.emulator_12l.content_shell_test_apk.filter +++ b/testing/buildbot/filters/android.emulator_12l.content_shell_test_apk.filter
@@ -1,10 +1,4 @@ -# https://crbug.com/1294427 --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_copy --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_cut --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_paste - # https://crbug.com/1417038 --org.chromium.content.browser.ContentTextSelectionTest.* -org.chromium.content.browser.input.SelectPopupTest.testReloadWhilePopupShowing # https://crbug.com/1417055
diff --git a/testing/buildbot/filters/android.emulator_14_15_16.content_shell_test_apk.filter b/testing/buildbot/filters/android.emulator_14_15_16.content_shell_test_apk.filter index 819ba43..e69de29 100644 --- a/testing/buildbot/filters/android.emulator_14_15_16.content_shell_test_apk.filter +++ b/testing/buildbot/filters/android.emulator_14_15_16.content_shell_test_apk.filter
@@ -1,36 +0,0 @@ -# crbug.com/343821809 --org.chromium.net.AndroidProxySelectorTest.* - -# crbug.com/343808767 --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarInputCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarInputCut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarInputPaste --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPasswordCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPasswordCut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPasswordPaste --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPlainTextCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarPlainTextCut --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarTextAreaCopy --org.chromium.content.browser.ContentTextSelectionTest.testSelectActionBarTextAreaCut --org.chromium.content.browser.ContentTextSelectionTest.testCorrectPasteMenuItemsAddedWhenThereIsNoSelection --org.chromium.content.browser.ContentTextSelectionTest.testCorrectSelectionMenuItemsAddedForInputSelection - -# crbug.com/343821701 --org.chromium.content.browser.input.ImeTest.testImeCopy --org.chromium.content.browser.input.ImeTest.testImeCut --org.chromium.content.browser.input.ImeTest.testImePaste --org.chromium.content.browser.input.ImeTest.testKeyboardNotDismissedAfterCopySelection - -# crbug.com/343810189 --org.chromium.content.browser.input.StylusGestureEndToEndTest.testDeleteGesture --org.chromium.content.browser.input.StylusGestureEndToEndTest.testDeleteRangeGesture --org.chromium.content.browser.input.StylusGestureEndToEndTest.testInsertGesture --org.chromium.content.browser.input.StylusGestureEndToEndTest.testJoinOrSplitGesture --org.chromium.content.browser.input.StylusGestureEndToEndTest.testRemoveSpaceGesture --org.chromium.content.browser.input.StylusGestureEndToEndTest.testSelectGesture --org.chromium.content.browser.input.StylusGestureEndToEndTest.testSelectRangeGesture - -# crbug.com/1294427 --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_copy --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_cut --org.chromium.content.browser.accessibility.WebContentsAccessibilityTest.testPerformAction_paste
diff --git a/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter b/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter index 9a03d39..e69de29 100644 --- a/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter +++ b/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter
@@ -1,2 +0,0 @@ -# crbug.com/351017155 --org.chromium.android_webview.test.VariationsSeedLoaderTest.testFinchSeedExpirationAgeFlag
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index cb4f9b1..9a3ba68 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -395,6 +395,21 @@ ] } ], + "AndroidBottomToolbar": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AndroidBottomToolbar" + ] + } + ] + } + ], "AndroidBrowserControlsInViz": [ { "platforms": [ @@ -709,6 +724,21 @@ ] } ], + "AppBoundDataReencrypt": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AppBoundDataReencrypt" + ] + } + ] + } + ], "AppCloseRefreshClankStudy": [ { "platforms": [ @@ -4838,11 +4868,12 @@ { "name": "Enabled", "enable_features": [ - "WelcomeTourV2" + "WelcomeTourV3" ], "disable_features": [ "WelcomeTourCounterfactualArm", - "WelcomeTourHoldbackArm" + "WelcomeTourHoldbackArm", + "WelcomeTourV2" ] } ] @@ -11912,6 +11943,24 @@ ] } ], + "IOSSetUpListShortenedDuration": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "SetUpListDurationParam": "3" + }, + "enable_features": [ + "SetUpListShortenedDuration" + ] + } + ] + } + ], "IOSSharedHighlightingColorChange": [ { "platforms": [ @@ -17283,10 +17332,9 @@ ] } ], - "Prerender2EarlyDocumentLifecycleUpdate": [ + "Prerender2EarlyDocumentLifecycleUpdateV2": [ { "platforms": [ - "android", "linux", "mac", "windows", @@ -20918,6 +20966,21 @@ ] } ], + "ScreencastUseUSMForS3": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ProjectorUseUSMForS3" + ] + } + ] + } + ], "ScreenlockReauthChromeOS": [ { "platforms": [ @@ -23857,166 +23920,6 @@ ] } ], - "UserLevelMemoryPressureSignalOn4GbDevices": [ - { - "platforms": [ - "android", - "android_webview" - ], - "experiments": [ - { - "name": "Enabled_default", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "458" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - }, - { - "name": "Enabled_99p_5m", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "803" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - }, - { - "name": "Enabled_99p_1m", - "params": { - "inert_interval_after_loading": "1m", - "memory_threshold_mb": "803" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - }, - { - "name": "Enabled_95p_5m", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "508" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - }, - { - "name": "Enabled_95p_1m", - "params": { - "inert_interval_after_loading": "1m", - "memory_threshold_mb": "508" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - }, - { - "name": "Enabled_90p_5m", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "405" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - }, - { - "name": "Enabled_90p_1m", - "params": { - "inert_interval_after_loading": "1m", - "memory_threshold_mb": "405" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn4GbDevices" - ] - } - ] - } - ], - "UserLevelMemoryPressureSignalOn6GbDevices": [ - { - "platforms": [ - "android", - "android_webview" - ], - "experiments": [ - { - "name": "Enabled_default", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "494" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - }, - { - "name": "Enabled_99p_5m", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "924" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - }, - { - "name": "Enabled_99p_1m", - "params": { - "inert_interval_after_loading": "1m", - "memory_threshold_mb": "924" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - }, - { - "name": "Enabled_95p_5m", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "580" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - }, - { - "name": "Enabled_95p_1m", - "params": { - "inert_interval_after_loading": "1m", - "memory_threshold_mb": "580" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - }, - { - "name": "Enabled_90p_5m", - "params": { - "inert_interval_after_loading": "5m", - "memory_threshold_mb": "460" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - }, - { - "name": "Enabled_90p_1m", - "params": { - "inert_interval_after_loading": "1m", - "memory_threshold_mb": "460" - }, - "enable_features": [ - "UserLevelMemoryPressureSignalOn6GbDevices" - ] - } - ] - } - ], "V8CodeFlushing": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index de3240d4..ebc1203 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -2581,10 +2581,6 @@ "SubSampleWindowProxyUsageMetrics", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kStylusPointerAdjustment, - "StylusPointerAdjustment", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kStylusRichGestures, "StylusRichGestures", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 682841d..84f0a49 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -1690,9 +1690,6 @@ // Stylus gestures for editable web content. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kStylusRichGestures); -// Apply touch adjustment for stylus pointer events. This feature allows -// enabling functions like writing into a nearby input element. -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kStylusPointerAdjustment); // If enabled, reads and decodes navigation body data off the main thread. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kThreadedBodyLoader);
diff --git a/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom index 258ec1fb..d6973897 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom
@@ -320,6 +320,9 @@ kWritingSuggestions = 262, kInk = 263, kVirtualKeyboard = 264, + kNonCookieStorageAccess = 265, + kIntlDurationFormat = 266, + kWindowControlsOverlay = 267, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/strings/BUILD.gn b/third_party/blink/public/strings/BUILD.gn index 8b776e4c..0a7fda7 100644 --- a/third_party/blink/public/strings/BUILD.gn +++ b/third_party/blink/public/strings/BUILD.gn
@@ -25,7 +25,7 @@ script = "//third_party/blink/renderer/build/scripts/generate_permission_element_grd.py" outfile_grd = "$root_gen_dir/third_party/blink/public/strings/permission_element_generated_strings.grd" - outfile_map = "$root_gen_dir/third_party/blink/renderer/core/html/html_permission_element_strings_map.h" + outfile_map = "$root_gen_dir/third_party/blink/renderer/core/html/html_permission_element_strings_map.cc" outputs = [ outfile_grd, outfile_map,
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc index 731b10b..f91d181 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.h" #include "build/build_config.h" @@ -136,9 +131,12 @@ sk_color_space_[4] = trfn.d; sk_color_space_[5] = trfn.e; sk_color_space_[6] = trfn.f; - for (uint32_t i = 0; i < 3; ++i) - for (uint32_t j = 0; j < 3; ++j) - sk_color_space_[7 + 3 * i + j] = to_xyz.vals[i][j]; + for (uint32_t i = 0; i < 3; ++i) { + for (uint32_t j = 0; j < 3; ++j) { + // SAFETY: skcms_Matrix3x3 always creates 3x3 array. + sk_color_space_[7 + 3 * i + j] = UNSAFE_BUFFERS(to_xyz.vals[i][j]); + } + } switch (info.colorType()) { default: @@ -230,9 +228,13 @@ trfn.d = static_cast<float>(sk_color_space_[4]); trfn.e = static_cast<float>(sk_color_space_[5]); trfn.f = static_cast<float>(sk_color_space_[6]); - for (uint32_t i = 0; i < 3; ++i) - for (uint32_t j = 0; j < 3; ++j) - to_xyz.vals[i][j] = static_cast<float>(sk_color_space_[7 + 3 * i + j]); + for (uint32_t i = 0; i < 3; ++i) { + for (uint32_t j = 0; j < 3; ++j) { + // SAFETY: skcms_Matrix3x3 always creates 3x3 array. + UNSAFE_BUFFERS(to_xyz.vals[i][j]) = + static_cast<float>(sk_color_space_[7 + 3 * i + j]); + } + } sk_color_space = SkColorSpace::MakeRGB(trfn, to_xyz); }
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc index 1899089..66d73873 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
@@ -28,11 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include <memory> @@ -113,8 +108,9 @@ const String& data) { base::CheckedNumeric<size_t> data_buffer_size = data.length(); data_buffer_size *= 2; - if (!data_buffer_size.IsValid()) + if (!data_buffer_size.IsValid()) { return Create(); + } DataBufferPtr data_buffer = AllocateBuffer(data_buffer_size.ValueOrDie()); // TODO(danakj): This cast is valid, since it's at the start of the allocation @@ -122,9 +118,11 @@ // byte pointers to other types is problematic and can cause UB. String should // provide a way to copy directly to a byte array without forcing the caller // to do this case. - data.CopyTo( - base::span(reinterpret_cast<UChar*>(data_buffer.data()), data.length()), - 0); + // SAFETY: The preceding code ensures that `data.length()` matches + // `data_buffer.data()` as a `UChar*`. + data.CopyTo(UNSAFE_BUFFERS(base::span( + reinterpret_cast<UChar*>(data_buffer.data()), data.length())), + 0); return base::AdoptRef(new SerializedScriptValue(std::move(data_buffer))); } @@ -469,11 +467,10 @@ HeapHashSet<Member<DOMArrayBufferBase>> visited; shared_array_buffers_contents_.Grow(array_buffers.size()); - wtf_size_t i = 0; - for (auto it = array_buffers.begin(); it != array_buffers.end(); ++it) { - DOMSharedArrayBuffer* shared_array_buffer = *it; - if (visited.Contains(shared_array_buffer)) + for (wtf_size_t i = 0; const auto& shared_array_buffer : array_buffers) { + if (visited.Contains(shared_array_buffer)) { continue; + } visited.insert(shared_array_buffer); shared_array_buffer->ShareContentsWith(shared_array_buffers_contents_[i]); i++; @@ -566,17 +563,15 @@ if (!array_buffers.size()) return ArrayBufferContentsArray(); - for (auto it = array_buffers.begin(); it != array_buffers.end(); ++it) { - DOMArrayBufferBase* array_buffer = *it; + for (wtf_size_t i = 0; const auto& array_buffer : array_buffers) { if (array_buffer->IsDetached()) { - wtf_size_t index = - static_cast<wtf_size_t>(std::distance(array_buffers.begin(), it)); exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError, "ArrayBuffer at index " + - String::Number(index) + + String::Number(i) + " is already detached."); return ArrayBufferContentsArray(); } + i++; } contents.Grow(array_buffers.size()); @@ -591,14 +586,12 @@ static_cast<HeapHashSet<Member<DOMArrayBufferBase>>*>(buffer)->clear(); } } promptly_free_array_buffers{&visited}; - for (auto it = array_buffers.begin(); it != array_buffers.end(); ++it) { - DOMArrayBufferBase* array_buffer_base = *it; + for (wtf_size_t i = 0; auto& array_buffer_base : array_buffers) { + auto index = i++; if (visited.Contains(array_buffer_base)) continue; visited.insert(array_buffer_base); - wtf_size_t index = - static_cast<wtf_size_t>(std::distance(array_buffers.begin(), it)); if (array_buffer_base->IsShared()) { exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError, "SharedArrayBuffer at index " + @@ -607,7 +600,7 @@ return ArrayBufferContentsArray(); } else { DOMArrayBuffer* array_buffer = - static_cast<DOMArrayBuffer*>(array_buffer_base); + static_cast<DOMArrayBuffer*>(array_buffer_base.Get()); if (!array_buffer->IsDetachable(isolate)) { exception_state.ThrowTypeError(
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc index d04c8705..1c9e6d9 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_fuzzer.cc
@@ -2,19 +2,14 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include <algorithm> #include <cstddef> #include <cstdint> -#include "base/test/allow_check_is_test_for_testing.h" #include "base/numerics/safe_conversions.h" +#include "base/test/allow_check_is_test_for_testing.h" #include "build/build_config.h" #include "testing/libfuzzer/libfuzzer_exports.h" #include "third_party/blink/public/common/messaging/message_port_descriptor.h" @@ -51,7 +46,17 @@ return 0; } -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t data_size) { +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Truncate the input. + // SAFETY: Wrapping arguments from libFuzzer in a span. + auto data_span = + UNSAFE_BUFFERS(base::span(data, base::saturated_cast<wtf_size_t>(size))); + // Odd sizes are handled in various ways, depending how they arrive. + // Let's not worry about that case here. + if (data_span.size() % sizeof(UChar)) { + return 0; + } + test::TaskEnvironment task_environment; auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); @@ -61,15 +66,6 @@ blob_info_array->emplace_back(WebBlobInfo::FileForTesting( "d875dfc2-4505-461b-98fe-0cf6cc5eaf44", "path", "text/plain")); - // Odd sizes are handled in various ways, depending how they arrive. - // Let's not worry about that case here. - if (data_size % sizeof(UChar)) - return 0; - - // Truncate the input. - auto data_span = - base::span(data, base::saturated_cast<wtf_size_t>(data_size)); - // Used to control what kind of extra data is provided to the deserializer. unsigned hash = StringHasher::HashMemory(data_span);
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc index f491481..8efc5495 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -2,13 +2,9 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h" +#include <array> #include <limits> #include <optional> @@ -97,10 +93,10 @@ // returned. size_t ReadVersionEnvelope(SerializedScriptValue* serialized_script_value, uint32_t* out_version) { - const uint8_t* raw_data = serialized_script_value->Data(); - const size_t length = serialized_script_value->DataLengthInBytes(); - if (!length || raw_data[0] != kVersionTag) + auto data = serialized_script_value->GetWireData(); + if (data.empty() || data[0] != kVersionTag) { return 0; + } // Read a 32-bit unsigned integer from varint encoding. uint32_t version = 0; @@ -108,9 +104,10 @@ unsigned shift = 0; bool has_another_byte; do { - if (i >= length) + if (i >= data.size()) { return 0; - uint8_t byte = raw_data[i]; + } + uint8_t byte = data[i]; if (shift < 32) [[likely]] { version |= static_cast<uint32_t>(byte & 0x7f) << shift; shift += 7; @@ -130,8 +127,9 @@ 1 + sizeof(uint64_t) + sizeof(uint32_t); DCHECK_LT(i, std::numeric_limits<size_t>::max() - kTrailerOffsetDataSize); i += kTrailerOffsetDataSize; - if (i >= length) + if (i >= data.size()) { return 0; + } } // Otherwise, we did read the envelope. Hurray! @@ -529,7 +527,7 @@ return ReadDOMRectReadOnly(); } case kDOMQuadTag: { - DOMPointInit* point_inits[4]; + std::array<DOMPointInit*, 4> point_inits; for (int i = 0; i < 4; ++i) { auto* init = DOMPointInit::Create(); double x = 0, y = 0, z = 0, w = 0;
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc index 2def74e..4b7e9c8 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
@@ -2,13 +2,10 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h" +#include <array> + #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "build/build_config.h" @@ -1208,11 +1205,12 @@ // component is presented as a half float in Skia. However, difference in // GPU hardware may result in small differences in lower significant byte in // Skia color conversion pipeline. Hence, we use a tolerance of 2 here. - uint8_t pixel[8] = {}; + std::array<uint8_t, 8> pixel = {}; ASSERT_TRUE( new_image_bitmap->BitmapImage()->PaintImageForCurrentFrame().readPixels( info.makeWH(1, 1), &pixel, 8, 3, 3)); - uint8_t p3_red[8] = {0x57, 0x3B, 0x68, 0x32, 0x6E, 0x30, 0x00, 0x3C}; + std::array<uint8_t, 8> p3_red = {0x57, 0x3B, 0x68, 0x32, + 0x6E, 0x30, 0x00, 0x3C}; bool approximate_match = true; uint8_t tolerance = 2; for (int i = 0; i < 8; i++) {
diff --git a/third_party/blink/renderer/build/scripts/generate_permission_element_grd.py b/third_party/blink/renderer/build/scripts/generate_permission_element_grd.py index 81560bc..44222c1 100644 --- a/third_party/blink/renderer/build/scripts/generate_permission_element_grd.py +++ b/third_party/blink/renderer/build/scripts/generate_permission_element_grd.py
@@ -34,63 +34,131 @@ </grit> ''' -kStringMapHeaderPrefix = '''/// Copyright 2024 The Chromium Authors +kStringMapCcPrefix = '''// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ELEMENT_STRINGS_MAP_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ELEMENT_STRINGS_MAP_H_ +// Generated by third_party/blink/renderer/build/scripts/generate_permission_element_grd.py -#include <iterator> +#include <stdint.h> + +#include <bit> #include <optional> #include <string_view> #include <utility> #include "base/containers/fixed_flat_map.h" #include "base/containers/fixed_flat_set.h" +#include "third_party/blink/renderer/core/html/html_permission_element_strings_map.h" #include "third_party/blink/public/strings/grit/permission_element_generated_strings.h" #include "third_party/blink/public/strings/grit/permission_element_strings.h" namespace blink { -inline std::optional<int> GetPermissionElementMessageId( - std::string_view language_code, - int base_message) { - // This is a separate table to reduce the number of relocations, with a small - // runtime cost due to the additional lookup. - static constexpr auto kLanguageIds = base::MakeFixedFlatSet<std::string_view>({ -''' -kStringMapHeaderMidfix = ''' - }); - static constexpr auto kMessageIds = base::MakeFixedFlatMap<std::pair<int, int>, int>({ -''' -kStringMapHeaderSuffix = ''' - }); +namespace { - auto lang_id = kLanguageIds.find(language_code); - if (lang_id == kLanguageIds.end()) { - return std::nullopt; +static constexpr std::string_view kLanguages = +''' +kStringMapCcMidfix = ''' + +template <size_t kSize> +constexpr auto IndexTypeForSizeHelper() { + constexpr int kMinBits = std::bit_width(kSize); + if constexpr (kMinBits <= 8) { + return uint8_t(); + } else if constexpr (kMinBits <= 16) { + return uint16_t(); + } else if constexpr (kMinBits <= 32) { + return uint32_t(); + } else { + return size_t(); } - auto message_id = kMessageIds.find({std::distance(kLanguageIds.begin(), lang_id), base_message}); - if (message_id == kMessageIds.end()) { - return std::nullopt; +} + +template <size_t size> +struct IndexTypeForSize { + public: + using Type = decltype(IndexTypeForSizeHelper<size>()); +}; + +template <const std::string_view& kConstant> +struct StringSlice { + using IndexType = typename IndexTypeForSize<kConstant.size()>::Type; + + IndexType offset; + IndexType length; + + friend constexpr bool operator==(StringSlice lhs, StringSlice rhs) { + return std::string_view(lhs) == std::string_view(rhs); } - return message_id->second; + friend constexpr auto operator<=>(StringSlice lhs, StringSlice rhs) { + return std::string_view(lhs) <=> std::string_view(rhs); + } + constexpr operator std::string_view() const { + return kConstant.substr(offset, length); + } + +}; + +using LangStringSlice = StringSlice<kLanguages>; + +// In C++20, pairs required exactly-matching types to be comparable, i.e. +// std::pair<T1, T2> cannot be compared against std::pair<U1, U2>, even if T1 +// and T2 are comparable against U1 and U2. This was addressed in C++23 in +// https://cplusplus.github.io/LWG/issue3865. However, older versions of +// libstdc++ do not support this, so the lookup needs to be wrapped with a +// type that is heterogeneously comparable with the key pair type... +struct LookupHelper { + std::string_view lang; + uint16_t id; + + // The style guide requires operator== to be defined if operator<=> is + // defined. However, operator== is never actually used, which causes a + // compiler warning. Explicitly delete it instead... if it's ever needed, + // the build will start failing. + friend constexpr bool operator==(LookupHelper lhs, + std::pair<LangStringSlice, uint16_t> rhs) = delete; + friend constexpr auto operator<=>(LookupHelper lhs, + std::pair<LangStringSlice, uint16_t> rhs) { + return lhs.lang != rhs.first ? lhs.lang <=> rhs.first : lhs.id <=> rhs.second; + } +}; + +} // namespace + +std::optional<uint16_t> GetPermissionElementMessageId( + std::string_view language_code, + uint16_t base_message) { + static constexpr auto kMessageIds = + base::MakeFixedFlatMap<std::pair<LangStringSlice, uint16_t>, uint16_t>({ +''' +kStringMapCcSuffix = ''' + }); + + auto message = kMessageIds.find( + LookupHelper{language_code, static_cast<uint16_t>(base_message)}); + return message == kMessageIds.end() + ? std::nullopt + : std::optional(message->second); } } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ELEMENT_STRINGS_MAP_H_ ''' -def get_message_id_map(input_base_dir): +def get_message_id_map_and_orderings(input_base_dir): dom = parse(input_base_dir + "permission_element_strings.grd") dic = {} messages = dom.getElementsByTagName("message") for message in messages: dic[tclib.GenerateMessageId( message.firstChild.data.strip())] = message.getAttribute("name") - return dic + # The returned orderings are used to help sort keys for the fixed flat map. + # Empirically, resource IDs appear to be allocated in the order the messages + # are listed in the grd. + return (dic, + dict((message.getAttribute("name"), i) + for (i, message) in enumerate(messages))) def generate_grd_file(id_map, file_list, output_file_path): @@ -120,7 +188,7 @@ output_file.write(doc.toxml(encoding='UTF-8')) -def generate_cpp_mapping(input_file_path, output_file_path): +def generate_cpp_mapping(orderings, input_file_path, output_file_path): doc = parse(input_file_path) messages = doc.getElementsByTagName("message") with open(output_file_path, 'w') as output_file: @@ -132,8 +200,9 @@ # this code will use `pt-pt` (Portuguese from Portugal). custom_locale_mappings = {"en-gb": "en", "pt-pt": "pt", "zh-cn": "zh"} - languages = [] - message_mappings = [] + langs = '' + lang_map = {} + message_map = [] for message in messages: message_name = message.getAttribute('name') base_message = re.split('_[a-z]', message_name)[0] @@ -141,28 +210,34 @@ '_', 1)[1].lower().replace("_", "-") if locale in custom_locale_mappings: locale = custom_locale_mappings[locale] + if locale not in lang_map: + # String concatenation is inefficientin Python, since strings + # are immutable. However, maintaining a list of chars and + # re-implementing find() is also unpleasant. + langs_idx = langs.find(locale) + if langs_idx < 0: + lang_map[locale] = (len(langs), len(locale)) + langs += locale + else: + # If locale is already a substring in the existing list, + # the substring can simply be reused to save some space. + lang_map[locale] = (langs_idx, len(locale)) + message_map.append((locale, base_message, message_name)) - languages.append(locale) - message_mappings.append((locale, base_message, message_name)) - - # The map stores multiple (language, base message) mappings per - # language. To reduce the number of relocations, just store the - # language once and use its position in the flat set (which is - # sorted) as an implicit ID in the primary message mapping map. - # This reduces the number of relocations by a factor of 10x. - language_mappings = dict( - (language, i) - for (i, language) in enumerate(sorted(set(languages)))) - - output_file.write(kStringMapHeaderPrefix) - for (language, i) in sorted(list(language_mappings.items())): - output_file.write(f' "{language}", // {i}\n') - output_file.write(kStringMapHeaderMidfix) - for (language, base_message, message_name) in message_mappings: + output_file.write(kStringMapCcPrefix) + output_file.write(f' "{langs}";\n') + output_file.write(kStringMapCcMidfix) + # Pre-sorting is important here to avoid running into constexpr + # evaluation limits at compile time, since the translation tables can be + # quite large. + for (lang, base_message, + message_name) in sorted(message_map, + key=lambda x: (x[0], orderings[x[1]])): output_file.write( - f' {{{{{language_mappings[language]}, {base_message}}}, {message_name}}},\n' + f' {{{{{{{lang_map[lang][0]}, {lang_map[lang][1]}}}, {base_message}}}, {message_name}}},\n' ) - output_file.write(kStringMapHeaderSuffix) + # Argh + output_file.write(kStringMapCcSuffix) def main(argv): @@ -170,13 +245,13 @@ output_map_file_position = argv.index('--output_map') input_base_dir_position = argv.index('--input_base_dir') input_base_dir = argv[input_base_dir_position + 1] - id_map = get_message_id_map(input_base_dir) + id_map, orderings = get_message_id_map_and_orderings(input_base_dir) translated_files = list( glob.glob(input_base_dir + "translations/permission_element_strings_*")) generate_grd_file(id_map, translated_files, argv[output_grd_file_position + 1]) - generate_cpp_mapping(argv[output_grd_file_position + 1], + generate_cpp_mapping(orderings, argv[output_grd_file_position + 1], argv[output_map_file_position + 1])
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 1e35ea1..1cbda22 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -6823,7 +6823,8 @@ } if (HasElementFlag(ElementFlags::kTabIndexWasSetExplicitly) || IsRootEditableElementWithCounting(*this) || - IsScrollControlPseudoElement() || SupportsSpatialNavigationFocus()) { + IsScrollMarkerGroupPseudoElement() || IsScrollControlPseudoElement() || + SupportsSpatialNavigationFocus()) { return FocusableState::kFocusable; } if (CanBeKeyboardFocusableScroller(update_behavior)) {
diff --git a/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.cc b/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.cc index d9184a05..980b87a 100644 --- a/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.cc +++ b/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.cc
@@ -74,7 +74,11 @@ Element* originating_element, PseudoId pseudo_id) : PseudoElement(originating_element, pseudo_id), - ScrollSnapshotClient(originating_element->GetDocument().GetFrame()) {} + ScrollSnapshotClient(originating_element->GetDocument().GetFrame()) { + // Setting tab index explicitly here, as this pseudo element should be + // focusable. + SetTabIndexExplicitly(); +} void ScrollMarkerGroupPseudoElement::Trace(Visitor* v) const { v->Trace(selected_marker_);
diff --git a/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h b/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h index 280ea57e..f22ae6f4 100644 --- a/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h +++ b/third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h
@@ -132,6 +132,8 @@ bool IsScrollMarkerGroupPseudoElement() const final { return true; } + int DefaultTabIndex() const override { return 0; } + void AddToFocusGroup(ScrollMarkerPseudoElement& scroll_marker); void RemoveFromFocusGroup(const ScrollMarkerPseudoElement& scroll_marker); void ClearFocusGroup(); @@ -140,7 +142,7 @@ } // Set selected scroll marker. Returns true if the selected marker changed. CORE_EXPORT bool SetSelected(ScrollMarkerPseudoElement& scroll_marker); - ScrollMarkerPseudoElement* Selected() { return selected_marker_; } + ScrollMarkerPseudoElement* Selected() const { return selected_marker_; } void ActivateNextScrollMarker(); void ActivatePrevScrollMarker(); void ActivateScrollMarker(ScrollMarkerPseudoElement* scroll_marker);
diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc index 3471f97f..9fdcd5c 100644 --- a/third_party/blink/renderer/core/editing/frame_selection.cc +++ b/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -587,7 +587,8 @@ Element* const focused_element = GetDocument().FocusedElement() ? GetDocument().FocusedElement() : GetDocument().documentElement(); - if (!focused_element || focused_element->IsScrollControlPseudoElement()) { + if (!focused_element || focused_element->IsScrollControlPseudoElement() || + focused_element->IsScrollMarkerGroupPseudoElement()) { return false; } if (RuntimeEnabledFeatures::SelectionOnShadowDOMWithDelegatesFocusEnabled()) {
diff --git a/third_party/blink/renderer/core/fetch/fetch_later_util.cc b/third_party/blink/renderer/core/fetch/fetch_later_util.cc index 621e25d7..ca88a18 100644 --- a/third_party/blink/renderer/core/fetch/fetch_later_util.cc +++ b/third_party/blink/renderer/core/fetch/fetch_later_util.cc
@@ -23,41 +23,68 @@ namespace blink { namespace { -// Calculates "framesWithMinimalQuotaPolicy" by running Step 7 of -// https://whatpr.org/fetch/1647.html#determine-subframe-deferred-fetch-policy +// The max containers with minimal quota is 16. +// https://whatpr.org/fetch/1647.html#max-containers-with-minimal-quota +constexpr uint32_t kMaxContainersWithMinimalQuota = 16; + +// Converts `policy` to one of possible values of reserved deferred-fetch quota. +// https://whatpr.org/fetch/1647.html#reserved-deferred-fetch-quota +uint32_t ToReservedDeferredFetchQuota(FramePolicy::DeferredFetchPolicy policy) { + switch (policy) { + case FramePolicy::DeferredFetchPolicy::kDisabled: + return 0; + case FramePolicy::DeferredFetchPolicy::kDeferredFetch: + return kNormalReservedDeferredFetchQuota; + case FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal: + return kMinimalReservedDeferredFetchQuota; + } +} + +// Tells if the given two frames shares the same origin. +// https://html.spec.whatwg.org/multipage/browsers.html#same-origin +bool AreSameOrigin(const Frame* frame_a, const Frame* frame_b) { + CHECK(frame_a); + CHECK(frame_b); + + return frame_a->GetSecurityContext()->GetSecurityOrigin()->IsSameOriginWith( + frame_b->GetSecurityContext()->GetSecurityOrigin()); +} + +// Calculates the total number of frames according to Step 5 of +// https://whatpr.org/fetch/1647.html#reserve-deferred-fetch-quota // -// `container_frame` is an iframe to decide deferred fetch policy for. -// `top_level_relatives` is from executing the following for the parent of -// `container_frame`: -// https://whatpr.org/fetch/1647.html#available-deferred-fetching-quota -uint32_t CountFramesWithMinimalQuotaPolicy( - FrameOwner* container_frame, - const HeapHashSet<Member<Frame>>& top_level_relatives) { +// `container_frame` is an iframe to count the result for. Note that it must be +// an iframe with `PermissionsPolicyFeature::kDeferredFetchMinimal` enabled +// before calling this function. +// +// Example (with default Permissions Policy on every origin): +// root (a.com) -> frame-1 (a.com) +// -> frame-2 (a.com) +// -> frame-3 (b.com) +// -> frame-4 (b.com) +// * `container_frame` cannot be frame-1, frame-2. +// * When `container_frame` = frame-3 or frame-4, the result is 2. +uint32_t CountContainersWithReservedMinimalQuota( + const FrameOwner* container_frame) { CHECK(container_frame); uint32_t count = 0; - for (const auto& relative : top_level_relatives) { - // 7-2. topLevelRelatives contains navigable’s parent. - for (Frame* navigable = relative->FirstChild(); navigable; - navigable = navigable->NextSibling()) { - // 7-1. navigable is not container’s content navigable. - if (navigable == container_frame->ContentFrame()) { - continue; - } - // 7-3. topLevelRelatives does not contain navigable. - if (top_level_relatives.find(navigable) != top_level_relatives.end()) { - continue; - } - // 7-4. navigable’s navigable container’s deferred fetch policy is - // "deferred-fetch-minimal". - auto* navigable_container = navigable->Owner(); - if (navigable_container && - navigable_container->GetFramePolicy().deferred_fetch_policy == - FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal) { - count++; - } + // 5. Let containersWithReservedMinimalQuota be container’s node navigable’s + // top-level traversable’s descendant navigables + auto* top_frame = container_frame->ContentFrame()->Top(); + CHECK(top_frame); + for (const auto* navigable = top_frame; navigable; + navigable = navigable->Tree().TraverseNext(top_frame)) { + // removing any navigable whose reserved deferred-fetch quota is not minimal + // quota. + if (auto* navigable_container = navigable->Owner(); + navigable_container && + navigable_container->GetFramePolicy().deferred_fetch_policy == + FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal) { + count++; } } + return count; } @@ -81,30 +108,6 @@ // IsSubframeDeprioritizationEnabled. } -HeapHashSet<Member<Frame>> GetDeferredFetchQuotaSharingFrames(Frame* frame) { - HeapHashSet<Member<Frame>> result; - if (!frame) { - return result; - } - - auto* top_frame = frame->Top(); - for (auto* current_frame = top_frame; current_frame; - current_frame = current_frame->Tree().TraverseNext(top_frame)) { - if (!current_frame->IsLocalFrame()) { - // Skips non-local frames. - continue; - } - if (!frame->GetSecurityContext()->GetSecurityOrigin()->CanAccess( - current_frame->GetSecurityContext()->GetSecurityOrigin())) { - // Skips cross-origin frames. - continue; - } - result.insert(current_frame); - } - - return result; -} - FramePolicy::DeferredFetchPolicy GetContainerDeferredFetchPolicyOnNavigation( FrameOwner* container_frame) { CHECK(container_frame); @@ -118,58 +121,59 @@ auto* permissions_policy = container_frame->ContentFrame() ->GetSecurityContext() ->GetPermissionsPolicy(); - // 1. Set container’s deferred fetch policy to disabled. + // 1. Set container’s reserved deferred-fetch quota to 0. // 2. If the inherited policy for "deferred-fetch", container and // originToNavigateTo is Enabled, // TODO(crbug.com/40276121): and the available deferred fetching quota for - // container’s container document is equal or greater than 64 kibibytes, + // container’s container document is equal or greater than normal quota: if (permissions_policy->IsFeatureEnabledForOrigin( mojom::blink::PermissionsPolicyFeature::kDeferredFetch, to_url_origin)) { - // then set container’s deferred fetch policy to "deferred-fetch" and + // then set container’s reserved deferred-fetch quota to normal quota and // return. return FramePolicy::DeferredFetchPolicy::kDeferredFetch; } // 3. If the inherited policy for "deferred-fetch-minimal", container and - // originToNavigateTo is Disabled, then set container’s deferred fetch policy - // to disabled and return. + // originToNavigateTo is Disabled: if (!permissions_policy->IsFeatureEnabledForOrigin( mojom::blink::PermissionsPolicyFeature::kDeferredFetchMinimal, to_url_origin)) { + // then return. + return FramePolicy::DeferredFetchPolicy::kDisabled; + } + // 4. If container’s node document's origin is not same origin with + // container’s node navigable’s top-level traversable’s active document’s + // origin: + if (!AreSameOrigin(container_frame->ContentFrame()->Parent(), + container_frame->ContentFrame()->Top())) { + // then return. return FramePolicy::DeferredFetchPolicy::kDisabled; } - // 4. Let topLevelRelatives be container’s container document’s deferred - // fetch quota-sharing navigables. - auto top_level_relatives = GetDeferredFetchQuotaSharingFrames( - container_frame->ContentFrame()->Parent()); - // 5. If topLevelRelatives does not contain container’s node navigable’s - // top-level traversable, then set container’s deferred fetch policy to - // disabled and return. - if (top_level_relatives.find(container_frame->ContentFrame()->Top()) == - top_level_relatives.end()) { - return FramePolicy::DeferredFetchPolicy::kDisabled; - } - - // 7. For each navigable that matches the following conditions: - uint32_t frames_with_minimal_quota_policy = - CountFramesWithMinimalQuotaPolicy(container_frame, top_level_relatives); - - // 8. If framesWithMinimalQuotaPolicy is less than 16, then set container’s - // deferred fetch policy to "deferred-fetch-minimal". - if (frames_with_minimal_quota_policy < 16) { - return FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal; - } - - return FramePolicy::DeferredFetchPolicy::kDisabled; + // 5. Let containersWithReservedMinimalQuota be ... + // 6. If containersWithReservedMinimalQuota’s size is less than max containers + // with minimal quota, then set container’s reserved deferred-fetch quota to + // minimal quota. + return CountContainersWithReservedMinimalQuota(container_frame) < + kMaxContainersWithMinimalQuota + ? FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal + : FramePolicy::DeferredFetchPolicy::kDisabled; } -uint32_t CountFramesWithMinimalQuotaPolicyForTesting( - FrameOwner* container_frame, - const HeapHashSet<Member<Frame>>& top_level_relatives) { - return CountFramesWithMinimalQuotaPolicy(container_frame, - top_level_relatives); +// For testing only: +uint32_t ToReservedDeferredFetchQuotaForTesting( + FramePolicy::DeferredFetchPolicy policy) { + return ToReservedDeferredFetchQuota(policy); +} + +bool AreSameOriginForTesting(const Frame* frame_a, const Frame* frame_b) { + return AreSameOrigin(frame_a, frame_b); +} + +uint32_t CountContainersWithReservedMinimalQuotaForTesting( + const FrameOwner* container_frame) { + return CountContainersWithReservedMinimalQuota(container_frame); } } // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/fetch_later_util.h b/third_party/blink/renderer/core/fetch/fetch_later_util.h index 0a3deadd..d08ebff 100644 --- a/third_party/blink/renderer/core/fetch/fetch_later_util.h +++ b/third_party/blink/renderer/core/fetch/fetch_later_util.h
@@ -9,7 +9,6 @@ #include "third_party/blink/public/common/frame/frame_policy.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" #include "third_party/blink/renderer/platform/loader/fetch/resource.h" @@ -23,11 +22,15 @@ // The ResourceType of FetchLater requests. inline constexpr ResourceType kFetchLaterResourceType = ResourceType::kRaw; -// 64 kibibytes. -inline constexpr uint32_t kInitialSubframeDeferredFetchBytes = 64 * 1024; +// The minimal quota is 8 kibibytes, one of the possible values for +// "reserved deferred-fetch quota". +// https://whatpr.org/fetch/1647.html#reserved-deferred-fetch-quota-minimal-quota +inline constexpr uint32_t kMinimalReservedDeferredFetchQuota = 8 * 1024; -// 8 kibibytes. -inline constexpr uint32_t kInitialSubframeDeferredFetchMinimalBytes = 8 * 1024; +// The normal quota is 64 kibibytes, one of the possible values for +// "reserved deferred-fetch quota". +// https://whatpr.org/fetch/1647.html#reserved-deferred-fetch-quota-normal-quota +inline constexpr uint32_t kNormalReservedDeferredFetchQuota = 64 * 1024; // Tells whether the FetchLater API should use subframe deferred fetch // policy to decide whether a frame show allow using the API. @@ -37,17 +40,14 @@ ResourceLoadPriority CORE_EXPORT ComputeFetchLaterLoadPriority(const FetchParameters& params); -// Returns all frames that shares the same deferred fetch quota with `frame`, -// i.e. all same-origin same-process frames of `frame`. -// Note that the result includes the `frame` itself if not null. -// https://whatpr.org/fetch/1647.html#deferred-fetch-quota-sharing-navigables -HeapHashSet<Member<Frame>> CORE_EXPORT -GetDeferredFetchQuotaSharingFrames(Frame* frame); - // Determines the deferred fetch policy of a navigable container // `container_frame`, e.g. iframe, when it navigates its content to a target // URL, by the following algorithm: -// https://whatpr.org/fetch/1647.html#determine-subframe-deferred-fetch-policy +// https://whatpr.org/fetch/1647.html#reserve-deferred-fetch-quota +// `container_frame` is a FrameOwner on navigation, i.e. an iframe. +// Returns an enum that can be mapped to a "reserved deferred-fetch quota" by +// calling `ToReservedDeferredFetchQuota()`. +// // This must be called after "inherited policy" for `container_frame` is // available, i.e. after `PermissionsPolicy::CreateFromParentPolicy()` is // already executed. @@ -55,9 +55,12 @@ GetContainerDeferredFetchPolicyOnNavigation(FrameOwner* container_frame); // For testing only: -uint32_t CORE_EXPORT CountFramesWithMinimalQuotaPolicyForTesting( - FrameOwner* container_frame, - const HeapHashSet<Member<Frame>>& top_level_relatives); +uint32_t CORE_EXPORT +ToReservedDeferredFetchQuotaForTesting(FramePolicy::DeferredFetchPolicy policy); +bool CORE_EXPORT AreSameOriginForTesting(const Frame* frame_a, + const Frame* frame_b); +uint32_t CORE_EXPORT CountContainersWithReservedMinimalQuotaForTesting( + const FrameOwner* container_frame); } // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/fetch_later_util_test.cc b/third_party/blink/renderer/core/fetch/fetch_later_util_test.cc index ede560ed..dbbb0d38 100644 --- a/third_party/blink/renderer/core/fetch/fetch_later_util_test.cc +++ b/third_party/blink/renderer/core/fetch/fetch_later_util_test.cc
@@ -148,7 +148,7 @@ } // Renders a series of sibling <iframe> elements with the given `iframe_urls`. - String RenderWithIframes(const Vector<String>& iframe_urls) { + static String RenderWithIframes(const Vector<String>& iframe_urls) { StringBuilder html; for (const auto& url : iframe_urls) { html.Append("<iframe src=\""); @@ -158,209 +158,42 @@ return html.ToString(); } + static void CheckFrameEnableDeferredFetchMinimal(Frame* frame) { + CHECK(frame->GetSecurityContext() + ->GetPermissionsPolicy() + ->IsFeatureEnabledForOrigin( + mojom::blink::PermissionsPolicyFeature::kDeferredFetchMinimal, + frame->GetSecurityContext() + ->GetSecurityOrigin() + ->ToUrlOrigin())); + } + LocalFrame* GetMainFrame() { return GetDocument().GetFrame(); } private: base::test::ScopedFeatureList feature_list_; }; -using GetDeferredFetchQuotaSharingFramesTest = DeferredFetchPolicyTestBase; - -TEST_F(GetDeferredFetchQuotaSharingFramesTest, Null) { - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(nullptr), testing::IsEmpty()); -} - -// The main frame shares the deferred fetch quota with itself. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, SingleDocument) { - NavigateTo(kMainUrl, ""); - - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(GetMainFrame()), - testing::SizeIs(1)); -} - -// The about::blank iframe shares the deferred fetch quota with the main frame. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, SingleDocumentSingleBlankFrame) { - NavigateTo(kMainUrl, "<iframe></iframe>"); - - auto* root = GetMainFrame(); - auto* blank_frame = root->Tree().FirstChild(); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(root), testing::SizeIs(2)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(blank_frame), - testing::SizeIs(2)); -} - -// The same-origin iframe shares the deferred fetch quota with the main frame. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, - SingleDocumentSingleSameOriginFrame) { - // The structure of the document: - // root -> frame_a (same-origin) - String root_url = kMainUrl; - String frame_a_url = kMainUrl + "frame-a.html"; - - NavigateTo(root_url, RenderWithIframes({"frame-a.html"}), - {{frame_a_url, ""}}); - - // Root and Frame A are same-origin. - auto* root = GetMainFrame(); - auto* frame_a = root->Tree().FirstChild(); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(root), testing::SizeIs(2)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_a), testing::SizeIs(2)); -} - -// The same-origin iframe does not share the deferred fetch quota with the main -// frame. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, - SingleDocumentSingleCrossOriginFrame) { - // The structure of the document: - // root -> frame_a (cross-origin) - String root_url = kMainUrl; - String frame_a_url = kCrossSubdomainUrl + "frame-a.html"; - - NavigateTo(root_url, RenderWithIframes({frame_a_url}), {{frame_a_url, ""}}); - - // Root and Frame A are cross-origin. - auto* root = GetMainFrame(); - auto* frame_a = root->Tree().FirstChild(); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(root), testing::SizeIs(1)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_a), testing::SizeIs(1)); -} - -// The main frame and 3 cross-origin iframes don't share the same deferred -// fetch quota. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, - MultipleCrossOriginSiblingFrames) { - // The structure of the document: - // root -> frame_a (cross-origin) - // -> frame_b (cross-origin) - // -> frame_c (cross-origin) - String root_url = kMainUrl; - String frame_a_url = kCrossSubdomainUrl + "frame-a.html"; - String frame_b_url = kCrossSubdomainUrl + "frame-b.html"; - String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; - - NavigateTo(root_url, - RenderWithIframes({frame_a_url, frame_b_url, frame_c_url}), - {{frame_a_url, ""}, {frame_b_url, ""}, {frame_c_url, ""}}); - - auto* root = GetMainFrame(); - auto* frame_a = root->Tree().FirstChild(); - auto* frame_b = frame_a->Tree().NextSibling(); - auto* frame_c = frame_b->Tree().NextSibling(); - - // Root is its owned origin. - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(root), testing::SizeIs(1)); - - // Frame A, B, and C are same-origin. - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_a), testing::SizeIs(3)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_b), testing::SizeIs(3)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_c), testing::SizeIs(3)); -} - -// The same-origin main frame, frame-a, frame-b are in the same frame group for -// deferred fetch quota, while cross-origin frame-c, frame-d are in their own -// group. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, - MultipleDifferentOriginSiblingFrames) { - // The structure of the document: - // root -> frame_a (same-origin) - // -> frame_b (same-origin) - // -> frame_c (cross-origin) - // -> frame_d (cross-origin) - String root_url = kMainUrl; - String frame_a_url = kMainUrl + "frame-a.html"; - String frame_b_url = kMainUrl + "frame-b.html"; - String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; - String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; - - NavigateTo(root_url, - RenderWithIframes( - {"frame-a.html", frame_b_url, frame_c_url, frame_d_url}), - {{frame_a_url, ""}, - {frame_b_url, ""}, - {frame_c_url, ""}, - {frame_d_url, ""}}); - - auto* root = GetMainFrame(); - auto* frame_a = root->Tree().FirstChild(); - auto* frame_b = frame_a->Tree().NextSibling(); - auto* frame_c = frame_b->Tree().NextSibling(); - auto* frame_d = frame_c->Tree().NextSibling(); - - // Root, Frame A and Frame B are same-origin. - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(root), testing::SizeIs(3)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_a), testing::SizeIs(3)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_b), testing::SizeIs(3)); - - // Frame C and D are same-origin. - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_c), testing::SizeIs(2)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_d), testing::SizeIs(2)); -} - -// The same-origin main frame, frame-a, frame-b are in the same frame group for -// deferred fetch quota, while cross-origin frame-c, frame-d are in their own -// group. -TEST_F(GetDeferredFetchQuotaSharingFramesTest, MultipleLevelFrames) { - // The structure of the document: - // root -> frame_a (same-origin) -> frame_c (cross-origin) - // -> frame_d (cross-origin) -> frame_b (same-origin) - String root_url = kMainUrl; - String frame_a_url = kMainUrl + "frame-a.html"; - String frame_b_url = kMainUrl + "frame-b.html"; - String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; - String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; - - NavigateTo(root_url, RenderWithIframes({"frame-a.html", frame_d_url}), - {{frame_a_url, RenderWithIframes({frame_c_url})}, - {frame_d_url, RenderWithIframes({frame_b_url})}, - {frame_c_url, ""}, - {frame_b_url, ""}}); - - auto* root = GetMainFrame(); - auto* frame_a = root->Tree().FirstChild(); - auto* frame_d = frame_a->Tree().NextSibling(); - auto* frame_c = frame_a->Tree().FirstChild(); - auto* frame_b = frame_d->Tree().FirstChild(); - - // Root, Frame A and Frame B are same-origin. - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(root), testing::SizeIs(3)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_a), testing::SizeIs(3)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_b), testing::SizeIs(3)); - - // Frame C and D are same-origin. - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_c), testing::SizeIs(2)); - EXPECT_THAT(GetDeferredFetchQuotaSharingFrames(frame_d), testing::SizeIs(2)); -} - -class CountFramesWithMinimalQuotaPolicyTest +class CountContainersWithReservedMinimalQuotaTest : public DeferredFetchPolicyTestBase { protected: - [[nodiscard]] size_t CountFramesWithMinimalQuotaPolicyFor( + [[nodiscard]] static size_t CountContainersWithReservedMinimalQuotaFor( Frame* target_frame) { // Should only be called by content of an iframe. CHECK(target_frame->Owner()); // Should not be called by frame without permissions policy - // `deferred-fetch`. - CHECK(!target_frame->GetSecurityContext() - ->GetPermissionsPolicy() - ->IsFeatureEnabledForOrigin( - mojom::blink::PermissionsPolicyFeature::kDeferredFetch, - target_frame->GetSecurityContext() - ->GetSecurityOrigin() - ->ToUrlOrigin())); + // `deferred-fetch-minimal`. + CheckFrameEnableDeferredFetchMinimal(target_frame); - // `GetDeferredFetchQuotaSharingFrames()` must be run on the - // `container’s container document`. - auto top_level_relatives = - GetDeferredFetchQuotaSharingFrames(target_frame->Parent()); - return CountFramesWithMinimalQuotaPolicyForTesting(target_frame->Owner(), - top_level_relatives); + return CountContainersWithReservedMinimalQuotaForTesting( + target_frame->Owner()); } }; // The single cross-origin iframe has default `deferred-fetch-minimal` policy -// enabled `*`. However, there is no other cross-origin iframs share this quota +// enabled `*`. However, there is no other cross-origin iframe shares this quota // with it. -TEST_F(CountFramesWithMinimalQuotaPolicyTest, SingleCrossOriginFrame) { +TEST_F(CountContainersWithReservedMinimalQuotaTest, SingleCrossOriginFrame) { // The structure of the document: // root -> frame_a (cross-origin) String root_url = kMainUrl; @@ -370,11 +203,11 @@ auto* root = GetMainFrame(); auto* frame_a = root->Tree().FirstChild(); - // Expects no other frames share the minimal quota policy with `frame_a`. - EXPECT_EQ(CountFramesWithMinimalQuotaPolicyFor(frame_a), 0u); + // Expects only `frame_a` share the minimal quota policy. + EXPECT_EQ(CountContainersWithReservedMinimalQuotaFor(frame_a), 1u); } -TEST_F(CountFramesWithMinimalQuotaPolicyTest, +TEST_F(CountContainersWithReservedMinimalQuotaTest, MultipleDifferentOriginSiblingFrames) { // The structure of the document: // root -> frame_a (same-origin) @@ -403,12 +236,43 @@ // Frame A and Frame B are same-origin with root and are not counted toward // minimal quota policy. Hence, they cannot be used in - // `CountFramesWithMinimalQuotaPolicyFor()`. + // `CountContainersWithReservedMinimalQuotaFor()`. // Frame C and D are different origin with root, and shares the minimal quota // policy with each other. - EXPECT_EQ(CountFramesWithMinimalQuotaPolicyFor(frame_c), 1u); - EXPECT_EQ(CountFramesWithMinimalQuotaPolicyFor(frame_d), 1u); + EXPECT_EQ(CountContainersWithReservedMinimalQuotaFor(frame_c), 2u); + EXPECT_EQ(CountContainersWithReservedMinimalQuotaFor(frame_d), 2u); +} + +TEST_F(CountContainersWithReservedMinimalQuotaTest, MultipleLevelFrames) { + // The structure of the document: + // root -> frame_a (same-origin) -> frame_c (cross-origin) + // -> frame_d (cross-origin) -> frame_b (same-origin) + String root_url = kMainUrl; + String frame_a_url = kMainUrl + "frame-a.html"; + String frame_b_url = kMainUrl + "frame-b.html"; + String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; + String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; + + NavigateTo(root_url, RenderWithIframes({"frame-a.html", frame_d_url}), + {{frame_a_url, RenderWithIframes({frame_c_url})}, + {frame_d_url, RenderWithIframes({frame_b_url})}, + {frame_c_url, ""}, + {frame_b_url, ""}}); + + auto* root = GetMainFrame(); + auto* frame_a = root->Tree().FirstChild(); + auto* frame_d = frame_a->Tree().NextSibling(); + auto* frame_c = frame_a->Tree().FirstChild(); + + // Frame A and Frame B are same-origin with root and are not counted toward + // minimal quota policy. Hence, they cannot be used in + // `CountContainersWithReservedMinimalQuotaFor()`. + + // Frame C and D are different origin with root, and shares the minimal quota + // policy with each other. + EXPECT_EQ(CountContainersWithReservedMinimalQuotaFor(frame_c), 2u); + EXPECT_EQ(CountContainersWithReservedMinimalQuotaFor(frame_d), 2u); } using GetContainerDeferredFetchPolicyOnNavigationTest = @@ -458,6 +322,84 @@ FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal); } +TEST_F(GetContainerDeferredFetchPolicyOnNavigationTest, + MultipleDifferentOriginSiblingFrames) { + // The structure of the document: + // root -> frame_a (same-origin) + // -> frame_b (same-origin) + // -> frame_c (cross-origin) + // -> frame_d (cross-origin) + String root_url = kMainUrl; + String frame_a_url = kMainUrl + "frame-a.html"; + String frame_b_url = kMainUrl + "frame-b.html"; + String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; + String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; + + NavigateTo(root_url, + RenderWithIframes( + {"frame-a.html", frame_b_url, frame_c_url, frame_d_url}), + {{frame_a_url, ""}, + {frame_b_url, ""}, + {frame_c_url, ""}, + {frame_d_url, ""}}); + + auto* root = GetMainFrame(); + auto* frame_a = root->Tree().FirstChild(); + auto* frame_b = frame_a->Tree().NextSibling(); + auto* frame_c = frame_b->Tree().NextSibling(); + auto* frame_d = frame_c->Tree().NextSibling(); + + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_a->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetch); + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_b->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetch); + + // Frame C and Frame D should have minimal quota policy set. + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_c->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal); + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_d->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal); +} + +TEST_F(GetContainerDeferredFetchPolicyOnNavigationTest, MultipleLevelFrames) { + // The structure of the document: + // root -> frame_a (same-origin) -> frame_c (cross-origin) + // -> frame_d (cross-origin) -> frame_b (same-origin) + String root_url = kMainUrl; + String frame_a_url = kMainUrl + "frame-a.html"; + String frame_b_url = kMainUrl + "frame-b.html"; + String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; + String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; + + NavigateTo(root_url, RenderWithIframes({"frame-a.html", frame_d_url}), + {{frame_a_url, RenderWithIframes({frame_c_url})}, + {frame_d_url, RenderWithIframes({frame_b_url})}, + {frame_c_url, ""}, + {frame_b_url, ""}}); + + auto* root = GetMainFrame(); + auto* frame_a = root->Tree().FirstChild(); + auto* frame_d = frame_a->Tree().NextSibling(); + auto* frame_c = frame_a->Tree().FirstChild(); + auto* frame_b = frame_d->Tree().FirstChild(); + + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_a->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetch); + // Frame B will have NO quota, as + // (1) its "inherited policy" from its parent Frame D, which is a cross-origin + // iframe, will not have "deferred-fetch" policy enabled by default but only + // "deferred-fetch-minimal". + // (2) its parent Frame D does not share same quota with root frame. + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_b->Owner()), + FramePolicy::DeferredFetchPolicy::kDisabled); + + // Frame C and Frame D should have minimal quota policy set. + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_c->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal); + EXPECT_EQ(GetContainerDeferredFetchPolicyOnNavigation(frame_d->Owner()), + FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal); +} + // Tests the default behavior of a document with 17 cross-origin sibling // iframes. The first 16 iframes should get kDeferredFetchMinimal as their // deferred fetch policy, while the last one should be kDisabled. @@ -498,5 +440,122 @@ << i + 1 << "-th cross-origin iframe"; } +using ToReservedDeferredFetchQuotaTest = DeferredFetchPolicyTestBase; + +TEST_F(ToReservedDeferredFetchQuotaTest, PolicyDisabled) { + EXPECT_EQ(ToReservedDeferredFetchQuotaForTesting( + FramePolicy::DeferredFetchPolicy::kDisabled), + 0u); +} + +TEST_F(ToReservedDeferredFetchQuotaTest, PolicyDeferredFetch) { + EXPECT_EQ(ToReservedDeferredFetchQuotaForTesting( + FramePolicy::DeferredFetchPolicy::kDeferredFetch), + kNormalReservedDeferredFetchQuota); +} + +TEST_F(ToReservedDeferredFetchQuotaTest, PolicyDeferredFetchMinimal) { + EXPECT_EQ(ToReservedDeferredFetchQuotaForTesting( + FramePolicy::DeferredFetchPolicy::kDeferredFetchMinimal), + kMinimalReservedDeferredFetchQuota); +} + +class AreSameOriginTest : public DeferredFetchPolicyTestBase { + protected: + [[nodiscard]] static bool AreSameOrigin(Frame* frame_a, Frame* frame_b) { + return AreSameOriginForTesting(frame_a, frame_b); + } +}; + +TEST_F(AreSameOriginTest, MultipleDifferentOriginSiblingFrames) { + // The structure of the document: + // root -> frame_a (same-origin) + // -> frame_b (same-origin) + // -> frame_c (cross-origin) + // -> frame_d (cross-origin) + String root_url = kMainUrl; + String frame_a_url = kMainUrl + "frame-a.html"; + String frame_b_url = kMainUrl + "frame-b.html"; + String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; + String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; + + NavigateTo(root_url, + RenderWithIframes( + {"frame-a.html", frame_b_url, frame_c_url, frame_d_url}), + {{frame_a_url, ""}, + {frame_b_url, ""}, + {frame_c_url, ""}, + {frame_d_url, ""}}); + + auto* root = GetMainFrame(); + auto* frame_a = root->Tree().FirstChild(); + auto* frame_b = frame_a->Tree().NextSibling(); + auto* frame_c = frame_b->Tree().NextSibling(); + auto* frame_d = frame_c->Tree().NextSibling(); + + // Root, Frame A and Frame B are same-origin. + EXPECT_TRUE(AreSameOrigin(root, frame_a)); + EXPECT_TRUE(AreSameOrigin(frame_a, root)); + EXPECT_TRUE(AreSameOrigin(root, frame_b)); + EXPECT_TRUE(AreSameOrigin(frame_b, root)); + EXPECT_TRUE(AreSameOrigin(frame_a, frame_b)); + EXPECT_TRUE(AreSameOrigin(frame_b, frame_a)); + + // Frame C and D are different origin with root, and shares the minimal quota + // policy with each other. + EXPECT_TRUE(AreSameOrigin(frame_c, frame_d)); + EXPECT_TRUE(AreSameOrigin(frame_d, frame_c)); + + EXPECT_FALSE(AreSameOrigin(root, frame_c)); + EXPECT_FALSE(AreSameOrigin(root, frame_d)); + EXPECT_FALSE(AreSameOrigin(frame_a, frame_c)); + EXPECT_FALSE(AreSameOrigin(frame_a, frame_d)); + EXPECT_FALSE(AreSameOrigin(frame_b, frame_c)); + EXPECT_FALSE(AreSameOrigin(frame_b, frame_d)); +} + +TEST_F(AreSameOriginTest, MultipleLevelFrames) { + // The structure of the document: + // root -> frame_a (same-origin) -> frame_c (cross-origin) + // -> frame_d (cross-origin) -> frame_b (same-origin) + String root_url = kMainUrl; + String frame_a_url = kMainUrl + "frame-a.html"; + String frame_b_url = kMainUrl + "frame-b.html"; + String frame_c_url = kCrossSubdomainUrl + "frame-c.html"; + String frame_d_url = kCrossSubdomainUrl + "frame-d.html"; + + NavigateTo(root_url, RenderWithIframes({"frame-a.html", frame_d_url}), + {{frame_a_url, RenderWithIframes({frame_c_url})}, + {frame_d_url, RenderWithIframes({frame_b_url})}, + {frame_c_url, ""}, + {frame_b_url, ""}}); + + auto* root = GetMainFrame(); + auto* frame_a = root->Tree().FirstChild(); + auto* frame_d = frame_a->Tree().NextSibling(); + auto* frame_c = frame_a->Tree().FirstChild(); + auto* frame_b = frame_d->Tree().FirstChild(); + + // Root, Frame A and Frame B are same-origin. + EXPECT_TRUE(AreSameOrigin(root, frame_a)); + EXPECT_TRUE(AreSameOrigin(frame_a, root)); + EXPECT_TRUE(AreSameOrigin(root, frame_b)); + EXPECT_TRUE(AreSameOrigin(frame_b, root)); + EXPECT_TRUE(AreSameOrigin(frame_a, frame_b)); + EXPECT_TRUE(AreSameOrigin(frame_b, frame_a)); + + // Frame C and D are different origin with root, and shares the minimal quota + // policy with each other. + EXPECT_TRUE(AreSameOrigin(frame_c, frame_d)); + EXPECT_TRUE(AreSameOrigin(frame_d, frame_c)); + + EXPECT_FALSE(AreSameOrigin(root, frame_c)); + EXPECT_FALSE(AreSameOrigin(root, frame_d)); + EXPECT_FALSE(AreSameOrigin(frame_a, frame_c)); + EXPECT_FALSE(AreSameOrigin(frame_a, frame_d)); + EXPECT_FALSE(AreSameOrigin(frame_b, frame_c)); + EXPECT_FALSE(AreSameOrigin(frame_b, frame_d)); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc index 8f97cab0..1576debd 100644 --- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc +++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
@@ -68,6 +68,7 @@ void AnimationFrameTimingMonitor::BeginMainFrame( LocalDOMWindow& local_root_window, viz::BeginFrameId frame_id) { + current_begin_frame_id_ = frame_id; DOMWindowPerformance::performance(local_root_window) ->OnBeginMainFrame(frame_id); @@ -78,6 +79,7 @@ } current_frame_timing_info_->SetRenderStartTime(now); + current_frame_timing_info_->SetBeginFrameId(frame_id); state_ = State::kRenderingFrame; ApplyTaskDuration(now - current_task_start_); @@ -272,6 +274,7 @@ timing_info->SetScripts(scripts); timing_info->SetTotalBlockingDuration(task_duration - kLongAnimationFrameDuration); + timing_info->SetBeginFrameId(current_begin_frame_id_); if (did_pause) { timing_info->SetDidPause(); } @@ -334,10 +337,16 @@ const viz::FrameTimingDetails& presentation_details) { auto track_id = perfetto::Track::ThreadScoped(this); auto flow_id = perfetto::Flow::ProcessScoped(trace_id); - TRACE_EVENT_INSTANT("devtools.timeline", "AnimationFrame::Presentation", - track_id, - presentation_details.presentation_feedback.timestamp, - flow_id, "id", String::Format("%016" PRIx64, trace_id)); + TRACE_EVENT_INSTANT( + "devtools.timeline", "AnimationFrame::Presentation", track_id, + presentation_details.presentation_feedback.timestamp, flow_id, "id", + String::Format("%016" PRIx64, trace_id), [&](perfetto::EventContext ctx) { + auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); + auto* begin_frame_id = event->set_begin_frame_id(); + begin_frame_id->set_source_id(presentation_details.frame_id.source_id); + begin_frame_id->set_sequence_number( + presentation_details.frame_id.sequence_number); + }); } void AnimationFrameTimingMonitor::RecordLongAnimationFrameTrace( @@ -366,6 +375,11 @@ info.TotalBlockingDuration().InMilliseconds()); data->set_duration_ms(info.Duration().InMilliseconds()); data->set_num_scripts(info.Scripts().size()); + + auto* begin_frame_id = data->set_begin_frame_id(); + begin_frame_id->set_source_id(info.BeginFrameId().source_id); + begin_frame_id->set_sequence_number( + info.BeginFrameId().sequence_number); }); for (ScriptTimingInfo* script : info.Scripts()) { if (script->StartTime() < script->ExecutionStartTime()) {
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h index 415a7a77..fc6db83b 100644 --- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h +++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
@@ -107,6 +107,7 @@ private: Member<AnimationFrameTimingInfo> current_frame_timing_info_; HeapVector<Member<ScriptTimingInfo>> current_scripts_; + viz::BeginFrameId current_begin_frame_id_; struct PendingScriptInfo { ScriptTimingInfo::InvokerType invoker_type; base::TimeTicks start_time;
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni index f559957..a9f728d9 100644 --- a/third_party/blink/renderer/core/html/build.gni +++ b/third_party/blink/renderer/core/html/build.gni
@@ -358,6 +358,7 @@ "html_param_element.h", "html_permission_element.cc", "html_permission_element.h", + "html_permission_element_strings_map.h", "html_picture_element.cc", "html_picture_element.h", "html_plugin_element.cc", @@ -545,6 +546,7 @@ "trust_token_attribute_parsing.h", "window_name_collection.cc", "window_name_collection.h", + "$root_gen_dir/third_party/blink/renderer/core/html/html_permission_element_strings_map.cc", ] # Optimizing the HTML parser for speed yields significant gains in performance
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 57df26e..1cae8a4 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -1437,6 +1437,13 @@ return context_provider_wrapper->Utils()->Accelerated2DCanvasFeatureEnabled(); } +bool HTMLCanvasElement::CanStartSelection() const { + if (RuntimeEnabledFeatures::AvoidSelectionChangeOnCanvasClickEnabled()) { + return false; + } + return HTMLElement::CanStartSelection(); +} + bool HTMLCanvasElement::ShouldDisableAccelerationBecauseOfReadback() const { return DisabledAccelerationCounterSupplement::From(GetDocument()) .ShouldDisableAcceleration();
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h index f89fd5e..3b9d256 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -325,6 +325,8 @@ bool IsPlaceholder() const override { return IsOffscreenCanvasRegistered(); } + bool CanStartSelection() const override; + bool ShouldDisableAccelerationBecauseOfReadback() const; protected:
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element_test.cc b/third_party/blink/renderer/core/html/forms/html_form_element_test.cc index 0a95cafa..57a6fe7b4 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element_test.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element_test.cc
@@ -218,6 +218,56 @@ EXPECT_THAT(form1->ListedElements(), ElementsAre(GetListedElement("input1"))); } +// Regression test for crbug.com/347059988#comment47: Inserting a subtree that +// includes a shadow DOM *directly* into a form invalidates the form's cache of +// ListedElements(). +TEST_F(HTMLFormElementTest, + ListedElementsAfterIncludeShadowTreesWithDynamicChange) { + HTMLBodyElement* body = GetDocument().FirstBodyElement(); + body->setHTMLUnsafe(R"HTML( + <form id=form1> + <input id=input1> + <!-- + Dynamically we'll insert: + <div id=div1> + <template shadowrootmode=open> + <input id=input2> + </template> + </div> + --> + </form> + )HTML"); + + HTMLFormElement* form1 = GetFormElement("form1"); + ListedElement* input1 = GetListedElement("input1"); + ASSERT_NE(form1, nullptr); + ASSERT_NE(input1, nullptr); + + HTMLDivElement* div1 = MakeGarbageCollected<HTMLDivElement>(GetDocument()); + ShadowRoot& div1root = + div1->AttachShadowRootForTesting(ShadowRootMode::kOpen); + + HTMLInputElement* input2 = + MakeGarbageCollected<HTMLInputElement>(GetDocument()); + div1root.AppendChild(input2); + + EXPECT_THAT(form1->ListedElements(/*include_shadow_trees=*/true), + ElementsAre(input1)); + EXPECT_THAT(form1->ListedElements(), ElementsAre(input1)); + + form1->AppendChild(div1); + + EXPECT_THAT(form1->ListedElements(/*include_shadow_trees=*/true), + ElementsAre(input1, input2)); + EXPECT_THAT(form1->ListedElements(), ElementsAre(input1)); + + form1->RemoveChild(div1); + + EXPECT_THAT(form1->ListedElements(/*include_shadow_trees=*/true), + ElementsAre(input1)); + EXPECT_THAT(form1->ListedElements(), ElementsAre(input1)); +} + // Regression test for crbug.com/349121116: If there are no "form" attributes, // the traversal in CollectListedElements() must only collect descendants of the // form element.
diff --git a/third_party/blink/renderer/core/html/forms/listed_element.cc b/third_party/blink/renderer/core/html/forms/listed_element.cc index 9993e44..2679324 100644 --- a/third_party/blink/renderer/core/html/forms/listed_element.cc +++ b/third_party/blink/renderer/core/html/forms/listed_element.cc
@@ -59,10 +59,8 @@ void InvalidateShadowIncludingAncestorForms(ContainerNode& insertion_point) { // Let any forms in the shadow including ancestors know that this - // ListedElement has changed. We also cache listed elements inside - // (descendant) nested forms and therefore need to invalidate the caches also - // inside the same `TreeScope`. - ContainerNode* starting_node = insertion_point.ParentOrShadowHostNode(); + // ListedElement has changed. + ContainerNode* starting_node = &insertion_point; for (ContainerNode* parent = starting_node; parent; parent = parent->ParentOrShadowHostNode()) { if (HTMLFormElement* form = DynamicTo<HTMLFormElement>(parent)) {
diff --git a/third_party/blink/renderer/core/html/html_permission_element.cc b/third_party/blink/renderer/core/html/html_permission_element.cc index 96fad472..1a0fd37 100644 --- a/third_party/blink/renderer/core/html/html_permission_element.cc +++ b/third_party/blink/renderer/core/html/html_permission_element.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/core/html/html_permission_element.h" +#include <stdint.h> + #include <optional> #include "base/functional/bind.h" @@ -150,8 +152,8 @@ return Vector<PermissionDescriptorPtr>(); } -int GetTranslatedMessageID(int message_id, - const AtomicString& language_string) { +uint16_t GetTranslatedMessageID(uint16_t message_id, + const AtomicString& language_string) { DCHECK(language_string.IsLowerASCII()); if (language_string.empty()) { return message_id; @@ -180,9 +182,9 @@ // Helper to get permission text resource ID for the given map which has only // one element. -int GetUntranslatedMessageIDSinglePermission(PermissionName name, - bool granted, - bool is_precise_location) { +uint16_t GetUntranslatedMessageIDSinglePermission(PermissionName name, + bool granted, + bool is_precise_location) { if (name == PermissionName::VIDEO_CAPTURE) { return granted ? IDS_PERMISSION_REQUEST_CAMERA_ALLOWED : IDS_PERMISSION_REQUEST_CAMERA; @@ -209,7 +211,7 @@ // Helper to get permission text resource ID for the given map which has // multiple elements. Currently we only support "camera microphone" grouped // permissions. -int GetUntranslatedMessageIDMultiplePermissions(bool granted) { +uint16_t GetUntranslatedMessageIDMultiplePermissions(bool granted) { return granted ? IDS_PERMISSION_REQUEST_CAMERA_MICROPHONE_ALLOWED : IDS_PERMISSION_REQUEST_CAMERA_MICROPHONE; } @@ -1329,12 +1331,12 @@ AtomicString language_string = ComputeInheritedLanguage().LowerASCII(); - int untranslated_message_id = + uint16_t untranslated_message_id = permission_count == 1 ? GetUntranslatedMessageIDSinglePermission( permission_name, permission_granted, is_precise_location_) : GetUntranslatedMessageIDMultiplePermissions(permission_granted); - int translated_message_id = + uint16_t translated_message_id = GetTranslatedMessageID(untranslated_message_id, language_string); CHECK(translated_message_id); permission_text_span_->setInnerText(
diff --git a/third_party/blink/renderer/core/html/html_permission_element_strings_map.h b/third_party/blink/renderer/core/html/html_permission_element_strings_map.h new file mode 100644 index 0000000..2c3ec54 --- /dev/null +++ b/third_party/blink/renderer/core/html/html_permission_element_strings_map.h
@@ -0,0 +1,21 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ELEMENT_STRINGS_MAP_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ELEMENT_STRINGS_MAP_H_ + +#include <stdint.h> + +#include <optional> +#include <string_view> + +namespace blink { + +std::optional<uint16_t> GetPermissionElementMessageId( + std::string_view language_code, + uint16_t base_message); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ELEMENT_STRINGS_MAP_H_
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager.cc b/third_party/blink/renderer/core/input/pointer_event_manager.cc index 9c4b8ca..a96e565 100644 --- a/third_party/blink/renderer/core/input/pointer_event_manager.cc +++ b/third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -11,7 +11,6 @@ #include "base/auto_reset.h" #include "base/metrics/field_trial_params.h" -#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-blink.h" #include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h" #include "third_party/blink/renderer/core/dom/events/event_path.h" @@ -395,12 +394,10 @@ bool PointerEventManager::ShouldAdjustStylusPointerEvent( const WebPointerEvent& pointer_event) const { - return base::FeatureList::IsEnabled( - blink::features::kStylusPointerAdjustment) && - (pointer_event.pointer_type == - WebPointerProperties::PointerType::kPen || - pointer_event.pointer_type == - WebPointerProperties::PointerType::kEraser); + return pointer_event.pointer_type == + WebPointerProperties::PointerType::kPen || + pointer_event.pointer_type == + WebPointerProperties::PointerType::kEraser; } void PointerEventManager::AdjustPointerEvent(WebPointerEvent& pointer_event) {
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager_test.cc b/third_party/blink/renderer/core/input/pointer_event_manager_test.cc index ce5eb72..d1e6a36 100644 --- a/third_party/blink/renderer/core/input/pointer_event_manager_test.cc +++ b/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
@@ -619,10 +619,7 @@ class PanActionPointerEventTest : public PointerEventManagerTest { public: - PanActionPointerEventTest() { - feature_list_.InitWithFeatures({blink::features::kStylusPointerAdjustment}, - {}); - } + PanActionPointerEventTest() = default; frame_test_helpers::TestWebFrameWidget* CreateWebFrameWidget( base::PassKey<WebLocalFrame> pass_key, @@ -671,9 +668,6 @@ event.pointer_type = pointer_type; return event; } - - private: - base::test::ScopedFeatureList feature_list_; }; TEST_F(PanActionPointerEventTest, PanActionStylusWritable) {
diff --git a/third_party/blink/renderer/core/layout/block_break_token.cc b/third_party/blink/renderer/core/layout/block_break_token.cc index 020fab9..9b38bbc6 100644 --- a/third_party/blink/renderer/core/layout/block_break_token.cc +++ b/third_party/blink/renderer/core/layout/block_break_token.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/block_break_token.h" #include "third_party/blink/renderer/core/layout/box_fragment_builder.h" @@ -75,8 +70,10 @@ DCHECK(builder->HasBreakTokenData()); data_ = builder->break_token_data_; builder->break_token_data_ = nullptr; - for (wtf_size_t i = 0; i < builder->child_break_tokens_.size(); ++i) - child_break_tokens_[i] = builder->child_break_tokens_[i]; + for (wtf_size_t i = 0; i < builder->child_break_tokens_.size(); ++i) { + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + UNSAFE_TODO(child_break_tokens_[i]) = builder->child_break_tokens_[i]; + } } BlockBreakToken::BlockBreakToken(PassKey key, LayoutInputNode node) @@ -170,7 +167,8 @@ // Looking up |ChildBreakTokensInternal()| in Trace() here is safe because // |const_num_children_| is const. for (wtf_size_t i = 0; i < const_num_children_; ++i) { - visitor->Trace(child_break_tokens_[i]); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + visitor->Trace(UNSAFE_TODO(child_break_tokens_[i])); } BreakToken::TraceAfterDispatch(visitor); }
diff --git a/third_party/blink/renderer/core/layout/block_break_token.h b/third_party/blink/renderer/core/layout/block_break_token.h index 4a84067..0b32b60 100644 --- a/third_party/blink/renderer/core/layout/block_break_token.h +++ b/third_party/blink/renderer/core/layout/block_break_token.h
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_BLOCK_BREAK_TOKEN_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_BLOCK_BREAK_TOKEN_H_ @@ -259,7 +254,8 @@ private: const base::span<const Member<const BreakToken>> ChildBreakTokensInternal() const { - return base::span(child_break_tokens_, const_num_children_); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + return UNSAFE_TODO(base::span(child_break_tokens_, const_num_children_)); } Member<BlockBreakTokenData> data_;
diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni index 8dd8bb25..ea8f3507 100644 --- a/third_party/blink/renderer/core/layout/build.gni +++ b/third_party/blink/renderer/core/layout/build.gni
@@ -111,6 +111,7 @@ "flex/flex_break_token_data.h", "flex/flex_child_iterator.cc", "flex/flex_child_iterator.h", + "flex/flex_item.h", "flex/flex_item_iterator.cc", "flex/flex_item_iterator.h", "flex/flex_layout_algorithm.cc", @@ -119,6 +120,8 @@ "flex/flexible_box_algorithm.h", "flex/layout_flexible_box.cc", "flex/layout_flexible_box.h", + "flex/line_flexer.h", + "flex/line_flexer.cc", "flex/ng_flex_line.h", "floats_utils.cc", "floats_utils.h",
diff --git a/third_party/blink/renderer/core/layout/flex/flex_item.h b/third_party/blink/renderer/core/layout/flex/flex_item.h new file mode 100644 index 0000000..5ba0fdf4 --- /dev/null +++ b/third_party/blink/renderer/core/layout/flex/flex_item.h
@@ -0,0 +1,140 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_FLEX_ITEM_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_FLEX_ITEM_H_ + +#include "third_party/blink/renderer/core/layout/baseline_utils.h" +#include "third_party/blink/renderer/core/layout/block_node.h" +#include "third_party/blink/renderer/core/layout/layout_result.h" +#include "third_party/blink/renderer/core/layout/min_max_sizes.h" +#include "third_party/blink/renderer/platform/geometry/layout_unit.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +struct FlexItem { + DISALLOW_NEW(); + + public: + FlexItem(BlockNode block_node, + wtf_size_t item_index, + float flex_grow, + float flex_shrink, + LayoutUnit base_content_size, + MinMaxSizes main_axis_min_max_sizes, + LayoutUnit main_axis_border_padding, + PhysicalBoxStrut initial_margins, + BoxStrut initial_scrollbars, + uint8_t main_axis_auto_margin_count, + ItemPosition alignment, + WritingMode baseline_writing_mode, + BaselineGroup baseline_group, + bool is_initial_block_size_indefinite, + bool is_used_flex_basis_indefinite, + bool depends_on_min_max_sizes, + bool is_horizontal_flow, + std::optional<LayoutUnit> max_content_contribution) + : block_node(block_node), + item_index(item_index), + flex_grow(flex_grow), + flex_shrink(flex_shrink), + base_content_size(base_content_size), + hypothetical_content_size( + main_axis_min_max_sizes.ClampSizeToMinAndMax(base_content_size)), + main_axis_min_max_sizes(main_axis_min_max_sizes), + main_axis_border_padding(main_axis_border_padding), + initial_margins(initial_margins), + initial_scrollbars(initial_scrollbars), + main_axis_auto_margin_count(main_axis_auto_margin_count), + alignment(alignment), + baseline_writing_direction( + {baseline_writing_mode, TextDirection::kLtr}), + baseline_group(baseline_group), + is_initial_block_size_indefinite(is_initial_block_size_indefinite), + is_used_flex_basis_indefinite(is_used_flex_basis_indefinite), + depends_on_min_max_sizes(depends_on_min_max_sizes), + is_horizontal_flow(is_horizontal_flow), + frozen(false), + max_content_contribution(max_content_contribution) {} + + LayoutUnit HypotheticalMainAxisMarginBoxSize() const { + return hypothetical_content_size + main_axis_border_padding + + MainAxisMarginExtent(); + } + + LayoutUnit FlexBaseMarginBoxSize() const { + return base_content_size + main_axis_border_padding + + MainAxisMarginExtent(); + } + + LayoutUnit FlexedBorderBoxSize() const { + return flexed_content_size + main_axis_border_padding; + } + + LayoutUnit FlexedMarginBoxSize() const { + return flexed_content_size + main_axis_border_padding + + MainAxisMarginExtent(); + } + + LayoutUnit MainAxisMarginExtent() const { + return is_horizontal_flow ? initial_margins.HorizontalSum() + : initial_margins.VerticalSum(); + } + LayoutUnit CrossAxisMarginExtent() const { + return is_horizontal_flow ? initial_margins.VerticalSum() + : initial_margins.HorizontalSum(); + } + + void Trace(Visitor* visitor) const { + visitor->Trace(block_node); + visitor->Trace(layout_result); + } + + const BlockNode block_node; + const wtf_size_t item_index; + + const float flex_grow; + const float flex_shrink; + + // `base_content_size` include the scrollbar, but not border/padding. + const LayoutUnit base_content_size; + const LayoutUnit hypothetical_content_size; + + // `main_axis_min_max_sizes` is the resolved min/max size properties, and also + // does not include border/padding. + const MinMaxSizes main_axis_min_max_sizes; + const LayoutUnit main_axis_border_padding; + + // `initial_margins` are the margins with auto-margins applied. + // `initial_scrollbars` is the scrollbar state at the beginning of running + // flex layout, so it can be compared to the final state. + const PhysicalBoxStrut initial_margins; + const BoxStrut initial_scrollbars; + + const uint8_t main_axis_auto_margin_count; + + const ItemPosition alignment; + const WritingDirectionMode baseline_writing_direction; + const BaselineGroup baseline_group; + + const bool is_initial_block_size_indefinite; + const bool is_used_flex_basis_indefinite; + const bool depends_on_min_max_sizes; + const bool is_horizontal_flow; + bool frozen; + + LayoutUnit flexed_content_size; + + // The above fields are used by the flex algorithm. The following fields, by + // contrast, are just convenient storage. + Member<const LayoutResult> layout_result; + std::optional<LayoutUnit> max_content_contribution; +}; + +} // namespace blink + +WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::FlexItem) + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_FLEX_ITEM_H_
diff --git a/third_party/blink/renderer/core/layout/flex/flex_item_iterator.cc b/third_party/blink/renderer/core/layout/flex/flex_item_iterator.cc index 5d682523..379479be 100644 --- a/third_party/blink/renderer/core/layout/flex/flex_item_iterator.cc +++ b/third_party/blink/renderer/core/layout/flex/flex_item_iterator.cc
@@ -117,8 +117,9 @@ NGFlexItem* flex_item = const_cast<NGFlexItem*>(&flex_line.line_items[flex_item_idx_++]); if (!item_break_token || - flex_item->ng_input_node == item_break_token->InputNode()) + flex_item->block_node == item_break_token->InputNode()) { return flex_item; + } } } // If the current column had a break token, but later columns do not, that
diff --git a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc index 7c03f11..08e1342 100644 --- a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc
@@ -20,6 +20,7 @@ #include "third_party/blink/renderer/core/layout/flex/flex_item_iterator.h" #include "third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h" #include "third_party/blink/renderer/core/layout/flex/layout_flexible_box.h" +#include "third_party/blink/renderer/core/layout/flex/line_flexer.h" #include "third_party/blink/renderer/core/layout/flex/ng_flex_line.h" #include "third_party/blink/renderer/core/layout/geometry/box_strut.h" #include "third_party/blink/renderer/core/layout/geometry/logical_size.h" @@ -213,12 +214,11 @@ LayoutUnit FlexLayoutAlgorithm::BaselineAscent( const FlexItem& item, - const PhysicalBoxFragment& fragment, - ItemPosition alignment) const { - LogicalBoxFragment baseline_fragment(item.baseline_writing_direction_, + const PhysicalBoxFragment& fragment) const { + LogicalBoxFragment baseline_fragment(item.baseline_writing_direction, fragment); - const bool is_last_baseline = alignment == ItemPosition::kLastBaseline; + const bool is_last_baseline = item.alignment == ItemPosition::kLastBaseline; const auto font_baseline = Style().GetFontBaseline(); LayoutUnit baseline = is_last_baseline @@ -230,9 +230,9 @@ const PhysicalToFlex margins( GetConstraintSpace().GetWritingDirection(), is_column_, - item.physical_margins_.top, item.physical_margins_.right, - item.physical_margins_.bottom, item.physical_margins_.left); - return item.baseline_group_ == BaselineGroup::kMajor + item.initial_margins.top, item.initial_margins.right, + item.initial_margins.bottom, item.initial_margins.left); + return item.baseline_group == BaselineGroup::kMajor ? margins.CrossStart() + baseline : margins.CrossEnd() + baseline; } @@ -398,7 +398,7 @@ HeapVector<Member<blink::Node>> reading_flow_nodes; // Add flex item if it is a DOM node auto AddItemIfNeeded = [&](const NGFlexItem& item) { - if (blink::Node* node = item.ng_input_node.GetDOMNode()) { + if (blink::Node* node = item.block_node.GetDOMNode()) { reading_flow_nodes.push_back(node); } }; @@ -653,7 +653,7 @@ border_padding_in_child_writing_mode.ConvertToPhysical( child_style.GetWritingDirection())); - const unsigned main_axis_auto_margin_count = + const uint8_t main_axis_auto_margin_count = is_horizontal_flow_ ? child_style.MarginLeft().IsAuto() + child_style.MarginRight().IsAuto() : child_style.MarginTop().IsAuto() + @@ -720,7 +720,7 @@ !Node().GetLayoutBox()->NeedsLayout()) { disable_side_effects.emplace(); } - layout_result = child.Layout(child_space, /* break_token */ nullptr); + layout_result = child.Layout(child_space); DCHECK(layout_result); } intrinsic_size = layout_result->IntrinsicBlockSize(); @@ -833,7 +833,7 @@ // Blink's FlexibleBoxAlgorithm expects it to be content + scrollbar widths, // but no padding or border. DCHECK_GE(flex_base_border_box, main_axis_border_padding); - const LayoutUnit flex_base_content_size = + const LayoutUnit base_content_size = flex_base_border_box - main_axis_border_padding; std::optional<Length> auto_min_length; @@ -904,7 +904,7 @@ DCHECK_GE(min_max_sizes_in_main_axis_direction.min_size, LayoutUnit()); DCHECK_GE(min_max_sizes_in_main_axis_direction.max_size, LayoutUnit()); - const BoxStrut scrollbars = ComputeScrollbarsForNonAnonymous(child); + const BoxStrut initial_scrollbars = ComputeScrollbarsForNonAnonymous(child); auto AspectRatioProvidesBlockMainSize = [&]() -> bool { if (is_main_axis_inline_axis) { @@ -928,33 +928,34 @@ ChildAvailableSize().block_size == kIndefiniteSize && is_used_flex_basis_indefinite && !AspectRatioProvidesBlockMainSize(); + const float flex_grow = child_style.ResolvedFlexGrow(Style()); + const float flex_shrink = child_style.ResolvedFlexShrink(Style()); + const auto container_writing_direction = GetConstraintSpace().GetWritingDirection(); - bool is_last_baseline = - FlexibleBoxAlgorithm::AlignmentForChild(Style(), child_style) == - ItemPosition::kLastBaseline; + const ItemPosition alignment = + FlexibleBoxAlgorithm::AlignmentForChild(Style(), child_style); const auto baseline_writing_mode = DetermineBaselineWritingMode( container_writing_direction, child_writing_mode, /* is_parallel_context */ !is_column_); const auto baseline_group = DetermineBaselineGroup( container_writing_direction, baseline_writing_mode, - /* is_parallel_context */ !is_column_, is_last_baseline, + /* is_parallel_context */ !is_column_, + /* is_last_baseline */ alignment == ItemPosition::kLastBaseline, /* is_flipped */ is_wrap_reverse_); - algorithm_ - .emplace_back(child.Style(), item_index++, main_axis_auto_margin_count, - flex_base_content_size, - min_max_sizes_in_main_axis_direction, - main_axis_border_padding, physical_child_margins, - scrollbars, baseline_writing_mode, baseline_group, - is_initial_block_size_indefinite, - is_used_flex_basis_indefinite, depends_on_min_max_sizes) - .ng_input_node_ = child; + + algorithm_.all_items_.emplace_back( + child, item_index++, flex_grow, flex_shrink, base_content_size, + min_max_sizes_in_main_axis_direction, main_axis_border_padding, + physical_child_margins, initial_scrollbars, main_axis_auto_margin_count, + alignment, baseline_writing_mode, baseline_group, + is_initial_block_size_indefinite, is_used_flex_basis_indefinite, + depends_on_min_max_sizes, is_horizontal_flow_, + max_content_contribution); // Save the layout result so that we can maybe reuse it later. if (layout_result && !is_main_axis_inline_axis) { - algorithm_.all_items_.back().layout_result_ = layout_result; + algorithm_.all_items_.back().layout_result = layout_result; } - algorithm_.all_items_.back().max_content_contribution_ = - max_content_contribution; } } @@ -1135,11 +1136,11 @@ while ((line = algorithm_.ComputeNextFlexLine())) { const LayoutUnit main_axis_inner_size = MainAxisContentExtent(line->sum_hypothetical_main_size_); - line->SetContainerMainInnerSize(main_axis_inner_size); - line->FreezeInflexibleItems(); - while (!line->ResolveFlexibleLengths()) { - continue; - } + + // Flex the items. + LineFlexer(base::span(line->line_items_), line->sum_hypothetical_main_size_, + line->sum_flex_base_size_, main_axis_inner_size) + .Run(); if (layout_info_for_devtools_) [[unlikely]] { layout_info_for_devtools_->lines.push_back(DevtoolsFlexInfo::Line()); @@ -1155,26 +1156,28 @@ LayoutUnit max_minor_ascent = LayoutUnit::Min(); LayoutUnit max_major_descent = LayoutUnit::Min(); LayoutUnit max_minor_descent = LayoutUnit::Min(); + unsigned main_axis_auto_margin_count = 0; for (wtf_size_t i = 0; i < line->line_items_.size(); ++i) { FlexItem& flex_item = line->line_items_[i]; NGFlexItem& flex_item_output = flex_line_outputs->back().line_items[i]; - flex_item_output.item_index = flex_item.item_index_; - flex_item_output.ng_input_node = flex_item.ng_input_node_; + flex_item_output.item_index = flex_item.item_index; + flex_item_output.block_node = flex_item.block_node; flex_item_output.main_axis_final_size = flex_item.FlexedBorderBoxSize(); flex_item_output.is_initial_block_size_indefinite = - flex_item.is_initial_block_size_indefinite_; + flex_item.is_initial_block_size_indefinite; flex_item_output.is_used_flex_basis_indefinite = - flex_item.is_used_flex_basis_indefinite_; + flex_item.is_used_flex_basis_indefinite; main_axis_free_space -= flex_item.FlexedMarginBoxSize(); + main_axis_auto_margin_count += flex_item.main_axis_auto_margin_count; const LayoutUnit cross_axis_size = ([&]() { const ConstraintSpace space = BuildSpaceForLayout( - flex_item.ng_input_node_, flex_item.FlexedBorderBoxSize(), - flex_item.is_initial_block_size_indefinite_, - flex_item.max_content_contribution_); + flex_item.block_node, flex_item.FlexedBorderBoxSize(), + flex_item.is_initial_block_size_indefinite, + flex_item.max_content_contribution); // We need to get the item's cross-axis size given its new main size. // @@ -1186,32 +1189,31 @@ // Even when we only need inline-size, we have to lay out the item if: // * This is the item's last chance to layout (i.e. doesn't stretch). // * The item has not yet been laid out. - if (DoesItemStretch(flex_item.ng_input_node_) && - flex_item.layout_result_) { - const auto& item_style = flex_item.ng_input_node_.Style(); + if (DoesItemStretch(flex_item.block_node) && flex_item.layout_result) { + const auto& item_style = flex_item.block_node.Style(); DCHECK_NE(is_horizontal_flow_, item_style.IsHorizontalWritingMode()); const BoxStrut border_padding = - ComputeBorders(space, flex_item.ng_input_node_) + + ComputeBorders(space, flex_item.block_node) + ComputePadding(space, item_style); - if (flex_item.ng_input_node_.IsReplaced()) { - return ComputeReplacedSize(flex_item.ng_input_node_, space, + if (flex_item.block_node.IsReplaced()) { + return ComputeReplacedSize(flex_item.block_node, space, border_padding) .inline_size; } - return ComputeInlineSizeForFragment(space, flex_item.ng_input_node_, + return ComputeInlineSizeForFragment(space, flex_item.block_node, border_padding); } if (is_computing_multiline_column_intrinsic_size) { - return *flex_item.max_content_contribution_; + return *flex_item.max_content_contribution; } DCHECK((space.CacheSlot() == LayoutResultCacheSlot::kLayout) || - !flex_item.layout_result_); - flex_item.layout_result_ = flex_item.ng_input_node_.Layout(space); - DCHECK_EQ(flex_item.layout_result_->Status(), LayoutResult::kSuccess); + !flex_item.layout_result); + flex_item.layout_result = flex_item.block_node.Layout(space); + DCHECK_EQ(flex_item.layout_result->Status(), LayoutResult::kSuccess); const PhysicalSize size = - flex_item.layout_result_->GetPhysicalFragment().Size(); + flex_item.layout_result->GetPhysicalFragment().Size(); return is_horizontal_flow_ ? size.height : size.width; })(); @@ -1226,17 +1228,14 @@ // TODO(crbug.com/1272533): We may not have a layout-result during // min/max calculations. This is incorrect, and we should produce a // layout-result when baseline aligned. - const auto alignment = flex_item.Alignment(); - if (flex_item.layout_result_ && - (alignment == ItemPosition::kBaseline || - alignment == ItemPosition::kLastBaseline)) { - const LayoutUnit ascent = - BaselineAscent(flex_item, - To<PhysicalBoxFragment>( - flex_item.layout_result_->GetPhysicalFragment()), - alignment); + if (flex_item.layout_result && + (flex_item.alignment == ItemPosition::kBaseline || + flex_item.alignment == ItemPosition::kLastBaseline)) { + const LayoutUnit ascent = BaselineAscent( + flex_item, To<PhysicalBoxFragment>( + flex_item.layout_result->GetPhysicalFragment())); const LayoutUnit descent = cross_axis_margin_size - ascent; - if (flex_item.baseline_group_ == BaselineGroup::kMajor) { + if (flex_item.baseline_group == BaselineGroup::kMajor) { max_major_ascent = std::max(max_major_ascent, ascent); max_major_descent = std::max(max_major_descent, descent); cross_axis_margin_size = max_major_ascent + max_major_descent; @@ -1252,7 +1251,7 @@ flex_line_outputs->back().sum_hypothetical_main_size = line->sum_hypothetical_main_size_; flex_line_outputs->back().main_axis_auto_margin_count = - line->main_axis_auto_margin_count_; + main_axis_auto_margin_count; flex_line_outputs->back().line_cross_size = line_cross_size; flex_line_outputs->back().major_baseline = max_major_ascent; flex_line_outputs->back().minor_baseline = max_minor_ascent; @@ -1485,17 +1484,15 @@ const FlexItem& item = algorithm_.FlexItemAtIndex(flex_item.item_index); const LayoutResult* layout_result = nullptr; - if (DoesItemStretch(flex_item.ng_input_node)) { + if (DoesItemStretch(flex_item.block_node)) { ConstraintSpace child_space = BuildSpaceForLayout( - flex_item.ng_input_node, flex_item.main_axis_final_size, + flex_item.block_node, flex_item.main_axis_final_size, flex_item.is_initial_block_size_indefinite, /* override_inline_size */ std::nullopt, line_output.line_cross_size); - layout_result = - flex_item.ng_input_node.Layout(child_space, - /* break_token */ nullptr); + layout_result = flex_item.block_node.Layout(child_space); } else { - layout_result = item.layout_result_; + layout_result = item.layout_result; } flex_item.has_descendant_that_depends_on_percentage_block_size = @@ -1545,7 +1542,7 @@ const LayoutUnit cross_axis_size = is_column_ ? fragment.InlineSize() : fragment.BlockSize(); - PhysicalBoxStrut physical_margins = item.physical_margins_; + PhysicalBoxStrut physical_margins = item.initial_margins; const PhysicalToFlex<LayoutUnit&> margin( writing_direction, is_column_, physical_margins.top, physical_margins.right, physical_margins.bottom, @@ -1595,21 +1592,19 @@ space = space.ClampNegativeToZero(); } - const ItemPosition alignment = item.Alignment(); LayoutUnit baseline_offset; - if (alignment == ItemPosition::kBaseline || - alignment == ItemPosition::kLastBaseline) { - const bool is_major = item.baseline_group_ == BaselineGroup::kMajor; - const LayoutUnit ascent = - BaselineAscent(item, physical_fragment, alignment); + if (item.alignment == ItemPosition::kBaseline || + item.alignment == ItemPosition::kLastBaseline) { + const bool is_major = item.baseline_group == BaselineGroup::kMajor; + const LayoutUnit ascent = BaselineAscent(item, physical_fragment); const LayoutUnit max_ascent = is_major ? line_output.major_baseline : line_output.minor_baseline; const LayoutUnit baseline_delta = max_ascent - ascent; baseline_offset = is_major ? baseline_delta : space - baseline_delta; } return line_cross_axis_offset + margin.CrossStart() + - FlexItem::AlignmentOffset(space, alignment, baseline_offset, - is_wrap_reverse_); + FlexibleBoxAlgorithm::AlignmentOffset( + space, item.alignment, baseline_offset, is_wrap_reverse_); })(); main_axis_offset += margin.MainStart(); @@ -1853,8 +1848,8 @@ if (!is_column_) container_builder_.SetLineCount(flex_line_idx); if (IsEarlyBreakTarget(*early_break_, container_builder_, - flex_item->ng_input_node)) { - container_builder_.AddBreakBeforeChild(flex_item->ng_input_node, + flex_item->block_node)) { + container_builder_.AddBreakBeforeChild(flex_item->block_node, kBreakAppealPerfect, /* is_forced_break */ false); if (early_break_->Type() == EarlyBreak::kLine) { @@ -1876,7 +1871,7 @@ continue; } else { early_break_in_child = - EnterEarlyBreakInChild(flex_item->ng_input_node, *early_break_); + EnterEarlyBreakInChild(flex_item->block_node, *early_break_); } } @@ -1901,7 +1896,7 @@ } std::optional<LayoutUnit> line_cross_size_for_stretch = - DoesItemStretch(flex_item->ng_input_node) + DoesItemStretch(flex_item->block_node) ? std::optional<LayoutUnit>(line_output.line_cross_size) : std::nullopt; @@ -1923,11 +1918,11 @@ const bool min_block_size_should_encompass_intrinsic_size = MinBlockSizeShouldEncompassIntrinsicSize(*flex_item); ConstraintSpace child_space = BuildSpaceForLayout( - flex_item->ng_input_node, flex_item->main_axis_final_size, + flex_item->block_node, flex_item->main_axis_final_size, flex_item->is_initial_block_size_indefinite, /* override_inline_size */ std::nullopt, line_cross_size_for_stretch, offset.block_offset, min_block_size_should_encompass_intrinsic_size); - const LayoutResult* layout_result = flex_item->ng_input_node.Layout( + const LayoutResult* layout_result = flex_item->block_node.Layout( child_space, item_break_token, early_break_in_child); BreakStatus break_status = BreakStatus::kContinue; @@ -1951,7 +1946,7 @@ BreakStatus row_break_status = BreakBeforeRowIfNeeded( line_output, row_block_offset, (*row_break_between_outputs)[flex_line_idx], flex_line_idx, - flex_item->ng_input_node, row_container_separation, + flex_item->block_node, row_container_separation, is_first_for_row); if (row_break_status == BreakStatus::kBrokeBefore) { ConsumeRemainingFragmentainerSpace(offset_in_stitched_container, @@ -1988,7 +1983,7 @@ } } break_status = BreakBeforeChildIfNeeded( - flex_item->ng_input_node, *layout_result, + flex_item->block_node, *layout_result, FragmentainerOffsetForChildren() + offset.block_offset, has_container_separation, !is_column_, current_column_break_info); @@ -2059,7 +2054,7 @@ if (is_column_) { LayoutUnit cloned_block_decorations; if (!is_at_block_end && - flex_item->ng_input_node.Style().BoxDecorationBreak() == + flex_item->block_node.Style().BoxDecorationBreak() == EBoxDecorationBreak::kClone) { cloned_block_decorations = fragment.BoxDecorations().BlockSum(); } @@ -2224,30 +2219,28 @@ // devtools uses margin box. item_rect.Expand(physical_margins); DCHECK_GE(layout_info_for_devtools_->lines.size(), 1u); - DevtoolsFlexInfo::Item item( - item_rect, - BaselineAscent(flex_item, physical_fragment, flex_item.Alignment())); + DevtoolsFlexInfo::Item item(item_rect, + BaselineAscent(flex_item, physical_fragment)); layout_info_for_devtools_->lines[flex_line_idx].items.push_back(item); } // Detect if the flex-item had its scrollbar state change. If so we need // to relayout as the input to the flex algorithm is incorrect. if (!ignore_child_scrollbar_changes_) { - if (flex_item.scrollbars_ != - ComputeScrollbarsForNonAnonymous(flex_item.ng_input_node_)) { + if (flex_item.initial_scrollbars != + ComputeScrollbarsForNonAnonymous(flex_item.block_node)) { status = LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges; } // The flex-item scrollbars may not have changed, but an descendant's // scrollbars might have causing the min/max sizes to be incorrect. - if (flex_item.depends_on_min_max_sizes_ && - flex_item.ng_input_node_.GetLayoutBox() - ->IntrinsicLogicalWidthsDirty()) { + if (flex_item.depends_on_min_max_sizes && + flex_item.block_node.GetLayoutBox()->IntrinsicLogicalWidthsDirty()) { status = LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges; } } else { - DCHECK_EQ(flex_item.scrollbars_, - ComputeScrollbarsForNonAnonymous(flex_item.ng_input_node_)); + DCHECK_EQ(flex_item.initial_scrollbars, + ComputeScrollbarsForNonAnonymous(flex_item.block_node)); } return status; } @@ -2299,7 +2292,7 @@ LayoutUnit largest_outer_min_content_contribution; for (const FlexItem& item : algorithm_.all_items_) { - const BlockNode& child = item.ng_input_node_; + const BlockNode& child = item.block_node; const ConstraintSpace space = BuildSpaceForIntrinsicInlineSize(child); MinMaxSizesResult min_max_content_contributions = @@ -2309,14 +2302,14 @@ MinMaxSizes item_final_contribution; const LayoutUnit flex_base_size_border_box = - item.flex_base_content_size_ + item.main_axis_border_padding_; + item.base_content_size + item.main_axis_border_padding; const LayoutUnit hypothetical_main_size_border_box = - item.hypothetical_main_content_size_ + item.main_axis_border_padding_; + item.hypothetical_content_size + item.main_axis_border_padding; if (algorithm_.IsMultiline()) { const LayoutUnit main_axis_margins = - is_horizontal_flow_ ? item.physical_margins_.HorizontalSum() - : item.physical_margins_.VerticalSum(); + is_horizontal_flow_ ? item.initial_margins.HorizontalSum() + : item.initial_margins.VerticalSum(); largest_outer_min_content_contribution = std::max( largest_outer_min_content_contribution, min_max_content_contributions.sizes.min_size + main_axis_margins); @@ -2324,10 +2317,10 @@ const LayoutUnit min_contribution = min_max_content_contributions.sizes.min_size; const bool cant_move = (min_contribution > flex_base_size_border_box && - item.flex_grow_ == 0.f) || + item.flex_grow == 0.f) || (min_contribution < flex_base_size_border_box && - item.flex_shrink_ == 0.f); - if (cant_move && !item.is_used_flex_basis_indefinite_) { + item.flex_shrink == 0.f); + if (cant_move && !item.is_used_flex_basis_indefinite) { item_final_contribution.min_size = hypothetical_main_size_border_box; } else { item_final_contribution.min_size = min_contribution; @@ -2337,10 +2330,10 @@ const LayoutUnit max_contribution = min_max_content_contributions.sizes.max_size; const bool cant_move = (max_contribution > flex_base_size_border_box && - item.flex_grow_ == 0.f) || + item.flex_grow == 0.f) || (max_contribution < flex_base_size_border_box && - item.flex_shrink_ == 0.f); - if (cant_move && !item.is_used_flex_basis_indefinite_) { + item.flex_shrink == 0.f); + if (cant_move && !item.is_used_flex_basis_indefinite) { item_final_contribution.max_size = hypothetical_main_size_border_box; } else { item_final_contribution.max_size = max_contribution; @@ -2349,8 +2342,8 @@ container_sizes += item_final_contribution; const LayoutUnit main_axis_margins = - is_horizontal_flow_ ? item.physical_margins_.HorizontalSum() - : item.physical_margins_.VerticalSum(); + is_horizontal_flow_ ? item.initial_margins.HorizontalSum() + : item.initial_margins.VerticalSum(); container_sizes += main_axis_margins; } @@ -2648,10 +2641,11 @@ if (item.has_descendant_that_depends_on_percentage_block_size) return false; - if (item.ng_input_node.IsMonolithic()) + if (item.block_node.IsMonolithic()) { return false; + } - const auto& item_style = item.ng_input_node.Style(); + const auto& item_style = item.block_node.Style(); // NOTE: We currently assume that writing-mode roots are monolithic, but // this may change in the future. @@ -2672,18 +2666,18 @@ // can't shrink or its min-height is auto. if (item_style.LogicalHeight().HasAutoOrContentOrIntrinsic() && (!can_shrink || algorithm_.ShouldApplyMinSizeAutoForChild( - *item.ng_input_node.GetLayoutBox()))) { + *item.block_node.GetLayoutBox()))) { return true; } } else { // Don't grow if the item's block-size should be the same as its container. - if (WillChildCrossSizeBeContainerCrossSize(item.ng_input_node) && + if (WillChildCrossSizeBeContainerCrossSize(item.block_node) && !Style().LogicalHeight().HasAutoOrContentOrIntrinsic()) { return false; } // Only allow growth if the item's cross size is auto. - if (DoesItemComputedCrossSizeHaveAuto(item.ng_input_node)) { + if (DoesItemComputedCrossSizeHaveAuto(item.block_node)) { return true; } }
diff --git a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h index b6779b89..a0f202bd 100644 --- a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h
@@ -93,9 +93,7 @@ LayoutUnit MainAxisContentExtent(LayoutUnit sum_hypothetical_main_size) const; // Returns the position of the baseline, given a physical fragment. - LayoutUnit BaselineAscent(const FlexItem&, - const PhysicalBoxFragment&, - ItemPosition alignment) const; + LayoutUnit BaselineAscent(const FlexItem&, const PhysicalBoxFragment&) const; void HandleOutOfFlowPositionedItems( HeapVector<Member<LayoutBox>>& oof_children);
diff --git a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc index 4b65f34..97de4cc 100644 --- a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc +++ b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc
@@ -75,69 +75,12 @@ } // namespace -FlexItem::FlexItem(const FlexibleBoxAlgorithm* algorithm, - const ComputedStyle& style, - wtf_size_t item_index, - unsigned main_axis_auto_margin_count, - LayoutUnit flex_base_content_size, - MinMaxSizes min_max_main_sizes, - LayoutUnit main_axis_border_padding, - PhysicalBoxStrut physical_margins, - BoxStrut scrollbars, - WritingMode baseline_writing_mode, - BaselineGroup baseline_group, - bool is_initial_block_size_indefinite, - bool is_used_flex_basis_indefinite, - bool depends_on_min_max_sizes) - : algorithm_(algorithm), - style_(style), - item_index_(item_index), - flex_grow_(style.ResolvedFlexGrow(algorithm_->StyleRef())), - flex_shrink_(style.ResolvedFlexShrink(algorithm_->StyleRef())), - main_axis_auto_margin_count_(main_axis_auto_margin_count), - flex_base_content_size_(flex_base_content_size), - min_max_main_sizes_(min_max_main_sizes), - hypothetical_main_content_size_( - min_max_main_sizes.ClampSizeToMinAndMax(flex_base_content_size)), - main_axis_border_padding_(main_axis_border_padding), - physical_margins_(physical_margins), - scrollbars_(scrollbars), - baseline_writing_direction_({baseline_writing_mode, TextDirection::kLtr}), - baseline_group_(baseline_group), - is_initial_block_size_indefinite_(is_initial_block_size_indefinite), - is_used_flex_basis_indefinite_(is_used_flex_basis_indefinite), - depends_on_min_max_sizes_(depends_on_min_max_sizes), - frozen_(false), - ng_input_node_(/* LayoutBox* */ nullptr) { - DCHECK_GE(min_max_main_sizes.max_size, LayoutUnit()) - << "Use LayoutUnit::Max() for no max size"; -} - -LayoutUnit FlexItem::MainAxisMarginExtent() const { - return algorithm_->IsHorizontalFlow() ? physical_margins_.HorizontalSum() - : physical_margins_.VerticalSum(); -} - -LayoutUnit FlexItem::CrossAxisMarginExtent() const { - return algorithm_->IsHorizontalFlow() ? physical_margins_.VerticalSum() - : physical_margins_.HorizontalSum(); -} - -ItemPosition FlexItem::Alignment() const { - return FlexibleBoxAlgorithm::AlignmentForChild(*algorithm_->Style(), *style_); -} - -void FlexItem::Trace(Visitor* visitor) const { - visitor->Trace(style_); - visitor->Trace(ng_input_node_); - visitor->Trace(layout_result_); -} - // static -LayoutUnit FlexItem::AlignmentOffset(LayoutUnit available_free_space, - ItemPosition position, - LayoutUnit baseline_offset, - bool is_wrap_reverse) { +LayoutUnit FlexibleBoxAlgorithm::AlignmentOffset( + LayoutUnit available_free_space, + ItemPosition position, + LayoutUnit baseline_offset, + bool is_wrap_reverse) { switch (position) { case ItemPosition::kLegacy: case ItemPosition::kAuto: @@ -176,113 +119,6 @@ return LayoutUnit(); } -void FlexLine::FreezeViolations(ViolationsVector& violations) { - for (auto* violation : violations) { - DCHECK(!violation->frozen_); - remaining_free_space_ -= - violation->flexed_content_size_ - violation->flex_base_content_size_; - total_flex_grow_ -= violation->flex_grow_; - total_flex_shrink_ -= violation->flex_shrink_; - total_weighted_flex_shrink_ -= - violation->flex_shrink_ * violation->flex_base_content_size_; - // total_weighted_flex_shrink can be negative when we exceed the precision - // of a double when we initially calculate total_weighted_flex_shrink. We - // then subtract each child's weighted flex shrink with full precision, now - // leading to a negative result. See - // css3/flexbox/large-flex-shrink-assert.html - total_weighted_flex_shrink_ = std::max(total_weighted_flex_shrink_, 0.0); - violation->frozen_ = true; - } -} - -void FlexLine::FreezeInflexibleItems() { - // Per https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths step 2, - // we freeze all items with a flex factor of 0 as well as those with a min/max - // size violation. - const FlexSign flex_sign = Sign(); - remaining_free_space_ = container_main_inner_size_ - sum_flex_base_size_; - - ViolationsVector new_inflexible_items; - for (auto& flex_item : line_items_) { - DCHECK(!flex_item.frozen_); - float flex_factor = (flex_sign == kPositiveFlexibility) - ? flex_item.flex_grow_ - : flex_item.flex_shrink_; - if (flex_factor == 0 || - (flex_sign == kPositiveFlexibility && - flex_item.flex_base_content_size_ > - flex_item.hypothetical_main_content_size_) || - (flex_sign == kNegativeFlexibility && - flex_item.flex_base_content_size_ < - flex_item.hypothetical_main_content_size_)) { - flex_item.flexed_content_size_ = - flex_item.hypothetical_main_content_size_; - new_inflexible_items.push_back(&flex_item); - } - } - FreezeViolations(new_inflexible_items); - initial_free_space_ = remaining_free_space_; -} - -bool FlexLine::ResolveFlexibleLengths() { - LayoutUnit total_violation; - LayoutUnit used_free_space; - ViolationsVector min_violations; - ViolationsVector max_violations; - - const FlexSign flex_sign = Sign(); - const double sum_flex_factors = (flex_sign == kPositiveFlexibility) - ? total_flex_grow_ - : total_flex_shrink_; - if (sum_flex_factors > 0 && sum_flex_factors < 1) { - LayoutUnit fractional(initial_free_space_ * sum_flex_factors); - if (fractional.Abs() < remaining_free_space_.Abs()) - remaining_free_space_ = fractional; - } - - for (auto& flex_item : line_items_) { - if (flex_item.frozen_) - continue; - - LayoutUnit child_size = flex_item.flex_base_content_size_; - double extra_space = 0; - if (remaining_free_space_ > 0 && total_flex_grow_ > 0 && - flex_sign == kPositiveFlexibility && std::isfinite(total_flex_grow_)) { - extra_space = - remaining_free_space_ * flex_item.flex_grow_ / total_flex_grow_; - } else if (remaining_free_space_ < 0 && total_weighted_flex_shrink_ > 0 && - flex_sign == kNegativeFlexibility && - std::isfinite(total_weighted_flex_shrink_) && - flex_item.flex_shrink_) { - extra_space = remaining_free_space_ * flex_item.flex_shrink_ * - flex_item.flex_base_content_size_ / - total_weighted_flex_shrink_; - } - if (std::isfinite(extra_space)) - child_size += LayoutUnit::FromFloatRound(extra_space); - - LayoutUnit adjusted_child_size = flex_item.ClampSizeToMinAndMax(child_size); - DCHECK_GE(adjusted_child_size, 0); - flex_item.flexed_content_size_ = adjusted_child_size; - used_free_space += adjusted_child_size - flex_item.flex_base_content_size_; - - LayoutUnit violation = adjusted_child_size - child_size; - if (violation > 0) - min_violations.push_back(&flex_item); - else if (violation < 0) - max_violations.push_back(&flex_item); - total_violation += violation; - } - - if (total_violation) { - FreezeViolations(total_violation < 0 ? max_violations : min_violations); - } else { - remaining_free_space_ -= used_free_space; - } - - return !total_violation; -} - // static LayoutUnit FlexibleBoxAlgorithm::GapBetweenItems( const ComputedStyle& style, @@ -352,10 +188,6 @@ FlexLine* FlexibleBoxAlgorithm::ComputeNextFlexLine() { LayoutUnit sum_flex_base_size; LayoutUnit sum_hypothetical_main_size; - double total_flex_grow = 0; - double total_flex_shrink = 0; - double total_weighted_flex_shrink = 0; - unsigned main_axis_auto_margin_count = 0; bool line_has_in_flow_item = false; @@ -375,11 +207,6 @@ flex_item.FlexBaseMarginBoxSize() + gap_between_items_; sum_hypothetical_main_size += flex_item.HypotheticalMainAxisMarginBoxSize() + gap_between_items_; - total_flex_grow += flex_item.flex_grow_; - total_flex_shrink += flex_item.flex_shrink_; - total_weighted_flex_shrink += - flex_item.flex_shrink_ * flex_item.flex_base_content_size_; - main_axis_auto_margin_count += flex_item.main_axis_auto_margin_count_; } if (line_has_in_flow_item) { // We added a gap after every item but there shouldn't be one after the last @@ -393,10 +220,8 @@ next_item_index_ == all_items_.size()); if (next_item_index_ > start_index) { return &flex_lines_.emplace_back( - this, FlexItemVectorView(&all_items_, start_index, next_item_index_), - sum_flex_base_size, sum_hypothetical_main_size, total_flex_grow, - total_flex_shrink, total_weighted_flex_shrink, - main_axis_auto_margin_count); + FlexItemVectorView(&all_items_, start_index, next_item_index_), + sum_flex_base_size, sum_hypothetical_main_size); } return nullptr; }
diff --git a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h index 848c515..948f087 100644 --- a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h +++ b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h
@@ -34,6 +34,7 @@ #include "base/check_op.h" #include "third_party/blink/renderer/core/layout/baseline_utils.h" #include "third_party/blink/renderer/core/layout/block_node.h" +#include "third_party/blink/renderer/core/layout/flex/flex_item.h" #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/min_max_sizes.h" #include "third_party/blink/renderer/core/style/computed_style.h" @@ -44,109 +45,12 @@ namespace blink { -class FlexItem; class FlexLayoutAlgorithm; class FlexLine; class FlexibleBoxAlgorithm; -struct MinMaxSizes; - -enum FlexSign { - kPositiveFlexibility, - kNegativeFlexibility, -}; typedef HeapVector<FlexItem, 8> FlexItemVector; -class FlexItem { - DISALLOW_NEW(); - - public: - // Parameters: - // - |flex_base_content_size| includes scrollbar size but not border/padding. - // - |min_max_main_sizes| is the resolved min and max size properties in the - // main axis direction (not intrinsic widths). It does not include - // border/padding. - // |min_max_cross_sizes| does include cross_axis_border_padding. - FlexItem(const FlexibleBoxAlgorithm*, - const ComputedStyle& style, - wtf_size_t item_index, - unsigned main_axis_auto_margin_count, - LayoutUnit flex_base_content_size, - MinMaxSizes min_max_main_sizes, - LayoutUnit main_axis_border_padding, - PhysicalBoxStrut physical_margins, - BoxStrut scrollbars, - WritingMode baseline_writing_mode, - BaselineGroup baseline_group, - bool is_initial_block_size_indefinite, - bool is_used_flex_basis_indefinite, - bool depends_on_min_max_sizes); - - LayoutUnit HypotheticalMainAxisMarginBoxSize() const { - return hypothetical_main_content_size_ + main_axis_border_padding_ + - MainAxisMarginExtent(); - } - - LayoutUnit FlexBaseMarginBoxSize() const { - return flex_base_content_size_ + main_axis_border_padding_ + - MainAxisMarginExtent(); - } - - LayoutUnit FlexedBorderBoxSize() const { - return flexed_content_size_ + main_axis_border_padding_; - } - - LayoutUnit FlexedMarginBoxSize() const { - return flexed_content_size_ + main_axis_border_padding_ + - MainAxisMarginExtent(); - } - - LayoutUnit ClampSizeToMinAndMax(LayoutUnit size) const { - return min_max_main_sizes_.ClampSizeToMinAndMax(size); - } - - ItemPosition Alignment() const; - - LayoutUnit MainAxisMarginExtent() const; - LayoutUnit CrossAxisMarginExtent() const; - - static LayoutUnit AlignmentOffset(LayoutUnit available_free_space, - ItemPosition position, - LayoutUnit baseline_offset, - bool is_wrap_reverse); - - void Trace(Visitor*) const; - - const FlexibleBoxAlgorithm* algorithm_; - Member<const ComputedStyle> style_; - - const wtf_size_t item_index_; - const float flex_grow_; - const float flex_shrink_; - const unsigned main_axis_auto_margin_count_; - const LayoutUnit flex_base_content_size_; - const MinMaxSizes min_max_main_sizes_; - const LayoutUnit hypothetical_main_content_size_; - const LayoutUnit main_axis_border_padding_; - const PhysicalBoxStrut physical_margins_; - const BoxStrut scrollbars_; - const WritingDirectionMode baseline_writing_direction_; - const BaselineGroup baseline_group_; - - LayoutUnit flexed_content_size_; - - const bool is_initial_block_size_indefinite_; - const bool is_used_flex_basis_indefinite_; - const bool depends_on_min_max_sizes_; - bool frozen_; - - // The above fields are used by the flex algorithm. The following fields, by - // contrast, are just convenient storage. - BlockNode ng_input_node_; - Member<const LayoutResult> layout_result_; - std::optional<LayoutUnit> max_content_contribution_; -}; - class FlexItemVectorView { DISALLOW_NEW(); @@ -183,67 +87,18 @@ DISALLOW_NEW(); public: - typedef Vector<FlexItem*, 8> ViolationsVector; - // This will std::move the passed-in line_items. - FlexLine(FlexibleBoxAlgorithm* algorithm, - FlexItemVectorView line_items, + FlexLine(FlexItemVectorView line_items, LayoutUnit sum_flex_base_size, - LayoutUnit sum_hypothetical_main_size, - double total_flex_grow, - double total_flex_shrink, - double total_weighted_flex_shrink, - unsigned main_axis_auto_margin_count) - : algorithm_(algorithm), - line_items_(std::move(line_items)), + LayoutUnit sum_hypothetical_main_size) + : line_items_(std::move(line_items)), sum_flex_base_size_(sum_flex_base_size), - sum_hypothetical_main_size_(sum_hypothetical_main_size), - total_flex_grow_(total_flex_grow), - total_flex_shrink_(total_flex_shrink), - total_weighted_flex_shrink_(total_weighted_flex_shrink), - main_axis_auto_margin_count_(main_axis_auto_margin_count) {} + sum_hypothetical_main_size_(sum_hypothetical_main_size) {} - FlexSign Sign() const { - return sum_hypothetical_main_size_ < container_main_inner_size_ - ? kPositiveFlexibility - : kNegativeFlexibility; - } - - void SetContainerMainInnerSize(LayoutUnit size) { - container_main_inner_size_ = size; - } - - void FreezeInflexibleItems(); - - // This modifies remaining_free_space. - void FreezeViolations(ViolationsVector& violations); - - // Should be called in a loop until it returns false. - // This modifies remaining_free_space. - bool ResolveFlexibleLengths(); - - FlexibleBoxAlgorithm* algorithm_; FlexItemVectorView line_items_; const LayoutUnit sum_flex_base_size_; const LayoutUnit sum_hypothetical_main_size_; - - double total_flex_grow_; - double total_flex_shrink_; - double total_weighted_flex_shrink_; - - const unsigned main_axis_auto_margin_count_; - - // This gets set by SetContainerMainInnerSize - LayoutUnit container_main_inner_size_; - // initial_free_space is the initial amount of free space in this flexbox. - // remaining_free_space starts out at the same value but as we place and lay - // out flex items we subtract from it. Note that both values can be - // negative. - // These get set by FreezeInflexibleItems, see spec: - // https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths step 3 - LayoutUnit initial_free_space_; - LayoutUnit remaining_free_space_; }; // This class implements the CSS Flexbox layout algorithm: @@ -279,11 +134,6 @@ ~FlexibleBoxAlgorithm() { all_items_.clear(); } FlexibleBoxAlgorithm& operator=(const FlexibleBoxAlgorithm&) = delete; - template <typename... Args> - FlexItem& emplace_back(Args&&... args) { - return all_items_.emplace_back(this, std::forward<Args>(args)...); - } - wtf_size_t NumItems() const { return all_items_.size(); } const ComputedStyle* Style() const { return style_.Get(); } @@ -307,6 +157,11 @@ static ItemPosition AlignmentForChild(const ComputedStyle& flexbox_style, const ComputedStyle& child_style); + static LayoutUnit AlignmentOffset(LayoutUnit available_free_space, + ItemPosition position, + LayoutUnit baseline_offset, + bool is_wrap_reverse); + static LayoutUnit ContentDistributionSpaceBetweenChildren( LayoutUnit available_free_space, const StyleContentAlignmentData&, @@ -336,6 +191,4 @@ } // namespace blink -WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::FlexItem) - #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_FLEXIBLE_BOX_ALGORITHM_H_
diff --git a/third_party/blink/renderer/core/layout/flex/line_flexer.cc b/third_party/blink/renderer/core/layout/flex/line_flexer.cc new file mode 100644 index 0000000..ec117db --- /dev/null +++ b/third_party/blink/renderer/core/layout/flex/line_flexer.cc
@@ -0,0 +1,126 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/layout/flex/line_flexer.h" + +namespace blink { + +LineFlexer::LineFlexer(base::span<FlexItem> line_items, + LayoutUnit sum_hypothetical_main_size, + LayoutUnit sum_flex_base_size, + LayoutUnit main_axis_inner_size) + : line_items_(line_items), + flex_sign_(sum_hypothetical_main_size < main_axis_inner_size + ? kPositive + : kNegative) { + // Per https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths step 2, + // we freeze all items with a flex factor of 0 as well as those with a min/max + // size violation. + remaining_free_space_ = main_axis_inner_size - sum_flex_base_size; + + ViolationsVector new_inflexible_items; + for (auto& flex_item : line_items_) { + DCHECK(!flex_item.frozen); + + total_flex_grow_ += flex_item.flex_grow; + total_flex_shrink_ += flex_item.flex_shrink; + total_weighted_flex_shrink_ += + flex_item.flex_shrink * flex_item.base_content_size; + + float flex_factor = + (flex_sign_ == kPositive) ? flex_item.flex_grow : flex_item.flex_shrink; + if (flex_factor == 0 || + (flex_sign_ == kPositive && + flex_item.base_content_size > flex_item.hypothetical_content_size) || + (flex_sign_ == kNegative && + flex_item.base_content_size < flex_item.hypothetical_content_size)) { + flex_item.flexed_content_size = flex_item.hypothetical_content_size; + new_inflexible_items.push_back(&flex_item); + } + } + FreezeViolations(new_inflexible_items); + initial_free_space_ = remaining_free_space_; +} + +void LineFlexer::FreezeViolations(ViolationsVector& violations) { + for (auto* violation : violations) { + DCHECK(!violation->frozen); + remaining_free_space_ -= + violation->flexed_content_size - violation->base_content_size; + total_flex_grow_ -= violation->flex_grow; + total_flex_shrink_ -= violation->flex_shrink; + total_weighted_flex_shrink_ -= + violation->flex_shrink * violation->base_content_size; + // total_weighted_flex_shrink can be negative when we exceed the precision + // of a double when we initially calculate total_weighted_flex_shrink. We + // then subtract each child's weighted flex shrink with full precision, now + // leading to a negative result. See + // css3/flexbox/large-flex-shrink-assert.html + total_weighted_flex_shrink_ = std::max(total_weighted_flex_shrink_, 0.0); + violation->frozen = true; + } +} + +bool LineFlexer::ResolveFlexibleLengths() { + LayoutUnit total_violation; + LayoutUnit used_free_space; + ViolationsVector min_violations; + ViolationsVector max_violations; + + const double sum_flex_factors = + (flex_sign_ == kPositive) ? total_flex_grow_ : total_flex_shrink_; + if (sum_flex_factors > 0 && sum_flex_factors < 1) { + LayoutUnit fractional(initial_free_space_ * sum_flex_factors); + if (fractional.Abs() < remaining_free_space_.Abs()) { + remaining_free_space_ = fractional; + } + } + + for (auto& flex_item : line_items_) { + if (flex_item.frozen) { + continue; + } + + LayoutUnit child_size = flex_item.base_content_size; + double extra_space = 0; + if (remaining_free_space_ > 0 && total_flex_grow_ > 0 && + flex_sign_ == kPositive && std::isfinite(total_flex_grow_)) { + extra_space = + remaining_free_space_ * flex_item.flex_grow / total_flex_grow_; + } else if (remaining_free_space_ < 0 && total_weighted_flex_shrink_ > 0 && + flex_sign_ == kNegative && + std::isfinite(total_weighted_flex_shrink_) && + flex_item.flex_shrink) { + extra_space = remaining_free_space_ * flex_item.flex_shrink * + flex_item.base_content_size / total_weighted_flex_shrink_; + } + if (std::isfinite(extra_space)) { + child_size += LayoutUnit::FromFloatRound(extra_space); + } + + const LayoutUnit adjusted_child_size = + flex_item.main_axis_min_max_sizes.ClampSizeToMinAndMax(child_size); + DCHECK_GE(adjusted_child_size, 0); + flex_item.flexed_content_size = adjusted_child_size; + used_free_space += adjusted_child_size - flex_item.base_content_size; + + const LayoutUnit violation = adjusted_child_size - child_size; + if (violation > 0) { + min_violations.push_back(&flex_item); + } else if (violation < 0) { + max_violations.push_back(&flex_item); + } + total_violation += violation; + } + + if (total_violation) { + FreezeViolations(total_violation < 0 ? max_violations : min_violations); + } else { + remaining_free_space_ -= used_free_space; + } + + return total_violation; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/flex/line_flexer.h b/third_party/blink/renderer/core/layout/flex/line_flexer.h new file mode 100644 index 0000000..c7da845 --- /dev/null +++ b/third_party/blink/renderer/core/layout/flex/line_flexer.h
@@ -0,0 +1,55 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_LINE_FLEXER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_LINE_FLEXER_H_ + +#include "third_party/blink/renderer/core/layout/flex/flex_item.h" +#include "third_party/blink/renderer/platform/geometry/layout_unit.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +// Takes a span of FlexItems and resolves their main-axis content-size based on +// their flex-grow/flex-shrink properties. +class LineFlexer { + STACK_ALLOCATED(); + + public: + LineFlexer(base::span<FlexItem> line_items, + LayoutUnit sum_hypothetical_main_size, + LayoutUnit sum_flex_base_size, + LayoutUnit main_axis_inner_size); + + void Run() { + while (ResolveFlexibleLengths()) { + continue; + } + } + + private: + typedef Vector<FlexItem*, 8> ViolationsVector; + + enum FlexSign { + kPositive, + kNegative, + }; + + void FreezeViolations(ViolationsVector& violations); + bool ResolveFlexibleLengths(); + + base::span<FlexItem> line_items_; + const FlexSign flex_sign_; + + double total_flex_grow_ = 0.0; + double total_flex_shrink_ = 0.0; + double total_weighted_flex_shrink_ = 0.0; + + LayoutUnit remaining_free_space_; + LayoutUnit initial_free_space_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FLEX_LINE_FLEXER_H_
diff --git a/third_party/blink/renderer/core/layout/flex/ng_flex_line.h b/third_party/blink/renderer/core/layout/flex/ng_flex_line.h index 416fcdf..59dec10 100644 --- a/third_party/blink/renderer/core/layout/flex/ng_flex_line.h +++ b/third_party/blink/renderer/core/layout/flex/ng_flex_line.h
@@ -14,11 +14,11 @@ DISALLOW_NEW(); public: - NGFlexItem() : ng_input_node(nullptr) {} + NGFlexItem() : block_node(nullptr) {} - const ComputedStyle& Style() const { return ng_input_node.Style(); } + const ComputedStyle& Style() const { return block_node.Style(); } - void Trace(Visitor* visitor) const { visitor->Trace(ng_input_node); } + void Trace(Visitor* visitor) const { visitor->Trace(block_node); } wtf_size_t item_index; LayoutUnit main_axis_final_size; @@ -32,7 +32,7 @@ bool is_initial_block_size_indefinite = false; bool is_used_flex_basis_indefinite = false; bool has_descendant_that_depends_on_percentage_block_size = false; - BlockNode ng_input_node; + BlockNode block_node; }; struct NGFlexLine {
diff --git a/third_party/blink/renderer/core/layout/ink_overflow.cc b/third_party/blink/renderer/core/layout/ink_overflow.cc index 9b1cab6..dbffc80 100644 --- a/third_party/blink/renderer/core/layout/ink_overflow.cc +++ b/third_party/blink/renderer/core/layout/ink_overflow.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/ink_overflow.h" #include "build/chromeos_buildflags.h" @@ -81,8 +76,10 @@ "outsets should be the size of a pointer"); single_ = source.single_; #if DCHECK_IS_ON() - for (wtf_size_t i = 0; i < std::size(outsets_); ++i) - DCHECK_EQ(outsets_[i], source.outsets_[i]); + for (wtf_size_t i = 0; i < std::size(outsets_); ++i) { + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + UNSAFE_TODO(DCHECK_EQ(outsets_[i], source.outsets_[i])); + } #endif break; case Type::kSelf: @@ -110,8 +107,10 @@ "outsets should be the size of a pointer"); single_ = source.single_; #if DCHECK_IS_ON() - for (wtf_size_t i = 0; i < std::size(outsets_); ++i) - DCHECK_EQ(outsets_[i], source.outsets_[i]); + for (wtf_size_t i = 0; i < std::size(outsets_); ++i) { + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + UNSAFE_TODO(DCHECK_EQ(outsets_[i], source.outsets_[i])); + } #endif break; case Type::kSelf: @@ -150,11 +149,16 @@ } PhysicalRect InkOverflow::FromOutsets(const PhysicalSize& size) const { - const LayoutUnit left_outset(LayoutUnit::FromRawValue(outsets_[0])); - const LayoutUnit top_outset(LayoutUnit::FromRawValue(outsets_[1])); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + const LayoutUnit left_outset( + LayoutUnit::FromRawValue(UNSAFE_TODO(outsets_[0]))); + const LayoutUnit top_outset( + LayoutUnit::FromRawValue(UNSAFE_TODO(outsets_[1]))); return {-left_outset, -top_outset, - left_outset + size.width + LayoutUnit::FromRawValue(outsets_[2]), - top_outset + size.height + LayoutUnit::FromRawValue(outsets_[3])}; + left_outset + size.width + + LayoutUnit::FromRawValue(UNSAFE_TODO(outsets_[2])), + top_outset + size.height + + LayoutUnit::FromRawValue(UNSAFE_TODO(outsets_[3]))}; } PhysicalRect InkOverflow::Self(Type type, const PhysicalSize& size) const { @@ -252,9 +256,10 @@ return false; Reset(type); outsets_[0] = left_outset.RawValue(); - outsets_[1] = top_outset.RawValue(); - outsets_[2] = right_outset.RawValue(); - outsets_[3] = bottom_outset.RawValue(); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + UNSAFE_TODO(outsets_[1]) = top_outset.RawValue(); + UNSAFE_TODO(outsets_[2]) = right_outset.RawValue(); + UNSAFE_TODO(outsets_[3]) = bottom_outset.RawValue(); return true; }
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 97d46e3..99ce76a 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -20,11 +20,6 @@ * */ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BOX_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BOX_H_ @@ -688,7 +683,8 @@ const PhysicalBoxFragment& operator*() const; Iterator& operator++() { - ++iterator_; + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + UNSAFE_TODO(++iterator_); return *this; } Iterator operator++(int) {
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc index 6d04dc7..a0a360c 100644 --- a/third_party/blink/renderer/core/layout/layout_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/layout_object.h" #include "testing/gmock/include/gmock/gmock-matchers.h" @@ -1441,7 +1436,8 @@ child->GetTransformFromContainer(ancestor, PhysicalOffset(), transform); std::optional<gfx::DecomposedTransform> decomp = transform.Decompose(); ASSERT_TRUE(decomp); - EXPECT_EQ(0, decomp->perspective[2]); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + EXPECT_EQ(0, UNSAFE_TODO(decomp->perspective[2])); } TEST_F(LayoutObjectTest, PerspectiveWithAnonymousTable) { @@ -1461,7 +1457,8 @@ child->GetTransformFromContainer(ancestor, PhysicalOffset(), transform); std::optional<gfx::DecomposedTransform> decomp = transform.Decompose(); ASSERT_TRUE(decomp); - EXPECT_EQ(-0.01, decomp->perspective[2]); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + EXPECT_EQ(-0.01, UNSAFE_TODO(decomp->perspective[2])); } TEST_F(LayoutObjectTest, LocalToAncestoRectIgnoreAncestorScroll) {
diff --git a/third_party/blink/renderer/core/layout/layout_shift_region_test.cc b/third_party/blink/renderer/core/layout/layout_shift_region_test.cc index d9e6a225..7daf72b 100644 --- a/third_party/blink/renderer/core/layout/layout_shift_region_test.cc +++ b/third_party/blink/renderer/core/layout/layout_shift_region_test.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/layout_shift_region.h" #include <gtest/gtest.h> @@ -95,8 +90,9 @@ }; uint64_t expected_area = 9201862875ul; for (unsigned i = 0; i < 100; i++) { - const int* d = data + (i * 4); - gfx::Rect r(d[0], d[1], d[2], d[3]); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + const int* d = UNSAFE_TODO(data + (i * 4)); + gfx::Rect UNSAFE_TODO(r(d[0], d[1], d[2], d[3])); region.AddRect(r); naive_region.Union(r); }
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc index a82796a..1e026626 100644 --- a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc +++ b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h" #include "third_party/blink/public/common/input/web_mouse_event.h" @@ -868,7 +863,9 @@ // - add/remove a cc::Layer and a PaintLayer together static const char* states[] = {"", "pl", "pl tr", "pl", "", "tr", ""}; - element->setAttribute(html_names::kClassAttr, AtomicString(states[state])); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + element->setAttribute(html_names::kClassAttr, + AtomicString(UNSAFE_TODO(states[state]))); UpdateAllLifecyclePhasesForTest(); return ++state < sizeof states / sizeof *states; };
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index 77f7c57..2a5f9e5 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -22,11 +22,6 @@ * */ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/layout_text.h" #include <algorithm> @@ -74,6 +69,7 @@ #include "third_party/blink/renderer/platform/text/hyphenation.h" #include "third_party/blink/renderer/platform/text/text_break_iterator.h" #include "third_party/blink/renderer/platform/wtf/size_assertions.h" +#include "third_party/blink/renderer/platform/wtf/text/character_visitor.h" #include "third_party/blink/renderer/platform/wtf/text/string_buffer.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/text/text_offset_map.h" @@ -724,21 +720,11 @@ bool LayoutText::IsAllCollapsibleWhitespace() const { NOT_DESTROYED(); - unsigned length = text_.length(); - if (text_.Is8Bit()) { - for (unsigned i = 0; i < length; ++i) { - if (!StyleRef().IsCollapsibleWhiteSpace(text_.Characters8()[i])) { - return false; - } - } - return true; - } - for (unsigned i = 0; i < length; ++i) { - if (!StyleRef().IsCollapsibleWhiteSpace(text_.Characters16()[i])) { - return false; - } - } - return true; + const ComputedStyle& style = StyleRef(); + return WTF::VisitCharacters(text_, [&style](auto chars) { + return base::ranges::all_of( + chars, [&style](auto ch) { return style.IsCollapsibleWhiteSpace(ch); }); + }); } UChar32 LayoutText::FirstCharacterAfterWhitespaceCollapsing() const {
diff --git a/third_party/blink/renderer/core/layout/oof_positioned_node.h b/third_party/blink/renderer/core/layout/oof_positioned_node.h index f8cc6f2..73bc5f45 100644 --- a/third_party/blink/renderer/core/layout/oof_positioned_node.h +++ b/third_party/blink/renderer/core/layout/oof_positioned_node.h
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_OOF_POSITIONED_NODE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_OOF_POSITIONED_NODE_H_ @@ -383,7 +378,7 @@ HeapVector<PhysicalOofNodeForFragmentation>& descendants = const_cast<HeapVector<PhysicalOofNodeForFragmentation>&>( oof_data->oof_positioned_fragmentainer_descendants); - return {descendants.data(), descendants.size()}; + return descendants; } void Trace(Visitor* visitor) const override {
diff --git a/third_party/blink/renderer/core/layout/page_container_layout_algorithm.cc b/third_party/blink/renderer/core/layout/page_container_layout_algorithm.cc index 3f333ef..c2de93e3 100644 --- a/third_party/blink/renderer/core/layout/page_container_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/page_container_layout_algorithm.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/page_container_layout_algorithm.h" #include "third_party/blink/renderer/core/css/page_margins_style.h" @@ -352,10 +347,10 @@ const ComputedStyle* end_box_style, const PhysicalRect& edge_rect, EdgeAdjacency edge_adjacency) { - BlockNode nodes[3] = {CreateBlockNodeIfNeeded(start_box_style), - CreateBlockNodeIfNeeded(center_box_style), - CreateBlockNodeIfNeeded(end_box_style)}; - LayoutUnit main_axis_sizes[3]; + std::array<BlockNode, 3> nodes = {CreateBlockNodeIfNeeded(start_box_style), + CreateBlockNodeIfNeeded(center_box_style), + CreateBlockNodeIfNeeded(end_box_style)}; + std::array<LayoutUnit, 3> main_axis_sizes; ProgressionDirection dir; switch (edge_adjacency) { @@ -518,9 +513,9 @@ void PageContainerLayoutAlgorithm::CalculateEdgeMarginBoxSizes( PhysicalSize available_physical_size, - const BlockNode nodes[3], + const std::array<BlockNode, 3>& nodes, ProgressionDirection dir, - LayoutUnit final_main_axis_sizes[3]) const { + std::array<LayoutUnit, 3>& final_main_axis_sizes) const { LayoutUnit available_main_axis_size; if (IsHorizontal(dir)) { available_main_axis_size = available_physical_size.width; @@ -530,22 +525,23 @@ LogicalSize available_logical_size = available_physical_size.ConvertToLogical(Style().GetWritingMode()); - PreferredSizeInfo preferred_main_axis_sizes[3]; + std::array<PreferredSizeInfo, 3> preferred_main_axis_sizes; LayoutUnit total_max_size_for_auto; bool has_auto_sized_box = false; for (int i = 0; i < 3; i++) { if (!nodes[i]) { continue; } - preferred_main_axis_sizes[i] = + PreferredSizeInfo& preferred_size = preferred_main_axis_sizes[i]; + preferred_size = EdgeMarginNodePreferredSize(nodes[i], available_logical_size, dir); // Tentatively set main sizes to the preferred ones. Any auto specified size // will be adjusted further below. - final_main_axis_sizes[i] = preferred_main_axis_sizes[i].MaxLength(); + final_main_axis_sizes[i] = preferred_size.MaxLength(); - if (preferred_main_axis_sizes[i].IsAuto()) { + if (preferred_size.IsAuto()) { has_auto_sized_box = true; - total_max_size_for_auto += preferred_main_axis_sizes[i].MaxLength(); + total_max_size_for_auto += preferred_size.MaxLength(); } } @@ -574,10 +570,10 @@ // should therefore not be stretched). // // See https://drafts.csswg.org/css-page-3/#variable-auto-sizing - PreferredSizeInfo ac_sizes_for_start[3] = { + std::array<PreferredSizeInfo, 3> ac_sizes_for_start = { preferred_main_axis_sizes[CenterMarginBox], PreferredSizeInfo(), preferred_main_axis_sizes[StartMarginBox].Doubled()}; - PreferredSizeInfo ac_sizes_for_end[3] = { + std::array<PreferredSizeInfo, 3> ac_sizes_for_end = { preferred_main_axis_sizes[CenterMarginBox], PreferredSizeInfo(), preferred_main_axis_sizes[EndMarginBox].Doubled()}; @@ -622,7 +618,7 @@ } void PageContainerLayoutAlgorithm::ResolveTwoEdgeMarginBoxLengths( - const PreferredSizeInfo preferred_main_axis_sizes[3], + const std::array<PreferredSizeInfo, 3>& preferred_main_axis_sizes, LayoutUnit available_main_axis_size, LayoutUnit* first_main_axis_size, LayoutUnit* second_main_axis_size) { @@ -654,8 +650,8 @@ } LayoutUnit flex_space; // Additional space to distribute to auto-sized boxes. - LayoutUnit unflexed_sizes[3]; - LayoutUnit flex_factors[3]; + std::array<LayoutUnit, 3> unflexed_sizes; + std::array<LayoutUnit, 3> flex_factors; if (available_main_axis_size_for_flex > total_auto_max_size) { flex_space = available_main_axis_size_for_flex - total_auto_max_size; // The sum of the max content lengths is less than available length. Each
diff --git a/third_party/blink/renderer/core/layout/page_container_layout_algorithm.h b/third_party/blink/renderer/core/layout/page_container_layout_algorithm.h index 7201922..fadcbb03 100644 --- a/third_party/blink/renderer/core/layout/page_container_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/page_container_layout_algorithm.h
@@ -188,16 +188,17 @@ // Based on available size, size properties and intrinsic sizes, calculate the // main-axis size for each of the (up to) three page margin boxes along one of // the four edges, and place the result in `final_main_axis_sizes`. - void CalculateEdgeMarginBoxSizes(PhysicalSize available_physical_size, - const BlockNode nodes[3], - ProgressionDirection, - LayoutUnit final_main_axis_sizes[3]) const; + void CalculateEdgeMarginBoxSizes( + PhysicalSize available_physical_size, + const std::array<BlockNode, 3>& nodes, + ProgressionDirection, + std::array<LayoutUnit, 3>& final_main_axis_sizes) const; // Resolve at most two auto size values. The first and last entry in // preferred_main_axis_sizes may be auto. The one in the middle is required to // be non-auto. static void ResolveTwoEdgeMarginBoxLengths( - const PreferredSizeInfo preferred_main_axis_sizes[3], + const std::array<PreferredSizeInfo, 3>& preferred_main_axis_sizes, LayoutUnit available_main_axis_size, LayoutUnit* first_main_axis_size, LayoutUnit* second_main_axis_size);
diff --git a/third_party/blink/renderer/core/layout/physical_box_fragment.h b/third_party/blink/renderer/core/layout/physical_box_fragment.h index e68551f64..5bc6cdfa 100644 --- a/third_party/blink/renderer/core/layout/physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/physical_box_fragment.h
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_PHYSICAL_BOX_FRAGMENT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_PHYSICAL_BOX_FRAGMENT_H_ @@ -123,7 +118,8 @@ protected: friend class OutOfFlowLayoutPart; base::span<PhysicalFragmentLink> Children() const { - return base::span(buffer_, num_children_); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + return UNSAFE_TODO(base::span(buffer_, num_children_)); } private: @@ -677,8 +673,10 @@ const FragmentItems* ComputeItemsAddress() const { DCHECK(HasItems()); + // TODO(crbug.com/351564777): Resolve a buffer safety issue. return reinterpret_cast<const FragmentItems*>(base::bits::AlignUp( - reinterpret_cast<const uint8_t*>(this + 1), alignof(FragmentItems))); + reinterpret_cast<const uint8_t*>(UNSAFE_TODO(this + 1)), + alignof(FragmentItems))); } void SetInkOverflow(const PhysicalRect& self, const PhysicalRect& contents);
diff --git a/third_party/blink/renderer/core/layout/physical_fragment.cc b/third_party/blink/renderer/core/layout/physical_fragment.cc index 44d29e6..863e475e9 100644 --- a/third_party/blink/renderer/core/layout/physical_fragment.cc +++ b/third_party/blink/renderer/core/layout/physical_fragment.cc
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "base/ranges/algorithm.h" @@ -501,8 +496,7 @@ PhysicalFragment::OutOfFlowPositionedDescendants() const { if (!HasOutOfFlowPositionedDescendants()) return base::span<PhysicalOofPositionedNode>(); - return {oof_data_->OofPositionedDescendants().data(), - oof_data_->OofPositionedDescendants().size()}; + return oof_data_->OofPositionedDescendants(); } const FragmentedOofData* PhysicalFragment::GetFragmentedOofData() const {
diff --git a/third_party/blink/renderer/core/layout/physical_fragment.h b/third_party/blink/renderer/core/layout/physical_fragment.h index 13f0856b..813a5d9 100644 --- a/third_party/blink/renderer/core/layout/physical_fragment.h +++ b/third_party/blink/renderer/core/layout/physical_fragment.h
@@ -2,11 +2,6 @@ // 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/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_PHYSICAL_FRAGMENT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_PHYSICAL_FRAGMENT_H_ @@ -567,7 +562,8 @@ ConstIterator() = default; ConstIterator(const PhysicalFragmentLink* current, wtf_size_t size) - : current_(current), end_(current + size) { + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + : current_(current), end_(UNSAFE_TODO(current + size)) { SkipInvalidAndSetPostLayout(); } @@ -575,7 +571,8 @@ const PhysicalFragmentLink* operator->() const { return &post_layout_; } ConstIterator& operator++() { - ++current_; + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + UNSAFE_TODO(++current_); SkipInvalidAndSetPostLayout(); return *this; } @@ -593,7 +590,8 @@ private: void SkipInvalidAndSetPostLayout() { - for (; current_ != end_; ++current_) { + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + for (; current_ != end_; UNSAFE_TODO(++current_)) { const PhysicalFragment* fragment = current_->fragment.Get(); if (fragment->IsLayoutObjectDestroyedOrMoved()) [[unlikely]] { continue; @@ -613,7 +611,10 @@ using const_iterator = ConstIterator; const_iterator begin() const { return const_iterator(buffer_, count_); } - const_iterator end() const { return const_iterator(buffer_ + count_, 0); } + const_iterator end() const { + // TODO(crbug.com/351564777): Resolve a buffer safety issue. + return const_iterator(UNSAFE_TODO(buffer_ + count_), 0); + } wtf_size_t size() const { return count_; } bool empty() const { return count_ == 0; }
diff --git a/third_party/blink/renderer/core/layout/table/table_layout_utils.cc b/third_party/blink/renderer/core/layout/table/table_layout_utils.cc index 5222ff9..f831a56 100644 --- a/third_party/blink/renderer/core/layout/table/table_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/table/table_layout_utils.cc
@@ -478,8 +478,8 @@ // https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm enum { kMinGuess, kPercentageGuess, kSpecifiedGuess, kMaxGuess, kAboveMax }; // sizes are collected for all guesses except kAboveMax - LayoutUnit guess_sizes[kAboveMax]; - LayoutUnit guess_size_total_increases[kAboveMax]; + std::array<LayoutUnit, kAboveMax> guess_sizes; + std::array<LayoutUnit, kAboveMax> guess_size_total_increases; float total_percent = 0.0f; LayoutUnit total_auto_max_inline_size; LayoutUnit total_fixed_max_inline_size; @@ -501,30 +501,29 @@ total_percent += *column->percent; LayoutUnit percent_inline_size = column->ResolvePercentInlineSize(target_inline_size); - // TODO(crbug.com/351564777): Resolve a buffer safety issue. - UNSAFE_TODO(guess_sizes[kMinGuess]) += *column->min_inline_size; - UNSAFE_TODO(guess_sizes[kPercentageGuess]) += percent_inline_size; - UNSAFE_TODO(guess_sizes[kSpecifiedGuess]) += percent_inline_size; - UNSAFE_TODO(guess_sizes[kMaxGuess]) += percent_inline_size; - UNSAFE_TODO(guess_size_total_increases[kPercentageGuess]) += + guess_sizes[kMinGuess] += *column->min_inline_size; + guess_sizes[kPercentageGuess] += percent_inline_size; + guess_sizes[kSpecifiedGuess] += percent_inline_size; + guess_sizes[kMaxGuess] += percent_inline_size; + guess_size_total_increases[kPercentageGuess] += percent_inline_size - *column->min_inline_size; } else if (column->is_constrained) { // Fixed column fixed_columns_count++; total_fixed_max_inline_size += *column->max_inline_size; - UNSAFE_TODO(guess_sizes[kMinGuess]) += *column->min_inline_size; - UNSAFE_TODO(guess_sizes[kPercentageGuess]) += *column->min_inline_size; - UNSAFE_TODO(guess_sizes[kSpecifiedGuess]) += *column->max_inline_size; - UNSAFE_TODO(guess_sizes[kMaxGuess]) += *column->max_inline_size; - UNSAFE_TODO(guess_size_total_increases[kSpecifiedGuess]) += + guess_sizes[kMinGuess] += *column->min_inline_size; + guess_sizes[kPercentageGuess] += *column->min_inline_size; + guess_sizes[kSpecifiedGuess] += *column->max_inline_size; + guess_sizes[kMaxGuess] += *column->max_inline_size; + guess_size_total_increases[kSpecifiedGuess] += *column->max_inline_size - *column->min_inline_size; } else { // Auto column auto_columns_count++; total_auto_max_inline_size += *column->max_inline_size; - UNSAFE_TODO(guess_sizes[kMinGuess]) += *column->min_inline_size; - UNSAFE_TODO(guess_sizes[kPercentageGuess]) += *column->min_inline_size; - UNSAFE_TODO(guess_sizes[kSpecifiedGuess]) += *column->min_inline_size; - UNSAFE_TODO(guess_sizes[kMaxGuess]) += *column->max_inline_size; - UNSAFE_TODO(guess_size_total_increases[kMaxGuess]) += + guess_sizes[kMinGuess] += *column->min_inline_size; + guess_sizes[kPercentageGuess] += *column->min_inline_size; + guess_sizes[kSpecifiedGuess] += *column->min_inline_size; + guess_sizes[kMaxGuess] += *column->max_inline_size; + guess_size_total_increases[kMaxGuess] += *column->max_inline_size - *column->min_inline_size; } } @@ -536,14 +535,11 @@ // Target inline size must be wider than sum of min inline sizes. // This is always true for assignable_table_inline_size, but not for // colspan_cells. - // TODO(crbug.com/351564777): Resolve a buffer safety issue. - target_inline_size = - std::max(target_inline_size, UNSAFE_TODO(guess_sizes[kMinGuess])); + target_inline_size = std::max(target_inline_size, guess_sizes[kMinGuess]); unsigned starting_guess = kAboveMax; for (unsigned i = kMinGuess; i != kAboveMax; ++i) { - // TODO(crbug.com/351564777): Resolve a buffer safety issue. - if (UNSAFE_TODO(guess_sizes[i]) >= target_inline_size) { + if (guess_sizes[i] >= target_inline_size) { starting_guess = i; break; } @@ -565,11 +561,10 @@ case kPercentageGuess: { // Percent columns grow in proportion to difference between their // percentage size and their minimum size. - // TODO(crbug.com/351564777): Resolve a buffer safety issue. LayoutUnit percent_inline_size_increase = - UNSAFE_TODO(guess_size_total_increases[kPercentageGuess]); + guess_size_total_increases[kPercentageGuess]; LayoutUnit distributable_inline_size = - target_inline_size - UNSAFE_TODO(guess_sizes[kMinGuess]); + target_inline_size - guess_sizes[kMinGuess]; LayoutUnit remaining_deficit = distributable_inline_size; LayoutUnit* computed_size = computed_sizes.data(); LayoutUnit* last_computed_size = nullptr; @@ -606,11 +601,10 @@ } break; case kSpecifiedGuess: { // Fixed columns grow, auto gets min, percent gets %max. - // TODO(crbug.com/351564777): Resolve a buffer safety issue. LayoutUnit fixed_inline_size_increase = - UNSAFE_TODO(guess_size_total_increases[kSpecifiedGuess]); + guess_size_total_increases[kSpecifiedGuess]; LayoutUnit distributable_inline_size = - target_inline_size - UNSAFE_TODO(guess_sizes[kPercentageGuess]); + target_inline_size - guess_sizes[kPercentageGuess]; LayoutUnit remaining_deficit = distributable_inline_size; LayoutUnit* last_computed_size = nullptr; LayoutUnit* computed_size = computed_sizes.data(); @@ -645,20 +639,17 @@ } break; case kMaxGuess: { // Auto columns grow, fixed gets max, percent gets %max. - // TODO(crbug.com/351564777): Resolve a buffer safety issue. LayoutUnit auto_inline_size_increase = - UNSAFE_TODO(guess_size_total_increases[kMaxGuess]); + guess_size_total_increases[kMaxGuess]; LayoutUnit distributable_inline_size = - UNSAFE_TODO(target_inline_size - guess_sizes[kSpecifiedGuess]); + target_inline_size - guess_sizes[kSpecifiedGuess]; // When the inline-sizes match exactly, this usually means that table // inline-size is auto, and that columns should be wide enough to // accommodate content without wrapping. // Instead of using the distributing math to compute final column // inline-size, we use the max inline-size. Using distributing math can // cause rounding errors, and unintended line wrap. - // TODO(crbug.com/351564777): Resolve a buffer safety issue. - bool is_exact_match = - target_inline_size == UNSAFE_TODO(guess_sizes[kMaxGuess]); + bool is_exact_match = target_inline_size == guess_sizes[kMaxGuess]; LayoutUnit remaining_deficit = is_exact_match ? LayoutUnit() : distributable_inline_size; LayoutUnit* last_computed_size = nullptr; @@ -694,9 +685,8 @@ } } break; case kAboveMax: { - // TODO(crbug.com/351564777): Resolve a buffer safety issue. LayoutUnit distributable_inline_size = - target_inline_size - UNSAFE_TODO(guess_sizes[kMaxGuess]); + target_inline_size - guess_sizes[kMaxGuess]; if (auto_columns_count > 0) { // Grow auto columns if available. LayoutUnit remaining_deficit = distributable_inline_size;
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc index f196c331..d605d7c 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -779,7 +779,9 @@ data.referrer_policy = network::mojom::ReferrerPolicy::kNever; data.link_text = anchor->innerText().Utf8(); + } + if (auto* anchor = DynamicTo<HTMLAnchorElementBase>(result.URLElement())) { if (AttributionSrcLoader* attribution_src_loader = selected_frame->GetAttributionSrcLoader()) { data.impression = attribution_src_loader->PrepareContextMenuNavigation(
diff --git a/third_party/blink/renderer/core/page/context_menu_controller_test.cc b/third_party/blink/renderer/core/page/context_menu_controller_test.cc index 1e345db..07c51750 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller_test.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
@@ -47,6 +47,7 @@ #include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/html_anchor_element.h" +#include "third_party/blink/renderer/core/html/html_area_element.h" #include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/html_embed_element.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h" @@ -2068,29 +2069,38 @@ }, }; - for (const auto& test_case : kTestCases) { - Persistent<HTMLAnchorElement> anchor = - MakeGarbageCollected<HTMLAnchorElement>(*GetDocument()); - anchor->setInnerText("abc"); + for (bool use_anchor : {true, false}) { + for (const auto& test_case : kTestCases) { + Persistent<HTMLAnchorElementBase> anchor; + if (use_anchor) { + anchor = MakeGarbageCollected<HTMLAnchorElement>(*GetDocument()); + } else { + anchor = MakeGarbageCollected<HTMLAreaElement>(*GetDocument()); + } - if (test_case.href) - anchor->SetHref(AtomicString(test_case.href)); + anchor->setInnerText("abc"); - if (test_case.attributionsrc) { - anchor->setAttribute(html_names::kAttributionsrcAttr, - AtomicString(test_case.attributionsrc)); + if (test_case.href) { + anchor->SetHref(AtomicString(test_case.href)); + } + + if (test_case.attributionsrc) { + anchor->setAttribute(html_names::kAttributionsrcAttr, + AtomicString(test_case.attributionsrc)); + } + + GetPage()->SetAttributionSupport( + network::mojom::AttributionSupport::kWeb); + + GetDocument()->body()->AppendChild(anchor); + ASSERT_TRUE(ShowContextMenuForElement(anchor, kMenuSourceMouse)); + + ContextMenuData context_menu_data = + GetWebFrameClient().GetContextMenuData(); + + EXPECT_EQ(context_menu_data.impression.has_value(), + test_case.impression_expected); } - - GetPage()->SetAttributionSupport(network::mojom::AttributionSupport::kWeb); - - GetDocument()->body()->AppendChild(anchor); - ASSERT_TRUE(ShowContextMenuForElement(anchor, kMenuSourceMouse)); - - ContextMenuData context_menu_data = - GetWebFrameClient().GetContextMenuData(); - - EXPECT_EQ(context_menu_data.impression.has_value(), - test_case.impression_expected); } }
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc index 13dbf87..118dc22 100644 --- a/third_party/blink/renderer/core/page/focus_controller.cc +++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -77,34 +77,191 @@ namespace { -const Element* MaybeAdjustSearchElementForFocusGroup(const Element& element, - bool get_last) { - auto* scroll_marker = DynamicTo<ScrollMarkerPseudoElement>(element); - if (!scroll_marker) { - return &element; +// Start of carousel helpers for focus navigation. +// As per https://drafts.csswg.org/css-overflow-5/#focus-order, +// focus order for carousel scroller and pseudo elements is different +// from usual DOM order, these functions here help to achieve the specced +// order. +Element* GetSelectedScrollMarkerFromScrollMarkerGroup(const Element& current) { + if (auto* scroll_marker_group = + DynamicTo<ScrollMarkerGroupPseudoElement>(current)) { + return scroll_marker_group->Selected(); } - CHECK(scroll_marker->ScrollMarkerGroup()); - const auto& scroll_markers = - scroll_marker->ScrollMarkerGroup()->ScrollMarkers(); - return get_last ? scroll_markers.back() : scroll_markers.front(); + return nullptr; } -// https://open-ui.org/components/focusgroup.explainer/#last-focused-memory -Element* MaybeRestoreFocusedElementForFocusGroup(Element* element) { - if (!element) { - return nullptr; - } - auto* scroll_marker = DynamicTo<ScrollMarkerPseudoElement>(element); - if (!scroll_marker) { - return element; - } - CHECK(scroll_marker->ScrollMarkerGroup()); - if (!scroll_marker->ScrollMarkerGroup()->Selected()) { +bool ElementHasScrollButton(const Element& element) { + return element.GetPseudoElement(kPseudoIdScrollUpButton) || + element.GetPseudoElement(kPseudoIdScrollDownButton) || + element.GetPseudoElement(kPseudoIdScrollLeftButton) || + element.GetPseudoElement(kPseudoIdScrollRightButton); +} + +bool ElementHasPrecedingCarouselPseudoElement(const Element& element) { + return element.GetPseudoElement(kPseudoIdScrollMarkerGroupBefore) || + ElementHasScrollButton(element); +} + +// Overwrites the DOM source order if it is currently inside a carousel or might +// move into the carousel element. If not, it will call NextIncludingPseudo. +// Carousel here means scroller with some special pseudo elements and the focus +// order changes as described below. +// DOM order for carousel is: +// scroller, ::scroll-marker-group(before), ::scroll-button(), +// scroller's children (with ::scroll-markers), ::scroll-marker-group(after). +// Carousel focus order is +// (https://drafts.csswg.org/css-overflow-5/#focus-order): +// ::scroll-marker-group(before), active ::scroll-marker, ::scroll-button(), +// scroller, scroller's children, ::scroll-marker-group(after). +// In some cases, we need to continue searching in DOM order for next +// focusable element from the element returned by this function, but +// in other cases, we should immediately return that element. +// `should_continue_search` argument determines the way we should +// take. +Element* GetNextInCarouselOrDomOrder(const Element& current, + const ContainerNode* stay_within, + bool& should_continue_search) { + should_continue_search = true; + // We should go to active ::scroll-marker from ::scroll-marker-group. + // And we do it here, since ::scroll-marker is not child of + // ::scroll-marker-group in DOM tree, but only in layout tree. + // Return early here, as we are sure that it should be next element + // from NextInDomOrder. + if (Element* scroll_marker = + GetSelectedScrollMarkerFromScrollMarkerGroup(current)) { + should_continue_search = false; return scroll_marker; } - return scroll_marker->ScrollMarkerGroup()->Selected(); + // From ::scroll-marker we try to move to: + if (auto* scroll_marker = DynamicTo<ScrollMarkerPseudoElement>(current)) { + const Element* scroll_marker_group = scroll_marker->ScrollMarkerGroup(); + CHECK(scroll_marker_group); + Element* scroller = scroll_marker_group->parentElement(); + // - ::scroll-button(), if ::::scroll-marker-group is before and scroller + // has buttons; + // - next element in DOM order, if ::::scroll-marker-group is after. + if (ElementHasScrollButton(*scroller) || + scroll_marker_group->IsScrollMarkerGroupAfterPseudoElement()) { + return ElementTraversal::NextIncludingPseudo(*scroll_marker_group, + stay_within); + } + // - scroller, if ::::scroll-marker-group is before and scroller doesn't + // have buttons; also, return early here, as AdjustNextForCarouselFocusOrder + // checks for scroller and can change result. + should_continue_search = false; + return scroller; + } + // If `current` has a ::scroll-marker-group() or a ::scroll-button(), we + // need to move to the next element in DOM order. + // Note: We can only get here when `current` has preceding + // carousel pseudo elements, since we force them to be result of calling `next + // element for focus` function, once we detect element has pseudos. + if (ElementHasPrecedingCarouselPseudoElement(current)) { + return ElementTraversal::Next(current, stay_within); + } + // If no special case, just find regular next element. + return ElementTraversal::NextIncludingPseudo(current, stay_within); } +// Once we found our next candidate, we might want to change it to follow +// the carousel focus order. +Element* AdjustNextForCarouselFocusOrder(const Element& current, + Element* next) { + if (!next) { + return nullptr; + } + // If we went from preceding carousel pseudos to non ::scroll-button(), + // we should return scroller (look at carousel focus order). + if ((current.IsScrollMarkerGroupBeforePseudoElement() || + current.IsScrollButtonPseudoElement()) && + !next->IsScrollButtonPseudoElement()) { + return current.parentElement(); + } + // If we found a scroller with preceding carousel pseudos, we should + // return them instead (look at carousel focus order). + if (ElementHasPrecedingCarouselPseudoElement(*next)) { + return ElementTraversal::NextIncludingPseudo(*next); + } + return next; +} + +// All the same as above, but backwards. +Element* GetPreviousInCarouselOrDomOrder(const Element& current, + const ContainerNode* stay_within, + bool& should_continue_search) { + should_continue_search = true; + // As per https://drafts.csswg.org/css-overflow-5/#focus-order, + // we should go to ::scroll-marker-group from active ::scroll-marker. + // And we do it here, since ::scroll-marker is not child of + // ::scroll-marker-group in DOM tree, but only in layout tree. + // Return early here, as we are sure that it should be next element + // from PreviousInDomOrder. + if (auto* scroll_marker = DynamicTo<ScrollMarkerPseudoElement>(current)) { + should_continue_search = false; + DCHECK(scroll_marker->ScrollMarkerGroup()); + return scroll_marker->ScrollMarkerGroup(); + } + // If we found a scroller with preceding Carousel pseudos, we should + // return the last of them instead, or ::scroll-marker for + // ::scroll-marker-group(before) (look at Carousel focus order). + if (ElementHasPrecedingCarouselPseudoElement(current)) { + // This order is described in + // https://drafts.csswg.org/css-overflow-5/#scroll-buttons + static std::array<PseudoId, 5> order = { + kPseudoIdScrollRightButton, kPseudoIdScrollLeftButton, + kPseudoIdScrollDownButton, kPseudoIdScrollUpButton, + kPseudoIdScrollMarkerGroupBefore}; + for (auto pseudo_id : order) { + if (Element* pseudo = current.GetPseudoElement(pseudo_id)) { + should_continue_search = false; + if (Element* scroll_marker = + GetSelectedScrollMarkerFromScrollMarkerGroup(*pseudo)) { + return scroll_marker; + } + return pseudo; + } + } + } + Element* previous = + ElementTraversal::PreviousIncludingPseudo(current, stay_within); + if (!previous) { + return nullptr; + } + // If we go from preceding Carousel pseudos to scroller, we should skip + // scroller. + if ((current.IsScrollButtonPseudoElement() || + current.IsScrollMarkerGroupBeforePseudoElement()) && + !previous->IsScrollButtonPseudoElement() && + !previous->IsScrollMarkerGroupBeforePseudoElement()) { + return ElementTraversal::PreviousIncludingPseudo(*current.parentElement(), + stay_within); + } + // If no special case, just find regular previous element. + return previous; +} + +Element* AdjustPreviousForCarouselFocusOrder(const Element& current, + Element* previous) { + if (!previous) { + return nullptr; + } + // If we went from non ::scroll-button() to preceding Carousel pseudo, + // we should return scroller (look at Carousel focus order). + if (!current.IsScrollButtonPseudoElement() && + (previous->IsScrollMarkerGroupBeforePseudoElement() || + previous->IsScrollButtonPseudoElement())) { + return previous->parentElement(); + } + // If we found ::scroll-marker-group, we should + // return its active ::scroll-marker, if it exists. + if (Element* scroll_marker = + GetSelectedScrollMarkerFromScrollMarkerGroup(*previous)) { + return scroll_marker; + } + return previous; +} +// End of carousel helpers. + bool IsOpenPopoverWithInvoker(const Node* node) { auto* popover = DynamicTo<HTMLElement>(node); return popover && popover->HasPopoverAttribute() && popover->popoverOpen() && @@ -297,13 +454,19 @@ const Element* NextInDomOrder(const Element& current) { Element* next; if (RuntimeEnabledFeatures::PseudoElementsFocusableEnabled()) { - const Element* adjusted_current = - MaybeAdjustSearchElementForFocusGroup(current, /*get_last=*/true); - next = ElementTraversal::NextIncludingPseudo(*adjusted_current, root_); - while (next && !IsOwnedByRoot(*next)) { + bool should_continue_search; + next = + GetNextInCarouselOrDomOrder(current, root_, should_continue_search); + if (!should_continue_search) { + return next; + } + // We skip every ::scroll-marker we find inside scroller, + // since we only want to get to it from ::scroll-marker-group. + while (next && + (!IsOwnedByRoot(*next) || next->IsScrollMarkerPseudoElement())) { next = ElementTraversal::NextIncludingPseudo(*next, root_); } - next = MaybeRestoreFocusedElementForFocusGroup(next); + next = AdjustNextForCarouselFocusOrder(current, next); } else { next = ElementTraversal::Next(current, root_); while (next && !IsOwnedByRoot(*next)) { @@ -327,17 +490,22 @@ const Element* PreviousInDomOrder(const Element& current) { Element* previous; if (RuntimeEnabledFeatures::PseudoElementsFocusableEnabled()) { - const Element* adjusted_current = - MaybeAdjustSearchElementForFocusGroup(current, /*get_last=*/false); - previous = - ElementTraversal::PreviousIncludingPseudo(*adjusted_current, root_); + bool should_continue_search; + previous = GetPreviousInCarouselOrDomOrder(current, root_, + should_continue_search); + if (!should_continue_search) { + return previous; + } if (previous == root_) { return nullptr; } - while (previous && !IsOwnedByRoot(*previous)) { + // We skip every ::scroll-marker we find inside scroller, + // since we only want to get to it from ::scroll-marker-group. + while (previous && (!IsOwnedByRoot(*previous) || + previous->IsScrollMarkerPseudoElement())) { previous = ElementTraversal::PreviousIncludingPseudo(*previous, root_); } - previous = MaybeRestoreFocusedElementForFocusGroup(previous); + previous = AdjustPreviousForCarouselFocusOrder(current, previous); } else { previous = ElementTraversal::Previous(current, root_); if (previous == root_) {
diff --git a/third_party/blink/renderer/core/page/focus_controller_test.cc b/third_party/blink/renderer/core/page/focus_controller_test.cc index 456c4cd1..1529167 100644 --- a/third_party/blink/renderer/core/page/focus_controller_test.cc +++ b/third_party/blink/renderer/core/page/focus_controller_test.cc
@@ -387,159 +387,496 @@ password, mojom::blink::FocusType::kForward)); } -TEST_F(FocusControllerTest, ScrollMarkersAreFocusable) { +TEST_F(FocusControllerTest, FullCarouselFocusOrder) { GetDocument().body()->setInnerHTML(R"HTML( <style> - #scroller { - overflow-y: scroll; - width: 200px; - height: 200px; - scroll-marker-group: after; - &::scroll-marker-group { - display: block; - height: 100px; - } - div { height: 200px; } - div::scroll-marker { content: '-'; } - div::scroll-marker:focus { opacity: 0.5; } - } + .scroller { overflow: hidden; width: 100px; height: 100px; } + .before { scroll-marker-group: before; } + .after { scroll-marker-group: after; } + .scroller::scroll-marker-group { height: 100px; } + .scroller::scroll-button(up) { content: "u"; } + .scroller::scroll-button(down) { content: "d"; } + .scroller::scroll-button(left) { content: "l"; } + .scroller::scroll-button(right) { content: "r"; } + .scroller::scroll-button(up):focus { outline: 1px solid blue; } + .scroller::scroll-button(down):focus { outline: 1px solid blue; } + .scroller::scroll-button(left):focus { outline: 1px solid blue; } + .scroller::scroll-button(right):focus { outline: 1px solid blue; } + .item { width: 100px; height: 100px; } + .item::scroll-marker:focus { outline: 1px solid blue; opacity: 0.5; } + .item::scroll-marker { content: "*" } + .item::scroll-marker:target-current { color: red; } </style> <input id="pre-input"> - <div id="scroller"> - <div>X</div> - <div>Y</div> - <div>Z</div> + <div id="before-scroller" class="before scroller" tabindex="0"> + <div id="01" class="item" tabindex="0">1</div> + <div id="02" class="item" tabindex="0">2</div> + <div id="03" class="item">3</div> + </div> + + <div id="after-scroller" class="after scroller" tabindex="0"> + <div id="11" class="item" tabindex="0">1</div> + <div id="12" class="item">2</div> + <div id="13" class="item" tabindex="0">3</div> </div> <input id="post-input"> )HTML"); UpdateAllLifecyclePhasesForTest(); - Element* scroller = GetElementById("scroller"); Element* pre_input = GetElementById("pre-input"); + Element* before_scroller = GetElementById("before-scroller"); + Element* after_scroller = GetElementById("after-scroller"); Element* post_input = GetElementById("post-input"); - auto* scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( - scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupAfter)); - ASSERT_TRUE(scroll_marker_group); + Element* before_up_button = + before_scroller->GetPseudoElement(kPseudoIdScrollUpButton); + Element* before_down_button = + before_scroller->GetPseudoElement(kPseudoIdScrollDownButton); + Element* before_left_button = + before_scroller->GetPseudoElement(kPseudoIdScrollLeftButton); + Element* before_right_button = + before_scroller->GetPseudoElement(kPseudoIdScrollRightButton); - Element* first_scroll_marker = - scroller->firstElementChild()->GetPseudoElement(kPseudoIdScrollMarker); - ASSERT_TRUE(first_scroll_marker); + Element* before_first_child = before_scroller->firstElementChild(); + Element* before_second_child = before_first_child->nextElementSibling(); - Element* second_scroll_marker = - scroller->firstElementChild()->nextElementSibling()->GetPseudoElement( - kPseudoIdScrollMarker); - ASSERT_TRUE(second_scroll_marker); + auto* before_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + before_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupBefore)); + Element* before_first_scroll_marker = + before_first_child->GetPseudoElement(kPseudoIdScrollMarker); + Element* before_second_scroll_marker = + before_second_child->GetPseudoElement(kPseudoIdScrollMarker); - Element* last_scroll_marker = - scroller->lastElementChild()->GetPseudoElement(kPseudoIdScrollMarker); - ASSERT_TRUE(last_scroll_marker); + Element* after_up_button = + after_scroller->GetPseudoElement(kPseudoIdScrollUpButton); + Element* after_down_button = + after_scroller->GetPseudoElement(kPseudoIdScrollDownButton); + Element* after_left_button = + after_scroller->GetPseudoElement(kPseudoIdScrollLeftButton); + Element* after_right_button = + after_scroller->GetPseudoElement(kPseudoIdScrollRightButton); - EXPECT_EQ(scroller, GetFocusController().FindFocusableElementAfter( - *pre_input, mojom::blink::FocusType::kForward)); - EXPECT_EQ(first_scroll_marker, - GetFocusController().FindFocusableElementAfter( - *scroller, mojom::blink::FocusType::kForward)); - EXPECT_EQ(post_input, - GetFocusController().FindFocusableElementAfter( - *first_scroll_marker, mojom::blink::FocusType::kForward)); + Element* after_first_child = after_scroller->firstElementChild(); + Element* after_last_child = after_scroller->lastElementChild(); - EXPECT_EQ(pre_input, GetFocusController().FindFocusableElementAfter( - *scroller, mojom::blink::FocusType::kBackward)); - EXPECT_EQ(scroller, - GetFocusController().FindFocusableElementAfter( - *first_scroll_marker, mojom::blink::FocusType::kBackward)); - EXPECT_EQ(first_scroll_marker, - GetFocusController().FindFocusableElementAfter( - *post_input, mojom::blink::FocusType::kBackward)); + auto* after_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + after_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupAfter)); + Element* after_first_scroll_marker = + after_first_child->GetPseudoElement(kPseudoIdScrollMarker); - second_scroll_marker->Focus(); + std::array<Element*, 20> order = {pre_input, + before_scroll_marker_group, + before_first_scroll_marker, + before_up_button, + before_down_button, + before_left_button, + before_right_button, + before_scroller, + before_first_child, + before_second_child, + after_up_button, + after_down_button, + after_left_button, + after_right_button, + after_scroller, + after_first_child, + after_last_child, + after_scroll_marker_group, + after_first_scroll_marker, + post_input}; + + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i + 1], GetFocusController().FindFocusableElementAfter( + *order[i], mojom::blink::FocusType::kForward)); + } + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i], GetFocusController().FindFocusableElementAfter( + *order[i + 1], mojom::blink::FocusType::kBackward)); + } + + before_second_scroll_marker->Focus(); GetFocusController().SetActive(true); GetFocusController().SetFocused(true); - scroll_marker_group->SetSelected( - *To<ScrollMarkerPseudoElement>(second_scroll_marker)); - const auto* style = second_scroll_marker->GetComputedStyle(); - EXPECT_TRUE(second_scroll_marker->IsFocused()); + before_scroll_marker_group->SetSelected( + *To<ScrollMarkerPseudoElement>(before_second_scroll_marker)); + const auto* style = before_second_scroll_marker->GetComputedStyle(); + EXPECT_TRUE(before_second_scroll_marker->IsFocused()); EXPECT_EQ(0.5, style->Opacity()); - - // Focusgroup restores last focused element. - EXPECT_EQ(scroller, GetFocusController().FindFocusableElementAfter( - *pre_input, mojom::blink::FocusType::kForward)); - EXPECT_EQ(second_scroll_marker, - GetFocusController().FindFocusableElementAfter( - *scroller, mojom::blink::FocusType::kForward)); - EXPECT_EQ(second_scroll_marker, - GetFocusController().FindFocusableElementAfter( - *post_input, mojom::blink::FocusType::kBackward)); - EXPECT_EQ(post_input, - GetFocusController().FindFocusableElementAfter( - *second_scroll_marker, mojom::blink::FocusType::kForward)); - EXPECT_EQ(scroller, - GetFocusController().FindFocusableElementAfter( - *second_scroll_marker, mojom::blink::FocusType::kBackward)); + EXPECT_EQ( + before_second_scroll_marker, + GetFocusController().FindFocusableElementAfter( + *before_scroll_marker_group, mojom::blink::FocusType::kForward)); + EXPECT_EQ(before_up_button, GetFocusController().FindFocusableElementAfter( + *before_second_scroll_marker, + mojom::blink::FocusType::kForward)); } -TEST_F(FocusControllerTest, ScrollButtonsAreFocusable) { +TEST_F(FocusControllerTest, CarouselWithOnlyButtonsFocusOrder) { GetDocument().body()->setInnerHTML(R"HTML( <style> - #scroller { - overflow: scroll; - width: 200px; - height: 200px; - &::scroll-button(inline-start), &::scroll-button(inline-end) { content: "-" } - &::scroll-button(inline-start):focus,&::scroll-button(inline-end):focus { opacity: 0.5 } - } - #spacer { width: 400px; height: 400px; } + .scroller { overflow: hidden; width: 100px; height: 100px; } + .scroller::scroll-button(up) { content: "u"; } + .scroller::scroll-button(down) { content: "d"; } + .scroller::scroll-button(left) { content: "l"; } + .scroller::scroll-button(right) { content: "r"; } + .scroller::scroll-button(up):focus { outline: 1px solid blue; opacity: 0.5; } + .scroller::scroll-button(down):focus { outline: 1px solid blue; } + .scroller::scroll-button(left):focus { outline: 1px solid blue; } + .scroller::scroll-button(right):focus { outline: 1px solid blue; } + .item { width: 100px; height: 100px; } </style> <input id="pre-input"> - <div id="scroller"> - <div id="spacer"></div> + <div id="before-scroller" class="before scroller" tabindex="0"> + <div id="01" class="item" tabindex="0">1</div> + <div id="02" class="item" tabindex="0">2</div> + <div id="03" class="item">3</div> </div> - <input id='post-input'> + + <div id="after-scroller" class="after scroller" tabindex="0"> + <div id="11" class="item" tabindex="0">1</div> + <div id="12" class="item">2</div> + <div id="13" class="item" tabindex="0">3</div> + </div> + <input id="post-input"> )HTML"); + UpdateAllLifecyclePhasesForTest(); - Element* scroller = GetElementById("scroller"); Element* pre_input = GetElementById("pre-input"); + Element* before_scroller = GetElementById("before-scroller"); + Element* after_scroller = GetElementById("after-scroller"); Element* post_input = GetElementById("post-input"); - PseudoElement* scroll_left_button = - scroller->GetPseudoElement(kPseudoIdScrollLeftButton); - ASSERT_TRUE(scroll_left_button); - PseudoElement* scroll_right_button = - scroller->GetPseudoElement(kPseudoIdScrollRightButton); - ASSERT_TRUE(scroll_right_button); + Element* before_up_button = + before_scroller->GetPseudoElement(kPseudoIdScrollUpButton); + Element* before_down_button = + before_scroller->GetPseudoElement(kPseudoIdScrollDownButton); + Element* before_left_button = + before_scroller->GetPseudoElement(kPseudoIdScrollLeftButton); + Element* before_right_button = + before_scroller->GetPseudoElement(kPseudoIdScrollRightButton); - EXPECT_EQ(scroller, GetFocusController().FindFocusableElementAfter( - *pre_input, mojom::blink::FocusType::kForward)); - EXPECT_EQ(scroll_left_button, - GetFocusController().FindFocusableElementAfter( - *scroller, mojom::blink::FocusType::kForward)); - EXPECT_EQ(scroll_right_button, - GetFocusController().FindFocusableElementAfter( - *scroll_left_button, mojom::blink::FocusType::kForward)); - EXPECT_EQ(post_input, - GetFocusController().FindFocusableElementAfter( - *scroll_right_button, mojom::blink::FocusType::kForward)); + Element* before_first_child = before_scroller->firstElementChild(); + Element* before_second_child = + before_scroller->firstElementChild()->nextElementSibling(); - EXPECT_EQ(pre_input, GetFocusController().FindFocusableElementAfter( - *scroller, mojom::blink::FocusType::kBackward)); - EXPECT_EQ(scroller, - GetFocusController().FindFocusableElementAfter( - *scroll_left_button, mojom::blink::FocusType::kBackward)); - EXPECT_EQ(scroll_left_button, - GetFocusController().FindFocusableElementAfter( - *scroll_right_button, mojom::blink::FocusType::kBackward)); - EXPECT_EQ(scroll_right_button, - GetFocusController().FindFocusableElementAfter( - *post_input, mojom::blink::FocusType::kBackward)); + Element* after_up_button = + after_scroller->GetPseudoElement(kPseudoIdScrollUpButton); + Element* after_down_button = + after_scroller->GetPseudoElement(kPseudoIdScrollDownButton); + Element* after_left_button = + after_scroller->GetPseudoElement(kPseudoIdScrollLeftButton); + Element* after_right_button = + after_scroller->GetPseudoElement(kPseudoIdScrollRightButton); - scroll_right_button->Focus(); + Element* after_first_child = after_scroller->firstElementChild(); + Element* after_last_child = after_scroller->lastElementChild(); + + std::array<Element*, 16> order = { + pre_input, before_up_button, before_down_button, + before_left_button, before_right_button, before_scroller, + before_first_child, before_second_child, after_up_button, + after_down_button, after_left_button, after_right_button, + after_scroller, after_first_child, after_last_child, + post_input}; + + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i + 1], GetFocusController().FindFocusableElementAfter( + *order[i], mojom::blink::FocusType::kForward)); + } + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i], GetFocusController().FindFocusableElementAfter( + *order[i + 1], mojom::blink::FocusType::kBackward)); + } + + before_up_button->Focus(); GetFocusController().SetActive(true); GetFocusController().SetFocused(true); - - const ComputedStyle* style = scroll_right_button->GetComputedStyle(); - EXPECT_TRUE(scroll_right_button->IsFocused()); + const auto* style = before_up_button->GetComputedStyle(); + EXPECT_TRUE(before_up_button->IsFocused()); EXPECT_EQ(0.5, style->Opacity()); } +TEST_F(FocusControllerTest, CarouselWithOnlyScrollMarkersFocusOrder) { + GetDocument().body()->setInnerHTML(R"HTML( + <style> + .scroller { overflow: hidden; width: 100px; height: 100px; } + .before { scroll-marker-group: before; } + .after { scroll-marker-group: after; } + .scroller::scroll-marker-group { height: 100px; } + .item { width: 100px; height: 100px; } + .item::scroll-marker:focus { outline: 1px solid blue; opacity: 0.5; } + .item::scroll-marker { content: "*" } + .item::scroll-marker:target-current { color: red; } + </style> + <input id="pre-input"> + <div id="before-scroller" class="before scroller" tabindex="0"> + <div id="01" class="item" tabindex="0">1</div> + <div id="02" class="item" tabindex="0">2</div> + <div id="03" class="item">3</div> + </div> + + <div id="after-scroller" class="after scroller" tabindex="0"> + <div id="11" class="item" tabindex="0">1</div> + <div id="12" class="item">2</div> + <div id="13" class="item" tabindex="0">3</div> + </div> + <input id="post-input"> + )HTML"); + + UpdateAllLifecyclePhasesForTest(); + Element* pre_input = GetElementById("pre-input"); + Element* before_scroller = GetElementById("before-scroller"); + Element* after_scroller = GetElementById("after-scroller"); + Element* post_input = GetElementById("post-input"); + + Element* before_first_child = before_scroller->firstElementChild(); + Element* before_second_child = + before_scroller->firstElementChild()->nextElementSibling(); + + auto* before_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + before_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupBefore)); + Element* before_first_scroll_marker = + before_first_child->GetPseudoElement(kPseudoIdScrollMarker); + + Element* after_first_child = after_scroller->firstElementChild(); + Element* after_last_child = after_scroller->lastElementChild(); + + auto* after_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + after_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupAfter)); + Element* after_first_scroll_marker = + after_first_child->GetPseudoElement(kPseudoIdScrollMarker); + + std::array<Element*, 12> order = {pre_input, + before_scroll_marker_group, + before_first_scroll_marker, + before_scroller, + before_first_child, + before_second_child, + after_scroller, + after_first_child, + after_last_child, + after_scroll_marker_group, + after_first_scroll_marker, + post_input}; + + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i + 1], GetFocusController().FindFocusableElementAfter( + *order[i], mojom::blink::FocusType::kForward)); + } + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i], GetFocusController().FindFocusableElementAfter( + *order[i + 1], mojom::blink::FocusType::kBackward)); + } +} + +TEST_F(FocusControllerTest, + CarouselWithOnlyScrollMarkersAndChildrenFocusOrder) { + GetDocument().body()->setInnerHTML(R"HTML( + <style> + .scroller { overflow: hidden; width: 100px; height: 100px; } + .before { scroll-marker-group: before; } + .after { scroll-marker-group: after; } + .scroller::scroll-marker-group { height: 100px; } + .item { width: 100px; height: 100px; } + </style> + <input id="pre-input"> + <div id="before-scroller" class="before scroller" tabindex="0"> + <div id="01" class="item" tabindex="0">1</div> + <div id="02" class="item" tabindex="0">2</div> + <div id="03" class="item">3</div> + </div> + + <div id="after-scroller" class="after scroller" tabindex="0"> + <div id="11" class="item" tabindex="0">1</div> + <div id="12" class="item">2</div> + <div id="13" class="item" tabindex="0">3</div> + </div> + <input id="post-input"> + )HTML"); + + UpdateAllLifecyclePhasesForTest(); + Element* pre_input = GetElementById("pre-input"); + Element* before_scroller = GetElementById("before-scroller"); + Element* after_scroller = GetElementById("after-scroller"); + Element* post_input = GetElementById("post-input"); + + Element* before_first_child = before_scroller->firstElementChild(); + Element* before_second_child = + before_scroller->firstElementChild()->nextElementSibling(); + + auto* before_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + before_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupBefore)); + + Element* after_first_child = after_scroller->firstElementChild(); + Element* after_last_child = after_scroller->lastElementChild(); + + auto* after_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + after_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupAfter)); + + std::array<Element*, 10> order = { + pre_input, before_scroll_marker_group, before_scroller, + before_first_child, before_second_child, after_scroller, + after_first_child, after_last_child, after_scroll_marker_group, + post_input}; + + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i + 1], GetFocusController().FindFocusableElementAfter( + *order[i], mojom::blink::FocusType::kForward)); + } + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i], GetFocusController().FindFocusableElementAfter( + *order[i + 1], mojom::blink::FocusType::kBackward)); + } +} + +TEST_F(FocusControllerTest, CarouselWithOnlyScrollMarkerGroupFocusOrder) { + GetDocument().body()->setInnerHTML(R"HTML( + <style> + .scroller { overflow: hidden; width: 100px; height: 100px; } + .before { scroll-marker-group: before; } + .after { scroll-marker-group: after; } + .scroller::scroll-marker-group { height: 100px; } + </style> + <input id="pre-input"> + <div id="before-scroller" class="before scroller" tabindex="0"></div> + + <div id="after-scroller" class="after scroller" tabindex="0"></div> + <input id="post-input"> + )HTML"); + + UpdateAllLifecyclePhasesForTest(); + Element* pre_input = GetElementById("pre-input"); + Element* before_scroller = GetElementById("before-scroller"); + Element* after_scroller = GetElementById("after-scroller"); + Element* post_input = GetElementById("post-input"); + + auto* before_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + before_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupBefore)); + + auto* after_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + after_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupAfter)); + + std::array<Element*, 6> order = { + pre_input, before_scroll_marker_group, before_scroller, + after_scroller, after_scroll_marker_group, post_input}; + + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i + 1], GetFocusController().FindFocusableElementAfter( + *order[i], mojom::blink::FocusType::kForward)); + } + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i], GetFocusController().FindFocusableElementAfter( + *order[i + 1], mojom::blink::FocusType::kBackward)); + } +} + +TEST_F(FocusControllerTest, FullCarouselWithExtraPseudoElementsFocusOrder) { + GetDocument().body()->setInnerHTML(R"HTML( + <style> + .scroller { overflow: hidden; width: 100px; height: 100px; } + .before { scroll-marker-group: before; } + .after { scroll-marker-group: after; } + .scroller::after { content: "after"; } + .scroller::before { content: "before"; } + .scroller::scroll-marker-group { height: 100px; } + .scroller::scroll-button(up) { content: "u"; } + .scroller::scroll-button(down) { content: "d"; } + .scroller::scroll-button(left) { content: "l"; } + .scroller::scroll-button(right) { content: "r"; } + .scroller::scroll-button(up):focus { outline: 1px solid blue; } + .scroller::scroll-button(down):focus { outline: 1px solid blue; } + .scroller::scroll-button(left):focus { outline: 1px solid blue; } + .scroller::scroll-button(right):focus { outline: 1px solid blue; } + .item { width: 100px; height: 100px; } + .item::scroll-marker:focus { outline: 1px solid blue; opacity: 0.5; } + .item::scroll-marker { content: "*" } + .item::scroll-marker:target-current { color: red; } + </style> + <input id="pre-input"> + <div id="before-scroller" class="before scroller" tabindex="0"> + <div id="01" class="item" tabindex="0">1</div> + <div id="02" class="item" tabindex="0">2</div> + <div id="03" class="item">3</div> + </div> + + <div id="after-scroller" class="after scroller" tabindex="0"> + <div id="11" class="item" tabindex="0">1</div> + <div id="12" class="item">2</div> + <div id="13" class="item" tabindex="0">3</div> + </div> + <input id="post-input"> + )HTML"); + + UpdateAllLifecyclePhasesForTest(); + Element* pre_input = GetElementById("pre-input"); + Element* before_scroller = GetElementById("before-scroller"); + Element* after_scroller = GetElementById("after-scroller"); + Element* post_input = GetElementById("post-input"); + + Element* before_up_button = + before_scroller->GetPseudoElement(kPseudoIdScrollUpButton); + Element* before_down_button = + before_scroller->GetPseudoElement(kPseudoIdScrollDownButton); + Element* before_left_button = + before_scroller->GetPseudoElement(kPseudoIdScrollLeftButton); + Element* before_right_button = + before_scroller->GetPseudoElement(kPseudoIdScrollRightButton); + + Element* before_first_child = before_scroller->firstElementChild(); + Element* before_second_child = + before_scroller->firstElementChild()->nextElementSibling(); + + auto* before_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + before_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupBefore)); + Element* before_first_scroll_marker = + before_first_child->GetPseudoElement(kPseudoIdScrollMarker); + + Element* after_up_button = + after_scroller->GetPseudoElement(kPseudoIdScrollUpButton); + Element* after_down_button = + after_scroller->GetPseudoElement(kPseudoIdScrollDownButton); + Element* after_left_button = + after_scroller->GetPseudoElement(kPseudoIdScrollLeftButton); + Element* after_right_button = + after_scroller->GetPseudoElement(kPseudoIdScrollRightButton); + + Element* after_first_child = after_scroller->firstElementChild(); + Element* after_last_child = after_scroller->lastElementChild(); + + auto* after_scroll_marker_group = To<ScrollMarkerGroupPseudoElement>( + after_scroller->GetPseudoElement(kPseudoIdScrollMarkerGroupAfter)); + Element* after_first_scroll_marker = + after_first_child->GetPseudoElement(kPseudoIdScrollMarker); + + std::array<Element*, 20> order = {pre_input, + before_scroll_marker_group, + before_first_scroll_marker, + before_up_button, + before_down_button, + before_left_button, + before_right_button, + before_scroller, + before_first_child, + before_second_child, + after_up_button, + after_down_button, + after_left_button, + after_right_button, + after_scroller, + after_first_child, + after_last_child, + after_scroll_marker_group, + after_first_scroll_marker, + post_input}; + + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i + 1], GetFocusController().FindFocusableElementAfter( + *order[i], mojom::blink::FocusType::kForward)); + } + for (std::size_t i = 0u; i < order.size() - 1; ++i) { + EXPECT_EQ(order[i], GetFocusController().FindFocusableElementAfter( + *order[i + 1], mojom::blink::FocusType::kBackward)); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/timing/animation_frame_timing_info.h b/third_party/blink/renderer/core/timing/animation_frame_timing_info.h index 0056c45..f925f31b 100644 --- a/third_party/blink/renderer/core/timing/animation_frame_timing_info.h +++ b/third_party/blink/renderer/core/timing/animation_frame_timing_info.h
@@ -137,6 +137,11 @@ total_blocking_duration_ = duration; } + void SetBeginFrameId(viz::BeginFrameId begin_frame_id) { + begin_frame_id_ = begin_frame_id; + } + viz::BeginFrameId BeginFrameId() const { return begin_frame_id_; } + void SetDidPause() { did_pause_ = true; } bool DidPause() const { return did_pause_; } @@ -170,6 +175,9 @@ HeapVector<Member<ScriptTimingInfo>> scripts_; + // Id for the BeginFrame, which triggered this animation frame. + viz::BeginFrameId begin_frame_id_; + // Whether the LoAF included sync XHR or alerts (pause). bool did_pause_ = false;
diff --git a/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc b/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc index 5192c79..1ef6e3b5 100644 --- a/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc +++ b/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
@@ -20,17 +20,15 @@ * Boston, MA 02110-1301, USA. */ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "third_party/blink/renderer/core/xml/xslt_processor.h" #include <libxslt/imports.h> #include <libxslt/security.h> #include <libxslt/variables.h> #include <libxslt/xsltutils.h> + +#include "base/containers/heap_array.h" +#include "base/containers/span.h" #include "base/numerics/checked_math.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/transform_source.h" @@ -54,7 +52,6 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" -#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" #include "third_party/blink/renderer/platform/wtf/shared_buffer.h" #include "third_party/blink/renderer/platform/wtf/text/string_buffer.h" #include "third_party/blink/renderer/platform/wtf/text/utf8.h" @@ -191,13 +188,13 @@ if (!len) return 0; - StringBuffer<UChar> string_buffer(len); + // SAFETY: libxslt provides `len` bytes pointed to by `buffer`. + auto source_buffer = + UNSAFE_BUFFERS(base::span(buffer, base::checked_cast<size_t>(len))); - base::span<const uint8_t> source_buffer( - reinterpret_cast<const uint8_t*>(buffer), - base::checked_cast<size_t>(len)); - WTF::unicode::ConversionResult result = - WTF::unicode::ConvertUTF8ToUTF16(source_buffer, string_buffer.Span()); + StringBuffer<UChar> string_buffer(len); + WTF::unicode::ConversionResult result = WTF::unicode::ConvertUTF8ToUTF16( + base::as_bytes(source_buffer), string_buffer.Span()); CHECK(result.status == WTF::unicode::kConversionOK || result.status == WTF::unicode::kSourceExhausted); @@ -233,49 +230,44 @@ return true; } -static char* AllocateParameterArray(const char* data) { - size_t length = strlen(data) + 1; - char* parameter_array = static_cast<char*>(WTF::Partitions::FastMalloc( - length, WTF_HEAP_PROFILER_TYPE_NAME(XSLTProcessor))); - memcpy(parameter_array, data, length); - return parameter_array; +static char* AllocateParameterValue(const String& value) { + StringUTF8Adaptor utf8(value); + auto parameter_value = base::HeapArray<char>::Uninit( + base::CheckAdd(utf8.size(), 1u).ValueOrDie()); + parameter_value.copy_prefix_from(base::span(utf8)); + parameter_value[utf8.size()] = '\0'; + return std::move(parameter_value).leak().data(); } -static const char** XsltParamArrayFromParameterMap( +static Vector<char*> XsltParamArrayFromParameterMap( XSLTProcessor::ParameterMap& parameters) { if (parameters.empty()) - return nullptr; + return {}; - base::CheckedNumeric<size_t> size = parameters.size(); + base::CheckedNumeric<wtf_size_t> size = parameters.size(); size *= 2; ++size; - size *= sizeof(char*); - const char** parameter_array = - static_cast<const char**>(WTF::Partitions::FastMalloc( - size.ValueOrDie(), WTF_HEAP_PROFILER_TYPE_NAME(XSLTProcessor))); + + Vector<char*> parameter_array(size.ValueOrDie()); unsigned index = 0; for (auto& parameter : parameters) { - parameter_array[index++] = - AllocateParameterArray(parameter.key.Utf8().c_str()); - parameter_array[index++] = - AllocateParameterArray(parameter.value.Utf8().c_str()); + parameter_array[index++] = AllocateParameterValue(parameter.key); + parameter_array[index++] = AllocateParameterValue(parameter.value); } parameter_array[index] = nullptr; - return parameter_array; } -static void FreeXsltParamArray(const char** params) { - const char** temp = params; - if (!params) +static void FreeXsltParamArray(Vector<char*>& params) { + if (params.empty()) { return; - - while (*temp) { - WTF::Partitions::FastFree(const_cast<char*>(*(temp++))); - WTF::Partitions::FastFree(const_cast<char*>(*(temp++))); } - WTF::Partitions::FastFree(params); + + for (auto& param : params) { + base::HeapArray<char>::DeleteLeakedData(param); + } + params.clear(); } static xsltStylesheetPtr XsltStylesheetPointer( @@ -406,8 +398,10 @@ if (!transform_context->globalVars) transform_context->globalVars = xmlHashCreate(20); - const char** params = XsltParamArrayFromParameterMap(parameters_); - xsltQuoteUserParams(transform_context, params); + Vector<char*> params = XsltParamArrayFromParameterMap(parameters_); + xsltQuoteUserParams( + transform_context, + static_cast<const char**>(static_cast<void*>(params.data()))); xmlDocPtr result_doc = xsltApplyStylesheetUser( sheet, source_doc, nullptr, nullptr, nullptr, transform_context);
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc index 6a422a0..21d3a8c 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_event_queue.cc
@@ -5,7 +5,6 @@ #include "third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h" #include "base/containers/contains.h" -#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/task/sequenced_task_runner.h" #include "base/time/default_tick_clock.h" @@ -15,13 +14,6 @@ namespace blink { -// This feature flag enables a new behavior that waits -// processing events until the top-level script is evaluated. -// See: https://crbug.com/1462568 -BASE_FEATURE(kServiceWorkerEventQueueWaitForScriptEvaluation, - "ServiceWorkerEventQueueWaitForScriptEvaluation", - base::FEATURE_ENABLED_BY_DEFAULT); - // static constexpr base::TimeDelta ServiceWorkerEventQueue::kEventTimeout; constexpr base::TimeDelta ServiceWorkerEventQueue::kUpdateInterval; @@ -63,12 +55,7 @@ : task_runner_(std::move(task_runner)), before_start_event_callback_(std::move(before_start_event_callback)), idle_callback_(std::move(idle_callback)), - tick_clock_(tick_clock) { - if (!base::FeatureList::IsEnabled( - kServiceWorkerEventQueueWaitForScriptEvaluation)) { - is_ready_for_processing_events_ = true; - } -} + tick_clock_(tick_clock) {} ServiceWorkerEventQueue::~ServiceWorkerEventQueue() { // Abort all callbacks. @@ -83,15 +70,9 @@ timer_.Start(FROM_HERE, kUpdateInterval, WTF::BindRepeating(&ServiceWorkerEventQueue::UpdateStatus, WTF::Unretained(this))); - if (base::FeatureList::IsEnabled( - kServiceWorkerEventQueueWaitForScriptEvaluation)) { - is_ready_for_processing_events_ = true; - ResetIdleTimeout(); - ProcessEvents(); - } else if (!HasInflightEvent() && !HasScheduledIdleCallback()) { - // If no event happens until Start(), the idle callback should be scheduled. - OnNoInflightEvent(); - } + is_ready_for_processing_events_ = true; + ResetIdleTimeout(); + ProcessEvents(); } void ServiceWorkerEventQueue::EnqueueNormal(
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.cc b/third_party/blink/renderer/modules/webgpu/gpu.cc index 670828da..3509b30a 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -72,6 +72,16 @@ } } +wgpu::FeatureLevel AsDawnFeatureLevel(const String& feature_level) { + CHECK(feature_level == "core" || feature_level == "compatibility"); + + if (feature_level == "compatibility") { + return wgpu::FeatureLevel::Compatibility; + } + + return wgpu::FeatureLevel::Core; +} + wgpu::RequestAdapterOptions AsDawnType( const GPURequestAdapterOptions* webgpu_options) { DCHECK(webgpu_options); @@ -79,10 +89,11 @@ wgpu::RequestAdapterOptions dawn_options; dawn_options.forceFallbackAdapter = webgpu_options->forceFallbackAdapter(); - dawn_options.compatibilityMode = webgpu_options->compatibilityMode(); - if (RuntimeEnabledFeatures::WebGPUFeatureLevelEnabled() && - webgpu_options->featureLevel() == "compatibility") { - dawn_options.compatibilityMode = true; + if (webgpu_options->compatibilityMode()) { + dawn_options.featureLevel = wgpu::FeatureLevel::Compatibility; + } else if (RuntimeEnabledFeatures::WebGPUFeatureLevelEnabled()) { + dawn_options.featureLevel = + AsDawnFeatureLevel(webgpu_options->featureLevel()); } if (webgpu_options->hasPowerPreference()) { @@ -392,6 +403,15 @@ "https://github.com/gpuweb/gpuweb/issues/4266"); } + if (options->compatibilityMode() && + options->featureLevel() != "compatibility") { + AddConsoleWarning(execution_context, + "The \"compatibilityMode\" option is deprecated. Use " + "\"featureLevel\": \"compatibility\" instead. See " + "https://gpuweb.github.io/gpuweb/" + "#dom-gpurequestadapteroptions-featurelevel"); + } + wgpu::RequestAdapterOptions dawn_options = AsDawnType(options); auto* callback = MakeWGPUOnceCallback(resolver->WrapCallbackInScriptScope( WTF::BindOnce(&GPU::OnRequestAdapterCallback, WrapPersistent(this),
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index c4caa949..bb3906c 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1790,6 +1790,7 @@ "//services/service_manager/public/cpp", "//services/viz/public/cpp/gpu", "//skia", + "//skia:rusty_png_feature_detection", "//skia:skcms", "//third_party:freetype_buildflags", "//third_party:freetype_harfbuzz",
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index 8f282a32..b00423e 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -183,44 +183,31 @@ if (!out_resource) return true; + auto client_shared_image = GetClientSharedImage(); + if (!client_shared_image) { + return false; + } + if (!CreatesAcceleratedTransferableResources()) { // Create a TransferableResource to be used with the software compositor. TRACE_EVENT0("blink", "CanvasResource::PrepareUnacceleratedTransferableResource"); - auto client_shared_image = GetClientSharedImage(); - if (!client_shared_image) { - return false; - } - *out_resource = viz::TransferableResource::MakeSoftwareSharedImage( client_shared_image, GetSyncToken(), client_shared_image->size(), client_shared_image->format(), viz::TransferableResource::ResourceSource::kCanvas); - out_resource->color_space = client_shared_image->color_space(); return true; } - return PrepareAcceleratedTransferableResourceFromClientSI( - out_resource, needs_verified_synctoken); -} - -bool CanvasResource::PrepareAcceleratedTransferableResourceFromClientSI( - viz::TransferableResource* out_resource, - bool needs_verified_synctoken) { TRACE_EVENT0("blink", "CanvasResource::PrepareAcceleratedTransferableResource"); - CHECK(CreatesAcceleratedTransferableResources()); // Gpu compositing is a prerequisite for compositing an accelerated resource DCHECK(SharedGpuContext::IsGpuCompositingEnabled()); if (!ContextProviderWrapper()) return false; - auto client_shared_image = GetClientSharedImage(); - - // The SharedImage should exist as long as the ContextProviderWrapper exists. - CHECK(client_shared_image); *out_resource = viz::TransferableResource::MakeGpu( client_shared_image->mailbox(), client_shared_image->GetTextureTarget(),
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h index 92dbc3a..2ac6aff 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -197,12 +197,6 @@ virtual base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper() const = 0; - // Prepares GPU TransferableResource from the resource's ClientSharedImage. - // Invoked if the resource is accelerated. - bool PrepareAcceleratedTransferableResourceFromClientSI( - viz::TransferableResource* out_resource, - bool needs_verified_synctoken); - CanvasResourceProvider* Provider() { return provider_.get(); } base::WeakPtr<CanvasResourceProvider> WeakProvider() { return provider_; }
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 66c839d..bba1024 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -1955,7 +1955,6 @@ // Set only when using swap chains. scoped_refptr<gpu::ClientSharedImage> front_buffer_shared_image; GLenum texture_target = GL_TEXTURE_2D; - bool created_mappable_si = false; // The SharedImages created here are read to and written from by WebGL. They // may also be read via the raster interface for WebGL->video and/or @@ -1996,6 +1995,8 @@ back_buffer_shared_image = std::move(shared_images.back_buffer); front_buffer_shared_image = std::move(shared_images.front_buffer); } else { + // First see if creating a SharedImage that can be used as an overlay is + // feasible. if (ShouldUseChromiumImage()) { #if !BUILDFLAG(IS_ANDROID) // Android's SharedImage backing for ChromiumImage does not support BGRX. @@ -2021,49 +2022,37 @@ } #endif // !BUILDFLAG(IS_ANDROID) - // TODO(crbug.com/911176): When RGB emulation is not needed, we should use - // the non-GMB CreateSharedImage with gpu::SHARED_IMAGE_USAGE_SCANOUT in - // order to allocate the GMB service-side and avoid a synchronous - // round-trip to the browser process here. - gpu::SharedImageUsageSet additional_usage_flags = - gpu::SHARED_IMAGE_USAGE_SCANOUT; - if (low_latency_enabled()) { - additional_usage_flags |= gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE; - } - if (gpu::IsImageFromGpuMemoryBufferFormatSupported( viz::SinglePlaneSharedImageFormatToBufferFormat( color_buffer_format_), ContextProvider()->GetCapabilities())) { - auto client_shared_image = sii->CreateSharedImage( + usage = usage | gpu::SHARED_IMAGE_USAGE_SCANOUT; + if (low_latency_enabled()) { + usage = usage | gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE; + } + back_buffer_shared_image = sii->CreateSharedImage( {color_buffer_format_, size, color_space_, origin, - back_buffer_alpha_type, - gpu::SharedImageUsageSet(usage | additional_usage_flags), - "WebGLDrawingBuffer"}, + back_buffer_alpha_type, usage, "WebGLDrawingBuffer"}, gpu::kNullSurfaceHandle); - created_mappable_si = true; - back_buffer_shared_image = std::move(client_shared_image); texture_target = back_buffer_shared_image->GetTextureTarget(); } } - // Create a normal SharedImage if Mappable SharedImage is not needed or the - // allocation above failed. - if (!created_mappable_si) { - // We want to set the correct SkAlphaType on the new shared image but in - // the case of ShouldUseChromiumImage() we instead keep this buffer - // premultiplied, draw to |premultiplied_alpha_false_mailbox_|, and - // convert during copy. + // If creating a SharedImage that can be used as an overlay was not an + // option, create a SharedImage without adding SCANOUT usage. + if (!back_buffer_shared_image) { + // Set the correct SkAlphaType on the new shared image (note that in the + // above case of creating a SharedImage that can be used as an overlay + // we instead keep this buffer premultiplied, draw to + // |premultiplied_alpha_false_mailbox_|, and convert during copy). if (requested_alpha_type_ == kUnpremul_SkAlphaType) { back_buffer_alpha_type = kUnpremul_SkAlphaType; } back_buffer_shared_image = sii->CreateSharedImage( {color_buffer_format_, size, color_space_, origin, - back_buffer_alpha_type, gpu::SharedImageUsageSet(usage), - "WebGLDrawingBuffer"}, + back_buffer_alpha_type, usage, "WebGLDrawingBuffer"}, gpu::kNullSurfaceHandle); - CHECK(back_buffer_shared_image); } }
diff --git a/third_party/blink/renderer/platform/image-encoders/DEPS b/third_party/blink/renderer/platform/image-encoders/DEPS index ed918fe..959d2da 100644 --- a/third_party/blink/renderer/platform/image-encoders/DEPS +++ b/third_party/blink/renderer/platform/image-encoders/DEPS
@@ -6,6 +6,7 @@ "+third_party/blink/renderer/platform/image-encoders", # Dependencies. + "+skia/rusty_png_feature.h", "+third_party/blink/renderer/platform/graphics/graphics_types.h", "+third_party/blink/renderer/platform/instrumentation/histogram.h", "+third_party/blink/renderer/platform/network/mime/mime_type_registry.h",
diff --git a/third_party/blink/renderer/platform/image-encoders/image_encoder.cc b/third_party/blink/renderer/platform/image-encoders/image_encoder.cc index 7bbab0fa..ff88a1475 100644 --- a/third_party/blink/renderer/platform/image-encoders/image_encoder.cc +++ b/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
@@ -6,14 +6,14 @@ #include "base/notreached.h" #include "build/build_config.h" +#include "skia/rusty_png_feature.h" #if BUILDFLAG(IS_WIN) #include <basetsd.h> // Included before jpeglib.h because of INT32 clash #endif -#include <stdio.h> // Needed by jpeglib.h +#include <stdio.h> // Needed by jpeglib.h #include "jpeglib.h" // for JPEG_MAX_DIMENSION - #include "third_party/libwebp/src/src/webp/encode.h" // for WEBP_MAX_DIMENSION namespace blink { @@ -29,7 +29,7 @@ const SkPixmap& src, const SkPngEncoder::Options& options) { VectorWStream dst_stream(dst); - return SkPngEncoder::Encode(&dst_stream, src, options); + return skia::EncodePng(&dst_stream, src, options); } bool ImageEncoder::Encode(Vector<unsigned char>* dst, @@ -59,7 +59,7 @@ const SkPngEncoder::Options& options) { std::unique_ptr<ImageEncoder> image_encoder(new ImageEncoder(dst)); image_encoder->encoder_ = - SkPngEncoder::Make(&image_encoder->dst_, src, options); + skia::MakePngEncoder(&image_encoder->dst_, src, options); if (!image_encoder->encoder_) { return nullptr; }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 1e70dea..90e4863 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -512,6 +512,12 @@ name: "AutoPictureInPictureVideoHeuristics", status: "experimental", }, + // When enabled, clicking on canvas element will not update the selection. + // See crbug.com/40130450. + { + name: "AvoidSelectionChangeOnCanvasClick", + status: "stable" + }, // When enabled, enforces new interoperable semantics for 3D transforms. // See crbug.com/1008483. { @@ -3819,7 +3825,7 @@ // only <option>, <optgroup>, and <hr>. // https://github.com/whatwg/html/issues/10310 name: "SelectParserRelaxation", - status: "experimental", + status: "stable", public: true, }, {
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 d304ec7..38cbcce 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
@@ -965,6 +965,7 @@ 'third_party/blink/renderer/core/frame/web_frame_widget_impl', 'third_party/blink/renderer/core/html/canvas', 'third_party/blink/renderer/core/offscreencanvas', + 'third_party/blink/renderer/core/timing/animation_frame_timing_info.h', 'third_party/blink/renderer/core/timing/window_performance', ], 'allowed': [
diff --git a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py index 09c9d138..57fcad9 100644 --- a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py +++ b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
@@ -392,7 +392,7 @@ for exclusive_test in suite.exclusive_tests: if not fs.exists(port.abspath_for_test( - exclusive_test)) and base not in wpt_tests: + exclusive_test)) and exclusive_test not in wpt_tests: failure = 'Exclusive_tests entry "{}" in virtual suite "{}" must refer to a real file or directory'.format( exclusive_test, prefix) failures.append(failure)
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index f97a91a..2d22cfe 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -4597,7 +4597,8 @@ "external/wpt/webidl/ecmascript-binding/global-mutable-prototype.any.shadowrealm-in-window.html", "external/wpt/webidl/ecmascript-binding/global-mutable-prototype.https.any.shadowrealm-in-audioworklet.html", "external/wpt/webidl/ecmascript-binding/global-mutable-prototype.https.any.shadowrealm-in-serviceworker.html", - "external/wpt/webidl/idlharness.any.shadowrealm-in-window.html" + "external/wpt/webidl/idlharness.any.shadowrealm-in-window.html", + "http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm.html" ], "exclusive_tests": "ALL", "args": ["--js-flags=--harmony-shadow-realm"],
diff --git a/third_party/blink/web_tests/editing/selection/doubleclick-canvas.html b/third_party/blink/web_tests/editing/selection/doubleclick-canvas.html new file mode 100644 index 0000000..e1ca18a --- /dev/null +++ b/third_party/blink/web_tests/editing/selection/doubleclick-canvas.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Clicking on canvas should not modify the selection</title> +<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> +<canvas id="target" width="50px" height="50px" style="background-color: #ADD8E6;"></canvas> +<p>Some text</p> +<script> + const selection = document.getSelection(); + const canvas = document.getElementById("target"); + generateDoubleClickSequence = () => new test_driver.Actions() + .pointerMove(0, 0, { origin: canvas }) + .pointerDown() + .pointerUp() + .pause(10) + .pointerDown() + .pointerUp(); + + promise_test(async () => { + let doubleClickEventFired = false; + canvas.addEventListener("dblclick", () => { + doubleClickEventFired = true; + }); + + assert_equals(selection.anchorNode, null, "Selection should be empty initially."); + assert_false(doubleClickEventFired); + + // Double cick on the canvas. + await generateDoubleClickSequence().send(); + + assert_true(doubleClickEventFired, "dblclick event should be fired."); + assert_equals(selection.anchorNode, null, "Selection should not change."); + }, "Clicking on canvas should not modify the selection."); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-error-event-exception.any.js b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-error-event-exception.any.js new file mode 100644 index 0000000..ade2a72 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-error-event-exception.any.js
@@ -0,0 +1,194 @@ +// META: global=window,worker +// META: title=Fire error event - Exception thrown +// META: script=resources/support.js + +// Spec: "https://w3c.github.io/IndexedDB/#fire-error-event" + +'use strict'; + +setup({allow_uncaught_exception: true}); + +function fire_error_event_test(func, description) { + indexeddb_test( + (t, db) => { + db.createObjectStore('s'); + }, + (t, db) => { + const tx = db.transaction('s', 'readwrite', {durability: 'relaxed'}); + tx.oncomplete = t.unreached_func('transaction should abort'); + const store = tx.objectStore('s'); + store.put(0, 0); + const request = store.add(0, 0); + request.onsuccess = t.unreached_func('request should fail'); + func(t, db, tx, request); + tx.addEventListener('abort', t.step_func_done(() => { + assert_equals(tx.error.name, 'AbortError'); + })); + }, + description); +} + +// Listeners on the request. + +fire_error_event_test((t, db, tx, request) => { + request.onerror = () => { + throw Error(); + }; +}, 'Exception in error event handler on request'); + +fire_error_event_test((t, db, tx, request) => { + request.onerror = e => { + e.preventDefault(); + throw Error(); + }; +}, 'Exception in error event handler on request, with preventDefault'); + +fire_error_event_test((t, db, tx, request) => { + request.addEventListener('error', () => { + throw Error(); + }); +}, 'Exception in error event listener on request'); + +fire_error_event_test((t, db, tx, request) => { + request.addEventListener('error', { + get handleEvent() { + throw new Error(); + }, + }); +}, 'Exception in error event listener ("handleEvent" lookup) on request'); + +fire_error_event_test((t, db, tx, request) => { + request.addEventListener('error', {}); +}, 'Exception in error event listener (non-callable "handleEvent") on request'); + +fire_error_event_test((t, db, tx, request) => { + request.addEventListener( + 'error', + () => { + // no-op + }); + request.addEventListener('error', () => { + throw Error(); + }); +}, 'Exception in second error event listener on request'); + +fire_error_event_test( + (t, db, tx, request) => { + let second_listener_called = false; + request.addEventListener('error', () => { + throw Error(); + }); + request.addEventListener('error', t.step_func(() => { + second_listener_called = true; + assert_true( + is_transaction_active(tx, 's'), + 'Transaction should be active until dispatch completes'); + })); + tx.addEventListener('abort', t.step_func(() => { + assert_true(second_listener_called); + })); + }, + 'Exception in first error event listener on request, ' + + 'transaction active in second'); + +// Listeners on the transaction. + +fire_error_event_test((t, db, tx, request) => { + tx.onerror = () => { + throw Error(); + }; +}, 'Exception in error event handler on transaction'); + +fire_error_event_test((t, db, tx, request) => { + tx.onerror = e => { + e.preventDefault(); + throw Error(); + }; +}, 'Exception in error event handler on transaction, with preventDefault'); + +fire_error_event_test((t, db, tx, request) => { + tx.addEventListener('error', () => { + throw Error(); + }); +}, 'Exception in error event listener on transaction'); + +fire_error_event_test((t, db, tx, request) => { + tx.addEventListener( + 'error', + () => { + // no-op + }); + tx.addEventListener('error', () => { + throw Error(); + }); +}, 'Exception in second error event listener on transaction'); + +fire_error_event_test( + (t, db, tx, request) => { + let second_listener_called = false; + tx.addEventListener('error', () => { + throw Error(); + }); + tx.addEventListener('error', t.step_func(() => { + second_listener_called = true; + assert_true( + is_transaction_active(tx, 's'), + 'Transaction should be active until dispatch completes'); + })); + tx.addEventListener('abort', t.step_func(() => { + assert_true(second_listener_called); + })); + }, + 'Exception in first error event listener on transaction, ' + + 'transaction active in second'); + +// Listeners on the connection. + +fire_error_event_test((t, db, tx, request) => { + db.onerror = () => { + throw Error(); + }; +}, 'Exception in error event handler on connection'); + +fire_error_event_test((t, db, tx, request) => { + db.onerror = e => { + e.preventDefault() + throw Error(); + }; +}, 'Exception in error event handler on connection, with preventDefault'); + +fire_error_event_test((t, db, tx, request) => { + db.addEventListener('error', () => { + throw Error(); + }); +}, 'Exception in error event listener on connection'); + +fire_error_event_test((t, db, tx, request) => { + db.addEventListener( + 'error', + () => { + // no-op + }); + db.addEventListener('error', () => { + throw Error(); + }); +}, 'Exception in second error event listener on connection'); + +fire_error_event_test( + (t, db, tx, request) => { + let second_listener_called = false; + db.addEventListener('error', () => { + throw Error(); + }); + db.addEventListener('error', t.step_func(() => { + second_listener_called = true; + assert_true( + is_transaction_active(tx, 's'), + 'Transaction should be active until dispatch completes'); + })); + tx.addEventListener('abort', t.step_func(() => { + assert_true(second_listener_called); + })); + }, + 'Exception in first error event listener on connection, ' + + 'transaction active in second');
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-error-event-exception.html b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-error-event-exception.html deleted file mode 100644 index f380e4081..0000000 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-error-event-exception.html +++ /dev/null
@@ -1,181 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>Fire error event - Exception thrown</title> -<link rel="help" href="https://w3c.github.io/IndexedDB/#fire-error-event"> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script src=resources/support.js></script> -<script> -setup({allow_uncaught_exception:true}); - -function fire_error_event_test(func, description) { - indexeddb_test( - (t, db) => { - db.createObjectStore('s'); - }, - (t, db) => { - const tx = db.transaction('s', 'readwrite', {durability: 'relaxed'}); - tx.oncomplete = t.unreached_func('transaction should abort'); - const store = tx.objectStore('s'); - store.put(0, 0); - const request = store.add(0, 0); - request.onsuccess = t.unreached_func('request should fail'); - func(t, db, tx, request); - tx.addEventListener('abort', t.step_func_done(() => { - assert_equals(tx.error.name, 'AbortError'); - })); - }, - description); -} - -// Listeners on the request. - -fire_error_event_test((t, db, tx, request) => { - request.onerror = () => { - throw Error(); - }; -}, 'Exception in error event handler on request'); - -fire_error_event_test((t, db, tx, request) => { - request.onerror = e => { - e.preventDefault(); - throw Error(); - }; -}, 'Exception in error event handler on request, with preventDefault'); - -fire_error_event_test((t, db, tx, request) => { - request.addEventListener('error', () => { - throw Error(); - }); -}, 'Exception in error event listener on request'); - -fire_error_event_test((t, db, tx, request) => { - request.addEventListener('error', { - get handleEvent() { - throw new Error(); - }, - }); -}, 'Exception in error event listener ("handleEvent" lookup) on request'); - -fire_error_event_test((t, db, tx, request) => { - request.addEventListener('error', {}); -}, 'Exception in error event listener (non-callable "handleEvent") on request'); - -fire_error_event_test((t, db, tx, request) => { - request.addEventListener('error', () => { - // no-op - }); - request.addEventListener('error', () => { - throw Error(); - }); -}, 'Exception in second error event listener on request'); - -fire_error_event_test((t, db, tx, request) => { - let second_listener_called = false; - request.addEventListener('error', () => { - throw Error(); - }); - request.addEventListener('error', t.step_func(() => { - second_listener_called = true; - assert_true(is_transaction_active(tx, 's'), - 'Transaction should be active until dispatch completes'); - })); - tx.addEventListener('abort', t.step_func(() => { - assert_true(second_listener_called); - })); -}, 'Exception in first error event listener on request, ' + - 'transaction active in second'); - -// Listeners on the transaction. - -fire_error_event_test((t, db, tx, request) => { - tx.onerror = () => { - throw Error(); - }; -}, 'Exception in error event handler on transaction'); - -fire_error_event_test((t, db, tx, request) => { - tx.onerror = e => { - e.preventDefault(); - throw Error(); - }; -}, 'Exception in error event handler on transaction, with preventDefault'); - -fire_error_event_test((t, db, tx, request) => { - tx.addEventListener('error', () => { - throw Error(); - }); -}, 'Exception in error event listener on transaction'); - -fire_error_event_test((t, db, tx, request) => { - tx.addEventListener('error', () => { - // no-op - }); - tx.addEventListener('error', () => { - throw Error(); - }); -}, 'Exception in second error event listener on transaction'); - -fire_error_event_test((t, db, tx, request) => { - let second_listener_called = false; - tx.addEventListener('error', () => { - throw Error(); - }); - tx.addEventListener('error', t.step_func(() => { - second_listener_called = true; - assert_true(is_transaction_active(tx, 's'), - 'Transaction should be active until dispatch completes'); - })); - tx.addEventListener('abort', t.step_func(() => { - assert_true(second_listener_called); - })); -}, 'Exception in first error event listener on transaction, ' + - 'transaction active in second'); - -// Listeners on the connection. - -fire_error_event_test((t, db, tx, request) => { - db.onerror = () => { - throw Error(); - }; -}, 'Exception in error event handler on connection'); - -fire_error_event_test((t, db, tx, request) => { - db.onerror = e => { - e.preventDefault() - throw Error(); - }; -}, 'Exception in error event handler on connection, with preventDefault'); - -fire_error_event_test((t, db, tx, request) => { - db.addEventListener('error', () => { - throw Error(); - }); -}, 'Exception in error event listener on connection'); - -fire_error_event_test((t, db, tx, request) => { - db.addEventListener('error', () => { - // no-op - }); - db.addEventListener('error', () => { - throw Error(); - }); -}, 'Exception in second error event listener on connection'); - -fire_error_event_test((t, db, tx, request) => { - let second_listener_called = false; - db.addEventListener('error', () => { - throw Error(); - }); - db.addEventListener('error', t.step_func(() => { - second_listener_called = true; - assert_true(is_transaction_active(tx, 's'), - 'Transaction should be active until dispatch completes'); - })); - tx.addEventListener('abort', t.step_func(() => { - assert_true(second_listener_called); - })); -}, 'Exception in first error event listener on connection, ' + - 'transaction active in second'); - -</script>
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-success-event-exception.any.js b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-success-event-exception.any.js new file mode 100644 index 0000000..bd757ea6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-success-event-exception.any.js
@@ -0,0 +1,80 @@ +// META: global=window,worker +// META: title=Fire success event - Exception thrown +// META: script=resources/support.js + +// Spec: "https://w3c.github.io/IndexedDB/#fire-success-event" + +'use strict'; + +setup({allow_uncaught_exception: true}); + +function fire_success_event_test(func, description) { + indexeddb_test( + (t, db) => { + db.createObjectStore('s'); + }, + (t, db) => { + const tx = db.transaction('s', 'readonly', {durability: 'relaxed'}); + tx.oncomplete = t.unreached_func('transaction should abort'); + const store = tx.objectStore('s'); + const request = store.get(0); + func(t, db, tx, request); + tx.addEventListener('abort', t.step_func_done(() => { + assert_equals(tx.error.name, 'AbortError'); + })); + }, + description); +} + +fire_success_event_test((t, db, tx, request) => { + request.onsuccess = () => { + throw Error(); + }; +}, 'Exception in success event handler on request'); + +fire_success_event_test((t, db, tx, request) => { + request.addEventListener('success', () => { + throw Error(); + }); +}, 'Exception in success event listener on request'); + +fire_success_event_test((t, db, tx, request) => { + request.addEventListener('success', { + get handleEvent() { + throw new Error(); + }, + }); +}, 'Exception in success event listener ("handleEvent" lookup) on request'); + +fire_success_event_test((t, db, tx, request) => { + request.addEventListener('success', { + handleEvent: null, + }); +}, 'Exception in success event listener (non-callable "handleEvent") on request'); + +fire_success_event_test((t, db, tx, request) => { + request.addEventListener( + 'success', + () => { + // no-op + }); + request.addEventListener('success', () => { + throw Error(); + }); +}, 'Exception in second success event listener on request'); + +fire_success_event_test((t, db, tx, request) => { + let second_listener_called = false; + request.addEventListener('success', () => { + throw Error(); + }); + request.addEventListener('success', t.step_func(() => { + second_listener_called = true; + assert_true( + is_transaction_active(tx, 's'), + 'Transaction should be active until dispatch completes'); + })); + tx.addEventListener('abort', t.step_func(() => { + assert_true(second_listener_called); + })); +}, 'Exception in first success event listener, tx active in second');
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-success-event-exception.html b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-success-event-exception.html deleted file mode 100644 index eaff1b9..0000000 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-success-event-exception.html +++ /dev/null
@@ -1,79 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>Fire success event - Exception thrown</title> -<link rel="help" href="https://w3c.github.io/IndexedDB/#fire-success-event"> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script src=resources/support.js></script> -<script> -setup({allow_uncaught_exception:true}); - -function fire_success_event_test(func, description) { - indexeddb_test( - (t, db) => { - db.createObjectStore('s'); - }, - (t, db) => { - const tx = db.transaction('s', 'readonly', {durability: 'relaxed'}); - tx.oncomplete = t.unreached_func('transaction should abort'); - const store = tx.objectStore('s'); - const request = store.get(0); - func(t, db, tx, request); - tx.addEventListener('abort', t.step_func_done(() => { - assert_equals(tx.error.name, 'AbortError'); - })); - }, - description); -} - -fire_success_event_test((t, db, tx, request) => { - request.onsuccess = () => { - throw Error(); - }; -}, 'Exception in success event handler on request'); - -fire_success_event_test((t, db, tx, request) => { - request.addEventListener('success', () => { - throw Error(); - }); -}, 'Exception in success event listener on request'); - -fire_success_event_test((t, db, tx, request) => { - request.addEventListener('success', { - get handleEvent() { - throw new Error(); - }, - }); -}, 'Exception in success event listener ("handleEvent" lookup) on request'); - -fire_success_event_test((t, db, tx, request) => { - request.addEventListener('success', { - handleEvent: null, - }); -}, 'Exception in success event listener (non-callable "handleEvent") on request'); - -fire_success_event_test((t, db, tx, request) => { - request.addEventListener('success', () => { - // no-op - }); - request.addEventListener('success', () => { - throw Error(); - }); -}, 'Exception in second success event listener on request'); - -fire_success_event_test((t, db, tx, request) => { - let second_listener_called = false; - request.addEventListener('success', () => { - throw Error(); - }); - request.addEventListener('success', t.step_func(() => { - second_listener_called = true; - assert_true(is_transaction_active(tx, 's'), - 'Transaction should be active until dispatch completes'); - })); - tx.addEventListener('abort', t.step_func(() => { - assert_true(second_listener_called); - })); -}, 'Exception in first success event listener, tx active in second'); - -</script>
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-upgradeneeded-event-exception.html b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-upgradeneeded-event-exception.any.js similarity index 74% rename from third_party/blink/web_tests/external/wpt/IndexedDB/fire-upgradeneeded-event-exception.html rename to third_party/blink/web_tests/external/wpt/IndexedDB/fire-upgradeneeded-event-exception.any.js index 7160dbd..3b17d90 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/fire-upgradeneeded-event-exception.html +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/fire-upgradeneeded-event-exception.any.js
@@ -1,16 +1,14 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>Fire upgradeneeded event - Exception thrown</title> -<link rel="help" href="https://w3c.github.io/IndexedDB/#fire-a-version-change-event"> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script src=resources/support.js></script> -<script> -setup({allow_uncaught_exception:true}); +// META: global=window,worker +// META: title=Fire upgradeneeded event - Exception thrown +// META: script=resources/support.js + +// Spec: "https://w3c.github.io/IndexedDB/#fire-a-version-change-event" + +setup({allow_uncaught_exception: true}); function fire_upgradeneeded_event_test(func, description) { async_test(t => { - const dbname = document.location + '-' + t.name; + const dbname = self.location + '-' + t.name; const del = indexedDB.deleteDatabase(dbname); del.onerror = t.unreached_func('deleteDatabase should succeed'); const open = indexedDB.open(dbname, 1); @@ -55,9 +53,11 @@ }, 'Exception in upgradeneeded due to non-callable "handleEvent"'); fire_upgradeneeded_event_test((t, open) => { - open.addEventListener('upgradeneeded', () => { - // No-op. - }); + open.addEventListener( + 'upgradeneeded', + () => { + // No-op. + }); open.addEventListener('upgradeneeded', () => { throw Error(); }); @@ -71,12 +71,11 @@ }); open.addEventListener('upgradeneeded', t.step_func(() => { second_listener_called = true; - assert_true(is_transaction_active(open.transaction, 's'), - 'Transaction should be active until dispatch completes'); + assert_true( + is_transaction_active(open.transaction, 's'), + 'Transaction should be active until dispatch completes'); })); open.addEventListener('error', t.step_func(() => { assert_true(second_listener_called); })); }, 'Exception in first upgradeneeded listener, tx active in second'); - -</script>
diff --git a/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js b/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js index b1916d0..a976fc55 100644 --- a/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js +++ b/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js
@@ -528,6 +528,132 @@ return outputs; } +function getInputName(operatorArguments, operandName) { + for (let argument of operatorArguments) { + const name = Object.keys(argument)[0]; + if (name === operandName) { + return argument[operandName]; + } else if (name === 'options') { + if (Object.keys(argument[name]).includes(operandName)) { + return argument[name][operandName]; + } + } + } + return null; +} + +// This assert() function is to check whether configurations of test case are +// set correctly. +function assert(condition, message) { + if (!condition) { + throw new Error(`Wrong test case, ${message}`); + } +} + +function validateContextSupportsGraph(context, graph) { + const supportLimits = context.opSupportLimits(); + const inputDataTypes = supportLimits.input.dataTypes; + const constantDataTypes = supportLimits.constant.dataTypes; + const outputDataTypes = supportLimits.output.dataTypes; + + function validateInputOrConstantDataType( + inputName, operatorSupportLimits, operand) { + const inputDataType = graph.inputs[inputName].descriptor.dataType; + if (graph.inputs[inputName].constant) { + if (!constantDataTypes.includes(inputDataType)) { + throw new TypeError( + `Unsupported data type, constant '${operand}' data type ${ + inputDataType} must be one of [${constantDataTypes}].`); + } + } else { + if (!inputDataTypes.includes(inputDataType)) { + throw new TypeError( + `Unsupported data type, input '${operand}' data type ${ + inputDataType} must be one of [${inputDataTypes}].`); + } + } + + if (!operatorSupportLimits[operand].dataTypes.includes(inputDataType)) { + throw new TypeError(`Unsupported data type, input '${ + operand}' data type ${inputDataType} must be one of [${ + operatorSupportLimits[operand].dataTypes}].`); + } + } + + function validateOutputDataType(outputName, operatorSupportLimits, operand) { + const outputDataType = + graph.expectedOutputs[outputName].descriptor.dataType; + if (!outputDataTypes.includes(outputDataType)) { + throw new TypeError( + `Unsupported data type, output '${operand}' data type ${ + outputDataType} must be one of [${outputDataTypes}].`); + } + + if (!operatorSupportLimits[operand].dataTypes.includes(outputDataType)) { + throw new TypeError(`Unsupported data type, output '${ + operand}' data type ${outputDataType} must be one of [${ + operatorSupportLimits[operand].dataTypes}].`); + } + } + + for (let operator of graph.operators) { + const operatorName = operator.name; + const operatorSupportLimits = supportLimits[operatorName]; + for (let operand of Object.keys(operatorSupportLimits)) { + if (operand === 'output') { + // single output operand + assert( + typeof operator.outputs === 'string', + `the outputs of ${operatorName} should be a string.`); + if (!graph.expectedOutputs[operator.outputs]) { + // intermediate output + continue; + } + validateOutputDataType( + operator.outputs, operatorSupportLimits, 'output'); + } else if (operand === 'outputs') { + // multiples output operands + assert( + Array.isArray(operator.outputs), + `the outputs of ${operatorName} should be a string array.`); + for (const outputName of operator.outputs) { + assert( + typeof outputName === 'string', + `the outputs' item of ${operatorName} should be a string.`); + if (!graph.expectedOutputs[outputName]) { + // intermediate output + continue; + } + validateOutputDataType(outputName, operatorSupportLimits, 'outputs'); + } + } else { + // input operand(s) + if (operatorName === 'concat') { + const inputNameArray = operator.arguments[0][operand]; + assert( + Array.isArray(inputNameArray), + `the inputs of ${operatorName} should be a string array.`); + for (const inputName of inputNameArray) { + assert( + typeof inputName === 'string', + `the inputs' item of ${operatorName} should be a string.`); + validateInputOrConstantDataType( + inputName, operatorSupportLimits, 'inputs'); + } + } else { + const inputName = getInputName(operator.arguments, operand); + if (inputName === null || !graph.inputs[inputName]) { + // default options argument or intermediate input + continue; + } + validateInputOrConstantDataType( + inputName, operatorSupportLimits, operand); + } + } + } + } +} + /** * This function is to execute the compiled graph. * @param {MLContext} context @@ -825,7 +951,7 @@ sizes.reduce( (accumulator, currentValue) => accumulator * currentValue) : 1; - } + }; const webnn_conformance_test = (buildAndExecuteGraphFunc, toleranceFunc, testResources) => { @@ -837,6 +963,7 @@ throw new AssertionError( `Unable to create context for ${variant} variant. ${e}`); } + validateContextSupportsGraph(context, testResources.graph); const builder = new MLGraphBuilder(context); const {result, intermediateOperands} = await buildAndExecuteGraphFunc( context, builder, testResources.graph);
diff --git a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/expand.https.any_gpu-expected.txt b/third_party/blink/web_tests/flag-specific/enable-skia-graphite/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/expand.https.any_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-skia-graphite/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/expand.https.any_gpu-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/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt b/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt new file mode 100644 index 0000000..bfd27c4 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm-expected.txt
@@ -0,0 +1,46 @@ +CONSOLE MESSAGE: This test logs exposed APIs from ShadowRealmGlobalScope +CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface ShadowRealm +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method evaluate +CONSOLE MESSAGE: method importValue +CONSOLE MESSAGE: interface ShadowRealmGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: namespace console +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method assert +CONSOLE MESSAGE: method clear +CONSOLE MESSAGE: method context +CONSOLE MESSAGE: method count +CONSOLE MESSAGE: method countReset +CONSOLE MESSAGE: method debug +CONSOLE MESSAGE: method dir +CONSOLE MESSAGE: method dirxml +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: method group +CONSOLE MESSAGE: method groupCollapsed +CONSOLE MESSAGE: method groupEnd +CONSOLE MESSAGE: method info +CONSOLE MESSAGE: method log +CONSOLE MESSAGE: method profile +CONSOLE MESSAGE: method profileEnd +CONSOLE MESSAGE: method table +CONSOLE MESSAGE: method time +CONSOLE MESSAGE: method timeEnd +CONSOLE MESSAGE: method timeLog +CONSOLE MESSAGE: method timeStamp +CONSOLE MESSAGE: method trace +CONSOLE MESSAGE: method warn +CONSOLE MESSAGE: [GLOBAL OBJECT] +CONSOLE MESSAGE: attribute globalThis +CONSOLE MESSAGE: getter isSecureContext +CONSOLE MESSAGE: method atob +CONSOLE MESSAGE: method btoa +CONSOLE MESSAGE: method gc +CONSOLE MESSAGE: method queueMicrotask +CONSOLE MESSAGE: method reportError +CONSOLE MESSAGE: method structuredClone +
diff --git a/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm.html b/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm.html new file mode 100644 index 0000000..9ea7524 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/shadowrealm/webexposed/global-interface-listing-shadow-realm.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<body> +<script type="module"> + if (window.testRunner) { + testRunner.waitUntilDone(); + testRunner.dumpAsText(); + } + + console.log("This test logs exposed APIs from ShadowRealmGlobalScope"); + // TODO(crbug.com/41480387): This should be imported using importValue() once it is supported. + const response = await fetch("/js-test-resources/global-interface-listing.js"); + const code = await response.text(); + const shadowRealm = new ShadowRealm(); + // TODO(crbug.com/41480387): This should use ShadowRealm's console once it is supported. + shadowRealm.evaluate(` + (function(log) { + ${code} + var propertyNamesInGlobal = Object.getOwnPropertyNames(globalThis); + globalInterfaceListing(globalThis, propertyNamesInGlobal, false, log); + }); + `)(console.log); + if (window.testRunner) { + testRunner.notifyDone(); + } +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt deleted file mode 100644 index 8aaf1e47..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -[FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int64 for argument input, must be one of [float32, float16, int32]." -[FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16, int32]." -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt deleted file mode 100644 index 8aaf1e47..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -[FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int64 for argument input, must be one of [float32, float16, int32]." -[FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16, int32]." -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt deleted file mode 100644 index 554b03d4..0000000 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -[FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] batchNormalization default + relu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + leakyRelu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + sigmoid - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + clamp - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] batchNormalization default + elu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization options.axis=0 + gelu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -[FAIL] batchNormalization default + hardSigmoid - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + hardSwish - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + linear - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization options.axis=0 + softplus - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -[FAIL] batchNormalization default + softsign - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization options.axis=0 + softmax - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-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/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-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/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt deleted file mode 100644 index 554b03d4..0000000 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -[FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] batchNormalization default + relu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + leakyRelu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + sigmoid - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + clamp - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] batchNormalization default + elu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization options.axis=0 + gelu - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -[FAIL] batchNormalization default + hardSigmoid - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + hardSwish - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization default + linear - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization options.axis=0 + softplus - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -[FAIL] batchNormalization default + softsign - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] batchNormalization options.axis=0 + softmax - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-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/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-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/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt similarity index 89% rename from third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt rename to third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt similarity index 89% copy from third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt copy to third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt index 814eb43..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac14/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt
@@ -1,54 +1,8 @@ This is a testharness.js-based test. -[FAIL] conv2d default + relu - assert_true: assert_array_approx_equals_ulp: test conv2d relu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 18 ULP distance, but they have 9045 ULP distance expected true got false -[FAIL] reshape + conv2d default/ float16 - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] conv2d default + sigmoid - assert_true: assert_array_approx_equals_ulp: test conv2d sigmoid float32 actual 0.82177734375 should be close enough to expected 0.8223466873168945 by the acceptable 52 ULP distance, but they have 9552 ULP distance expected true got false -[FAIL] conv2d default + clamp - assert_true: assert_array_approx_equals_ulp: test conv2d clamp float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 18 ULP distance, but they have 9045 ULP distance expected true got false -[FAIL] conv2d default + leakyRelu - assert_true: assert_array_approx_equals_ulp: test conv2d leakyRelu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 19 ULP distance, but they have 9045 ULP distance expected true got false -[FAIL] conv2d default + elu - assert_true: assert_array_approx_equals_ulp: test conv2d elu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 36 ULP distance, but they have 9045 ULP distance expected true got false [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] conv2d default + hardSwish - assert_true: assert_array_approx_equals_ulp: test conv2d hardSwish float32 actual 1.1552734375 should be close enough to expected 1.157502485501543 by the acceptable 22 ULP distance, but they have 18699 ULP distance expected true got false -[FAIL] conv2d default + gelu - assert_true: assert_array_approx_equals_ulp: test conv2d gelu float32 actual 1.4345703125 should be close enough to expected 1.436219573020935 by the acceptable 36 ULP distance, but they have 13835 ULP distance expected true got false -[FAIL] conv2d default + hardSigmoid - assert_true: assert_array_approx_equals_ulp: test conv2d hardSigmoid float32 actual 0.80615234375 should be close enough to expected 0.8064656598030677 by the acceptable 20 ULP distance, but they have 5257 ULP distance expected true got false -[FAIL] conv2d default + linear - assert_true: assert_array_approx_equals_ulp: test conv2d linear float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 20 ULP distance, but they have 9045 ULP distance expected true got false -[FAIL] conv2d default + softplus - assert_true: assert_array_approx_equals_ulp: test conv2d softplus float32 actual 1.7265625 should be close enough to expected 1.727921485900879 by the acceptable 36 ULP distance, but they have 11400 ULP distance expected true got false -[FAIL] conv2d default + softsign - assert_true: assert_array_approx_equals_ulp: test conv2d softsign float32 actual 0.6044921875 should be close enough to expected 0.6051064941347312 by the acceptable 21 ULP distance, but they have 10306 ULP distance expected true got false -[FAIL] convTranspose2d default + relu - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + leakyRelu - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + sigmoid - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + softplus - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + clamp - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + elu - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + gelu - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + hardSigmoid - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + hardSwish - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d default + linear - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." -[FAIL] convTranspose2d default + softsign - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -58,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu @@ -73,15 +27,7 @@ promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." [FAIL] batchNormalization default + softsign promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." -[FAIL] conv2d with options.inputLayout='nchw' + softmax - assert_true: assert_array_approx_equals_ulp: test conv2d softmax float32 actual 0.33315548300743103 should be close enough to expected 0.3331032991409302 by the acceptable 20 ULP distance, but they have 1751 ULP distance expected true got false -[FAIL] convTranspose2d default + softmax - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" -[FAIL] convTranspose2d with options.inputLayout=nchw + softmax - assert_true: assert_array_approx_equals_ulp: test convTranspose2d softmax float32 actual 0.4983367919921875 should be close enough to expected 0.49833576343872565 by the acceptable 27 ULP distance, but they have 35 ULP distance expected true got false [FAIL] batchNormalization options.axis=0 + softmax promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported axis for batchNormalization. It must be the channel dimension." -[FAIL] add + sub + mul + gather default - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': Error computing results" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any.worker_npu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/split.https.any_npu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-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/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-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/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any.worker_gpu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt index 5b37deb..d2490db 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/split.https.any_gpu-expected.txt
@@ -1,4 +1,3 @@ This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-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/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-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/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_cpu-expected.txt index 4165806..e80c1f974 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_cpu-expected.txt
@@ -1,45 +1,73 @@ This is a testharness.js-based test. [FAIL] cast float32 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast int32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any_cpu-expected.txt index 4165806..e80c1f974 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/cast.https.any_cpu-expected.txt
@@ -1,45 +1,73 @@ This is a testharness.js-based test. [FAIL] cast float32 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast int32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt index 2365dc7..97fcd5c 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt index 694adad4..bcc6b7e 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] dequantizeLinear int8 0D tensor with float32 scalar scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] dequantizeLinear constant input - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt index 694adad4..bcc6b7e 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] dequantizeLinear int8 0D tensor with float32 scalar scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] dequantizeLinear constant input - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/equal.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/equal.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..0053d60 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/equal.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] equal float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/equal.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/equal.https.any_cpu-expected.txt new file mode 100644 index 0000000..0053d60 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/equal.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] equal float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_cpu-expected.txt index 1a94b5dc..3cf80d70 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_cpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gather float32 1D tensor and uint32 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 1D tensor and int64 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 2D tensor and int32 0D out-of-bound positive indices default options assert_true: assert_array_approx_equals_ulp: test gather float32 actual -66.05901336669922 should be close enough to expected 90.2870101928711 by the acceptable 0 ULP distance, but they have 2150659260 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any_cpu-expected.txt index 1a94b5dc..3cf80d70 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gather.https.any_cpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gather float32 1D tensor and uint32 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 1D tensor and int64 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 2D tensor and int32 0D out-of-bound positive indices default options assert_true: assert_array_approx_equals_ulp: test gather float32 actual -66.05901336669922 should be close enough to expected 90.2870101928711 by the acceptable 0 ULP distance, but they have 2150659260 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_cpu-expected.txt index 806e1b0..d2895fc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_cpu-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. [FAIL] gatherElements float32 2D input and uint32 indices options.axis=1 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherElements float32 3D input and int32 negative indices assert_true: assert_array_approx_equals_ulp: test gatherElements float32 actual -66.05901336669922 should be close enough to expected 89.0337142944336 by the acceptable 0 ULP distance, but they have 2150494988 ULP distance expected true got false [FAIL] gatherElements float32 1D input and int32 out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_cpu-expected.txt index 806e1b0..d2895fc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_cpu-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. [FAIL] gatherElements float32 2D input and uint32 indices options.axis=1 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherElements float32 3D input and int32 negative indices assert_true: assert_array_approx_equals_ulp: test gatherElements float32 actual -66.05901336669922 should be close enough to expected 89.0337142944336 by the acceptable 0 ULP distance, but they have 2150494988 ULP distance expected true got false [FAIL] gatherElements float32 1D input and int32 out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_cpu-expected.txt index 5d0b479..a4f6fb5 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_cpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gatherND float32 4D input and 1D uint32 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 4D input and 1D int64 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 2D input and 2D negative indices assert_true: assert_array_approx_equals_ulp: test gatherND float32 actual -66.05901336669922 should be close enough to expected 44.92119598388672 by the acceptable 0 ULP distance, but they have 2142212375 ULP distance expected true got false [FAIL] gatherND float32 1D input and 2D out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any_cpu-expected.txt index 5d0b479..a4f6fb5 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherND.https.any_cpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gatherND float32 4D input and 1D uint32 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 4D input and 1D int64 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 2D input and 2D negative indices assert_true: assert_array_approx_equals_ulp: test gatherND float32 actual -66.05901336669922 should be close enough to expected 44.92119598388672 by the acceptable 0 ULP distance, but they have 2142212375 ULP distance expected true got false [FAIL] gatherND float32 1D input and 2D out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..163c599 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greater float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater.https.any_cpu-expected.txt new file mode 100644 index 0000000..163c599 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greater float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..f61ec895 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greaterOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_cpu-expected.txt new file mode 100644 index 0000000..f61ec895 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greaterOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..ee456d7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesser float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser.https.any_cpu-expected.txt new file mode 100644 index 0000000..ee456d7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesser float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..f4d1184 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesserOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_cpu-expected.txt new file mode 100644 index 0000000..f4d1184 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesserOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..5b4922da --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalAnd uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_and.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_and.https.any_cpu-expected.txt new file mode 100644 index 0000000..5b4922da --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_and.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalAnd uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..d22037d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_cpu-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +[FAIL] logicalNot uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D constant tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 5D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_not.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_not.https.any_cpu-expected.txt new file mode 100644 index 0000000..d22037d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_not.https.any_cpu-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +[FAIL] logicalNot uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D constant tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 5D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..d7bb56a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalOr uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_or.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_or.https.any_cpu-expected.txt new file mode 100644 index 0000000..d7bb56a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_or.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalOr uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..46043f26 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalXor uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_xor.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_xor.https.any_cpu-expected.txt new file mode 100644 index 0000000..46043f26 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/logical_xor.https.any_cpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalXor uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_cpu-expected.txt index e2e55e12..51f7fa97 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_cpu-expected.txt
@@ -1,27 +1,27 @@ This is a testharness.js-based test. [FAIL] prelu float32 0D scalar - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D constant tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 2D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 3D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 4D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 5D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope of shape [1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 2D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 3D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 4D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any_cpu-expected.txt index e2e55e12..51f7fa97 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/prelu.https.any_cpu-expected.txt
@@ -1,27 +1,27 @@ This is a testharness.js-based test. [FAIL] prelu float32 0D scalar - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D constant tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 2D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 3D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 4D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 5D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope of shape [1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 2D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 3D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 4D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt index b740202..14b8256 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] quantizeLinear float32 0D scalar tensor with int8 scalar zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D constant tensor broadcasting zeroPoint and scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] per-tensor quantizeLinear for float32 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt index b740202..14b8256 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] quantizeLinear float32 0D scalar tensor with int8 scalar zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D constant tensor broadcasting zeroPoint and scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] per-tensor quantizeLinear for float32 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_cpu-expected.txt index 78d01b3..7007aa89 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_cpu-expected.txt
@@ -1,11 +1,11 @@ This is a testharness.js-based test. [FAIL] reverse float32 2D input with default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 3D input options.axes=[1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[3, 1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any_cpu-expected.txt index 78d01b3..7007aa89 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/reverse.https.any_cpu-expected.txt
@@ -1,11 +1,11 @@ This is a testharness.js-based test. [FAIL] reverse float32 2D input with default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 3D input options.axes=[1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[3, 1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt index da8de0fd..ca873dfc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt
@@ -1,17 +1,17 @@ This is a testharness.js-based test. [FAIL] sign float32 1D constant tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float16 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float16 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float16 must be one of []." [FAIL] sign float32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float32 1D tensor with -infinity and +infinity - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign int32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of []." [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'signInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt index da8de0fd..ca873dfc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt
@@ -1,17 +1,17 @@ This is a testharness.js-based test. [FAIL] sign float32 1D constant tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float16 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float16 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float16 must be one of []." [FAIL] sign float32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float32 1D tensor with -infinity and +infinity - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign int32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of []." [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'signInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_cpu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_cpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any_cpu-expected.txt index 554b03d4..79057441 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/subgraph.https.any_cpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + relu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + leakyRelu @@ -12,7 +12,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt index dd07420d..97701a6 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint32 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt index dd07420d..97701a6 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint32 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/where.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/where.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..0862992 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/where.https.any.worker_cpu-expected.txt
@@ -0,0 +1,35 @@ +This is a testharness.js-based test. +[FAIL] where float32 0D scalars + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors all broadcast 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/where.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/where.https.any_cpu-expected.txt new file mode 100644 index 0000000..0862992 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/where.https.any_cpu-expected.txt
@@ -0,0 +1,35 @@ +This is a testharness.js-based test. +[FAIL] where float32 0D scalars + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors all broadcast 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_gpu-expected.txt index 4165806..e80c1f974 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any.worker_gpu-expected.txt
@@ -1,45 +1,73 @@ This is a testharness.js-based test. [FAIL] cast float32 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast int32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any_gpu-expected.txt index 4165806..e80c1f974 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/cast.https.any_gpu-expected.txt
@@ -1,45 +1,73 @@ This is a testharness.js-based test. [FAIL] cast float32 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast int32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt index 2809466..483401e 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_gpu-expected.txt
@@ -6,17 +6,17 @@ [FAIL] clamp float32 1D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." [FAIL] clamp float32 2D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp float32 3D tensor default options
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt index 2809466..483401e 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/clamp.https.any_gpu-expected.txt
@@ -6,17 +6,17 @@ [FAIL] clamp float32 1D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." [FAIL] clamp float32 2D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp float32 3D tensor default options
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt index 694adad4..bcc6b7e 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] dequantizeLinear int8 0D tensor with float32 scalar scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] dequantizeLinear constant input - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt index 694adad4..bcc6b7e 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] dequantizeLinear int8 0D tensor with float32 scalar scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] dequantizeLinear constant input - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/equal.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/equal.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..0053d60 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/equal.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] equal float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/equal.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/equal.https.any_gpu-expected.txt new file mode 100644 index 0000000..0053d60 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/equal.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] equal float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_gpu-expected.txt index 1a94b5dc..3cf80d70 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any.worker_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gather float32 1D tensor and uint32 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 1D tensor and int64 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 2D tensor and int32 0D out-of-bound positive indices default options assert_true: assert_array_approx_equals_ulp: test gather float32 actual -66.05901336669922 should be close enough to expected 90.2870101928711 by the acceptable 0 ULP distance, but they have 2150659260 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any_gpu-expected.txt index 1a94b5dc..3cf80d70 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gather.https.any_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gather float32 1D tensor and uint32 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 1D tensor and int64 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 2D tensor and int32 0D out-of-bound positive indices default options assert_true: assert_array_approx_equals_ulp: test gather float32 actual -66.05901336669922 should be close enough to expected 90.2870101928711 by the acceptable 0 ULP distance, but they have 2150659260 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_gpu-expected.txt index 806e1b0..d2895fc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_gpu-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. [FAIL] gatherElements float32 2D input and uint32 indices options.axis=1 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherElements float32 3D input and int32 negative indices assert_true: assert_array_approx_equals_ulp: test gatherElements float32 actual -66.05901336669922 should be close enough to expected 89.0337142944336 by the acceptable 0 ULP distance, but they have 2150494988 ULP distance expected true got false [FAIL] gatherElements float32 1D input and int32 out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_gpu-expected.txt index 806e1b0..d2895fc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_gpu-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. [FAIL] gatherElements float32 2D input and uint32 indices options.axis=1 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherElements float32 3D input and int32 negative indices assert_true: assert_array_approx_equals_ulp: test gatherElements float32 actual -66.05901336669922 should be close enough to expected 89.0337142944336 by the acceptable 0 ULP distance, but they have 2150494988 ULP distance expected true got false [FAIL] gatherElements float32 1D input and int32 out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_gpu-expected.txt index 5d0b479..a4f6fb5 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gatherND float32 4D input and 1D uint32 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 4D input and 1D int64 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 2D input and 2D negative indices assert_true: assert_array_approx_equals_ulp: test gatherND float32 actual -66.05901336669922 should be close enough to expected 44.92119598388672 by the acceptable 0 ULP distance, but they have 2142212375 ULP distance expected true got false [FAIL] gatherND float32 1D input and 2D out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any_gpu-expected.txt index 5d0b479..a4f6fb5 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gatherND.https.any_gpu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gatherND float32 4D input and 1D uint32 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 4D input and 1D int64 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 2D input and 2D negative indices assert_true: assert_array_approx_equals_ulp: test gatherND float32 actual -66.05901336669922 should be close enough to expected 44.92119598388672 by the acceptable 0 ULP distance, but they have 2142212375 ULP distance expected true got false [FAIL] gatherND float32 1D input and 2D out-of-bounds indices
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..163c599 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greater float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater.https.any_gpu-expected.txt new file mode 100644 index 0000000..163c599 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greater float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..f61ec895 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greaterOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_gpu-expected.txt new file mode 100644 index 0000000..f61ec895 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greaterOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..ee456d7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesser float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser.https.any_gpu-expected.txt new file mode 100644 index 0000000..ee456d7 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesser float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..f4d1184 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesserOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_gpu-expected.txt new file mode 100644 index 0000000..f4d1184 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesserOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..5b4922da --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalAnd uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_and.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_and.https.any_gpu-expected.txt new file mode 100644 index 0000000..5b4922da --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_and.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalAnd uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..d22037d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_gpu-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +[FAIL] logicalNot uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D constant tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 5D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_not.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_not.https.any_gpu-expected.txt new file mode 100644 index 0000000..d22037d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_not.https.any_gpu-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +[FAIL] logicalNot uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D constant tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 5D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..d7bb56a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalOr uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_or.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_or.https.any_gpu-expected.txt new file mode 100644 index 0000000..d7bb56a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_or.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalOr uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..46043f26 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalXor uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_xor.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_xor.https.any_gpu-expected.txt new file mode 100644 index 0000000..46043f26 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/logical_xor.https.any_gpu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalXor uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_gpu-expected.txt index e2e55e12..51f7fa97 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_gpu-expected.txt
@@ -1,27 +1,27 @@ This is a testharness.js-based test. [FAIL] prelu float32 0D scalar - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D constant tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 2D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 3D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 4D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 5D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope of shape [1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 2D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 3D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 4D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any_gpu-expected.txt index e2e55e12..51f7fa97 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/prelu.https.any_gpu-expected.txt
@@ -1,27 +1,27 @@ This is a testharness.js-based test. [FAIL] prelu float32 0D scalar - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D constant tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 2D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 3D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 4D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 5D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope of shape [1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 2D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 3D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 4D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt index b740202..14b8256 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] quantizeLinear float32 0D scalar tensor with int8 scalar zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D constant tensor broadcasting zeroPoint and scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] per-tensor quantizeLinear for float32 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt index b740202..14b8256 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] quantizeLinear float32 0D scalar tensor with int8 scalar zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D constant tensor broadcasting zeroPoint and scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] per-tensor quantizeLinear for float32 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_gpu-expected.txt index 78d01b3..7007aa89 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_gpu-expected.txt
@@ -1,11 +1,11 @@ This is a testharness.js-based test. [FAIL] reverse float32 2D input with default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 3D input options.axes=[1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[3, 1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any_gpu-expected.txt index 78d01b3..7007aa89 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/reverse.https.any_gpu-expected.txt
@@ -1,11 +1,11 @@ This is a testharness.js-based test. [FAIL] reverse float32 2D input with default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 3D input options.axes=[1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[3, 1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_gpu-expected.txt index da8de0fd..ca873dfc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_gpu-expected.txt
@@ -1,17 +1,17 @@ This is a testharness.js-based test. [FAIL] sign float32 1D constant tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float16 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float16 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float16 must be one of []." [FAIL] sign float32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float32 1D tensor with -infinity and +infinity - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign int32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of []." [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'signInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any_gpu-expected.txt index da8de0fd..ca873dfc 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/sign.https.any_gpu-expected.txt
@@ -1,17 +1,17 @@ This is a testharness.js-based test. [FAIL] sign float32 1D constant tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float16 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float16 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float16 must be one of []." [FAIL] sign float32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float32 1D tensor with -infinity and +infinity - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign int32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of []." [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'signInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt index 0a2580b7..b59ea53882d 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_gpu-expected.txt
@@ -12,7 +12,7 @@ [FAIL] conv2d default + elu assert_true: assert_array_approx_equals_ulp: test conv2d elu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 36 ULP distance, but they have 9045 ULP distance expected true got false [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] conv2d default + hardSwish assert_true: assert_array_approx_equals_ulp: test conv2d hardSwish float32 actual 1.1552734375 should be close enough to expected 1.157502485501543 by the acceptable 22 ULP distance, but they have 18699 ULP distance expected true got false [FAIL] conv2d default + gelu @@ -46,7 +46,7 @@ [FAIL] convTranspose2d default + linear assert_true: assert_array_approx_equals_ulp: test convTranspose2d linear float32 actual 0 should be close enough to expected 0.1933533329919328 by the acceptable 10 ULP distance, but they have 1044774507 ULP distance expected true got false [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + softsign assert_true: assert_array_approx_equals_ulp: test convTranspose2d softsign float32 actual 0 should be close enough to expected 0.16202521324157715 by the acceptable 11 ULP distance, but they have 1042672112 ULP distance expected true got false [FAIL] batchNormalization default + relu @@ -58,7 +58,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt index 0a2580b7..b59ea53882d 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/subgraph.https.any_gpu-expected.txt
@@ -12,7 +12,7 @@ [FAIL] conv2d default + elu assert_true: assert_array_approx_equals_ulp: test conv2d elu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 36 ULP distance, but they have 9045 ULP distance expected true got false [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] conv2d default + hardSwish assert_true: assert_array_approx_equals_ulp: test conv2d hardSwish float32 actual 1.1552734375 should be close enough to expected 1.157502485501543 by the acceptable 22 ULP distance, but they have 18699 ULP distance expected true got false [FAIL] conv2d default + gelu @@ -46,7 +46,7 @@ [FAIL] convTranspose2d default + linear assert_true: assert_array_approx_equals_ulp: test convTranspose2d linear float32 actual 0 should be close enough to expected 0.1933533329919328 by the acceptable 10 ULP distance, but they have 1044774507 ULP distance expected true got false [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + softsign assert_true: assert_array_approx_equals_ulp: test convTranspose2d softsign float32 actual 0 should be close enough to expected 0.16202521324157715 by the acceptable 11 ULP distance, but they have 1042672112 ULP distance expected true got false [FAIL] batchNormalization default + relu @@ -58,7 +58,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_gpu-expected.txt index dd07420d..97701a6 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_gpu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint32 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any_gpu-expected.txt index dd07420d..97701a6 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/tile.https.any_gpu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint32 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt index 239c9348..0862992 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt
@@ -1,5 +1,35 @@ This is a testharness.js-based test. [FAIL] where float32 0D scalars - assert_true: assert_array_approx_equals_ulp: test where float32 actual -22.828125 should be close enough to expected -22.83924102783203 by the acceptable 0 ULP distance, but they have 5828 ULP distance expected true got false + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors all broadcast 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt index 239c9348..0862992 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt
@@ -1,5 +1,35 @@ This is a testharness.js-based test. [FAIL] where float32 0D scalars - assert_true: assert_array_approx_equals_ulp: test where float32 actual -22.828125 should be close enough to expected -22.83924102783203 by the acceptable 0 ULP distance, but they have 5828 ULP distance expected true got false + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors all broadcast 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt index 1ea06c4..fbb8221 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int64 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint64 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt index 1ea06c4..fbb8221 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt
@@ -1,15 +1,15 @@ This is a testharness.js-based test. [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int64 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint64 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt index 3066a24b..e48ee45 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt
@@ -4,12 +4,12 @@ [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': DequantizeLinear can't support block-wise." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt index 3066a24b..e48ee45 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt
@@ -4,12 +4,12 @@ [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': DequantizeLinear can't support block-wise." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt deleted file mode 100644 index 9e73a70..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] lstm float32 tensors steps=2 with all options - assert_true: assert_array_approx_equals_ulp: test lstm float32 actual 1 should be close enough to expected 10.469000816345215 by the acceptable 1 ULP distance, but they have 27754759 ULP distance expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt deleted file mode 100644 index 9e73a70..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] lstm float32 tensors steps=2 with all options - assert_true: assert_array_approx_equals_ulp: test lstm float32 actual 1 should be close enough to expected 10.469000816345215 by the acceptable 1 ULP distance, but they have 27754759 ULP distance expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt index 3110261..424c0c9 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt
@@ -18,33 +18,33 @@ [FAIL] averagePool2d float32 4D tensor options.dilations with options.strides assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 28.626827239990234 should be close enough to expected 42.940242767333984 by the acceptable 11 ULP distance, but they have 4636433 ULP distance expected true got false [FAIL] l2Pool2d float32 4D constant tensor all positive default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all positive options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all negative options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.windowDimensions - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.padding - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nchw - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nhwc - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations with options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] maxPool2d float32 4D tensor options.dilations promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Pool2d in tflite doesn't support dilations." [FAIL] maxPool2d float32 4D tensor options.roundingType=ceil
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt index 3110261..424c0c9 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt
@@ -18,33 +18,33 @@ [FAIL] averagePool2d float32 4D tensor options.dilations with options.strides assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 28.626827239990234 should be close enough to expected 42.940242767333984 by the acceptable 11 ULP distance, but they have 4636433 ULP distance expected true got false [FAIL] l2Pool2d float32 4D constant tensor all positive default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all positive options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all negative options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.windowDimensions - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.padding - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nchw - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nhwc - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations with options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] maxPool2d float32 4D tensor options.dilations promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Pool2d in tflite doesn't support dilations." [FAIL] maxPool2d float32 4D tensor options.roundingType=ceil
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt index b6000d4..b8cc599 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt
@@ -2,18 +2,18 @@ [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': QuantizeLinear can't support block-wise." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt index b6000d4..b8cc599 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt
@@ -2,18 +2,18 @@ [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': QuantizeLinear can't support block-wise." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt rename to third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt rename to third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt index 8aaf1e47..651b808 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int64 for argument input, must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt index 8aaf1e47..651b808 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int64 for argument input, must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt index b55b25da..453f3d9 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'tile' on 'MLGraphBuilder': Unsupported data type uint32 for argument input, must be one of [float32, float16, int32, int64, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32,int64,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt index b55b25da..453f3d9 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'tile' on 'MLGraphBuilder': Unsupported data type uint32 for argument input, must be one of [float32, float16, int32, int64, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32,int64,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt index acc4305..4d19be53 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt
@@ -4,18 +4,18 @@ [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt index acc4305..4d19be53 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt
@@ -4,18 +4,18 @@ [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt index 72dbce6..604bad38 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_gpu-expected.txt
@@ -2,18 +2,18 @@ [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt index 72dbce6..604bad38 100644 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_gpu-expected.txt
@@ -2,18 +2,18 @@ [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, uint64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any.worker_gpu-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/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/where.https.any_gpu-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/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..fbb8221 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_cpu-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +[FAIL] clamp int8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16]." +[FAIL] clamp uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16]." +[FAIL] clamp int32 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." +[FAIL] clamp uint32 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16]." +[FAIL] clamp int64 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16]." +[FAIL] clamp uint64 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt new file mode 100644 index 0000000..fbb8221 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/clamp.https.any_cpu-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +[FAIL] clamp int8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16]." +[FAIL] clamp uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16]." +[FAIL] clamp int32 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." +[FAIL] clamp uint32 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16]." +[FAIL] clamp int64 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16]." +[FAIL] clamp uint64 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt index 828fb62..e48ee45 100644 --- a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_cpu-expected.txt
@@ -4,16 +4,12 @@ [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': DequantizeLinear can't support block-wise." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." -[FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." -[FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt index 828fb62..e48ee45 100644 --- a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_cpu-expected.txt
@@ -4,16 +4,12 @@ [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': DequantizeLinear can't support block-wise." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." -[FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." -[FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/gatherElements.https.any_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt index e22b7e9..424c0c9 100644 --- a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any.worker_cpu-expected.txt
@@ -6,50 +6,50 @@ [FAIL] averagePool2d float32 4D tensor options.roundingType=floor assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: averagePool2dOutput" + assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.layout=nhwc and options.roundingType=floor assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.layout=nhwc and options.roundingType=ceil - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: averagePool2dOutput" + assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: averagePool2dOutput" + assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.dilations with options.strides assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 28.626827239990234 should be close enough to expected 42.940242767333984 by the acceptable 11 ULP distance, but they have 4636433 ULP distance expected true got false [FAIL] l2Pool2d float32 4D constant tensor all positive default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all positive options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all negative options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.windowDimensions - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.padding - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nchw - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nhwc - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations with options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] maxPool2d float32 4D tensor options.dilations promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Pool2d in tflite doesn't support dilations." [FAIL] maxPool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: maxPool2dOutput" + assert_true: assert_array_approx_equals_ulp: test maxPool2d float32 actual 99.28312683105469 should be close enough to expected -39.03501892089844 by the acceptable 0 ULP distance, but they have 2158652698 ULP distance expected true got false [FAIL] maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: maxPool2dOutput" + assert_true: assert_array_approx_equals_ulp: test maxPool2d float32 actual 99.28312683105469 should be close enough to expected -39.03501892089844 by the acceptable 0 ULP distance, but they have 2158652698 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt index e22b7e9..424c0c9 100644 --- a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/pooling.https.any_cpu-expected.txt
@@ -6,50 +6,50 @@ [FAIL] averagePool2d float32 4D tensor options.roundingType=floor assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: averagePool2dOutput" + assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.layout=nhwc and options.roundingType=floor assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.layout=nhwc and options.roundingType=ceil - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: averagePool2dOutput" + assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: averagePool2dOutput" + assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 36.13502502441406 should be close enough to expected 54.20252990722656 by the acceptable 11 ULP distance, but they have 4736288 ULP distance expected true got false [FAIL] averagePool2d float32 4D tensor options.dilations with options.strides assert_true: assert_array_approx_equals_ulp: test averagePool2d float32 actual 28.626827239990234 should be close enough to expected 42.940242767333984 by the acceptable 11 ULP distance, but they have 4636433 ULP distance expected true got false [FAIL] l2Pool2d float32 4D constant tensor all positive default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all positive options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor default all negative options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.windowDimensions - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.padding - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nchw - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.layout=nhwc - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.outputSizes ignores options.roundingType=ceil - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] l2Pool2d float32 4D tensor options.dilations with options.strides - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'l2Pool2d' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] maxPool2d float32 4D tensor options.dilations promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Pool2d in tflite doesn't support dilations." [FAIL] maxPool2d float32 4D tensor options.roundingType=ceil - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: maxPool2dOutput" + assert_true: assert_array_approx_equals_ulp: test maxPool2d float32 actual 99.28312683105469 should be close enough to expected -39.03501892089844 by the acceptable 0 ULP distance, but they have 2158652698 ULP distance expected true got false [FAIL] maxPool2d float32 4D tensor options.outputSizes ignores options.roundingType=floor - promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'compute' on 'MLContext': The output tensor size does not match graph's expectation: maxPool2dOutput" + assert_true: assert_array_approx_equals_ulp: test maxPool2d float32 actual 99.28312683105469 should be close enough to expected -39.03501892089844 by the acceptable 0 ULP distance, but they have 2158652698 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt index d917dd1..b8cc599 100644 --- a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_cpu-expected.txt
@@ -1,23 +1,19 @@ This is a testharness.js-based test. -[FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Only support pre-node quantize at current stage." -[FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Only support pre-node quantize at current stage." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Only support pre-node quantize at current stage." + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': QuantizeLinear can't support block-wise." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt index d917dd1..b8cc599 100644 --- a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_cpu-expected.txt
@@ -1,23 +1,19 @@ This is a testharness.js-based test. -[FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Only support pre-node quantize at current stage." -[FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Only support pre-node quantize at current stage." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Only support pre-node quantize at current stage." + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': QuantizeLinear can't support block-wise." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type int4 for argument input, must be one of [int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int4 must be one of [int8,uint8]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, uint32, int64, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint4 must be one of [float32,float16,int32,uint32,int64,uint64,int8,uint8,int4]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt similarity index 100% copy from third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt copy to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any.worker_cpu-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt similarity index 100% copy from third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt copy to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterElements.https.any_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any.worker_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any.worker_cpu-expected.txt rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any.worker_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any_cpu-expected.txt rename to third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/scatterND.https.any_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..651b808 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any.worker_cpu-expected.txt
@@ -0,0 +1,7 @@ +This is a testharness.js-based test. +[FAIL] sign int64 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] sign int8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt new file mode 100644 index 0000000..651b808 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/sign.https.any_cpu-expected.txt
@@ -0,0 +1,7 @@ +This is a testharness.js-based test. +[FAIL] sign int64 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] sign int8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/split.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/split.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..a07f5b7 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/split.https.any.worker_cpu-expected.txt
@@ -0,0 +1,23 @@ +This is a testharness.js-based test. +[FAIL] split float32 1D constant tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 1D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 2D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 3D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 4D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 5D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 4D tensor array splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 4D tensor number splits options.axis + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 5D tensor array splits=[3, 3] options.axis=2 + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 5D tensor array splits=[2, 4] options.axis=0 + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/split.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/split.https.any_cpu-expected.txt new file mode 100644 index 0000000..a07f5b7 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/split.https.any_cpu-expected.txt
@@ -0,0 +1,23 @@ +This is a testharness.js-based test. +[FAIL] split float32 1D constant tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 1D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 2D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 3D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 4D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 5D tensor number splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 4D tensor array splits default options + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 4D tensor number splits options.axis + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 5D tensor array splits=[3, 3] options.axis=2 + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +[FAIL] split float32 5D tensor array splits=[2, 4] options.axis=0 + promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'dataTypes')" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt new file mode 100644 index 0000000..453f3d9 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any.worker_cpu-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] tile uint32 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32,int64,uint8]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt new file mode 100644 index 0000000..453f3d9 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/tile.https.any_cpu-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] tile uint32 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32,int64,uint8]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt new file mode 100644 index 0000000..995fe07 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_gpu-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +[FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. + promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." +[FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] + promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." +[FAIL] dequantizeLinear uint4 1D tensor with even input size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear uint4 1D tensor with odd input size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear int4 1D tensor with even size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type int4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear int4 1D tensor with odd size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type int4 must be one of [int8,uint8]." +[FAIL] per-tensor dequantizeLinear for int4 4D constant + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type int4 must be one of [int8,uint8]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt new file mode 100644 index 0000000..995fe07 --- /dev/null +++ b/third_party/blink/web_tests/platform/win11-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_gpu-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +[FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. + promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." +[FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] + promise_test: Unhandled rejection with value: object "UnknownError: Failed to execute 'build' on 'MLGraphBuilder': DirectML: DequantizeLinear and quantizeLinear can't support block-wise when FL < 6.3." +[FAIL] dequantizeLinear uint4 1D tensor with even input size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear uint4 1D tensor with odd input size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type uint4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear int4 1D tensor with even size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type int4 must be one of [int8,uint8]." +[FAIL] dequantizeLinear int4 1D tensor with odd size + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type int4 must be one of [int8,uint8]." +[FAIL] per-tensor dequantizeLinear for int4 4D constant + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input data type int4 must be one of [int8,uint8]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt rename to third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any.worker_cpu-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/mac/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt rename to third_party/blink/web_tests/virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/lstm.https.any_cpu-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any.worker_npu-expected.txt index 4165806..e80c1f974 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any.worker_npu-expected.txt
@@ -1,45 +1,73 @@ This is a testharness.js-based test. [FAIL] cast float32 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast int32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any_npu-expected.txt index 4165806..e80c1f974 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/cast.https.any_npu-expected.txt
@@ -1,45 +1,73 @@ This is a testharness.js-based test. [FAIL] cast float32 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast float16 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast float16 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast int32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int32 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast uint32 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to float16 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to int8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] cast int64 4D tensor to uint8 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'castInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] cast int8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast int8 4D tensor to uint8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to float16 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int32 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to uint32 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] cast uint8 4D tensor to int64 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int64 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." +[FAIL] cast uint8 4D tensor to int8 + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt index 2809466..483401e 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any.worker_npu-expected.txt
@@ -6,17 +6,17 @@ [FAIL] clamp float32 1D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." [FAIL] clamp float32 2D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp float32 3D tensor default options
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt index 2809466..483401e 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/clamp.https.any_npu-expected.txt
@@ -6,17 +6,17 @@ [FAIL] clamp float32 1D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp int8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] clamp uint8 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of [float32,float16,int32]." [FAIL] clamp int32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'clamp' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of [float32, float16]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of [float32,float16]." [FAIL] clamp uint32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint32 must be one of [float32,float16,int32]." [FAIL] clamp int64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] clamp uint64 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type uint64 for input operand named 'clampInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint64 must be one of [float32,float16,int32]." [FAIL] clamp float32 2D tensor default options assert_true: assert_array_approx_equals_ulp: test clamp float32 actual -9.8125 should be close enough to expected -9.817828178405762 by the acceptable 0 ULP distance, but they have 5587 ULP distance expected true got false [FAIL] clamp float32 3D tensor default options
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_npu-expected.txt index 694adad4..bcc6b7e 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any.worker_npu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] dequantizeLinear int8 0D tensor with float32 scalar scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] dequantizeLinear constant input - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_npu-expected.txt index 694adad4..bcc6b7e 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/dequantizeLinear.https.any_npu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] dequantizeLinear int8 0D tensor with float32 scalar scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." [FAIL] dequantizeLinear constant input - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear uint8 1D constant tensor with implicit block_size = 2. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type uint8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type uint8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear int8 4D constant tensor with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'dequantizeLinear' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of []." [FAIL] dequantizeLinear uint4 1D tensor with even input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 1D tensor with odd input size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 4D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear uint4 3D input with block_size = [1, 1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] dequantizeLinear int4 1D tensor with odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." [FAIL] per-tensor dequantizeLinear for int4 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type int4 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/equal.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/equal.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..0053d60 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/equal.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] equal float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/equal.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/equal.https.any_npu-expected.txt new file mode 100644 index 0000000..0053d60 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/equal.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] equal float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] equal float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any.worker_npu-expected.txt index 1a94b5dc..3cf80d70 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any.worker_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gather float32 1D tensor and uint32 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 1D tensor and int64 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 2D tensor and int32 0D out-of-bound positive indices default options assert_true: assert_array_approx_equals_ulp: test gather float32 actual -66.05901336669922 should be close enough to expected 90.2870101928711 by the acceptable 0 ULP distance, but they have 2150659260 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any_npu-expected.txt index 1a94b5dc..3cf80d70 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gather.https.any_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gather float32 1D tensor and uint32 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 1D tensor and int64 0D scalar indices default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gather float32 2D tensor and int32 0D out-of-bound positive indices default options assert_true: assert_array_approx_equals_ulp: test gather float32 actual -66.05901336669922 should be close enough to expected 90.2870101928711 by the acceptable 0 ULP distance, but they have 2150659260 ULP distance expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_npu-expected.txt index 806e1b0..d2895fc 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any.worker_npu-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. [FAIL] gatherElements float32 2D input and uint32 indices options.axis=1 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherElements float32 3D input and int32 negative indices assert_true: assert_array_approx_equals_ulp: test gatherElements float32 actual -66.05901336669922 should be close enough to expected 89.0337142944336 by the acceptable 0 ULP distance, but they have 2150494988 ULP distance expected true got false [FAIL] gatherElements float32 1D input and int32 out-of-bounds indices
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any_npu-expected.txt index 806e1b0..d2895fc 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherElements.https.any_npu-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. [FAIL] gatherElements float32 2D input and uint32 indices options.axis=1 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherElements float32 3D input and int32 negative indices assert_true: assert_array_approx_equals_ulp: test gatherElements float32 actual -66.05901336669922 should be close enough to expected 89.0337142944336 by the acceptable 0 ULP distance, but they have 2150494988 ULP distance expected true got false [FAIL] gatherElements float32 1D input and int32 out-of-bounds indices
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_npu-expected.txt index 5d0b479..a4f6fb5 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any.worker_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gatherND float32 4D input and 1D uint32 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 4D input and 1D int64 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 2D input and 2D negative indices assert_true: assert_array_approx_equals_ulp: test gatherND float32 actual -66.05901336669922 should be close enough to expected 44.92119598388672 by the acceptable 0 ULP distance, but they have 2142212375 ULP distance expected true got false [FAIL] gatherND float32 1D input and 2D out-of-bounds indices
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any_npu-expected.txt index 5d0b479..a4f6fb5 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/gatherND.https.any_npu-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. [FAIL] gatherND float32 4D input and 1D uint32 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type uint32 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 4D input and 1D int64 indices - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'constant' on 'MLGraphBuilder': Unsupported data type int64 for constant, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'indices' data type int64 must be one of [float32,float16,int32,int8,uint8]." [FAIL] gatherND float32 2D input and 2D negative indices assert_true: assert_array_approx_equals_ulp: test gatherND float32 actual -66.05901336669922 should be close enough to expected 44.92119598388672 by the acceptable 0 ULP distance, but they have 2142212375 ULP distance expected true got false [FAIL] gatherND float32 1D input and 2D out-of-bounds indices
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..163c599 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greater float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater.https.any_npu-expected.txt new file mode 100644 index 0000000..163c599 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greater float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greater float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..f61ec895 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greaterOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_npu-expected.txt new file mode 100644 index 0000000..f61ec895 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/greater_or_equal.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] greaterOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] greaterOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..ee456d7 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesser float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser.https.any_npu-expected.txt new file mode 100644 index 0000000..ee456d7 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesser float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesser float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..f4d1184 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesserOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_npu-expected.txt new file mode 100644 index 0000000..f4d1184 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/lesser_or_equal.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] lesserOrEqual float32 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] lesserOrEqual float32 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..5b4922da --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_and.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalAnd uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_and.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_and.https.any_npu-expected.txt new file mode 100644 index 0000000..5b4922da --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_and.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalAnd uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalAnd uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..d22037d --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_not.https.any.worker_npu-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +[FAIL] logicalNot uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D constant tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 5D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_not.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_not.https.any_npu-expected.txt new file mode 100644 index 0000000..d22037d --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_not.https.any_npu-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +[FAIL] logicalNot uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D constant tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 1D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 2D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 3D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 4D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalNot uint8 5D tensor + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..d7bb56a --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_or.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalOr uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_or.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_or.https.any_npu-expected.txt new file mode 100644 index 0000000..d7bb56a --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_or.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalOr uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalOr uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_npu-expected.txt new file mode 100644 index 0000000..46043f26 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_xor.https.any.worker_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalXor uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_xor.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_xor.https.any_npu-expected.txt new file mode 100644 index 0000000..46043f26 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/logical_xor.https.any_npu-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +[FAIL] logicalXor uint8 0D scalar + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D constant tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +[FAIL] logicalXor uint8 broadcast 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'a' data type uint8 must be one of [float32,float16,int32]." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_npu-expected.txt index e2e55e12..51f7fa97 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any.worker_npu-expected.txt
@@ -1,27 +1,27 @@ This is a testharness.js-based test. [FAIL] prelu float32 0D scalar - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D constant tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 2D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 3D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 4D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 5D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope of shape [1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 2D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 3D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 4D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any_npu-expected.txt index e2e55e12..51f7fa97 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/prelu.https.any_npu-expected.txt
@@ -1,27 +1,27 @@ This is a testharness.js-based test. [FAIL] prelu float32 0D scalar - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D constant tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 1D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 2D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 3D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 4D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 5D tensors - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 1D slope of shape [1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 2D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 3D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] prelu float32 broadcast 4D x 4D slope - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_npu-expected.txt index b740202..14b8256 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any.worker_npu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] quantizeLinear float32 0D scalar tensor with int8 scalar zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D constant tensor broadcasting zeroPoint and scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] per-tensor quantizeLinear for float32 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_npu-expected.txt index b740202..14b8256 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/quantizeLinear.https.any_npu-expected.txt
@@ -1,29 +1,29 @@ This is a testharness.js-based test. [FAIL] quantizeLinear float32 0D scalar tensor with int8 scalar zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 1D constant tensor broadcasting zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D constant tensor broadcasting zeroPoint and scale - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 4D constant tensor broadcasting scale and zeroPoint - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] per-tensor quantizeLinear for float32 4D constant - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 3D input with implicit block_size = [1, 2, 1]. - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'quantizeLinear' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 2D tensor with int4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear int4 zeroPoint with block_size = [3, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type int4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has odd size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear float32 tensor with uint4 zeroPoint which has even size - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] quantizeLinear uint4 zeroPoint with block_size = 3 - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint4 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_npu-expected.txt index 78d01b3..7007aa89 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any.worker_npu-expected.txt
@@ -1,11 +1,11 @@ This is a testharness.js-based test. [FAIL] reverse float32 2D input with default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 3D input options.axes=[1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[3, 1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any_npu-expected.txt index 78d01b3..7007aa89 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/reverse.https.any_npu-expected.txt
@@ -1,11 +1,11 @@ This is a testharness.js-based test. [FAIL] reverse float32 2D input with default options - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 3D input options.axes=[1, 2] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[3, 1] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] reverse float32 4D input options.axes=[] - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'reverse' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any.worker_npu-expected.txt index da8de0fd..ca873dfc 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any.worker_npu-expected.txt
@@ -1,17 +1,17 @@ This is a testharness.js-based test. [FAIL] sign float32 1D constant tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float16 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float16 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float16 must be one of []." [FAIL] sign float32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float32 1D tensor with -infinity and +infinity - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign int32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of []." [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'signInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any_npu-expected.txt index da8de0fd..ca873dfc 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/sign.https.any_npu-expected.txt
@@ -1,17 +1,17 @@ This is a testharness.js-based test. [FAIL] sign float32 1D constant tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float16 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float16 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float16 must be one of []." [FAIL] sign float32 1D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign float32 1D tensor with -infinity and +infinity - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type float32 must be one of []." [FAIL] sign int32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int32 must be one of []." [FAIL] sign int64 3D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'input' on 'MLGraphBuilder': Unsupported data type int64 for input operand named 'signInput', must be one of [float32, float16, int32]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int64 must be one of [float32,float16,int32]." [FAIL] sign int8 4D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'sign' on 'MLGraphBuilder': Unsupported data type int8 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'input' data type int8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt index 0a2580b7..b59ea53882d 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any.worker_npu-expected.txt
@@ -12,7 +12,7 @@ [FAIL] conv2d default + elu assert_true: assert_array_approx_equals_ulp: test conv2d elu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 36 ULP distance, but they have 9045 ULP distance expected true got false [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] conv2d default + hardSwish assert_true: assert_array_approx_equals_ulp: test conv2d hardSwish float32 actual 1.1552734375 should be close enough to expected 1.157502485501543 by the acceptable 22 ULP distance, but they have 18699 ULP distance expected true got false [FAIL] conv2d default + gelu @@ -46,7 +46,7 @@ [FAIL] convTranspose2d default + linear assert_true: assert_array_approx_equals_ulp: test convTranspose2d linear float32 actual 0 should be close enough to expected 0.1933533329919328 by the acceptable 10 ULP distance, but they have 1044774507 ULP distance expected true got false [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + softsign assert_true: assert_array_approx_equals_ulp: test convTranspose2d softsign float32 actual 0 should be close enough to expected 0.16202521324157715 by the acceptable 11 ULP distance, but they have 1042672112 ULP distance expected true got false [FAIL] batchNormalization default + relu @@ -58,7 +58,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt index 0a2580b7..b59ea53882d 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/subgraph.https.any_npu-expected.txt
@@ -12,7 +12,7 @@ [FAIL] conv2d default + elu assert_true: assert_array_approx_equals_ulp: test conv2d elu float32 actual 1.53125 should be close enough to expected 1.5323282480239868 by the acceptable 36 ULP distance, but they have 9045 ULP distance expected true got false [FAIL] conv2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] conv2d default + hardSwish assert_true: assert_array_approx_equals_ulp: test conv2d hardSwish float32 actual 1.1552734375 should be close enough to expected 1.157502485501543 by the acceptable 22 ULP distance, but they have 18699 ULP distance expected true got false [FAIL] conv2d default + gelu @@ -46,7 +46,7 @@ [FAIL] convTranspose2d default + linear assert_true: assert_array_approx_equals_ulp: test convTranspose2d linear float32 actual 0 should be close enough to expected 0.1933533329919328 by the acceptable 10 ULP distance, but they have 1044774507 ULP distance expected true got false [FAIL] convTranspose2d default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] convTranspose2d default + softsign assert_true: assert_array_approx_equals_ulp: test convTranspose2d softsign float32 actual 0 should be close enough to expected 0.16202521324157715 by the acceptable 11 ULP distance, but they have 1042672112 ULP distance expected true got false [FAIL] batchNormalization default + relu @@ -58,7 +58,7 @@ [FAIL] batchNormalization default + clamp promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization default + prelu - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'prelu' on 'MLGraphBuilder': Unsupported data type float32 for argument input, must be one of []." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, output 'output' data type float32 must be one of []." [FAIL] batchNormalization default + elu promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unsupported rank for batchNormalization. It must be between 3 and 5." [FAIL] batchNormalization options.axis=0 + gelu
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any.worker_npu-expected.txt index dd07420d..97701a6 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any.worker_npu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint32 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any_npu-expected.txt index dd07420d..97701a6 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/tile.https.any_npu-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. [FAIL] tile uint32 2D tensor - promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'cast' on 'MLGraphBuilder': Unsupported data type uint32 for output, must be one of [float32, float16, int32, int8, uint8]." + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, constant 'input' data type uint32 must be one of [float32,float16,int32,int8,uint8]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt index 239c9348..0862992 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any.worker_npu-expected.txt
@@ -1,5 +1,35 @@ This is a testharness.js-based test. [FAIL] where float32 0D scalars - assert_true: assert_array_approx_equals_ulp: test where float32 actual -22.828125 should be close enough to expected -22.83924102783203 by the acceptable 0 ULP distance, but they have 5828 ULP distance expected true got false + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors all broadcast 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt index 239c9348..0862992 100644 --- a/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt +++ b/third_party/blink/web_tests/virtual/webnn-service-on-npu/external/wpt/webnn/conformance_tests/where.https.any_npu-expected.txt
@@ -1,5 +1,35 @@ This is a testharness.js-based test. [FAIL] where float32 0D scalars - assert_true: assert_array_approx_equals_ulp: test where float32 actual -22.828125 should be close enough to expected -22.83924102783203 by the acceptable 0 ULP distance, but they have 5828 ULP distance expected true got false + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 1D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 2D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 3D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 5D tensors + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 0D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 1D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast condition 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 2D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast trueValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 3D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors only broadcast falseValues 4D to 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." +[FAIL] where float32 4D tensors all broadcast 4D + promise_test: Unhandled rejection with value: object "TypeError: Unsupported data type, input 'condition' data type uint8 must be one of [float32,float16,int32]." Harness: the test ran to completion.
diff --git a/third_party/boringssl/src b/third_party/boringssl/src index 830e786..aefa5d2 160000 --- a/third_party/boringssl/src +++ b/third_party/boringssl/src
@@ -1 +1 @@ -Subproject commit 830e786772558fa9b80aa7e7118aaa5b2a042344 +Subproject commit aefa5d24da34ef77ac797bdbe684734e5bd870f4
diff --git a/third_party/catapult b/third_party/catapult index 2cbeabb..bfa1c497 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 2cbeabb6a85ec0ec5ad214ca4fc9a403a4ed3139 +Subproject commit bfa1c497260c357345844a06eeb70bd69ac46245
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index 0dc34c7..1ec8516 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit 0dc34c7c88996e0dbd967e45d0c1359dfc595939 +Subproject commit 1ec85168f5e4e8290cfef0ba9a7baf2c898919c3
diff --git a/third_party/cpuinfo/README.chromium b/third_party/cpuinfo/README.chromium index 6f0d890..34ba3687f 100644 --- a/third_party/cpuinfo/README.chromium +++ b/third_party/cpuinfo/README.chromium
@@ -1,8 +1,8 @@ Name: cpuinfo Short Name: cpuinfo URL: https://github.com/pytorch/cpuinfo -Version: cebb0933058d7f181c979afd50601dc311e1bf8c -Date: 2024-11-20 +Version: ca156f7bc9109c552973414a63d310f76ef0cbf8 +Date: 2024-12-09 License: BSD-2-Clause License File: src/LICENSE Security Critical: Yes
diff --git a/third_party/cpuinfo/src b/third_party/cpuinfo/src index cebb093..ca156f7 160000 --- a/third_party/cpuinfo/src +++ b/third_party/cpuinfo/src
@@ -1 +1 @@ -Subproject commit cebb0933058d7f181c979afd50601dc311e1bf8c +Subproject commit ca156f7bc9109c552973414a63d310f76ef0cbf8
diff --git a/third_party/crossbench b/third_party/crossbench index 692b047..d64333a 160000 --- a/third_party/crossbench +++ b/third_party/crossbench
@@ -1 +1 @@ -Subproject commit 692b047779e4e658d748581bfadebbd1552ea335 +Subproject commit d64333a2353b602e2623119369c0b120c505bd22
diff --git a/third_party/dawn b/third_party/dawn index 00934c2..b8306de1 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 00934c211879c15a9ca6b5a031949c587837f1af +Subproject commit b8306de17c9a5775819a8526802fe85a860f5216
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal deleted file mode 160000 index 4b0016e..0000000 --- a/third_party/devtools-frontend-internal +++ /dev/null
@@ -1 +0,0 @@ -Subproject commit 4b0016e116288e419beb13a521994b584acc435e
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 3c51433..e5f236b 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 3c514332542cdc7893afbc30de905e21753d9852 +Subproject commit e5f236b0250de3bc4cbfa43540e4bd0785a70eb1
diff --git a/third_party/eigen3/README.chromium b/third_party/eigen3/README.chromium index 0fe3f32a..55678ef 100644 --- a/third_party/eigen3/README.chromium +++ b/third_party/eigen3/README.chromium
@@ -1,8 +1,8 @@ Name: Eigen Short Name: eigen3 URL: https://gitlab.com/libeigen/eigen -Version: 5610a13b7767a94e063342277e0b9de4de13be57 -Date: 2024-11-25 +Version: 77a073aaa821300fc129ef24b3b052be2e670a3e +Date: 2024-12-09 License: MPL-2.0 License File: LICENSE Security Critical: Yes
diff --git a/third_party/eigen3/src b/third_party/eigen3/src index 5610a13..77a073a 160000 --- a/third_party/eigen3/src +++ b/third_party/eigen3/src
@@ -1 +1 @@ -Subproject commit 5610a13b7767a94e063342277e0b9de4de13be57 +Subproject commit 77a073aaa821300fc129ef24b3b052be2e670a3e
diff --git a/third_party/highway/BUILD.gn b/third_party/highway/BUILD.gn index c403e529..f3459d44 100644 --- a/third_party/highway/BUILD.gn +++ b/third_party/highway/BUILD.gn
@@ -98,7 +98,7 @@ ] deps = [ ":libhwy", + "//base/test:run_all_unittests", "//testing/gtest", - "//testing/gtest:gtest_main", ] }
diff --git a/third_party/libavif/BUILD.gn b/third_party/libavif/BUILD.gn index ca21763..3842cb5 100644 --- a/third_party/libavif/BUILD.gn +++ b/third_party/libavif/BUILD.gn
@@ -7,9 +7,8 @@ # Public configuration exported to users of the libavif target. config("avif_public_config") { - defines = [ "AVIF_ENABLE_GAIN_MAP" ] if (is_component_build) { - defines += [ "AVIF_DLL" ] + defines = [ "AVIF_DLL" ] } }
diff --git a/third_party/libavif/src b/third_party/libavif/src index 3196438..260879c 160000 --- a/third_party/libavif/src +++ b/third_party/libavif/src
@@ -1 +1 @@ -Subproject commit 3196438660ca478f85e8a3d209b166adcd845c4a +Subproject commit 260879ce2383da96de411d440ed6adf9ea98bfe6
diff --git a/third_party/libc++/src b/third_party/libc++/src index 643441d..2d9b9a9 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src
@@ -1 +1 @@ -Subproject commit 643441dc2f2da5fe3e09c7559249b558f224a2dc +Subproject commit 2d9b9a9eea77b09fe4bc7a41b33140fa7298d39f
diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src index d82e9c4..a6362b2 160000 --- a/third_party/libc++abi/src +++ b/third_party/libc++abi/src
@@ -1 +1 @@ -Subproject commit d82e9c4d06c1ec29dc3421e738aecb7514cc4bfc +Subproject commit a6362b2727ba0eea15d024bfac7e1dc8e79db009
diff --git a/third_party/libei/README.chromium b/third_party/libei/README.chromium index 1940b1c..5311bd18 100644 --- a/third_party/libei/README.chromium +++ b/third_party/libei/README.chromium
@@ -1,7 +1,7 @@ Name: libei URL: https://gitlab.freedesktop.org/libinput/libei -Version: f9d691e98b515b544fb803a3c0c387621fd2d332 -Revision: f9d691e98b515b544fb803a3c0c387621fd2d332 +Version: 1.3.0 +Revision: 997b7c0f37faea4f8bae59613c8f27370925d5b0 License: MIT License File: LICENSE Security Critical: yes
diff --git a/third_party/libevent/BUILD.gn b/third_party/libevent/BUILD.gn deleted file mode 100644 index 97ed48b..0000000 --- a/third_party/libevent/BUILD.gn +++ /dev/null
@@ -1,63 +0,0 @@ -# Copyright 2013 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/cronet/config.gni") -import("//build/config/nacl/config.gni") - -static_library("libevent") { - sources = [ - "event-config.h", - "event-internal.h", - "event.c", - "event.h", - "evsignal.h", - "evutil.c", - "evutil.h", - "log.c", - "log.h", - "min_heap.h", - "poll.c", - "select.c", - "signal.c", - "strlcpy-internal.h", - "strlcpy.c", - ] - - defines = [ "HAVE_CONFIG_H" ] - if (is_cronet_build) { - include_dirs = [ "compat" ] - } else { - include_dirs = [] - } - if (is_apple) { - sources += [ - "kqueue.c", - "mac/config.h", - "mac/event-config.h", - ] - include_dirs += [ "mac" ] - } else if (is_linux || is_chromeos) { - sources += [ - "epoll.c", - "linux/config.h", - "linux/event-config.h", - ] - include_dirs += [ "linux" ] - } else if (is_android) { - sources += [ - "android/config.h", - "android/event-config.h", - "epoll.c", - ] - include_dirs += [ "android" ] - } - - if (!is_debug) { - configs -= [ "//build/config/compiler:default_optimization" ] - configs += [ "//build/config/compiler:optimize_max" ] - } - - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ "//build/config/compiler:no_chromium_code" ] -}
diff --git a/third_party/libevent/ChangeLog b/third_party/libevent/ChangeLog deleted file mode 100644 index 893b0873..0000000 --- a/third_party/libevent/ChangeLog +++ /dev/null
@@ -1,253 +0,0 @@ -Changes in 1.4.15-stable (5 January 2015) - - o Avoid integer overflow bugs in evbuffer_add() and related functions. See CVE-2014-6272 advisory for more information. (d49bc0e88b81a5812116074dc007f1db0ca1eecd) - - o Pass flags to fcntl(F_SETFL) as int, not long (b3d0382) - o Backport and tweak the LICENSE file for 1.4 (8a5ebd3) - o set close-on-exec bit for filedescriptors created by dns subsystem (9985231 Ralf Schmitt) - o Replace unused case of FD_CLOSEONEXEC with a proper null statement. (44f04a2) - o Fix kqueue correctness test on x84_64 (1c25b07) - o Avoid deadlock when activating signals. (e0e6958) - o Backport doc fix for evhttp_bind_socket. (95b71d0 Marco) - o Fix an issue with forking and signal socketpairs in select/poll backends (f0ff765) - o Fix compilation on Visual Studio 2010 (53c47c2 VDm) - o Defensive programming to prevent (hopefully impossible) stack-stomping (2d8cf0b) - o Check for POLLERR, POLLHUP and POLLNVAL for Solaris event ports (353b4ac Trond Norbye) - o Fix a bug that could allow dns requests with duplicate tx ids (e50ba5b) - o Avoid truncating huge values for content-length (1d6e30e) - o Take generated files out of git; add correct m4 magic for libtool to auto* files (7cf794b) - o Prefer autoregen -ivf to manual autogen.sh (823d9be) - - -Changes in 1.4.14b-stable - o Set the VERSION_INFO correctly for 1.4.14 - - -Changes in 1.4.14-stable - o Add a .gitignore file for the 1.4 branch. (d014edb) - o Backport evbuffer_readln(). (b04cc60 Nicholas Marriott) - o Make the evbuffer_readln backport follow the current API (c545485) - o Valgrind fix: Clear struct kevent before checking for OSX bug. (5713d5d William Ahern) - o Fix a crash when reading badly formatted resolve.conf (5b10d00 Yasuoka Masahiko) - o Fix memory-leak of signal handler array with kqueue. [backport] (01f3775) - o Update sample/signal-test.c to use newer APIs and not leak. (891765c Evan Jones) - o Correct all versions in 1.4 branch (ac0d213) - o Make evutil_make_socket_nonblocking() leave any other flags alone. (81c26ba Jardel Weyrich) - o Adjusted fcntl() retval comparison on evutil_make_socket_nonblocking(). (5f2e250 Jardel Weyrich) - o Correct a debug message in evhttp_parse_request_line (35df59e) - o Merge branch 'readln-backport' into patches-1.4 (8771d5b) - o Do not send an HTTP error when we've already closed or responded. (4fd2dd9 Pavel Plesov) - o Re-add event_siglcb; some old code _was_ still using it. :( (bd03d06) - o Make Libevent 1.4 build on win32 with Unicode enabled. (bce58d6 Brodie Thiesfield) - o Distribute nmake makefile for 1.4 (20d706d) - o do not fail while sending on http connections the client closed. (5c8b446) - o make evhttp_send() safe against terminated connections, too (01ea0c5) - o Fix a free(NULL) in min_heap.h (2458934) - o Fix memory leak when setting up priorities; reported by Alexander Drozdov (cb1a722) - o Clean up properly when adding a signal handler fails. (ae6ece0 Gilad Benjamini) - o Do not abort HTTP requests missing a reason string. (29d7b32 Pierre Phaneuf) - o Fix compile warning in http.c (906d573) - o Define _REENTRANT as needed on Solaris, elsewhere (6cbea13) - - -Changes in 1.4.13-stable: - o If the kernel tells us that there are a negative number of bytes to read from a socket, do not believe it. Fixes bug 2841177; found by Alexander Pronchenkov. - o Do not allocate the maximum event queue and fd array for the epoll backend at startup. Instead, start out accepting 32 events at a time, and double the queue's size when it seems that the OS is generating events faster than we're requesting them. Saves up to 512K per epoll-based event_base. Resolves bug 2839240. - o Fix compilation on Android, which forgot to define fd_mask in its sys/select.h - o Do not drop data from evbuffer when out of memory; reported by Jacek Masiulaniec - o Rename our replacement compat/sys/_time.h header to avoid build a conflict on HPUX; reported by Kathryn Hogg. - o Build kqueue.c correctly on GNU/kFreeBSD platforms. Patch pulled upstream from Debian. - o Fix a problem with excessive memory allocation when using multiple event priorities. - o When running set[ug]id, don't check the environment. Based on a patch from OpenBSD. - - -Changes in 1.4.12-stable: - o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair. - o Fix an obscure timing-dependent, allocator-dependent crash in the evdns code. - o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC. - o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32). - o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.] - o Do not break evdns connections to nameservers when our IP changes. - o Set truncated flag correctly in evdns server replies. - o Disable strict aliasing with GCC: our code is not compliant with it. - -Changes in 1.4.11-stable: - o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen] - o Remove the limit on size of HTTP headers by removing static buffers. - o Fix a nasty dangling pointer bug in epoll.c that could occur after epoll_recalc(). [Patch from Kevin Springborn] - o Distribute Win32-Code/event-config.h, not ./event-config.h - -Changes in 1.4.10-stable: - o clean up buffered http connection data on reset; reported by Brian O'Kelley - o bug fix and potential race condition in signal handling; from Alexander Drozdov - o rename the Solaris event ports backend to evport - o support compilation on Haiku - o fix signal processing when a signal callback delivers a signal; from Alexander Drozdov - o const-ify some arguments to evdns functions. - o off-by-one error in epoll_recalc; reported by Victor Goya - o include Doxyfile in tar ball; from Jeff Garzik - o correctly parse queries with encoded \r, \n or + characters - -Changes in 1.4.9-stable: - o event_add would not return error for some backends; from Dean McNamee - o Clear the timer cache on entering the event loop; reported by Victor Chang - o Only bind the socket on connect when a local address has been provided; reported by Alejo Sanchez - o Allow setting of local port for evhttp connections to support millions of connections from a single system; from Richard Jones. - o Clear the timer cache when leaving the event loop; reported by Robin Haberkorn - o Fix a typo in setting the global event base; reported by lance. - o Fix a memory leak when reading multi-line headers - o Fix a memory leak by not running explicit close detection for server connections - -Changes in 1.4.8-stable: - o Match the query in DNS replies to the query in the request; from Vsevolod Stakhov. - o Fix a merge problem in which name_from_addr returned pointers to the stack; found by Jiang Hong. - o Do not remove Accept-Encoding header - -Changes in 1.4.7-stable: - o Fix a bug where headers arriving in multiple packets were not parsed; fix from Jiang Hong; test by me. - -Changes in 1.4.6-stable: - o evutil.h now includes <stdarg.h> directly - o switch all uses of [v]snprintf over to evutil - o Correct handling of trailing headers in chunked replies; from Scott Lamb. - o Support multi-line HTTP headers; based on a patch from Moshe Litvin - o Reject negative Content-Length headers; anonymous bug report - o Detect CLOCK_MONOTONIC at runtime for evdns; anonymous bug report - o Fix a bug where deleting signals with the kqueue backend would cause subsequent adds to fail - o Support multiple events listening on the same signal; make signals regular events that go on the same event queue; problem report by Alexander Drozdov. - o Deal with evbuffer_read() returning -1 on EINTR|EAGAIN; from Adam Langley. - o Fix a bug in which the DNS server would incorrectly set the type of a cname reply to a. - o Fix a bug where setting the timeout on a bufferevent would take not effect if the event was already pending. - o Fix a memory leak when using signals for some event bases; reported by Alexander Drozdov. - o Add libevent.vcproj file to distribution to help with Windows build. - o Fix a problem with epoll() and reinit; problem report by Alexander Drozdov. - o Fix off-by-one errors in devpoll; from Ian Bell - o Make event_add not change any state if it fails; reported by Ian Bell. - o Do not warn on accept when errno is either EAGAIN or EINTR - -Changes in 1.4.5-stable: - o Fix connection keep-alive behavior for HTTP/1.0 - o Fix use of freed memory in event_reinit; pointed out by Peter Postma - o Constify struct timeval * where possible; pointed out by Forest Wilkinson - o allow min_heap_erase to be called on removed members; from liusifan. - o Rename INPUT and OUTPUT to EVRPC_INPUT and EVRPC_OUTPUT. Retain INPUT/OUTPUT aliases on on-win32 platforms for backwards compatibility. - o Do not use SO_REUSEADDR when connecting - o Fix Windows build - o Fix a bug in event_rpcgen when generated fixed-sized entries - -Changes in 1.4.4-stable: - o Correct the documentation on buffer printf functions. - o Don't warn on unimplemented epoll_create(): this isn't a problem, just a reason to fall back to poll or select. - o Correctly handle timeouts larger than 35 minutes on Linux with epoll.c. This is probably a kernel defect, but we'll have to support old kernels anyway even if it gets fixed. - o Fix a potential stack corruption bug in tagging on 64-bit CPUs. - o expose bufferevent_setwatermark via header files and fix high watermark on read - o fix a bug in bufferevent read water marks and add a test for them - o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents - o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy. - o reduce system calls for getting current time by caching it. - o fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server. - o Build test directory correctly with CPPFLAGS set. - o Fix build under Visual C++ 2005. - o Expose evhttp_accept_socket() API. - o Merge windows gettimeofday() replacement into a new evutil_gettimeofday() function. - o Fix autoconf script behavior on IRIX. - o Make sure winsock2.h include always comes before windows.h include. - -Changes in 1.4.3-stable: - o include Content-Length in reply for HTTP/1.0 requests with keep-alive - o Patch from Tani Hosokawa: make some functions in http.c threadsafe. - o Do not free the kqop file descriptor in other processes, also allow it to be 0; from Andrei Nigmatulin - o make event_rpcgen.py generate code include event-config.h; reported by Sam Banks. - o make event methods static so that they are not exported; from Andrei Nigmatulin - o make RPC replies use application/octet-stream as mime type - o do not delete uninitialized timeout event in evdns - -Changes in 1.4.2-rc: - o remove pending timeouts on event_base_free() - o also check EAGAIN for Solaris' event ports; from W.C.A. Wijngaards - o devpoll and evport need reinit; tested by W.C.A Wijngaards - o event_base_get_method; from Springande Ulv - o Send CRLF after each chunk in HTTP output, for compliance with RFC2626. Patch from "propanbutan". Fixes bug 1894184. - o Add a int64_t parsing function, with unit tests, so we can apply Scott Lamb's fix to allow large HTTP values. - o Use a 64-bit field to hold HTTP content-lengths. Patch from Scott Lamb. - o Allow regression code to build even without Python installed - o remove NDEBUG ifdefs from evdns.c - o update documentation of event_loop and event_base_loop; from Tani Hosokawa. - o detect integer types properly on platforms without stdint.h - o Remove "AM_MAINTAINER_MODE" declaration in configure.in: now makefiles and configure should get re-generated automatically when Makefile.am or configure.in chanes. - o do not insert event into list when evsel->add fails - -Changes in 1.4.1-beta: - o free minheap on event_base_free(); from Christopher Layne - o debug cleanups in signal.c; from Christopher Layne - o provide event_base_new() that does not set the current_base global - o bufferevent_write now uses a const source argument; report from Charles Kerr - o better documentation for event_base_loopexit; from Scott Lamb. - o Make kqueue have the same behavior as other backends when a signal is caught between event_add() and event_loop(). Previously, it would catch and ignore such signals. - o Make kqueue restore signal handlers correctly when event_del() is called. - o provide event_reinit() to reintialize an event_base after fork - o small improvements to evhttp documentation - o always generate Date and Content-Length headers for HTTP/1.1 replies - o set the correct event base for HTTP close events - o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb - o Removed obsoleted recalc code - o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures. - o fix a bug with event_rpcgen for integers - o move EV_PERSIST handling out of the event backends - o support for 32-bit tag numbers in rpc structures; this is wire compatible, but changes the API slightly. - o prefix {encode,decode}_tag functions with evtag to avoid collisions - o Correctly handle DNS replies with no answers set (Fixes bug 1846282) - o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.) - o When building with GCC, use the "format" attribute to verify type correctness of calls to printf-like functions. - o removed linger from http server socket; reported by Ilya Martynov - o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr. - o demote most http warnings to debug messages - o Fix Solaris compilation; from Magne Mahre - o Add a "Date" header to HTTP responses, as required by HTTP 1.1. - o Support specifying the local address of an evhttp_connection using set_local_address - o Fix a memory leak in which failed HTTP connections would not free the request object - o Make adding of array members in event_rpcgen more efficient, but doubling memory allocation - o Fix a memory leak in the DNS server - o Fix compilation when DNS_USE_OPENSSL_FOR_ID is enabled - o Fix buffer size and string generation in evdns_resolve_reverse_ipv6(). - o Respond to nonstandard DNS queries with "NOTIMPL" rather than by ignoring them. - o In DNS responses, the CD flag should be preserved, not the TC flag. - o Fix http.c to compile properly with USE_DEBUG; from Christopher Layne - o Handle NULL timeouts correctly on Solaris; from Trond Norbye - o Recalculate pending events properly when reallocating event array on Solaris; from Trond Norbye - o Add Doxygen documentation to header files; from Mark Heily - o Add a evdns_set_transaction_id_fn() function to override the default - transaction ID generation code. - o Add an evutil module (with header evutil.h) to implement our standard cross-platform hacks, on the theory that somebody else would like to use them too. - o Fix signals implementation on windows. - o Fix http module on windows to close sockets properly. - o Make autogen.sh script run correctly on systems where /bin/sh isn't bash. (Patch from Trond Norbye, rewritten by Hagne Mahre and then Hannah Schroeter.) - o Skip calling gettime() in timeout_process if we are not in fact waiting for any events. (Patch from Trond Norbye) - o Make test subdirectory compile under mingw. - o Fix win32 buffer.c behavior so that it is correct for sockets (which do not like ReadFile and WriteFile). - o Make the test.sh script run unit tests for the evpoll method. - o Make the entire evdns.h header enclosed in "extern C" as appropriate. - o Fix implementation of strsep on platforms that lack it - o Fix implementation of getaddrinfo on platforms that lack it; mainly, this will make Windows http.c work better. Original patch by Lubomir Marinov. - o Fix evport implementation: port_disassociate called on unassociated events resulting in bogus errors; more efficient memory management; from Trond Norbye and Prakash Sangappa - o support for hooks on rpc input and output; can be used to implement rpc independent processing such as compression or authentication. - o use a min heap instead of a red-black tree for timeouts; as a result finding the min is a O(1) operation now; from Maxim Yegorushkin - o associate an event base with an rpc pool - o added two additional libraries: libevent_core and libevent_extra in addition to the regular libevent. libevent_core contains only the event core whereas libevent_extra contains dns, http and rpc support - o Begin using libtool's library versioning support correctly. If we don't mess up, this will more or less guarantee binaries linked against old versions of libevent continue working when we make changes to libevent that do not break backward compatibility. - o Fix evhttp.h compilation when TAILQ_ENTRY is not defined. - o Small code cleanups in epoll_dispatch(). - o Increase the maximum number of addresses read from a packet in evdns to 32. - o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much. Let us know if there's a good reason to put it back in. - o Rename the "class" field in evdns_server_request to dns_question_class, so that it won't break compilation under C++. Use a macro so that old code won't break. Mark the macro as deprecated. - o Fix DNS unit tests so that having a DNS server with broken IPv6 support is no longer cause for aborting the unit tests. - o Make event_base_free() succeed even if there are pending non-internal events on a base. This may still leak memory and fds, but at least it no longer crashes. - o Post-process the config.h file into a new, installed event-config.h file that we can install, and whose macros will be safe to include in header files. - o Remove the long-deprecated acconfig.h file. - o Do not require #include <sys/types.h> before #include <event.h>. - o Add new evutil_timer* functions to wrap (or replace) the regular timeval manipulation functions. - o Fix many build issues when using the Microsoft C compiler. - o Remove a bash-ism in autogen.sh - o When calling event_del on a signal, restore the signal handler's previous value rather than setting it to SIG_DFL. Patch from Christopher Layne. - o Make the logic for active events work better with internal events; patch from Christopher Layne. - o We do not need to specially remove a timeout before calling event_del; patch from Christopher Layne.
diff --git a/third_party/libevent/Doxyfile b/third_party/libevent/Doxyfile deleted file mode 100644 index 77f6de8..0000000 --- a/third_party/libevent/Doxyfile +++ /dev/null
@@ -1,230 +0,0 @@ -# Doxyfile 1.5.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = libevent - -# Place all output under 'doxygen/' - -OUTPUT_DIRECTORY = doxygen/ - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explicit @brief command for a brief description. - -JAVADOC_AUTOBRIEF = YES - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = event.h evdns.h evhttp.h evrpc.h - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = YES - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = YES - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = YES - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = TAILQ_ENTRY RB_ENTRY _EVENT_DEFINED_TQENTRY - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES
diff --git a/third_party/libevent/LICENSE b/third_party/libevent/LICENSE deleted file mode 100644 index cabd9fc..0000000 --- a/third_party/libevent/LICENSE +++ /dev/null
@@ -1,53 +0,0 @@ -Libevent is available for use under the following license, commonly known -as the 3-clause (or "modified") BSD license: - -============================== -Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu> -Copyright (c) 2007-2010 Niels Provos and Nick Mathewson - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -============================== - -Portions of Libevent are based on works by others, also made available by -them under the three-clause BSD license above. The copyright notices are -available in the corresponding source files; the license is as above. Here's -a list: - -log.c: - Copyright (c) 2000 Dug Song <dugsong@monkey.org> - Copyright (c) 1993 The Regents of the University of California. - -strlcpy.c: - Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - -win32.c: - Copyright (c) 2003 Michael A. Davis <mike@datanerds.net> - -evport.c: - Copyright (c) 2007 Sun Microsystems - -min_heap.h: - Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com> - -tree.h: - Copyright 2002 Niels Provos <provos@citi.umich.edu>
diff --git a/third_party/libevent/Makefile.am b/third_party/libevent/Makefile.am deleted file mode 100644 index c1ed62a..0000000 --- a/third_party/libevent/Makefile.am +++ /dev/null
@@ -1,152 +0,0 @@ -AUTOMAKE_OPTIONS = foreign no-dependencies - -ACLOCAL_AMFLAGS = -I m4 - -# This is the point release for libevent. It shouldn't include any -# a/b/c/d/e notations. -RELEASE = 1.4 - -# This is the version info for the libevent binary API. It has three -# numbers: -# Current -- the number of the binary API that we're implementing -# Revision -- which iteration of the implementation of the binary -# API are we supplying? -# Age -- How many previous binary API versions do we also -# support? -# -# If we release a new version that does not change the binary API, -# increment Revision. -# -# If we release a new version that changes the binary API, but does -# not break programs compiled against the old binary API, increment -# Current and Age. Set Revision to 0, since this is the first -# implementation of the new API. -# -# Otherwise, we're changing the binary API and breaking bakward -# compatibility with old binaries. Increment Current. Set Age to 0, -# since we're backward compatible with no previous APIs. Set Revision -# to 0 too. -VERSION_INFO = 4:1:2 - -### -# History: -# We started using Libtool around version 1.0d. For all versions from -# 1.0d through 1.3e, we set RELEASE to the version name, and -# VERSION_INFO to something haphazard. The didn't matter, since -# setting RELEASE meant that no version of Libevent was treated as -# binary-compatible with any other version. -# -# As of 1.4.0-beta, we set RELEASE to "1.4", so that releases in the -# 1.4.x series could be potentially binary-compatible with one another, -# but not with any other series. (They aren't.) We didn't necessarily -# set VERSION_INFO correctly, or update it as often as we should have. -# The VERSION_INFO values were: -# 1.4.0-beta .. 1.4.4-stable : 2:0:0 [See note 1] -# 1.4.5-stable : 3:0:1 (compatible ABI change) -# 1.4.6-stable : 3:1:1 (no ABI change) -# 1.4.7-stable : 3:1:1 [see note 1] -# 1.4.8-stable : 3:2:1 (no ABI change) -# 1.4.9-stable : 3:2:1 [see note 1] -# 1.4.10-stable : 3:3:1 (no ABI change) -# 1.4.11-stable .. 1.4.13-stable : 3:3:1 [see note 1] -# 1.4.14a-stable: : 3:3:2 [see note 2] -# 1.4.14b-stable: : 4:0:2 (compatible ABI change) -# 1.4.15-stable: : 4:1:2 (no ABI change) -# -# [1]: Using the same VERSION_INFO value was wrong; we should have been -# updating the Revision field. -# [2]: We set the VERSION_INFO completely wrong on 1.4.14b-stable - -bin_SCRIPTS = event_rpcgen.py - -EXTRA_DIST = autogen.sh event.h event-internal.h log.h evsignal.h evdns.3 \ - evrpc.h evrpc-internal.h min_heap.h \ - event.3 \ - Doxyfile \ - kqueue.c epoll_sub.c epoll.c select.c poll.c signal.c \ - evport.c devpoll.c event_rpcgen.py \ - sample/Makefile.am sample/Makefile.in sample/event-test.c \ - sample/signal-test.c sample/time-test.c \ - test/Makefile.am test/Makefile.in test/bench.c test/regress.c \ - test/test-eof.c test/test-weof.c test/test-time.c \ - test/test-init.c test/test.sh \ - compat/sys/queue.h compat/sys/_libevent_time.h \ - WIN32-Code/config.h \ - WIN32-Code/event-config.h \ - WIN32-Code/win32.c \ - WIN32-Code/tree.h \ - WIN32-Prj/event_test/event_test.dsp \ - WIN32-Prj/event_test/test.txt WIN32-Prj/libevent.dsp \ - WIN32-Prj/libevent.dsw WIN32-Prj/signal_test/signal_test.dsp \ - WIN32-Prj/time_test/time_test.dsp WIN32-Prj/regress/regress.vcproj \ - WIN32-Prj/libevent.sln WIN32-Prj/libevent.vcproj \ - Makefile.nmake test/Makefile.nmake \ - LICENSE - -lib_LTLIBRARIES = libevent.la libevent_core.la libevent_extra.la - -if BUILD_WIN32 - -SUBDIRS = . sample -SYS_LIBS = -lws2_32 -SYS_SRC = WIN32-Code/win32.c -SYS_INCLUDES = -IWIN32-Code - -else - -SUBDIRS = . sample test -SYS_LIBS = -SYS_SRC = -SYS_INCLUDES = - -endif - -BUILT_SOURCES = event-config.h - -event-config.h: config.h - echo '/* event-config.h' > $@ - echo ' * Generated by autoconf; post-processed by libevent.' >> $@ - echo ' * Do not edit this file.' >> $@ - echo ' * Do not rely on macros in this file existing in later versions.'>> $@ - echo ' */' >> $@ - echo '#ifndef _EVENT_CONFIG_H_' >> $@ - echo '#define _EVENT_CONFIG_H_' >> $@ - - sed -e 's/#define /#define _EVENT_/' \ - -e 's/#undef /#undef _EVENT_/' \ - -e 's/#ifndef /#ifndef _EVENT_/' < config.h >> $@ - echo "#endif" >> $@ - -CORE_SRC = event.c buffer.c evbuffer.c log.c evutil.c $(SYS_SRC) -EXTRA_SRC = event_tagging.c http.c evhttp.h http-internal.h evdns.c \ - evdns.h evrpc.c evrpc.h evrpc-internal.h \ - strlcpy.c strlcpy-internal.h strlcpy-internal.h - -libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC) -libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) -libevent_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO) - -libevent_core_la_SOURCES = $(CORE_SRC) -libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) -libevent_core_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO) - -libevent_extra_la_SOURCES = $(EXTRA_SRC) -libevent_extra_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS) -libevent_extra_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO) - -include_HEADERS = event.h evhttp.h evdns.h evrpc.h evutil.h - -nodist_include_HEADERS = event-config.h - -INCLUDES = -I$(srcdir)/compat $(SYS_INCLUDES) - -man_MANS = event.3 evdns.3 - -verify: libevent.la - cd test && make verify - -doxygen: FORCE - doxygen $(srcdir)/Doxyfile -FORCE: - -DISTCLEANFILES = *~ event-config.h
diff --git a/third_party/libevent/Makefile.nmake b/third_party/libevent/Makefile.nmake deleted file mode 100644 index f8d5722..0000000 --- a/third_party/libevent/Makefile.nmake +++ /dev/null
@@ -1,48 +0,0 @@ -# WATCH OUT! This makefile is a work in progress. It is probably missing -# tons of important things. DO NOT RELY ON IT TO BUILD A GOOD LIBEVENT. - -# Needed for correctness -CFLAGS=/Iinclude /Icompat /IWIN32-Code /DWIN32 /DHAVE_CONFIG_H /I. - -# For optimization and warnings -CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo - -# XXXX have a debug mode - -LIBFLAGS=/nologo - - -CORE_OBJS=event.obj buffer.obj evbuffer.obj \ - log.obj evutil.obj \ - strlcpy.obj signal.obj win32.obj -EXTRA_OBJS=event_tagging.obj http.obj evdns.obj evrpc.obj - -ALL_OBJS=$(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS) -STATIC_LIBS=libevent_core.lib libevent_extras.lib libevent.lib - - -all: static_libs tests - -static_libs: $(STATIC_LIBS) - -win32.obj: WIN32-Code\win32.c - $(CC) $(CFLAGS) /c WIN32-Code\win32.c - -libevent_core.lib: $(CORE_OBJS) - lib $(LIBFLAGS) $(CORE_OBJS) /out:libevent_core.lib - -libevent_extras.lib: $(EXTRA_OBJS) - lib $(LIBFLAGS) $(EXTRA_OBJS) /out:libevent_extras.lib - -libevent.lib: $(CORE_OBJ) $(EXTRA_OBJS) - lib $(LIBFLAGS) $(CORE_OBJS) $(EXTRA_OBJS) /out:libevent.lib - -clean: - del $(ALL_OBJS) - del $(STATIC_LIBS) - cd test - $(MAKE) /F Makefile.nmake clean - -tests: - cd test - $(MAKE) /F Makefile.nmake
diff --git a/third_party/libevent/OWNERS b/third_party/libevent/OWNERS deleted file mode 100644 index df8d6f3..0000000 --- a/third_party/libevent/OWNERS +++ /dev/null
@@ -1,5 +0,0 @@ -thakis@chromium.org - -# The only remaining dependency on libevent is within WebRTC. -handellm@google.com -mbonadei@chromium.org
diff --git a/third_party/libevent/README b/third_party/libevent/README deleted file mode 100644 index b065039..0000000 --- a/third_party/libevent/README +++ /dev/null
@@ -1,57 +0,0 @@ -To build libevent, type - -$ ./configure && make - - (If you got libevent from the subversion repository, you will - first need to run the included "autogen.sh" script in order to - generate the configure script.) - -Install as root via - -# make install - -You can run the regression tests by - -$ make verify - -Before, reporting any problems, please run the regression tests. - -To enable the low-level tracing build the library as: - -CFLAGS=-DUSE_DEBUG ./configure [...] - -Acknowledgements: ------------------ - -The following people have helped with suggestions, ideas, code or -fixing bugs: - - Alejo - Weston Andros Adamson - William Ahern - Stas Bekman - Andrew Danforth - Mike Davis - Shie Erlich - Alexander von Gernler - Artur Grabowski - Aaron Hopkins - Claudio Jeker - Scott Lamb - Adam Langley - Philip Lewis - David Libenzi - Nick Mathewson - Andrey Matveev - Richard Nyberg - Jon Oberheide - Phil Oleson - Dave Pacheco - Tassilo von Parseval - Pierre Phaneuf - Jon Poland - Bert JW Regeer - Dug Song - Taral - -If I have forgotten your name, please contact me.
diff --git a/third_party/libevent/README.chromium b/third_party/libevent/README.chromium deleted file mode 100644 index d5edd70..0000000 --- a/third_party/libevent/README.chromium +++ /dev/null
@@ -1,50 +0,0 @@ -Name: libevent -URL: http://libevent.org/ -Version: 1.4.15 -License: BSD-3-Clause -License File: LICENSE -Security Critical: yes -Shipped: yes -CPEPrefix: cpe:/a:libevent_project:libevent - -Local Modifications: -Rather than use libevent's own build system, we just build a Chrome -static library using GYP. - -1) Run configure and "make event-config.h" on Linux, FreeBSD, Solaris, - and Mac and copy config.h and event-config.h to linux/, freebsd/, - solaris/, and mac/ respectively. -2) Add BUILD.gn -3) chromium.patch is applied to make the following changes: - - Allow libevent to be used without being installed by changing <...> - #includes to "...". - - Fix a race condition in event_del. - - Optimistically assume CLOCK_MONOTONIC is available and fallback if it - fails, rather than explicitly testing for it. - - Remove an unneeded variable that causes a -Werror build failure. - - Add an #ifndef to fix a preprocessor redefined -Werror build failure. - - Revert the patch from http://sourceforge.net/p/levent/bugs/223/ that - introduces use-after-free memory corruption when an event callback frees - the struct event memory. - - Remove deprecated global variables, event_sigcb and event_gotsig - (essentially unused) that trigger tsan errors. (crbug/605894) -4) The directories WIN32-Code and WIN32-Prj are not included. -5) The configs for android were copied from Linux's which were very close to - android one with the exception of HAVE_FD_MASK and HAVE_STRLCPY. -6) Remove an unnecessary workaround for OS X 10.4 from kqueue.c. It was causing - problems on macOS Sierra. -7) Change _event_strlcpy in strlcpy.c to not use K&R syntax. -8) Deleted the following unused sources: - buffer.c - evbuffer.c - evdns.c - evdns.h - event_tagging.c - evhttp.h - evrpc-internal.h - evrpc.c - evrpc.h - http-internal.h - http.c -9) Deleted all references to evbuffer and evtag symbols in event.h -
diff --git a/third_party/libevent/aix/config.h b/third_party/libevent/aix/config.h deleted file mode 100644 index 89e1f11..0000000 --- a/third_party/libevent/aix/config.h +++ /dev/null
@@ -1,276 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -/* #undef HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -/* #undef HAVE_FD_MASK */ - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -/* #undef HAVE_LIBRESOLV */ - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -/* #undef HAVE_TIMERADD */ - -/* Define if timerclear is defined in <sys/time.h> */ -#define HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -/* #undef HAVE_VASPRINTF */ - -/* Define if kqueue works correctly with pipes */ -/* #undef HAVE_WORKING_KQUEUE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef __func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef socklen_t */
diff --git a/third_party/libevent/aix/event-config.h b/third_party/libevent/aix/event-config.h deleted file mode 100644 index 2679490..0000000 --- a/third_party/libevent/aix/event-config.h +++ /dev/null
@@ -1,284 +0,0 @@ -/* event-config.h - * Generated by autoconf; post-processed by libevent. - * Do not edit this file. - * Do not rely on macros in this file existing in later versions. - */ -#ifndef _EVENT_CONFIG_H_ -#define _EVENT_CONFIG_H_ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define _EVENT_HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef _EVENT_HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define _EVENT_HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef _EVENT_HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef _EVENT_HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -/* #undef _EVENT_HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define _EVENT_HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define _EVENT_HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define _EVENT_HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define _EVENT_HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define _EVENT_HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define _EVENT_HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define _EVENT_HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define _EVENT_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define _EVENT_HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define _EVENT_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef _EVENT_HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef _EVENT_HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define _EVENT_HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -/* #undef _EVENT_HAVE_LIBRESOLV */ - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define _EVENT_HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef _EVENT_HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define _EVENT_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef _EVENT_HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define _EVENT_HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define _EVENT_HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef _EVENT_HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef _EVENT_HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define _EVENT_HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define _EVENT_HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define _EVENT_HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define _EVENT_HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define _EVENT_HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define _EVENT_HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define _EVENT_HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define _EVENT_HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define _EVENT_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define _EVENT_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define _EVENT_HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define _EVENT_HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define _EVENT_HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define _EVENT_HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define _EVENT_HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define _EVENT_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define _EVENT_HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define _EVENT_HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define _EVENT_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define _EVENT_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define _EVENT_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define _EVENT_HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define _EVENT_HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -/* #undef _EVENT_HAVE_TIMERADD */ - -/* Define if timerclear is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define _EVENT_HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define _EVENT_HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define _EVENT_HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define _EVENT_HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define _EVENT_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -/* #undef _EVENT_HAVE_VASPRINTF */ - -/* Define if kqueue works correctly with pipes */ -/* #undef _EVENT_HAVE_WORKING_KQUEUE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define _EVENT_LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define _EVENT_NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define _EVENT_PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define _EVENT_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _EVENT_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define _EVENT_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define _EVENT_PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define _EVENT_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _EVENT_PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define _EVENT_SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define _EVENT_SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define _EVENT_STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define _EVENT_TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define _EVENT_VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef _EVENT___func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef _EVENT_const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef _EVENT___cplusplus -/* #undef _EVENT_inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef _EVENT_pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef _EVENT_size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef _EVENT_socklen_t */ -#endif
diff --git a/third_party/libevent/android/config.h b/third_party/libevent/android/config.h deleted file mode 100644 index 91f4dda..0000000 --- a/third_party/libevent/android/config.h +++ /dev/null
@@ -1,266 +0,0 @@ -/* Copied from Linux version and changed the features according Android, which - * is close to Linux */ - -/* Define if clock_gettime is available in libc */ -#define DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -#define HAVE_EPOLL 1 - -/* Define to 1 if you have the `epoll_ctl' function. */ -#define HAVE_EPOLL_CTL 1 - -/* Define if your system supports event ports */ -/* #undef HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -/* #undef HAVE_FD_MASK */ - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -#define HAVE_SYS_EPOLL_H 1 - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -/* #undef HAVE_WORKING_KQUEUE */ - -/* Name of package */ -#define PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "1.4.13-stable" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef __func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef socklen_t */
diff --git a/third_party/libevent/android/event-config.h b/third_party/libevent/android/event-config.h deleted file mode 100644 index 6563cb78..0000000 --- a/third_party/libevent/android/event-config.h +++ /dev/null
@@ -1,281 +0,0 @@ -/* Copied from Linux version and changed the features according Android, which - * is close to Linux */ -#ifndef _EVENT_CONFIG_H_ -#define _EVENT_CONFIG_H_ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define _EVENT_HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef _EVENT_HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define _EVENT_HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -#define _EVENT_HAVE_EPOLL 1 - -/* Define to 1 if you have the `epoll_ctl' function. */ -#define _EVENT_HAVE_EPOLL_CTL 1 - -/* Define if your system supports event ports */ -/* #undef _EVENT_HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define _EVENT_HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define _EVENT_HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -/* #undef _EVENT_HAVE_FD_MASK 1 */ - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define _EVENT_HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define _EVENT_HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define _EVENT_HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define _EVENT_HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define _EVENT_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define _EVENT_HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define _EVENT_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef _EVENT_HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef _EVENT_HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define _EVENT_HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define _EVENT_HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define _EVENT_HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef _EVENT_HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define _EVENT_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef _EVENT_HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define _EVENT_HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define _EVENT_HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef _EVENT_HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef _EVENT_HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define _EVENT_HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define _EVENT_HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define _EVENT_HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define _EVENT_HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define _EVENT_HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define _EVENT_HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define _EVENT_HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define _EVENT_HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define _EVENT_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define _EVENT_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define _EVENT_HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define _EVENT_HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define _EVENT_HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define _EVENT_HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -#define _EVENT_HAVE_SYS_EPOLL_H 1 - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define _EVENT_HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define _EVENT_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define _EVENT_HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define _EVENT_HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define _EVENT_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define _EVENT_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define _EVENT_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define _EVENT_HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define _EVENT_HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define _EVENT_HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define _EVENT_HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define _EVENT_HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define _EVENT_HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define _EVENT_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define _EVENT_HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -/* #undef _EVENT_HAVE_WORKING_KQUEUE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define _EVENT_LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define _EVENT_NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define _EVENT_PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define _EVENT_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _EVENT_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define _EVENT_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define _EVENT_PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define _EVENT_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _EVENT_PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define _EVENT_SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define _EVENT_SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define _EVENT_STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define _EVENT_TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define _EVENT_VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef _EVENT___func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef _EVENT_const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef _EVENT___cplusplus -/* #undef _EVENT_inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef _EVENT_pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef _EVENT_size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef _EVENT_socklen_t */ -#endif
diff --git a/third_party/libevent/autogen.sh b/third_party/libevent/autogen.sh deleted file mode 100755 index 099cb305..0000000 --- a/third_party/libevent/autogen.sh +++ /dev/null
@@ -1,15 +0,0 @@ -#!/bin/sh -if [ -x "`which autoreconf 2>/dev/null`" ] ; then - exec autoreconf -ivf -fi - -LIBTOOLIZE=libtoolize -SYSNAME=`uname` -if [ "x$SYSNAME" = "xDarwin" ] ; then - LIBTOOLIZE=glibtoolize -fi -aclocal && \ - autoheader && \ - $LIBTOOLIZE && \ - autoconf && \ - automake --add-missing --copy
diff --git a/third_party/libevent/chromium.patch b/third_party/libevent/chromium.patch deleted file mode 100644 index 5c7e72c..0000000 --- a/third_party/libevent/chromium.patch +++ /dev/null
@@ -1,165 +0,0 @@ -diff --git a/third_party/libevent/event.c b/third_party/libevent/event.c -index da6cd42..36b1c51 100644 ---- a/third_party/libevent/event.c -+++ b/third_party/libevent/event.c -@@ -107,11 +107,7 @@ static const struct eventop *eventops[] = { - /* Global state */ - struct event_base *current_base = NULL; - extern struct event_base *evsignal_base; --static int use_monotonic; -- --/* Handle signals - This is a deprecated interface */ --int (*event_sigcb)(void); /* Signal callback when gotsig is set */ --volatile sig_atomic_t event_gotsig; /* Set in signal handler */ -+static int use_monotonic = 1; - - /* Prototypes */ - static void event_queue_insert(struct event_base *, struct event *, int); -@@ -124,17 +120,6 @@ static int timeout_next(struct event_base *, struct timeval **); - static void timeout_process(struct event_base *); - static void timeout_correct(struct event_base *, struct timeval *); - --static void --detect_monotonic(void) --{ --#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) -- struct timespec ts; -- -- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) -- use_monotonic = 1; --#endif --} -- - static int - gettime(struct event_base *base, struct timeval *tp) - { -@@ -144,18 +129,18 @@ gettime(struct event_base *base, struct timeval *tp) - } - - #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) -- if (use_monotonic) { -- struct timespec ts; -- -- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) -- return (-1); -+ struct timespec ts; - -+ if (use_monotonic && -+ clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - tp->tv_sec = ts.tv_sec; - tp->tv_usec = ts.tv_nsec / 1000; - return (0); - } - #endif - -+ use_monotonic = 0; -+ - return (evutil_gettimeofday(tp, NULL)); - } - -@@ -179,10 +164,6 @@ event_base_new(void) - if ((base = calloc(1, sizeof(struct event_base))) == NULL) - event_err(1, "%s: calloc", __func__); - -- event_sigcb = NULL; -- event_gotsig = 0; -- -- detect_monotonic(); - gettime(base, &base->event_tv); - - min_heap_ctor(&base->timeheap); -@@ -398,12 +379,9 @@ event_process_active(struct event_base *base) - ncalls--; - ev->ev_ncalls = ncalls; - (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg); -- if (event_gotsig || base->event_break) { -- ev->ev_pncalls = NULL; -+ if (base->event_break) - return; -- } - } -- ev->ev_pncalls = NULL; - } - } - -@@ -506,18 +484,6 @@ event_base_loop(struct event_base *base, int flags) - break; - } - -- /* You cannot use this interface for multi-threaded apps */ -- while (event_gotsig) { -- event_gotsig = 0; -- if (event_sigcb) { -- res = (*event_sigcb)(); -- if (res == -1) { -- errno = EINTR; -- return (-1); -- } -- } -- } -- - timeout_correct(base, &tv); - - tv_p = &tv; -@@ -808,8 +774,6 @@ int - event_del(struct event *ev) - { - struct event_base *base; -- const struct eventop *evsel; -- void *evbase; - - event_debug(("event_del: %p, callback %p", - ev, ev->ev_callback)); -@@ -819,8 +783,6 @@ event_del(struct event *ev) - return (-1); - - base = ev->ev_base; -- evsel = base->evsel; -- evbase = base->evbase; - - assert(!(ev->ev_flags & ~EVLIST_ALL)); - -@@ -838,7 +800,7 @@ event_del(struct event *ev) - - if (ev->ev_flags & EVLIST_INSERTED) { - event_queue_remove(base, ev, EVLIST_INSERTED); -- return (evsel->del(evbase, ev)); -+ return (base->evsel->del(base->evbase, ev)); - } - - return (0); -diff --git a/third_party/libevent/event.h b/third_party/libevent/event.h -index d1f5d9e..f0887b9 100644 ---- a/third_party/libevent/event.h -+++ b/third_party/libevent/event.h -@@ -159,7 +159,7 @@ - extern "C" { - #endif - --#include <event-config.h> -+#include "event-config.h" - #ifdef _EVENT_HAVE_SYS_TYPES_H - #include <sys/types.h> - #endif -@@ -172,7 +172,7 @@ extern "C" { - #include <stdarg.h> - - /* For int types. */ --#include <evutil.h> -+#include "evutil.h" - - #ifdef WIN32 - #define WIN32_LEAN_AND_MEAN -diff --git a/third_party/libevent/evutil.h b/third_party/libevent/evutil.h -index dcb0013..8b664b9 100644 ---- a/third_party/libevent/evutil.h -+++ b/third_party/libevent/evutil.h -@@ -38,7 +38,7 @@ - extern "C" { - #endif - --#include <event-config.h> -+#include "event-config.h" - #ifdef _EVENT_HAVE_SYS_TIME_H - #include <sys/time.h> - #endif
diff --git a/third_party/libevent/compat/sys/_libevent_time.h b/third_party/libevent/compat/sys/_libevent_time.h deleted file mode 100644 index 8cabb0d..0000000 --- a/third_party/libevent/compat/sys/_libevent_time.h +++ /dev/null
@@ -1,163 +0,0 @@ -/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */ -/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ - -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)time.h 8.2 (Berkeley) 7/10/94 - */ - -#ifndef _SYS_TIME_H_ -#define _SYS_TIME_H_ - -#include <sys/types.h> - -/* - * Structure returned by gettimeofday(2) system call, - * and used in other calls. - */ -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; - -/* - * Structure defined by POSIX.1b to be like a timeval. - */ -struct timespec { - time_t tv_sec; /* seconds */ - long tv_nsec; /* and nanoseconds */ -}; - -#define TIMEVAL_TO_TIMESPEC(tv, ts) { \ - (ts)->tv_sec = (tv)->tv_sec; \ - (ts)->tv_nsec = (tv)->tv_usec * 1000; \ -} -#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ - (tv)->tv_sec = (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ -} - -struct timezone { - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; -#define DST_NONE 0 /* not on dst */ -#define DST_USA 1 /* USA style dst */ -#define DST_AUST 2 /* Australian style dst */ -#define DST_WET 3 /* Western European dst */ -#define DST_MET 4 /* Middle European dst */ -#define DST_EET 5 /* Eastern European dst */ -#define DST_CAN 6 /* Canada */ - -/* Operations on timevals. */ -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 -#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#define timercmp(tvp, uvp, cmp) \ - (((tvp)->tv_sec == (uvp)->tv_sec) ? \ - ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ - ((tvp)->tv_sec cmp (uvp)->tv_sec)) -#define timeradd(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ - if ((vvp)->tv_usec >= 1000000) { \ - (vvp)->tv_sec++; \ - (vvp)->tv_usec -= 1000000; \ - } \ - } while (0) -#define timersub(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ - if ((vvp)->tv_usec < 0) { \ - (vvp)->tv_sec--; \ - (vvp)->tv_usec += 1000000; \ - } \ - } while (0) - -/* Operations on timespecs. */ -#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 -#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec) -#define timespeccmp(tsp, usp, cmp) \ - (((tsp)->tv_sec == (usp)->tv_sec) ? \ - ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ - ((tsp)->tv_sec cmp (usp)->tv_sec)) -#define timespecadd(tsp, usp, vsp) \ - do { \ - (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ - (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ - if ((vsp)->tv_nsec >= 1000000000L) { \ - (vsp)->tv_sec++; \ - (vsp)->tv_nsec -= 1000000000L; \ - } \ - } while (0) -#define timespecsub(tsp, usp, vsp) \ - do { \ - (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ - (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ - if ((vsp)->tv_nsec < 0) { \ - (vsp)->tv_sec--; \ - (vsp)->tv_nsec += 1000000000L; \ - } \ - } while (0) - -/* - * Names of the interval timers, and structure - * defining a timer setting. - */ -#define ITIMER_REAL 0 -#define ITIMER_VIRTUAL 1 -#define ITIMER_PROF 2 - -struct itimerval { - struct timeval it_interval; /* timer interval */ - struct timeval it_value; /* current value */ -}; - -/* - * Getkerninfo clock information structure - */ -struct clockinfo { - int hz; /* clock frequency */ - int tick; /* micro-seconds per hz tick */ - int tickadj; /* clock skew rate for adjtime() */ - int stathz; /* statistics clock frequency */ - int profhz; /* profiling clock frequency */ -}; - -#define CLOCK_REALTIME 0 -#define CLOCK_VIRTUAL 1 -#define CLOCK_PROF 2 - -#define TIMER_RELTIME 0x0 /* relative timer */ -#define TIMER_ABSTIME 0x1 /* absolute timer */ - -/* --- stuff got cut here - niels --- */ - -#endif /* !_SYS_TIME_H_ */
diff --git a/third_party/libevent/compat/sys/queue.h b/third_party/libevent/compat/sys/queue.h deleted file mode 100644 index c0956dd..0000000 --- a/third_party/libevent/compat/sys/queue.h +++ /dev/null
@@ -1,488 +0,0 @@ -/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */ -/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. - * - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * Singly-linked List definitions. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#ifndef WIN32 -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} -#endif - -/* - * Singly-linked List access methods. - */ -#define SLIST_FIRST(head) ((head)->slh_first) -#define SLIST_END(head) NULL -#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - -/* - * Singly-linked List functions. - */ -#define SLIST_INIT(head) { \ - SLIST_FIRST(head) = SLIST_END(head); \ -} - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (0) - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List access methods - */ -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_END(head) NULL -#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_FOREACH(var, head, field) \ - for((var) = LIST_FIRST(head); \ - (var)!= LIST_END(head); \ - (var) = LIST_NEXT(var, field)) - -/* - * List functions. - */ -#define LIST_INIT(head) do { \ - LIST_FIRST(head) = LIST_END(head); \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (0) - -#define LIST_REPLACE(elm, elm2, field) do { \ - if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ - (elm2)->field.le_next->field.le_prev = \ - &(elm2)->field.le_next; \ - (elm2)->field.le_prev = (elm)->field.le_prev; \ - *(elm2)->field.le_prev = (elm2); \ -} while (0) - -/* - * Simple queue definitions. - */ -#define SIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define SIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue access methods. - */ -#define SIMPLEQ_FIRST(head) ((head)->sqh_first) -#define SIMPLEQ_END(head) NULL -#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - -#define SIMPLEQ_FOREACH(var, head, field) \ - for((var) = SIMPLEQ_FIRST(head); \ - (var) != SIMPLEQ_END(head); \ - (var) = SIMPLEQ_NEXT(var, field)) - -/* - * Simple queue functions. - */ -#define SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (0) - -#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (0) - -#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (0) - -#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \ - if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (0) - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -/* - * tail queue access methods - */ -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -/* XXX */ -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -#define TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) - -#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \ - for((var) = TAILQ_LAST(head, headname); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_PREV(var, headname, field)) - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ - (elm2)->field.tqe_next->field.tqe_prev = \ - &(elm2)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm2)->field.tqe_next; \ - (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ - *(elm2)->field.tqe_prev = (elm2); \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue access methods - */ -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -#define CIRCLEQ_EMPTY(head) \ - (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for((var) = CIRCLEQ_FIRST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_NEXT(var, field)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for((var) = CIRCLEQ_LAST(head); \ - (var) != CIRCLEQ_END(head); \ - (var) = CIRCLEQ_PREV(var, field)) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = CIRCLEQ_END(head); \ - (head)->cqh_last = CIRCLEQ_END(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = CIRCLEQ_END(head); \ - if ((head)->cqh_last == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = CIRCLEQ_END(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ -} while (0) - -#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ - CIRCLEQ_END(head)) \ - (head).cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ - CIRCLEQ_END(head)) \ - (head).cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */
diff --git a/third_party/libevent/configure.in b/third_party/libevent/configure.in deleted file mode 100644 index 468d7744..0000000 --- a/third_party/libevent/configure.in +++ /dev/null
@@ -1,421 +0,0 @@ -dnl configure.in for libevent -dnl Dug Song <dugsong@monkey.org> -AC_INIT(event.c) - -AM_INIT_AUTOMAKE(libevent,1.4.15) -AM_CONFIG_HEADER(config.h) -dnl AM_MAINTAINER_MODE - -AC_CONFIG_MACRO_DIR([m4]) - -AC_CANONICAL_HOST - -AC_DEFINE(NUMERIC_VERSION, 0x01040f00, [Numeric representation of the version]) - -dnl Initialize prefix. -if test "$prefix" = "NONE"; then - prefix="/usr/local" -fi - -dnl Checks for programs. -AC_PROG_CC -AC_PROG_INSTALL -AC_PROG_LN_S - -AC_PROG_GCC_TRADITIONAL -if test "$GCC" = yes ; then - CFLAGS="$CFLAGS -Wall" - # And disable the strict-aliasing optimization, since it breaks - # our sockaddr-handling code in strange ways. - CFLAGS="$CFLAGS -fno-strict-aliasing" -fi - -dnl Libevent 1.4 isn't multithreaded, but some of its functions are -dnl documented to be reentrant. If you don't define the right macros -dnl on some platforms, you get non-reentrant versions of the libc -dnl functinos (like an errno that's shared by all threads). -AC_MSG_CHECKING([whether we need extra flags to make libc reentrant]) -case $host in - *solaris* | *-osf* | *-hpux* ) - AC_MSG_RESULT([-D_REENTRANT]) - CFLAGS="$CFLAGS -D_REENTRANT" - ;; - *-aix* | *-freebsd* | *-darwin* ) - AC_MSG_RESULT([-D_THREAD_SAFE]) - CFLAGS="$CFLAGS -D_THREAD_SAFE" - ;; - *) - AC_MSG_RESULT(no) - ;; -esac - -AC_ARG_ENABLE(gcc-warnings, - AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings with GCC)) - -AC_PROG_LIBTOOL - -dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get -dnl built by default. You can also turn shared libs on and off from -dnl the command line with --enable-shared and --disable-shared. -dnl AC_DISABLE_SHARED -AC_SUBST(LIBTOOL_DEPS) - -dnl Checks for libraries. -AC_CHECK_LIB(socket, socket) -AC_CHECK_LIB(resolv, inet_aton) -AC_CHECK_LIB(rt, clock_gettime) -AC_CHECK_LIB(nsl, inet_ntoa) - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h sys/socket.h) -if test "x$ac_cv_header_sys_queue_h" = "xyes"; then - AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h) - AC_EGREP_CPP(yes, -[ -#include <sys/queue.h> -#ifdef TAILQ_FOREACH - yes -#endif -], [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_TAILQFOREACH, 1, - [Define if TAILQ_FOREACH is defined in <sys/queue.h>])], - AC_MSG_RESULT(no) - ) -fi - -if test "x$ac_cv_header_sys_time_h" = "xyes"; then - AC_MSG_CHECKING(for timeradd in sys/time.h) - AC_EGREP_CPP(yes, -[ -#include <sys/time.h> -#ifdef timeradd - yes -#endif -], [ AC_DEFINE(HAVE_TIMERADD, 1, - [Define if timeradd is defined in <sys/time.h>]) - AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) -) -fi - -if test "x$ac_cv_header_sys_time_h" = "xyes"; then - AC_MSG_CHECKING(for timercmp in sys/time.h) - AC_EGREP_CPP(yes, -[ -#include <sys/time.h> -#ifdef timercmp - yes -#endif -], [ AC_DEFINE(HAVE_TIMERCMP, 1, - [Define if timercmp is defined in <sys/time.h>]) - AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) -) -fi - -if test "x$ac_cv_header_sys_time_h" = "xyes"; then - AC_MSG_CHECKING(for timerclear in sys/time.h) - AC_EGREP_CPP(yes, -[ -#include <sys/time.h> -#ifdef timerclear - yes -#endif -], [ AC_DEFINE(HAVE_TIMERCLEAR, 1, - [Define if timerclear is defined in <sys/time.h>]) - AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) -) -fi - -if test "x$ac_cv_header_sys_time_h" = "xyes"; then - AC_MSG_CHECKING(for timerisset in sys/time.h) - AC_EGREP_CPP(yes, -[ -#include <sys/time.h> -#ifdef timerisset - yes -#endif -], [ AC_DEFINE(HAVE_TIMERISSET, 1, - [Define if timerisset is defined in <sys/time.h>]) - AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no) -) -fi - -dnl - check if the macro WIN32 is defined on this compiler. -dnl - (this is how we check for a windows version of GCC) -AC_MSG_CHECKING(for WIN32) -AC_TRY_COMPILE(, - [ -#ifndef WIN32 -die horribly -#endif - ], - bwin32=true; AC_MSG_RESULT(yes), - bwin32=false; AC_MSG_RESULT(no), -) - -AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_C_INLINE -AC_HEADER_TIME - -dnl Checks for library functions. -AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction strtoll issetugid geteuid getegid) - -AC_CHECK_SIZEOF(long) - -if test "x$ac_cv_func_clock_gettime" = "xyes"; then - AC_DEFINE(DNS_USE_CPU_CLOCK_FOR_ID, 1, [Define if clock_gettime is available in libc]) -else - AC_DEFINE(DNS_USE_GETTIMEOFDAY_FOR_ID, 1, [Define is no secure id variant is available]) -fi - -AC_MSG_CHECKING(for F_SETFD in fcntl.h) -AC_EGREP_CPP(yes, -[ -#define _GNU_SOURCE -#include <fcntl.h> -#ifdef F_SETFD -yes -#endif -], [ AC_DEFINE(HAVE_SETFD, 1, - [Define if F_SETFD is defined in <fcntl.h>]) - AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no)) - -needsignal=no -haveselect=no -AC_CHECK_FUNCS(select, [haveselect=yes], ) -if test "x$haveselect" = "xyes" ; then - AC_LIBOBJ(select) - needsignal=yes -fi - -havepoll=no -AC_CHECK_FUNCS(poll, [havepoll=yes], ) -if test "x$havepoll" = "xyes" ; then - AC_LIBOBJ(poll) - needsignal=yes -fi - -haveepoll=no -AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], ) -if test "x$haveepoll" = "xyes" ; then - AC_DEFINE(HAVE_EPOLL, 1, - [Define if your system supports the epoll system calls]) - AC_LIBOBJ(epoll) - needsignal=yes -fi - -havedevpoll=no -if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then - AC_DEFINE(HAVE_DEVPOLL, 1, - [Define if /dev/poll is available]) - AC_LIBOBJ(devpoll) -fi - -havekqueue=no -if test "x$ac_cv_header_sys_event_h" = "xyes"; then - AC_CHECK_FUNCS(kqueue, [havekqueue=yes], ) - if test "x$havekqueue" = "xyes" ; then - AC_MSG_CHECKING(for working kqueue) - AC_TRY_RUN( -#include <sys/types.h> -#include <sys/time.h> -#include <sys/event.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> - -int -main(int argc, char **argv) -{ - int kq; - int n; - int fd[[2]]; - struct kevent ev; - struct timespec ts; - char buf[[8000]]; - - if (pipe(fd) == -1) - exit(1); - if (fcntl(fd[[1]], F_SETFL, O_NONBLOCK) == -1) - exit(1); - - while ((n = write(fd[[1]], buf, sizeof(buf))) == sizeof(buf)) - ; - - if ((kq = kqueue()) == -1) - exit(1); - - memset(&ev, 0, sizeof(ev)); - ev.ident = fd[[1]]; - ev.filter = EVFILT_WRITE; - ev.flags = EV_ADD | EV_ENABLE; - n = kevent(kq, &ev, 1, NULL, 0, NULL); - if (n == -1) - exit(1); - - read(fd[[0]], buf, sizeof(buf)); - - ts.tv_sec = 0; - ts.tv_nsec = 0; - n = kevent(kq, NULL, 0, &ev, 1, &ts); - if (n == -1 || n == 0) - exit(1); - - exit(0); -}, [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_WORKING_KQUEUE, 1, - [Define if kqueue works correctly with pipes]) - AC_LIBOBJ(kqueue)], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) - fi -fi - -haveepollsyscall=no -if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then - if test "x$haveepoll" = "xno" ; then - AC_MSG_CHECKING(for epoll system call) - AC_TRY_RUN( -#include <stdint.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/syscall.h> -#include <sys/epoll.h> -#include <unistd.h> - -int -epoll_create(int size) -{ - return (syscall(__NR_epoll_create, size)); -} - -int -main(int argc, char **argv) -{ - int epfd; - - epfd = epoll_create(256); - exit (epfd == -1 ? 1 : 0); -}, [AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_EPOLL, 1, - [Define if your system supports the epoll system calls]) - needsignal=yes - AC_LIBOBJ(epoll_sub) - AC_LIBOBJ(epoll)], AC_MSG_RESULT(no), AC_MSG_RESULT(no)) - fi -fi - -haveeventports=no -AC_CHECK_FUNCS(port_create, [haveeventports=yes], ) -if test "x$haveeventports" = "xyes" ; then - AC_DEFINE(HAVE_EVENT_PORTS, 1, - [Define if your system supports event ports]) - AC_LIBOBJ(evport) - needsignal=yes -fi -if test "x$bwin32" = "xtrue"; then - needsignal=yes -fi -if test "x$bwin32" = "xtrue"; then - needsignal=yes -fi -if test "x$needsignal" = "xyes" ; then - AC_LIBOBJ(signal) -fi - -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_CHECK_TYPES([uint64_t, uint32_t, uint16_t, uint8_t], , , -[#ifdef HAVE_STDINT_H -#include <stdint.h> -#elif defined(HAVE_INTTYPES_H) -#include <inttypes.h> -#endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif]) -AC_CHECK_TYPES([fd_mask], , , -[#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SELECT_H -#include <select.h> -#endif]) - -AC_CHECK_SIZEOF(long long) -AC_CHECK_SIZEOF(int) -AC_CHECK_SIZEOF(short) -AC_CHECK_TYPES([struct in6_addr], , , -[#ifdef WIN32 -#include <winsock2.h> -#else -#include <sys/types.h> -#include <netinet/in.h> -#include <sys/socket.h> -#endif -#ifdef HAVE_NETINET_IN6_H -#include <netinet/in6.h> -#endif]) - -AC_MSG_CHECKING([for socklen_t]) -AC_TRY_COMPILE([ - #include <sys/types.h> - #include <sys/socket.h>], - [socklen_t x;], - AC_MSG_RESULT([yes]), - [AC_MSG_RESULT([no]) - AC_DEFINE(socklen_t, unsigned int, - [Define to unsigned int if you dont have it])] -) - -AC_MSG_CHECKING([whether our compiler supports __func__]) -AC_TRY_COMPILE([], - [ const char *cp = __func__; ], - AC_MSG_RESULT([yes]), - AC_MSG_RESULT([no]) - AC_MSG_CHECKING([whether our compiler supports __FUNCTION__]) - AC_TRY_COMPILE([], - [ const char *cp = __FUNCTION__; ], - AC_MSG_RESULT([yes]) - AC_DEFINE(__func__, __FUNCTION__, - [Define to appropriate substitue if compiler doesnt have __func__]), - AC_MSG_RESULT([no]) - AC_DEFINE(__func__, __FILE__, - [Define to appropriate substitue if compiler doesnt have __func__]))) - - -# Add some more warnings which we use in development but not in the -# released versions. (Some relevant gcc versions can't handle these.) -if test x$enable_gcc_warnings = xyes; then - - AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [ -#if !defined(__GNUC__) || (__GNUC__ < 4) -#error -#endif]), have_gcc4=yes, have_gcc4=no) - - AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [ -#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) -#error -#endif]), have_gcc42=yes, have_gcc42=no) - - CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror" - CFLAGS="$CFLAGS -Wno-unused-parameter -Wno-sign-compare -Wstrict-aliasing" - - if test x$have_gcc4 = xyes ; then - # These warnings break gcc 3.3.5 and work on gcc 4.0.2 - CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement" - #CFLAGS="$CFLAGS -Wold-style-definition" - fi - - if test x$have_gcc42 = xyes ; then - # These warnings break gcc 4.0.2 and work on gcc 4.2 - CFLAGS="$CFLAGS -Waddress -Wnormalized=id -Woverride-init" - fi - -##This will break the world on some 64-bit architectures -# CFLAGS="$CFLAGS -Winline" - -fi - -AC_OUTPUT(Makefile test/Makefile sample/Makefile)
diff --git a/third_party/libevent/devpoll.c b/third_party/libevent/devpoll.c deleted file mode 100644 index 2d34ae3..0000000 --- a/third_party/libevent/devpoll.c +++ /dev/null
@@ -1,417 +0,0 @@ -/* - * Copyright 2000-2004 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/resource.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#include <sys/queue.h> -#include <sys/devpoll.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <assert.h> - -#include "event.h" -#include "event-internal.h" -#include "evsignal.h" -#include "log.h" - -/* due to limitations in the devpoll interface, we need to keep track of - * all file descriptors outself. - */ -struct evdevpoll { - struct event *evread; - struct event *evwrite; -}; - -struct devpollop { - struct evdevpoll *fds; - int nfds; - struct pollfd *events; - int nevents; - int dpfd; - struct pollfd *changes; - int nchanges; -}; - -static void *devpoll_init (struct event_base *); -static int devpoll_add (void *, struct event *); -static int devpoll_del (void *, struct event *); -static int devpoll_dispatch (struct event_base *, void *, struct timeval *); -static void devpoll_dealloc (struct event_base *, void *); - -const struct eventop devpollops = { - "devpoll", - devpoll_init, - devpoll_add, - devpoll_del, - devpoll_dispatch, - devpoll_dealloc, - 1 /* need reinit */ -}; - -#define NEVENT 32000 - -static int -devpoll_commit(struct devpollop *devpollop) -{ - /* - * Due to a bug in Solaris, we have to use pwrite with an offset of 0. - * Write is limited to 2GB of data, until it will fail. - */ - if (pwrite(devpollop->dpfd, devpollop->changes, - sizeof(struct pollfd) * devpollop->nchanges, 0) == -1) - return(-1); - - devpollop->nchanges = 0; - return(0); -} - -static int -devpoll_queue(struct devpollop *devpollop, int fd, int events) { - struct pollfd *pfd; - - if (devpollop->nchanges >= devpollop->nevents) { - /* - * Change buffer is full, must commit it to /dev/poll before - * adding more - */ - if (devpoll_commit(devpollop) != 0) - return(-1); - } - - pfd = &devpollop->changes[devpollop->nchanges++]; - pfd->fd = fd; - pfd->events = events; - pfd->revents = 0; - - return(0); -} - -static void * -devpoll_init(struct event_base *base) -{ - int dpfd, nfiles = NEVENT; - struct rlimit rl; - struct devpollop *devpollop; - - /* Disable devpoll when this environment variable is set */ - if (evutil_getenv("EVENT_NODEVPOLL")) - return (NULL); - - if (!(devpollop = calloc(1, sizeof(struct devpollop)))) - return (NULL); - - if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && - rl.rlim_cur != RLIM_INFINITY) - nfiles = rl.rlim_cur; - - /* Initialize the kernel queue */ - if ((dpfd = open("/dev/poll", O_RDWR)) == -1) { - event_warn("open: /dev/poll"); - free(devpollop); - return (NULL); - } - - devpollop->dpfd = dpfd; - - /* Initialize fields */ - devpollop->events = calloc(nfiles, sizeof(struct pollfd)); - if (devpollop->events == NULL) { - free(devpollop); - close(dpfd); - return (NULL); - } - devpollop->nevents = nfiles; - - devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll)); - if (devpollop->fds == NULL) { - free(devpollop->events); - free(devpollop); - close(dpfd); - return (NULL); - } - devpollop->nfds = nfiles; - - devpollop->changes = calloc(nfiles, sizeof(struct pollfd)); - if (devpollop->changes == NULL) { - free(devpollop->fds); - free(devpollop->events); - free(devpollop); - close(dpfd); - return (NULL); - } - - evsignal_init(base); - - return (devpollop); -} - -static int -devpoll_recalc(struct event_base *base, void *arg, int max) -{ - struct devpollop *devpollop = arg; - - if (max >= devpollop->nfds) { - struct evdevpoll *fds; - int nfds; - - nfds = devpollop->nfds; - while (nfds <= max) - nfds <<= 1; - - fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll)); - if (fds == NULL) { - event_warn("realloc"); - return (-1); - } - devpollop->fds = fds; - memset(fds + devpollop->nfds, 0, - (nfds - devpollop->nfds) * sizeof(struct evdevpoll)); - devpollop->nfds = nfds; - } - - return (0); -} - -static int -devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - struct devpollop *devpollop = arg; - struct pollfd *events = devpollop->events; - struct dvpoll dvp; - struct evdevpoll *evdp; - int i, res, timeout = -1; - - if (devpollop->nchanges) - devpoll_commit(devpollop); - - if (tv != NULL) - timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; - - dvp.dp_fds = devpollop->events; - dvp.dp_nfds = devpollop->nevents; - dvp.dp_timeout = timeout; - - res = ioctl(devpollop->dpfd, DP_POLL, &dvp); - - if (res == -1) { - if (errno != EINTR) { - event_warn("ioctl: DP_POLL"); - return (-1); - } - - evsignal_process(base); - return (0); - } else if (base->sig.evsignal_caught) { - evsignal_process(base); - } - - event_debug(("%s: devpoll_wait reports %d", __func__, res)); - - for (i = 0; i < res; i++) { - int which = 0; - int what = events[i].revents; - struct event *evread = NULL, *evwrite = NULL; - - assert(events[i].fd < devpollop->nfds); - evdp = &devpollop->fds[events[i].fd]; - - if (what & POLLHUP) - what |= POLLIN | POLLOUT; - else if (what & POLLERR) - what |= POLLIN | POLLOUT; - - if (what & POLLIN) { - evread = evdp->evread; - which |= EV_READ; - } - - if (what & POLLOUT) { - evwrite = evdp->evwrite; - which |= EV_WRITE; - } - - if (!which) - continue; - - if (evread != NULL && !(evread->ev_events & EV_PERSIST)) - event_del(evread); - if (evwrite != NULL && evwrite != evread && - !(evwrite->ev_events & EV_PERSIST)) - event_del(evwrite); - - if (evread != NULL) - event_active(evread, EV_READ, 1); - if (evwrite != NULL) - event_active(evwrite, EV_WRITE, 1); - } - - return (0); -} - - -static int -devpoll_add(void *arg, struct event *ev) -{ - struct devpollop *devpollop = arg; - struct evdevpoll *evdp; - int fd, events; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_add(ev)); - - fd = ev->ev_fd; - if (fd >= devpollop->nfds) { - /* Extend the file descriptor array as necessary */ - if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1) - return (-1); - } - evdp = &devpollop->fds[fd]; - - /* - * It's not necessary to OR the existing read/write events that we - * are currently interested in with the new event we are adding. - * The /dev/poll driver ORs any new events with the existing events - * that it has cached for the fd. - */ - - events = 0; - if (ev->ev_events & EV_READ) { - if (evdp->evread && evdp->evread != ev) { - /* There is already a different read event registered */ - return(-1); - } - events |= POLLIN; - } - - if (ev->ev_events & EV_WRITE) { - if (evdp->evwrite && evdp->evwrite != ev) { - /* There is already a different write event registered */ - return(-1); - } - events |= POLLOUT; - } - - if (devpoll_queue(devpollop, fd, events) != 0) - return(-1); - - /* Update events responsible */ - if (ev->ev_events & EV_READ) - evdp->evread = ev; - if (ev->ev_events & EV_WRITE) - evdp->evwrite = ev; - - return (0); -} - -static int -devpoll_del(void *arg, struct event *ev) -{ - struct devpollop *devpollop = arg; - struct evdevpoll *evdp; - int fd, events; - int needwritedelete = 1, needreaddelete = 1; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_del(ev)); - - fd = ev->ev_fd; - if (fd >= devpollop->nfds) - return (0); - evdp = &devpollop->fds[fd]; - - events = 0; - if (ev->ev_events & EV_READ) - events |= POLLIN; - if (ev->ev_events & EV_WRITE) - events |= POLLOUT; - - /* - * The only way to remove an fd from the /dev/poll monitored set is - * to use POLLREMOVE by itself. This removes ALL events for the fd - * provided so if we care about two events and are only removing one - * we must re-add the other event after POLLREMOVE. - */ - - if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0) - return(-1); - - if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) { - /* - * We're not deleting all events, so we must resubmit the - * event that we are still interested in if one exists. - */ - - if ((events & POLLIN) && evdp->evwrite != NULL) { - /* Deleting read, still care about write */ - devpoll_queue(devpollop, fd, POLLOUT); - needwritedelete = 0; - } else if ((events & POLLOUT) && evdp->evread != NULL) { - /* Deleting write, still care about read */ - devpoll_queue(devpollop, fd, POLLIN); - needreaddelete = 0; - } - } - - if (needreaddelete) - evdp->evread = NULL; - if (needwritedelete) - evdp->evwrite = NULL; - - return (0); -} - -static void -devpoll_dealloc(struct event_base *base, void *arg) -{ - struct devpollop *devpollop = arg; - - evsignal_dealloc(base); - if (devpollop->fds) - free(devpollop->fds); - if (devpollop->events) - free(devpollop->events); - if (devpollop->changes) - free(devpollop->changes); - if (devpollop->dpfd >= 0) - close(devpollop->dpfd); - - memset(devpollop, 0, sizeof(struct devpollop)); - free(devpollop); -}
diff --git a/third_party/libevent/epoll.c b/third_party/libevent/epoll.c deleted file mode 100644 index 4387ef8..0000000 --- a/third_party/libevent/epoll.c +++ /dev/null
@@ -1,377 +0,0 @@ -/* - * Copyright 2000-2003 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdint.h> -#include <sys/types.h> -#include <sys/resource.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#include <sys/queue.h> -#include <sys/epoll.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#include "event.h" -#include "event-internal.h" -#include "evsignal.h" -#include "log.h" - -/* due to limitations in the epoll interface, we need to keep track of - * all file descriptors outself. - */ -struct evepoll { - struct event *evread; - struct event *evwrite; -}; - -struct epollop { - struct evepoll *fds; - int nfds; - struct epoll_event *events; - int nevents; - int epfd; -}; - -static void *epoll_init (struct event_base *); -static int epoll_add (void *, struct event *); -static int epoll_del (void *, struct event *); -static int epoll_dispatch (struct event_base *, void *, struct timeval *); -static void epoll_dealloc (struct event_base *, void *); - -const struct eventop epollops = { - "epoll", - epoll_init, - epoll_add, - epoll_del, - epoll_dispatch, - epoll_dealloc, - 1 /* need reinit */ -}; - -#ifdef HAVE_SETFD -#define FD_CLOSEONEXEC(x) do { \ - if (fcntl(x, F_SETFD, 1) == -1) \ - event_warn("fcntl(%d, F_SETFD)", x); \ -} while (0) -#else -#define FD_CLOSEONEXEC(x) -#endif - -/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout - * values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be - * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the - * largest number of msec we can support here is 2147482. Let's - * round that down by 47 seconds. - */ -#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000) - -#define INITIAL_NFILES 32 -#define INITIAL_NEVENTS 32 -#define MAX_NEVENTS 4096 - -static void * -epoll_init(struct event_base *base) -{ - int epfd; - struct epollop *epollop; - - /* Disable epollueue when this environment variable is set */ - if (evutil_getenv("EVENT_NOEPOLL")) - return (NULL); - - /* Initalize the kernel queue */ - if ((epfd = epoll_create(32000)) == -1) { - if (errno != ENOSYS) - event_warn("epoll_create"); - return (NULL); - } - - FD_CLOSEONEXEC(epfd); - - if (!(epollop = calloc(1, sizeof(struct epollop)))) - return (NULL); - - epollop->epfd = epfd; - - /* Initalize fields */ - epollop->events = malloc(INITIAL_NEVENTS * sizeof(struct epoll_event)); - if (epollop->events == NULL) { - free(epollop); - return (NULL); - } - epollop->nevents = INITIAL_NEVENTS; - - epollop->fds = calloc(INITIAL_NFILES, sizeof(struct evepoll)); - if (epollop->fds == NULL) { - free(epollop->events); - free(epollop); - return (NULL); - } - epollop->nfds = INITIAL_NFILES; - - evsignal_init(base); - - return (epollop); -} - -static int -epoll_recalc(struct event_base *base, void *arg, int max) -{ - struct epollop *epollop = arg; - - if (max >= epollop->nfds) { - struct evepoll *fds; - int nfds; - - nfds = epollop->nfds; - while (nfds <= max) - nfds <<= 1; - - fds = realloc(epollop->fds, nfds * sizeof(struct evepoll)); - if (fds == NULL) { - event_warn("realloc"); - return (-1); - } - epollop->fds = fds; - memset(fds + epollop->nfds, 0, - (nfds - epollop->nfds) * sizeof(struct evepoll)); - epollop->nfds = nfds; - } - - return (0); -} - -static int -epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - struct epollop *epollop = arg; - struct epoll_event *events = epollop->events; - struct evepoll *evep; - int i, res, timeout = -1; - - if (tv != NULL) - timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; - - if (timeout > MAX_EPOLL_TIMEOUT_MSEC) { - /* Linux kernels can wait forever if the timeout is too big; - * see comment on MAX_EPOLL_TIMEOUT_MSEC. */ - timeout = MAX_EPOLL_TIMEOUT_MSEC; - } - - res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout); - - if (res == -1) { - if (errno != EINTR) { - event_warn("epoll_wait"); - return (-1); - } - - evsignal_process(base); - return (0); - } else if (base->sig.evsignal_caught) { - evsignal_process(base); - } - - event_debug(("%s: epoll_wait reports %d", __func__, res)); - - for (i = 0; i < res; i++) { - int what = events[i].events; - struct event *evread = NULL, *evwrite = NULL; - int fd = events[i].data.fd; - - if (fd < 0 || fd >= epollop->nfds) - continue; - evep = &epollop->fds[fd]; - - if (what & (EPOLLHUP|EPOLLERR)) { - evread = evep->evread; - evwrite = evep->evwrite; - } else { - if (what & EPOLLIN) { - evread = evep->evread; - } - - if (what & EPOLLOUT) { - evwrite = evep->evwrite; - } - } - - if (!(evread||evwrite)) - continue; - - if (evread != NULL) - event_active(evread, EV_READ, 1); - if (evwrite != NULL) - event_active(evwrite, EV_WRITE, 1); - } - - if (res == epollop->nevents && epollop->nevents < MAX_NEVENTS) { - /* We used all of the event space this time. We should - be ready for more events next time. */ - int new_nevents = epollop->nevents * 2; - struct epoll_event *new_events; - - new_events = realloc(epollop->events, - new_nevents * sizeof(struct epoll_event)); - if (new_events) { - epollop->events = new_events; - epollop->nevents = new_nevents; - } - } - - return (0); -} - - -static int -epoll_add(void *arg, struct event *ev) -{ - struct epollop *epollop = arg; - struct epoll_event epev = {0, {0}}; - struct evepoll *evep; - int fd, op, events; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_add(ev)); - - fd = ev->ev_fd; - if (fd >= epollop->nfds) { - /* Extent the file descriptor array as necessary */ - if (epoll_recalc(ev->ev_base, epollop, fd) == -1) - return (-1); - } - evep = &epollop->fds[fd]; - op = EPOLL_CTL_ADD; - events = 0; - if (evep->evread != NULL) { - events |= EPOLLIN; - op = EPOLL_CTL_MOD; - } - if (evep->evwrite != NULL) { - events |= EPOLLOUT; - op = EPOLL_CTL_MOD; - } - - if (ev->ev_events & EV_READ) - events |= EPOLLIN; - if (ev->ev_events & EV_WRITE) - events |= EPOLLOUT; - - epev.data.fd = fd; - epev.events = events; - if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1) - return (-1); - - /* Update events responsible */ - if (ev->ev_events & EV_READ) - evep->evread = ev; - if (ev->ev_events & EV_WRITE) - evep->evwrite = ev; - - return (0); -} - -static int -epoll_del(void *arg, struct event *ev) -{ - struct epollop *epollop = arg; - struct epoll_event epev = {0, {0}}; - struct evepoll *evep; - int fd, events, op; - int needwritedelete = 1, needreaddelete = 1; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_del(ev)); - - fd = ev->ev_fd; - if (fd >= epollop->nfds) - return (0); - evep = &epollop->fds[fd]; - - op = EPOLL_CTL_DEL; - events = 0; - - if (ev->ev_events & EV_READ) - events |= EPOLLIN; - if (ev->ev_events & EV_WRITE) - events |= EPOLLOUT; - - if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) { - if ((events & EPOLLIN) && evep->evwrite != NULL) { - needwritedelete = 0; - events = EPOLLOUT; - op = EPOLL_CTL_MOD; - } else if ((events & EPOLLOUT) && evep->evread != NULL) { - needreaddelete = 0; - events = EPOLLIN; - op = EPOLL_CTL_MOD; - } - } - - epev.events = events; - epev.data.fd = fd; - - if (needreaddelete) - evep->evread = NULL; - if (needwritedelete) - evep->evwrite = NULL; - - if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1) - return (-1); - - return (0); -} - -static void -epoll_dealloc(struct event_base *base, void *arg) -{ - struct epollop *epollop = arg; - - evsignal_dealloc(base); - if (epollop->fds) - free(epollop->fds); - if (epollop->events) - free(epollop->events); - if (epollop->epfd >= 0) - close(epollop->epfd); - - memset(epollop, 0, sizeof(struct epollop)); - free(epollop); -}
diff --git a/third_party/libevent/epoll_sub.c b/third_party/libevent/epoll_sub.c deleted file mode 100644 index 431970c7..0000000 --- a/third_party/libevent/epoll_sub.c +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright 2003 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include <stdint.h> - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/syscall.h> -#include <sys/epoll.h> -#include <unistd.h> - -int -epoll_create(int size) -{ - return (syscall(__NR_epoll_create, size)); -} - -int -epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -{ - - return (syscall(__NR_epoll_ctl, epfd, op, fd, event)); -} - -int -epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) -{ - return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout)); -}
diff --git a/third_party/libevent/event-config.h b/third_party/libevent/event-config.h deleted file mode 100644 index 22c4b2e6..0000000 --- a/third_party/libevent/event-config.h +++ /dev/null
@@ -1,22 +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. - -// This file is Chromium-specific, and brings in the appropriate -// event-config.h depending on your platform. - -#if defined(__APPLE__) -#include "third_party/libevent/mac/event-config.h" -#elif defined(ANDROID) -#include "third_party/libevent/android/event-config.h" -#elif defined(__linux__) -#include "third_party/libevent/linux/event-config.h" -#elif defined(__FreeBSD__) -#include "third_party/libevent/freebsd/event-config.h" -#elif defined(__sun) -#include "third_party/libevent/solaris/event-config.h" -#elif defined(_AIX) -#include "third_party/libevent/aix/event-config.h" -#else -#error generate event-config.h for your platform -#endif
diff --git a/third_party/libevent/event-internal.h b/third_party/libevent/event-internal.h deleted file mode 100644 index b7f0040..0000000 --- a/third_party/libevent/event-internal.h +++ /dev/null
@@ -1,101 +0,0 @@ -/* - * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _EVENT_INTERNAL_H_ -#define _EVENT_INTERNAL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "config.h" -#include "min_heap.h" -#include "evsignal.h" - -struct eventop { - const char *name; - void *(*init)(struct event_base *); - int (*add)(void *, struct event *); - int (*del)(void *, struct event *); - int (*dispatch)(struct event_base *, void *, struct timeval *); - void (*dealloc)(struct event_base *, void *); - /* set if we need to reinitialize the event base */ - int need_reinit; -}; - -struct event_base { - const struct eventop *evsel; - void *evbase; - int event_count; /* counts number of total events */ - int event_count_active; /* counts number of active events */ - - int event_gotterm; /* Set to terminate loop */ - int event_break; /* Set to terminate loop immediately */ - - /* active event management */ - struct event_list **activequeues; - int nactivequeues; - - /* signal handling info */ - struct evsignal_info sig; - - struct event_list eventqueue; - struct timeval event_tv; - - struct min_heap timeheap; - - struct timeval tv_cache; -}; - -/* Internal use only: Functions that might be missing from <sys/queue.h> */ -#ifndef HAVE_TAILQFOREACH -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_END(head) NULL -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) -#endif /* TAILQ_FOREACH */ - -int _evsignal_set_handler(struct event_base *base, int evsignal, - void (*fn)(int)); -int _evsignal_restore_handler(struct event_base *base, int evsignal); - -/* defined in evutil.c */ -const char *evutil_getenv(const char *varname); - -#ifdef __cplusplus -} -#endif - -#endif /* _EVENT_INTERNAL_H_ */
diff --git a/third_party/libevent/event.3 b/third_party/libevent/event.3 deleted file mode 100644 index 5b33ec6..0000000 --- a/third_party/libevent/event.3 +++ /dev/null
@@ -1,624 +0,0 @@ -.\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $ -.\" -.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd August 8, 2000 -.Dt EVENT 3 -.Os -.Sh NAME -.Nm event_init , -.Nm event_dispatch , -.Nm event_loop , -.Nm event_loopexit , -.Nm event_loopbreak , -.Nm event_set , -.Nm event_base_dispatch , -.Nm event_base_loop , -.Nm event_base_loopexit , -.Nm event_base_loopbreak , -.Nm event_base_set , -.Nm event_base_free , -.Nm event_add , -.Nm event_del , -.Nm event_once , -.Nm event_base_once , -.Nm event_pending , -.Nm event_initialized , -.Nm event_priority_init , -.Nm event_priority_set , -.Nm evtimer_set , -.Nm evtimer_add , -.Nm evtimer_del , -.Nm evtimer_pending , -.Nm evtimer_initialized , -.Nm signal_set , -.Nm signal_add , -.Nm signal_del , -.Nm signal_pending , -.Nm signal_initialized , -.Nm bufferevent_new , -.Nm bufferevent_free , -.Nm bufferevent_write , -.Nm bufferevent_write_buffer , -.Nm bufferevent_read , -.Nm bufferevent_enable , -.Nm bufferevent_disable , -.Nm bufferevent_settimeout , -.Nm bufferevent_base_set , -.Nm evbuffer_new , -.Nm evbuffer_free , -.Nm evbuffer_add , -.Nm evbuffer_add_buffer , -.Nm evbuffer_add_printf , -.Nm evbuffer_add_vprintf , -.Nm evbuffer_drain , -.Nm evbuffer_write , -.Nm evbuffer_read , -.Nm evbuffer_find , -.Nm evbuffer_readline , -.Nm evhttp_new , -.Nm evhttp_bind_socket , -.Nm evhttp_free -.Nd execute a function when a specific event occurs -.Sh SYNOPSIS -.Fd #include <sys/time.h> -.Fd #include <event.h> -.Ft "struct event_base *" -.Fn "event_init" "void" -.Ft int -.Fn "event_dispatch" "void" -.Ft int -.Fn "event_loop" "int flags" -.Ft int -.Fn "event_loopexit" "struct timeval *tv" -.Ft int -.Fn "event_loopbreak" "void" -.Ft void -.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" -.Ft int -.Fn "event_base_dispatch" "struct event_base *base" -.Ft int -.Fn "event_base_loop" "struct event_base *base" "int flags" -.Ft int -.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv" -.Ft int -.Fn "event_base_loopbreak" "struct event_base *base" -.Ft int -.Fn "event_base_set" "struct event_base *base" "struct event *" -.Ft void -.Fn "event_base_free" "struct event_base *base" -.Ft int -.Fn "event_add" "struct event *ev" "struct timeval *tv" -.Ft int -.Fn "event_del" "struct event *ev" -.Ft int -.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv" -.Ft int -.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv" -.Ft int -.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv" -.Ft int -.Fn "event_initialized" "struct event *ev" -.Ft int -.Fn "event_priority_init" "int npriorities" -.Ft int -.Fn "event_priority_set" "struct event *ev" "int priority" -.Ft void -.Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg" -.Ft void -.Fn "evtimer_add" "struct event *ev" "struct timeval *" -.Ft void -.Fn "evtimer_del" "struct event *ev" -.Ft int -.Fn "evtimer_pending" "struct event *ev" "struct timeval *tv" -.Ft int -.Fn "evtimer_initialized" "struct event *ev" -.Ft void -.Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg" -.Ft void -.Fn "signal_add" "struct event *ev" "struct timeval *" -.Ft void -.Fn "signal_del" "struct event *ev" -.Ft int -.Fn "signal_pending" "struct event *ev" "struct timeval *tv" -.Ft int -.Fn "signal_initialized" "struct event *ev" -.Ft "struct bufferevent *" -.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg" -.Ft void -.Fn "bufferevent_free" "struct bufferevent *bufev" -.Ft int -.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size" -.Ft int -.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf" -.Ft size_t -.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size" -.Ft int -.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event" -.Ft int -.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event" -.Ft void -.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write" -.Ft int -.Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev" -.Ft "struct evbuffer *" -.Fn "evbuffer_new" "void" -.Ft void -.Fn "evbuffer_free" "struct evbuffer *buf" -.Ft int -.Fn "evbuffer_add" "struct evbuffer *buf" "const void *data" "size_t size" -.Ft int -.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src" -.Ft int -.Fn "evbuffer_add_printf" "struct evbuffer *buf" "const char *fmt" "..." -.Ft int -.Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap" -.Ft void -.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size" -.Ft int -.Fn "evbuffer_write" "struct evbuffer *buf" "int fd" -.Ft int -.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size" -.Ft "u_char *" -.Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size" -.Ft "char *" -.Fn "evbuffer_readline" "struct evbuffer *buf" -.Ft "struct evhttp *" -.Fn "evhttp_new" "struct event_base *base" -.Ft int -.Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "u_short port" -.Ft "void" -.Fn "evhttp_free" "struct evhttp *http" -.Ft int -.Fa (*event_sigcb)(void) ; -.Ft volatile sig_atomic_t -.Fa event_gotsig ; -.Sh DESCRIPTION -The -.Nm event -API provides a mechanism to execute a function when a specific event -on a file descriptor occurs or after a given time has passed. -.Pp -The -.Nm event -API needs to be initialized with -.Fn event_init -before it can be used. -.Pp -In order to process events, an application needs to call -.Fn event_dispatch . -This function only returns on error, and should replace the event core -of the application program. -.Pp -The function -.Fn event_set -prepares the event structure -.Fa ev -to be used in future calls to -.Fn event_add -and -.Fn event_del . -The event will be prepared to call the function specified by the -.Fa fn -argument with an -.Fa int -argument indicating the file descriptor, a -.Fa short -argument indicating the type of event, and a -.Fa void * -argument given in the -.Fa arg -argument. -The -.Fa fd -indicates the file descriptor that should be monitored for events. -The events can be either -.Va EV_READ , -.Va EV_WRITE , -or both, -indicating that an application can read or write from the file descriptor -respectively without blocking. -.Pp -The function -.Fa fn -will be called with the file descriptor that triggered the event and -the type of event which will be either -.Va EV_TIMEOUT , -.Va EV_SIGNAL , -.Va EV_READ , -or -.Va EV_WRITE . -Additionally, an event which has registered interest in more than one of the -preceeding events, via bitwise-OR to -.Fn event_set , -can provide its callback function with a bitwise-OR of more than one triggered -event. -The additional flag -.Va EV_PERSIST -makes an -.Fn event_add -persistent until -.Fn event_del -has been called. -.Pp -Once initialized, the -.Fa ev -structure can be used repeatedly with -.Fn event_add -and -.Fn event_del -and does not need to be reinitialized unless the function called and/or -the argument to it are to be changed. -However, when an -.Fa ev -structure has been added to libevent using -.Fn event_add -the structure must persist until the event occurs (assuming -.Fa EV_PERSIST -is not set) or is removed -using -.Fn event_del . -You may not reuse the same -.Fa ev -structure for multiple monitored descriptors; each descriptor -needs its own -.Fa ev . -.Pp -The function -.Fn event_add -schedules the execution of the -.Fa ev -event when the event specified in -.Fn event_set -occurs or in at least the time specified in the -.Fa tv . -If -.Fa tv -is -.Dv NULL , -no timeout occurs and the function will only be called -if a matching event occurs on the file descriptor. -The event in the -.Fa ev -argument must be already initialized by -.Fn event_set -and may not be used in calls to -.Fn event_set -until it has timed out or been removed with -.Fn event_del . -If the event in the -.Fa ev -argument already has a scheduled timeout, the old timeout will be -replaced by the new one. -.Pp -The function -.Fn event_del -will cancel the event in the argument -.Fa ev . -If the event has already executed or has never been added -the call will have no effect. -.Pp -The functions -.Fn evtimer_set , -.Fn evtimer_add , -.Fn evtimer_del , -.Fn evtimer_initialized , -and -.Fn evtimer_pending -are abbreviations for common situations where only a timeout is required. -The file descriptor passed will be \-1, and the event type will be -.Va EV_TIMEOUT . -.Pp -The functions -.Fn signal_set , -.Fn signal_add , -.Fn signal_del , -.Fn signal_initialized , -and -.Fn signal_pending -are abbreviations. -The event type will be a persistent -.Va EV_SIGNAL . -That means -.Fn signal_set -adds -.Va EV_PERSIST . -.Pp -In order to avoid races in signal handlers, the -.Nm event -API provides two variables: -.Va event_sigcb -and -.Va event_gotsig . -A signal handler -sets -.Va event_gotsig -to indicate that a signal has been received. -The application sets -.Va event_sigcb -to a callback function. -After the signal handler sets -.Va event_gotsig , -.Nm event_dispatch -will execute the callback function to process received signals. -The callback returns 1 when no events are registered any more. -It can return \-1 to indicate an error to the -.Nm event -library, causing -.Fn event_dispatch -to terminate with -.Va errno -set to -.Er EINTR . -.Pp -The function -.Fn event_once -is similar to -.Fn event_set . -However, it schedules a callback to be called exactly once and does not -require the caller to prepare an -.Fa event -structure. -This function supports -.Fa EV_TIMEOUT , -.Fa EV_READ , -and -.Fa EV_WRITE . -.Pp -The -.Fn event_pending -function can be used to check if the event specified by -.Fa event -is pending to run. -If -.Va EV_TIMEOUT -was specified and -.Fa tv -is not -.Dv NULL , -the expiration time of the event will be returned in -.Fa tv . -.Pp -The -.Fn event_initialized -macro can be used to check if an event has been initialized. -.Pp -The -.Nm event_loop -function provides an interface for single pass execution of pending -events. -The flags -.Va EVLOOP_ONCE -and -.Va EVLOOP_NONBLOCK -are recognized. -The -.Nm event_loopexit -function exits from the event loop. The next -.Fn event_loop -iteration after the -given timer expires will complete normally (handling all queued events) then -exit without blocking for events again. Subsequent invocations of -.Fn event_loop -will proceed normally. -The -.Nm event_loopbreak -function exits from the event loop immediately. -.Fn event_loop -will abort after the next event is completed; -.Fn event_loopbreak -is typically invoked from this event's callback. This behavior is analogous -to the "break;" statement. Subsequent invocations of -.Fn event_loop -will proceed normally. -.Pp -It is the responsibility of the caller to provide these functions with -pre-allocated event structures. -.Pp -.Sh EVENT PRIORITIES -By default -.Nm libevent -schedules all active events with the same priority. -However, sometimes it is desirable to process some events with a higher -priority than others. -For that reason, -.Nm libevent -supports strict priority queues. -Active events with a lower priority are always processed before events -with a higher priority. -.Pp -The number of different priorities can be set initially with the -.Fn event_priority_init -function. -This function should be called before the first call to -.Fn event_dispatch . -The -.Fn event_priority_set -function can be used to assign a priority to an event. -By default, -.Nm libevent -assigns the middle priority to all events unless their priority -is explicitly set. -.Sh THREAD SAFE EVENTS -.Nm Libevent -has experimental support for thread-safe events. -When initializing the library via -.Fn event_init , -an event base is returned. -This event base can be used in conjunction with calls to -.Fn event_base_set , -.Fn event_base_dispatch , -.Fn event_base_loop , -.Fn event_base_loopexit , -.Fn bufferevent_base_set -and -.Fn event_base_free . -.Fn event_base_set -should be called after preparing an event with -.Fn event_set , -as -.Fn event_set -assigns the provided event to the most recently created event base. -.Fn bufferevent_base_set -should be called after preparing a bufferevent with -.Fn bufferevent_new . -.Fn event_base_free -should be used to free memory associated with the event base -when it is no longer needed. -.Sh BUFFERED EVENTS -.Nm libevent -provides an abstraction on top of the regular event callbacks. -This abstraction is called a -.Va "buffered event" . -A buffered event provides input and output buffers that get filled -and drained automatically. -The user of a buffered event no longer deals directly with the IO, -but instead is reading from input and writing to output buffers. -.Pp -A new bufferevent is created by -.Fn bufferevent_new . -The parameter -.Fa fd -specifies the file descriptor from which data is read and written to. -This file descriptor is not allowed to be a -.Xr pipe 2 . -The next three parameters are callbacks. -The read and write callback have the following form: -.Ft void -.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" . -The error callback has the following form: -.Ft void -.Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" . -The argument is specified by the fourth parameter -.Fa "cbarg" . -A -.Fa bufferevent struct -pointer is returned on success, NULL on error. -Both the read and the write callback may be NULL. -The error callback has to be always provided. -.Pp -Once initialized, the bufferevent structure can be used repeatedly with -bufferevent_enable() and bufferevent_disable(). -The flags parameter can be a combination of -.Va EV_READ -and -.Va EV_WRITE . -When read enabled the bufferevent will try to read from the file -descriptor and call the read callback. -The write callback is executed -whenever the output buffer is drained below the write low watermark, -which is -.Va 0 -by default. -.Pp -The -.Fn bufferevent_write -function can be used to write data to the file descriptor. -The data is appended to the output buffer and written to the descriptor -automatically as it becomes available for writing. -.Fn bufferevent_write -returns 0 on success or \-1 on failure. -The -.Fn bufferevent_read -function is used to read data from the input buffer, -returning the amount of data read. -.Pp -If multiple bases are in use, bufferevent_base_set() must be called before -enabling the bufferevent for the first time. -.Sh NON-BLOCKING HTTP SUPPORT -.Nm libevent -provides a very thin HTTP layer that can be used both to host an HTTP -server and also to make HTTP requests. -An HTTP server can be created by calling -.Fn evhttp_new . -It can be bound to any port and address with the -.Fn evhttp_bind_socket -function. -When the HTTP server is no longer used, it can be freed via -.Fn evhttp_free . -.Pp -To be notified of HTTP requests, a user needs to register callbacks with the -HTTP server. -This can be done by calling -.Fn evhttp_set_cb . -The second argument is the URI for which a callback is being registered. -The corresponding callback will receive an -.Va struct evhttp_request -object that contains all information about the request. -.Pp -This section does not document all the possible function calls; please -check -.Va event.h -for the public interfaces. -.Sh ADDITIONAL NOTES -It is possible to disable support for -.Va epoll , kqueue , devpoll , poll -or -.Va select -by setting the environment variable -.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL -or -.Va EVENT_NOSELECT , -respectively. -By setting the environment variable -.Va EVENT_SHOW_METHOD , -.Nm libevent -displays the kernel notification method that it uses. -.Sh RETURN VALUES -Upon successful completion -.Fn event_add -and -.Fn event_del -return 0. -Otherwise, \-1 is returned and the global variable errno is -set to indicate the error. -.Sh SEE ALSO -.Xr kqueue 2 , -.Xr poll 2 , -.Xr select 2 , -.Xr evdns 3 , -.Xr timeout 9 -.Sh HISTORY -The -.Nm event -API manpage is based on the -.Xr timeout 9 -manpage by Artur Grabowski. -The port of -.Nm libevent -to Windows is due to Michael A. Davis. -Support for real-time signals is due to Taral. -.Sh AUTHORS -The -.Nm event -library was written by Niels Provos. -.Sh BUGS -This documentation is neither complete nor authoritative. -If you are in doubt about the usage of this API then -check the source code to find out how it works, write -up the missing piece of documentation and send it to -me for inclusion in this man page.
diff --git a/third_party/libevent/event.c b/third_party/libevent/event.c deleted file mode 100644 index 4aa326e..0000000 --- a/third_party/libevent/event.c +++ /dev/null
@@ -1,998 +0,0 @@ -/* - * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -#endif -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#include <sys/queue.h> -#include <stdio.h> -#include <stdlib.h> -#ifndef WIN32 -#include <unistd.h> -#endif -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <assert.h> -#include <time.h> - -#include "event.h" -#include "event-internal.h" -#include "evutil.h" -#include "log.h" - -#ifdef HAVE_EVENT_PORTS -extern const struct eventop evportops; -#endif -#ifdef HAVE_SELECT -extern const struct eventop selectops; -#endif -#ifdef HAVE_POLL -extern const struct eventop pollops; -#endif -#ifdef HAVE_EPOLL -extern const struct eventop epollops; -#endif -#ifdef HAVE_WORKING_KQUEUE -extern const struct eventop kqops; -#endif -#ifdef HAVE_DEVPOLL -extern const struct eventop devpollops; -#endif -#ifdef WIN32 -extern const struct eventop win32ops; -#endif - -/* In order of preference */ -static const struct eventop *eventops[] = { -#ifdef HAVE_EVENT_PORTS - &evportops, -#endif -#ifdef HAVE_WORKING_KQUEUE - &kqops, -#endif -#ifdef HAVE_EPOLL - &epollops, -#endif -#ifdef HAVE_DEVPOLL - &devpollops, -#endif -#ifdef HAVE_POLL - &pollops, -#endif -#ifdef HAVE_SELECT - &selectops, -#endif -#ifdef WIN32 - &win32ops, -#endif - NULL -}; - -/* Global state */ -struct event_base *current_base = NULL; -extern struct event_base *evsignal_base; -static int use_monotonic = 1; - -/* Prototypes */ -static void event_queue_insert(struct event_base *, struct event *, int); -static void event_queue_remove(struct event_base *, struct event *, int); -static int event_haveevents(struct event_base *); - -static void event_process_active(struct event_base *); - -static int timeout_next(struct event_base *, struct timeval **); -static void timeout_process(struct event_base *); -static void timeout_correct(struct event_base *, struct timeval *); - -static int -gettime(struct event_base *base, struct timeval *tp) -{ - if (base->tv_cache.tv_sec) { - *tp = base->tv_cache; - return (0); - } - -#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) - struct timespec ts; - - if (use_monotonic && - clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - tp->tv_sec = ts.tv_sec; - tp->tv_usec = ts.tv_nsec / 1000; - return (0); - } -#endif - - use_monotonic = 0; - - return (evutil_gettimeofday(tp, NULL)); -} - -struct event_base * -event_init(void) -{ - struct event_base *base = event_base_new(); - - if (base != NULL) - current_base = base; - - return (base); -} - -struct event_base * -event_base_new(void) -{ - int i; - struct event_base *base; - - if ((base = calloc(1, sizeof(struct event_base))) == NULL) - event_err(1, "%s: calloc", __func__); - - gettime(base, &base->event_tv); - - min_heap_ctor(&base->timeheap); - TAILQ_INIT(&base->eventqueue); - base->sig.ev_signal_pair[0] = -1; - base->sig.ev_signal_pair[1] = -1; - - base->evbase = NULL; - for (i = 0; eventops[i] && !base->evbase; i++) { - base->evsel = eventops[i]; - - base->evbase = base->evsel->init(base); - } - - if (base->evbase == NULL) - event_errx(1, "%s: no event mechanism available", __func__); - - if (evutil_getenv("EVENT_SHOW_METHOD")) - event_msgx("libevent using: %s\n", - base->evsel->name); - - /* allocate a single active event queue */ - event_base_priority_init(base, 1); - - return (base); -} - -void -event_base_free(struct event_base *base) -{ - int i, n_deleted=0; - struct event *ev; - - if (base == NULL && current_base) - base = current_base; - if (base == current_base) - current_base = NULL; - - /* XXX(niels) - check for internal events first */ - assert(base); - /* Delete all non-internal events. */ - for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) { - struct event *next = TAILQ_NEXT(ev, ev_next); - if (!(ev->ev_flags & EVLIST_INTERNAL)) { - event_del(ev); - ++n_deleted; - } - ev = next; - } - while ((ev = min_heap_top(&base->timeheap)) != NULL) { - event_del(ev); - ++n_deleted; - } - - for (i = 0; i < base->nactivequeues; ++i) { - for (ev = TAILQ_FIRST(base->activequeues[i]); ev; ) { - struct event *next = TAILQ_NEXT(ev, ev_active_next); - if (!(ev->ev_flags & EVLIST_INTERNAL)) { - event_del(ev); - ++n_deleted; - } - ev = next; - } - } - - if (n_deleted) - event_debug(("%s: %d events were still set in base", - __func__, n_deleted)); - - if (base->evsel->dealloc != NULL) - base->evsel->dealloc(base, base->evbase); - - for (i = 0; i < base->nactivequeues; ++i) - assert(TAILQ_EMPTY(base->activequeues[i])); - - assert(min_heap_empty(&base->timeheap)); - min_heap_dtor(&base->timeheap); - - for (i = 0; i < base->nactivequeues; ++i) - free(base->activequeues[i]); - free(base->activequeues); - - assert(TAILQ_EMPTY(&base->eventqueue)); - - free(base); -} - -/* reinitialized the event base after a fork */ -int -event_reinit(struct event_base *base) -{ - const struct eventop *evsel = base->evsel; - void *evbase = base->evbase; - int res = 0; - struct event *ev; - -#if 0 - /* Right now, reinit always takes effect, since even if the - backend doesn't require it, the signal socketpair code does. - */ - /* check if this event mechanism requires reinit */ - if (!evsel->need_reinit) - return (0); -#endif - - /* prevent internal delete */ - if (base->sig.ev_signal_added) { - /* we cannot call event_del here because the base has - * not been reinitialized yet. */ - event_queue_remove(base, &base->sig.ev_signal, - EVLIST_INSERTED); - if (base->sig.ev_signal.ev_flags & EVLIST_ACTIVE) - event_queue_remove(base, &base->sig.ev_signal, - EVLIST_ACTIVE); - base->sig.ev_signal_added = 0; - } - - if (base->evsel->dealloc != NULL) - base->evsel->dealloc(base, base->evbase); - evbase = base->evbase = evsel->init(base); - if (base->evbase == NULL) - event_errx(1, "%s: could not reinitialize event mechanism", - __func__); - - TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { - if (evsel->add(evbase, ev) == -1) - res = -1; - } - - return (res); -} - -int -event_priority_init(int npriorities) -{ - return event_base_priority_init(current_base, npriorities); -} - -int -event_base_priority_init(struct event_base *base, int npriorities) -{ - int i; - - if (base->event_count_active) - return (-1); - - if (npriorities == base->nactivequeues) - return (0); - - if (base->nactivequeues) { - for (i = 0; i < base->nactivequeues; ++i) { - free(base->activequeues[i]); - } - free(base->activequeues); - } - - /* Allocate our priority queues */ - base->nactivequeues = npriorities; - base->activequeues = (struct event_list **) - calloc(base->nactivequeues, sizeof(struct event_list *)); - if (base->activequeues == NULL) - event_err(1, "%s: calloc", __func__); - - for (i = 0; i < base->nactivequeues; ++i) { - base->activequeues[i] = malloc(sizeof(struct event_list)); - if (base->activequeues[i] == NULL) - event_err(1, "%s: malloc", __func__); - TAILQ_INIT(base->activequeues[i]); - } - - return (0); -} - -int -event_haveevents(struct event_base *base) -{ - return (base->event_count > 0); -} - -/* - * Active events are stored in priority queues. Lower priorities are always - * process before higher priorities. Low priority events can starve high - * priority ones. - */ - -static void -event_process_active(struct event_base *base) -{ - struct event *ev; - struct event_list *activeq = NULL; - int i; - short ncalls; - - for (i = 0; i < base->nactivequeues; ++i) { - if (TAILQ_FIRST(base->activequeues[i]) != NULL) { - activeq = base->activequeues[i]; - break; - } - } - - assert(activeq != NULL); - - for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) { - if (ev->ev_events & EV_PERSIST) - event_queue_remove(base, ev, EVLIST_ACTIVE); - else - event_del(ev); - - /* Allows deletes to work */ - ncalls = ev->ev_ncalls; - ev->ev_pncalls = &ncalls; - while (ncalls) { - ncalls--; - ev->ev_ncalls = ncalls; - (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg); - if (base->event_break) - return; - } - } -} - -/* - * Wait continously for events. We exit only if no events are left. - */ - -int -event_dispatch(void) -{ - return (event_loop(0)); -} - -int -event_base_dispatch(struct event_base *event_base) -{ - return (event_base_loop(event_base, 0)); -} - -const char * -event_base_get_method(struct event_base *base) -{ - assert(base); - return (base->evsel->name); -} - -static void -event_loopexit_cb(int fd, short what, void *arg) -{ - struct event_base *base = arg; - base->event_gotterm = 1; -} - -/* not thread safe */ -int -event_loopexit(const struct timeval *tv) -{ - return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, - current_base, tv)); -} - -int -event_base_loopexit(struct event_base *event_base, const struct timeval *tv) -{ - return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb, - event_base, tv)); -} - -/* not thread safe */ -int -event_loopbreak(void) -{ - return (event_base_loopbreak(current_base)); -} - -int -event_base_loopbreak(struct event_base *event_base) -{ - if (event_base == NULL) - return (-1); - - event_base->event_break = 1; - return (0); -} - - - -/* not thread safe */ - -int -event_loop(int flags) -{ - return event_base_loop(current_base, flags); -} - -int -event_base_loop(struct event_base *base, int flags) -{ - const struct eventop *evsel = base->evsel; - void *evbase = base->evbase; - struct timeval tv; - struct timeval *tv_p; - int res, done; - - /* clear time cache */ - base->tv_cache.tv_sec = 0; - - if (base->sig.ev_signal_added) - evsignal_base = base; - done = 0; - while (!done) { - /* Terminate the loop if we have been asked to */ - if (base->event_gotterm) { - base->event_gotterm = 0; - break; - } - - if (base->event_break) { - base->event_break = 0; - break; - } - - timeout_correct(base, &tv); - - tv_p = &tv; - if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) { - timeout_next(base, &tv_p); - } else { - /* - * if we have active events, we just poll new events - * without waiting. - */ - evutil_timerclear(&tv); - } - - /* If we have no events, we just exit */ - if (!event_haveevents(base)) { - event_debug(("%s: no events registered.", __func__)); - return (1); - } - - /* update last old time */ - gettime(base, &base->event_tv); - - /* clear time cache */ - base->tv_cache.tv_sec = 0; - - res = evsel->dispatch(base, evbase, tv_p); - - if (res == -1) - return (-1); - gettime(base, &base->tv_cache); - - timeout_process(base); - - if (base->event_count_active) { - event_process_active(base); - if (!base->event_count_active && (flags & EVLOOP_ONCE)) - done = 1; - } else if (flags & EVLOOP_NONBLOCK) - done = 1; - } - - /* clear time cache */ - base->tv_cache.tv_sec = 0; - - event_debug(("%s: asked to terminate loop.", __func__)); - return (0); -} - -/* Sets up an event for processing once */ - -struct event_once { - struct event ev; - - void (*cb)(int, short, void *); - void *arg; -}; - -/* One-time callback, it deletes itself */ - -static void -event_once_cb(int fd, short events, void *arg) -{ - struct event_once *eonce = arg; - - (*eonce->cb)(fd, events, eonce->arg); - free(eonce); -} - -/* not threadsafe, event scheduled once. */ -int -event_once(int fd, short events, - void (*callback)(int, short, void *), void *arg, const struct timeval *tv) -{ - return event_base_once(current_base, fd, events, callback, arg, tv); -} - -/* Schedules an event once */ -int -event_base_once(struct event_base *base, int fd, short events, - void (*callback)(int, short, void *), void *arg, const struct timeval *tv) -{ - struct event_once *eonce; - struct timeval etv; - int res; - - /* We cannot support signals that just fire once */ - if (events & EV_SIGNAL) - return (-1); - - if ((eonce = calloc(1, sizeof(struct event_once))) == NULL) - return (-1); - - eonce->cb = callback; - eonce->arg = arg; - - if (events == EV_TIMEOUT) { - if (tv == NULL) { - evutil_timerclear(&etv); - tv = &etv; - } - - evtimer_set(&eonce->ev, event_once_cb, eonce); - } else if (events & (EV_READ|EV_WRITE)) { - events &= EV_READ|EV_WRITE; - - event_set(&eonce->ev, fd, events, event_once_cb, eonce); - } else { - /* Bad event combination */ - free(eonce); - return (-1); - } - - res = event_base_set(base, &eonce->ev); - if (res == 0) - res = event_add(&eonce->ev, tv); - if (res != 0) { - free(eonce); - return (res); - } - - return (0); -} - -void -event_set(struct event *ev, int fd, short events, - void (*callback)(int, short, void *), void *arg) -{ - /* Take the current base - caller needs to set the real base later */ - ev->ev_base = current_base; - - ev->ev_callback = callback; - ev->ev_arg = arg; - ev->ev_fd = fd; - ev->ev_events = events; - ev->ev_res = 0; - ev->ev_flags = EVLIST_INIT; - ev->ev_ncalls = 0; - ev->ev_pncalls = NULL; - - min_heap_elem_init(ev); - - /* by default, we put new events into the middle priority */ - if(current_base) - ev->ev_pri = current_base->nactivequeues/2; -} - -int -event_base_set(struct event_base *base, struct event *ev) -{ - /* Only innocent events may be assigned to a different base */ - if (ev->ev_flags != EVLIST_INIT) - return (-1); - - ev->ev_base = base; - ev->ev_pri = base->nactivequeues/2; - - return (0); -} - -/* - * Set's the priority of an event - if an event is already scheduled - * changing the priority is going to fail. - */ - -int -event_priority_set(struct event *ev, int pri) -{ - if (ev->ev_flags & EVLIST_ACTIVE) - return (-1); - if (pri < 0 || pri >= ev->ev_base->nactivequeues) - return (-1); - - ev->ev_pri = pri; - - return (0); -} - -/* - * Checks if a specific event is pending or scheduled. - */ - -int -event_pending(struct event *ev, short event, struct timeval *tv) -{ - struct timeval now, res; - int flags = 0; - - if (ev->ev_flags & EVLIST_INSERTED) - flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)); - if (ev->ev_flags & EVLIST_ACTIVE) - flags |= ev->ev_res; - if (ev->ev_flags & EVLIST_TIMEOUT) - flags |= EV_TIMEOUT; - - event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL); - - /* See if there is a timeout that we should report */ - if (tv != NULL && (flags & event & EV_TIMEOUT)) { - gettime(ev->ev_base, &now); - evutil_timersub(&ev->ev_timeout, &now, &res); - /* correctly remap to real time */ - evutil_gettimeofday(&now, NULL); - evutil_timeradd(&now, &res, tv); - } - - return (flags & event); -} - -int -event_add(struct event *ev, const struct timeval *tv) -{ - struct event_base *base = ev->ev_base; - const struct eventop *evsel = base->evsel; - void *evbase = base->evbase; - int res = 0; - - event_debug(( - "event_add: event: %p, %s%s%scall %p", - ev, - ev->ev_events & EV_READ ? "EV_READ " : " ", - ev->ev_events & EV_WRITE ? "EV_WRITE " : " ", - tv ? "EV_TIMEOUT " : " ", - ev->ev_callback)); - - assert(!(ev->ev_flags & ~EVLIST_ALL)); - - /* - * prepare for timeout insertion further below, if we get a - * failure on any step, we should not change any state. - */ - if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) { - if (min_heap_reserve(&base->timeheap, - 1 + min_heap_size(&base->timeheap)) == -1) - return (-1); /* ENOMEM == errno */ - } - - if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) && - !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { - res = evsel->add(evbase, ev); - if (res != -1) - event_queue_insert(base, ev, EVLIST_INSERTED); - } - - /* - * we should change the timout state only if the previous event - * addition succeeded. - */ - if (res != -1 && tv != NULL) { - struct timeval now; - - /* - * we already reserved memory above for the case where we - * are not replacing an exisiting timeout. - */ - if (ev->ev_flags & EVLIST_TIMEOUT) - event_queue_remove(base, ev, EVLIST_TIMEOUT); - - /* Check if it is active due to a timeout. Rescheduling - * this timeout before the callback can be executed - * removes it from the active list. */ - if ((ev->ev_flags & EVLIST_ACTIVE) && - (ev->ev_res & EV_TIMEOUT)) { - /* See if we are just active executing this - * event in a loop - */ - if (ev->ev_ncalls && ev->ev_pncalls) { - /* Abort loop */ - *ev->ev_pncalls = 0; - } - - event_queue_remove(base, ev, EVLIST_ACTIVE); - } - - gettime(base, &now); - evutil_timeradd(&now, tv, &ev->ev_timeout); - - event_debug(( - "event_add: timeout in %ld seconds, call %p", - tv->tv_sec, ev->ev_callback)); - - event_queue_insert(base, ev, EVLIST_TIMEOUT); - } - - return (res); -} - -int -event_del(struct event *ev) -{ - struct event_base *base; - - event_debug(("event_del: %p, callback %p", - ev, ev->ev_callback)); - - /* An event without a base has not been added */ - if (ev->ev_base == NULL) - return (-1); - - base = ev->ev_base; - - assert(!(ev->ev_flags & ~EVLIST_ALL)); - - /* See if we are just active executing this event in a loop */ - if (ev->ev_ncalls && ev->ev_pncalls) { - /* Abort loop */ - *ev->ev_pncalls = 0; - } - - if (ev->ev_flags & EVLIST_TIMEOUT) - event_queue_remove(base, ev, EVLIST_TIMEOUT); - - if (ev->ev_flags & EVLIST_ACTIVE) - event_queue_remove(base, ev, EVLIST_ACTIVE); - - if (ev->ev_flags & EVLIST_INSERTED) { - event_queue_remove(base, ev, EVLIST_INSERTED); - return (base->evsel->del(base->evbase, ev)); - } - - return (0); -} - -void -event_active(struct event *ev, int res, short ncalls) -{ - /* We get different kinds of events, add them together */ - if (ev->ev_flags & EVLIST_ACTIVE) { - ev->ev_res |= res; - return; - } - - ev->ev_res = res; - ev->ev_ncalls = ncalls; - ev->ev_pncalls = NULL; - event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE); -} - -static int -timeout_next(struct event_base *base, struct timeval **tv_p) -{ - struct timeval now; - struct event *ev; - struct timeval *tv = *tv_p; - - if ((ev = min_heap_top(&base->timeheap)) == NULL) { - /* if no time-based events are active wait for I/O */ - *tv_p = NULL; - return (0); - } - - if (gettime(base, &now) == -1) - return (-1); - - if (evutil_timercmp(&ev->ev_timeout, &now, <=)) { - evutil_timerclear(tv); - return (0); - } - - evutil_timersub(&ev->ev_timeout, &now, tv); - - assert(tv->tv_sec >= 0); - assert(tv->tv_usec >= 0); - - event_debug(("timeout_next: in %ld seconds", tv->tv_sec)); - return (0); -} - -/* - * Determines if the time is running backwards by comparing the current - * time against the last time we checked. Not needed when using clock - * monotonic. - */ - -static void -timeout_correct(struct event_base *base, struct timeval *tv) -{ - struct event **pev; - unsigned int size; - struct timeval off; - - if (use_monotonic) - return; - - /* Check if time is running backwards */ - gettime(base, tv); - if (evutil_timercmp(tv, &base->event_tv, >=)) { - base->event_tv = *tv; - return; - } - - event_debug(("%s: time is running backwards, corrected", - __func__)); - evutil_timersub(&base->event_tv, tv, &off); - - /* - * We can modify the key element of the node without destroying - * the key, beause we apply it to all in the right order. - */ - pev = base->timeheap.p; - size = base->timeheap.n; - for (; size-- > 0; ++pev) { - struct timeval *ev_tv = &(**pev).ev_timeout; - evutil_timersub(ev_tv, &off, ev_tv); - } - /* Now remember what the new time turned out to be. */ - base->event_tv = *tv; -} - -void -timeout_process(struct event_base *base) -{ - struct timeval now; - struct event *ev; - - if (min_heap_empty(&base->timeheap)) - return; - - gettime(base, &now); - - while ((ev = min_heap_top(&base->timeheap))) { - if (evutil_timercmp(&ev->ev_timeout, &now, >)) - break; - - /* delete this event from the I/O queues */ - event_del(ev); - - event_debug(("timeout_process: call %p", - ev->ev_callback)); - event_active(ev, EV_TIMEOUT, 1); - } -} - -void -event_queue_remove(struct event_base *base, struct event *ev, int queue) -{ - if (!(ev->ev_flags & queue)) - event_errx(1, "%s: %p(fd %d) not on queue %x", __func__, - ev, ev->ev_fd, queue); - - if (~ev->ev_flags & EVLIST_INTERNAL) - base->event_count--; - - ev->ev_flags &= ~queue; - switch (queue) { - case EVLIST_INSERTED: - TAILQ_REMOVE(&base->eventqueue, ev, ev_next); - break; - case EVLIST_ACTIVE: - base->event_count_active--; - TAILQ_REMOVE(base->activequeues[ev->ev_pri], - ev, ev_active_next); - break; - case EVLIST_TIMEOUT: - min_heap_erase(&base->timeheap, ev); - break; - default: - event_errx(1, "%s: unknown queue %x", __func__, queue); - } -} - -void -event_queue_insert(struct event_base *base, struct event *ev, int queue) -{ - if (ev->ev_flags & queue) { - /* Double insertion is possible for active events */ - if (queue & EVLIST_ACTIVE) - return; - - event_errx(1, "%s: %p(fd %d) already on queue %x", __func__, - ev, ev->ev_fd, queue); - } - - if (~ev->ev_flags & EVLIST_INTERNAL) - base->event_count++; - - ev->ev_flags |= queue; - switch (queue) { - case EVLIST_INSERTED: - TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next); - break; - case EVLIST_ACTIVE: - base->event_count_active++; - TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri], - ev,ev_active_next); - break; - case EVLIST_TIMEOUT: { - min_heap_push(&base->timeheap, ev); - break; - } - default: - event_errx(1, "%s: unknown queue %x", __func__, queue); - } -} - -/* Functions for debugging */ - -const char * -event_get_version(void) -{ - return (VERSION); -} - -/* - * No thread-safe interface needed - the information should be the same - * for all threads. - */ - -const char * -event_get_method(void) -{ - return (current_base->evsel->name); -}
diff --git a/third_party/libevent/event.h b/third_party/libevent/event.h deleted file mode 100644 index f4a8b9f7..0000000 --- a/third_party/libevent/event.h +++ /dev/null
@@ -1,727 +0,0 @@ -/* - * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _EVENT_H_ -#define _EVENT_H_ - -/** @mainpage - - @section intro Introduction - - libevent is an event notification library for developing scalable network - servers. The libevent API provides a mechanism to execute a callback - function when a specific event occurs on a file descriptor or after a - timeout has been reached. Furthermore, libevent also support callbacks due - to signals or regular timeouts. - - libevent is meant to replace the event loop found in event driven network - servers. An application just needs to call event_dispatch() and then add or - remove events dynamically without having to change the event loop. - - Currently, libevent supports /dev/poll, kqueue(2), select(2), poll(2) and - epoll(4). It also has experimental support for real-time signals. The - internal event mechanism is completely independent of the exposed event API, - and a simple update of libevent can provide new functionality without having - to redesign the applications. As a result, Libevent allows for portable - application development and provides the most scalable event notification - mechanism available on an operating system. Libevent can also be used for - multi-threaded aplications; see Steven Grimm's explanation. Libevent should - compile on Linux, *BSD, Mac OS X, Solaris and Windows. - - @section usage Standard usage - - Every program that uses libevent must include the <event.h> header, and pass - the -levent flag to the linker. Before using any of the functions in the - library, you must call event_init() or event_base_new() to perform one-time - initialization of the libevent library. - - @section event Event notification - - For each file descriptor that you wish to monitor, you must declare an event - structure and call event_set() to initialize the members of the structure. - To enable notification, you add the structure to the list of monitored - events by calling event_add(). The event structure must remain allocated as - long as it is active, so it should be allocated on the heap. Finally, you - call event_dispatch() to loop and dispatch events. - - @section bufferevent I/O Buffers - - libevent provides an abstraction on top of the regular event callbacks. This - abstraction is called a buffered event. A buffered event provides input and - output buffers that get filled and drained automatically. The user of a - buffered event no longer deals directly with the I/O, but instead is reading - from input and writing to output buffers. - - Once initialized via bufferevent_new(), the bufferevent structure can be - used repeatedly with bufferevent_enable() and bufferevent_disable(). - Instead of reading and writing directly to a socket, you would call - bufferevent_read() and bufferevent_write(). - - When read enabled the bufferevent will try to read from the file descriptor - and call the read callback. The write callback is executed whenever the - output buffer is drained below the write low watermark, which is 0 by - default. - - @section timers Timers - - libevent can also be used to create timers that invoke a callback after a - certain amount of time has expired. The evtimer_set() function prepares an - event struct to be used as a timer. To activate the timer, call - evtimer_add(). Timers can be deactivated by calling evtimer_del(). - - @section timeouts Timeouts - - In addition to simple timers, libevent can assign timeout events to file - descriptors that are triggered whenever a certain amount of time has passed - with no activity on a file descriptor. The timeout_set() function - initializes an event struct for use as a timeout. Once initialized, the - event must be activated by using timeout_add(). To cancel the timeout, call - timeout_del(). - - @section evdns Asynchronous DNS resolution - - libevent provides an asynchronous DNS resolver that should be used instead - of the standard DNS resolver functions. These functions can be imported by - including the <evdns.h> header in your program. Before using any of the - resolver functions, you must call evdns_init() to initialize the library. To - convert a hostname to an IP address, you call the evdns_resolve_ipv4() - function. To perform a reverse lookup, you would call the - evdns_resolve_reverse() function. All of these functions use callbacks to - avoid blocking while the lookup is performed. - - @section evhttp Event-driven HTTP servers - - libevent provides a very simple event-driven HTTP server that can be - embedded in your program and used to service HTTP requests. - - To use this capability, you need to include the <evhttp.h> header in your - program. You create the server by calling evhttp_new(). Add addresses and - ports to listen on with evhttp_bind_socket(). You then register one or more - callbacks to handle incoming requests. Each URI can be assigned a callback - via the evhttp_set_cb() function. A generic callback function can also be - registered via evhttp_set_gencb(); this callback will be invoked if no other - callbacks have been registered for a given URI. - - @section evrpc A framework for RPC servers and clients - - libevents provides a framework for creating RPC servers and clients. It - takes care of marshaling and unmarshaling all data structures. - - @section api API Reference - - To browse the complete documentation of the libevent API, click on any of - the following links. - - event.h - The primary libevent header - - evdns.h - Asynchronous DNS resolution - - evhttp.h - An embedded libevent-based HTTP server - - evrpc.h - A framework for creating RPC servers and clients - - */ - -/** @file event.h - - A library for writing event-driven network servers - - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "event-config.h" -#ifdef _EVENT_HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef _EVENT_HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef _EVENT_HAVE_STDINT_H -#include <stdint.h> -#endif -#include <stdarg.h> - -/* For int types. */ -#include "evutil.h" - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -typedef unsigned char u_char; -typedef unsigned short u_short; -#endif - -#define EVLIST_TIMEOUT 0x01 -#define EVLIST_INSERTED 0x02 -#define EVLIST_SIGNAL 0x04 -#define EVLIST_ACTIVE 0x08 -#define EVLIST_INTERNAL 0x10 -#define EVLIST_INIT 0x80 - -/* EVLIST_X_ Private space: 0x1000-0xf000 */ -#define EVLIST_ALL (0xf000 | 0x9f) - -#define EV_TIMEOUT 0x01 -#define EV_READ 0x02 -#define EV_WRITE 0x04 -#define EV_SIGNAL 0x08 -#define EV_PERSIST 0x10 /* Persistant event */ - -/* Fix so that ppl dont have to run with <sys/queue.h> */ -#ifndef TAILQ_ENTRY -#define _EVENT_DEFINED_TQENTRY -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} -#endif /* !TAILQ_ENTRY */ - -struct event_base; -#ifndef EVENT_NO_STRUCT -struct event { - TAILQ_ENTRY (event) ev_next; - TAILQ_ENTRY (event) ev_active_next; - TAILQ_ENTRY (event) ev_signal_next; - unsigned int min_heap_idx; /* for managing timeouts */ - - struct event_base *ev_base; - - int ev_fd; - short ev_events; - short ev_ncalls; - short *ev_pncalls; /* Allows deletes in callback */ - - struct timeval ev_timeout; - - int ev_pri; /* smaller numbers are higher priority */ - - void (*ev_callback)(int, short, void *arg); - void *ev_arg; - - int ev_res; /* result passed to event callback */ - int ev_flags; -}; -#else -struct event; -#endif - -#define EVENT_SIGNAL(ev) (int)(ev)->ev_fd -#define EVENT_FD(ev) (int)(ev)->ev_fd - -/* - * Key-Value pairs. Can be used for HTTP headers but also for - * query argument parsing. - */ -struct evkeyval { - TAILQ_ENTRY(evkeyval) next; - - char *key; - char *value; -}; - -#ifdef _EVENT_DEFINED_TQENTRY -#undef TAILQ_ENTRY -struct event_list; -struct evkeyvalq; -#undef _EVENT_DEFINED_TQENTRY -#else -TAILQ_HEAD (event_list, event); -TAILQ_HEAD (evkeyvalq, evkeyval); -#endif /* _EVENT_DEFINED_TQENTRY */ - -/** - Initialize the event API. - - Use event_base_new() to initialize a new event base, but does not set - the current_base global. If using only event_base_new(), each event - added must have an event base set with event_base_set() - - @see event_base_set(), event_base_free(), event_init() - */ -struct event_base *event_base_new(void); - -/** - Initialize the event API. - - The event API needs to be initialized with event_init() before it can be - used. Sets the current_base global representing the default base for - events that have no base associated with them. - - @see event_base_set(), event_base_new() - */ -struct event_base *event_init(void); - -/** - Reinitialized the event base after a fork - - Some event mechanisms do not survive across fork. The event base needs - to be reinitialized with the event_reinit() function. - - @param base the event base that needs to be re-initialized - @return 0 if successful, or -1 if some events could not be re-added. - @see event_base_new(), event_init() -*/ -int event_reinit(struct event_base *base); - -/** - Loop to process events. - - In order to process events, an application needs to call - event_dispatch(). This function only returns on error, and should - replace the event core of the application program. - - @see event_base_dispatch() - */ -int event_dispatch(void); - - -/** - Threadsafe event dispatching loop. - - @param eb the event_base structure returned by event_init() - @see event_init(), event_dispatch() - */ -int event_base_dispatch(struct event_base *); - - -/** - Get the kernel event notification mechanism used by libevent. - - @param eb the event_base structure returned by event_base_new() - @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) - */ -const char *event_base_get_method(struct event_base *); - - -/** - Deallocate all memory associated with an event_base, and free the base. - - Note that this function will not close any fds or free any memory passed - to event_set as the argument to callback. - - @param eb an event_base to be freed - */ -void event_base_free(struct event_base *); - - -#define _EVENT_LOG_DEBUG 0 -#define _EVENT_LOG_MSG 1 -#define _EVENT_LOG_WARN 2 -#define _EVENT_LOG_ERR 3 -typedef void (*event_log_cb)(int severity, const char *msg); -/** - Redirect libevent's log messages. - - @param cb a function taking two arguments: an integer severity between - _EVENT_LOG_DEBUG and _EVENT_LOG_ERR, and a string. If cb is NULL, - then the default log is used. - */ -void event_set_log_callback(event_log_cb cb); - -/** - Associate a different event base with an event. - - @param eb the event base - @param ev the event - */ -int event_base_set(struct event_base *, struct event *); - -/** - event_loop() flags - */ -/*@{*/ -#define EVLOOP_ONCE 0x01 /**< Block at most once. */ -#define EVLOOP_NONBLOCK 0x02 /**< Do not block. */ -/*@}*/ - -/** - Handle events. - - This is a more flexible version of event_dispatch(). - - @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK - @return 0 if successful, -1 if an error occurred, or 1 if no events were - registered. - @see event_loopexit(), event_base_loop() -*/ -int event_loop(int); - -/** - Handle events (threadsafe version). - - This is a more flexible version of event_base_dispatch(). - - @param eb the event_base structure returned by event_init() - @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK - @return 0 if successful, -1 if an error occurred, or 1 if no events were - registered. - @see event_loopexit(), event_base_loop() - */ -int event_base_loop(struct event_base *, int); - -/** - Exit the event loop after the specified time. - - The next event_loop() iteration after the given timer expires will - complete normally (handling all queued events) then exit without - blocking for events again. - - Subsequent invocations of event_loop() will proceed normally. - - @param tv the amount of time after which the loop should terminate. - @return 0 if successful, or -1 if an error occurred - @see event_loop(), event_base_loop(), event_base_loopexit() - */ -int event_loopexit(const struct timeval *); - - -/** - Exit the event loop after the specified time (threadsafe variant). - - The next event_base_loop() iteration after the given timer expires will - complete normally (handling all queued events) then exit without - blocking for events again. - - Subsequent invocations of event_base_loop() will proceed normally. - - @param eb the event_base structure returned by event_init() - @param tv the amount of time after which the loop should terminate. - @return 0 if successful, or -1 if an error occurred - @see event_loopexit() - */ -int event_base_loopexit(struct event_base *, const struct timeval *); - -/** - Abort the active event_loop() immediately. - - event_loop() will abort the loop after the next event is completed; - event_loopbreak() is typically invoked from this event's callback. - This behavior is analogous to the "break;" statement. - - Subsequent invocations of event_loop() will proceed normally. - - @return 0 if successful, or -1 if an error occurred - @see event_base_loopbreak(), event_loopexit() - */ -int event_loopbreak(void); - -/** - Abort the active event_base_loop() immediately. - - event_base_loop() will abort the loop after the next event is completed; - event_base_loopbreak() is typically invoked from this event's callback. - This behavior is analogous to the "break;" statement. - - Subsequent invocations of event_loop() will proceed normally. - - @param eb the event_base structure returned by event_init() - @return 0 if successful, or -1 if an error occurred - @see event_base_loopexit - */ -int event_base_loopbreak(struct event_base *); - - -/** - Add a timer event. - - @param ev the event struct - @param tv timeval struct - */ -#define evtimer_add(ev, tv) event_add(ev, tv) - - -/** - Define a timer event. - - @param ev event struct to be modified - @param cb callback function - @param arg argument that will be passed to the callback function - */ -#define evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) - - -/** - * Delete a timer event. - * - * @param ev the event struct to be disabled - */ -#define evtimer_del(ev) event_del(ev) -#define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) -#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -/** - * Add a timeout event. - * - * @param ev the event struct to be disabled - * @param tv the timeout value, in seconds - */ -#define timeout_add(ev, tv) event_add(ev, tv) - - -/** - * Define a timeout event. - * - * @param ev the event struct to be defined - * @param cb the callback to be invoked when the timeout expires - * @param arg the argument to be passed to the callback - */ -#define timeout_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) - - -/** - * Disable a timeout event. - * - * @param ev the timeout event to be disabled - */ -#define timeout_del(ev) event_del(ev) - -#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) -#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -#define signal_add(ev, tv) event_add(ev, tv) -#define signal_set(ev, x, cb, arg) \ - event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) -#define signal_del(ev) event_del(ev) -#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv) -#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -/** - Prepare an event structure to be added. - - The function event_set() prepares the event structure ev to be used in - future calls to event_add() and event_del(). The event will be prepared to - call the function specified by the fn argument with an int argument - indicating the file descriptor, a short argument indicating the type of - event, and a void * argument given in the arg argument. The fd indicates - the file descriptor that should be monitored for events. The events can be - either EV_READ, EV_WRITE, or both. Indicating that an application can read - or write from the file descriptor respectively without blocking. - - The function fn will be called with the file descriptor that triggered the - event and the type of event which will be either EV_TIMEOUT, EV_SIGNAL, - EV_READ, or EV_WRITE. The additional flag EV_PERSIST makes an event_add() - persistent until event_del() has been called. - - @param ev an event struct to be modified - @param fd the file descriptor to be monitored - @param event desired events to monitor; can be EV_READ and/or EV_WRITE - @param fn callback function to be invoked when the event occurs - @param arg an argument to be passed to the callback function - - @see event_add(), event_del(), event_once() - - */ -void event_set(struct event *, int, short, void (*)(int, short, void *), void *); - -/** - Schedule a one-time event to occur. - - The function event_once() is similar to event_set(). However, it schedules - a callback to be called exactly once and does not require the caller to - prepare an event structure. - - @param fd a file descriptor to monitor - @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ | - EV_WRITE - @param callback callback function to be invoked when the event occurs - @param arg an argument to be passed to the callback function - @param timeout the maximum amount of time to wait for the event, or NULL - to wait forever - @return 0 if successful, or -1 if an error occurred - @see event_set() - - */ -int event_once(int, short, void (*)(int, short, void *), void *, - const struct timeval *); - - -/** - Schedule a one-time event (threadsafe variant) - - The function event_base_once() is similar to event_set(). However, it - schedules a callback to be called exactly once and does not require the - caller to prepare an event structure. - - @param base an event_base returned by event_init() - @param fd a file descriptor to monitor - @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ | - EV_WRITE - @param callback callback function to be invoked when the event occurs - @param arg an argument to be passed to the callback function - @param timeout the maximum amount of time to wait for the event, or NULL - to wait forever - @return 0 if successful, or -1 if an error occurred - @see event_once() - */ -int event_base_once(struct event_base *base, int fd, short events, - void (*callback)(int, short, void *), void *arg, - const struct timeval *timeout); - - -/** - Add an event to the set of monitored events. - - The function event_add() schedules the execution of the ev event when the - event specified in event_set() occurs or in at least the time specified in - the tv. If tv is NULL, no timeout occurs and the function will only be - called if a matching event occurs on the file descriptor. The event in the - ev argument must be already initialized by event_set() and may not be used - in calls to event_set() until it has timed out or been removed with - event_del(). If the event in the ev argument already has a scheduled - timeout, the old timeout will be replaced by the new one. - - @param ev an event struct initialized via event_set() - @param timeout the maximum amount of time to wait for the event, or NULL - to wait forever - @return 0 if successful, or -1 if an error occurred - @see event_del(), event_set() - */ -int event_add(struct event *ev, const struct timeval *timeout); - - -/** - Remove an event from the set of monitored events. - - The function event_del() will cancel the event in the argument ev. If the - event has already executed or has never been added the call will have no - effect. - - @param ev an event struct to be removed from the working set - @return 0 if successful, or -1 if an error occurred - @see event_add() - */ -int event_del(struct event *); - -void event_active(struct event *, int, short); - - -/** - Checks if a specific event is pending or scheduled. - - @param ev an event struct previously passed to event_add() - @param event the requested event type; any of EV_TIMEOUT|EV_READ| - EV_WRITE|EV_SIGNAL - @param tv an alternate timeout (FIXME - is this true?) - - @return 1 if the event is pending, or 0 if the event has not occurred - - */ -int event_pending(struct event *ev, short event, struct timeval *tv); - - -/** - Test if an event structure has been initialized. - - The event_initialized() macro can be used to check if an event has been - initialized. - - @param ev an event structure to be tested - @return 1 if the structure has been initialized, or 0 if it has not been - initialized - */ -#ifdef WIN32 -#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE) -#else -#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) -#endif - - -/** - Get the libevent version number. - - @return a string containing the version number of libevent - */ -const char *event_get_version(void); - - -/** - Get the kernel event notification mechanism used by libevent. - - @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) - */ -const char *event_get_method(void); - - -/** - Set the number of different event priorities. - - By default libevent schedules all active events with the same priority. - However, some time it is desirable to process some events with a higher - priority than others. For that reason, libevent supports strict priority - queues. Active events with a lower priority are always processed before - events with a higher priority. - - The number of different priorities can be set initially with the - event_priority_init() function. This function should be called before the - first call to event_dispatch(). The event_priority_set() function can be - used to assign a priority to an event. By default, libevent assigns the - middle priority to all events unless their priority is explicitly set. - - @param npriorities the maximum number of priorities - @return 0 if successful, or -1 if an error occurred - @see event_base_priority_init(), event_priority_set() - - */ -int event_priority_init(int); - - -/** - Set the number of different event priorities (threadsafe variant). - - See the description of event_priority_init() for more information. - - @param eb the event_base structure returned by event_init() - @param npriorities the maximum number of priorities - @return 0 if successful, or -1 if an error occurred - @see event_priority_init(), event_priority_set() - */ -int event_base_priority_init(struct event_base *, int); - - -/** - Assign a priority to an event. - - @param ev an event struct - @param priority the new priority to be assigned - @return 0 if successful, or -1 if an error occurred - @see event_priority_init() - */ -int event_priority_set(struct event *, int); - -#ifdef __cplusplus -} -#endif - -#endif /* _EVENT_H_ */
diff --git a/third_party/libevent/event_rpcgen.py b/third_party/libevent/event_rpcgen.py deleted file mode 100755 index 4ec77a6..0000000 --- a/third_party/libevent/event_rpcgen.py +++ /dev/null
@@ -1,1423 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2005 Niels Provos <provos@citi.umich.edu> -# All rights reserved. -# -# Generates marshaling code based on libevent. - -import sys -import re - -# -_NAME = "event_rpcgen.py" -_VERSION = "0.1" -_STRUCT_RE = '[a-z][a-z_0-9]*' - -# Globals -line_count = 0 - -white = re.compile(r'^\s+') -cppcomment = re.compile(r'\/\/.*$') -headerdirect = [] -cppdirect = [] - -# Holds everything that makes a struct -class Struct: - def __init__(self, name): - self._name = name - self._entries = [] - self._tags = {} - print >>sys.stderr, ' Created struct: %s' % name - - def AddEntry(self, entry): - if self._tags.has_key(entry.Tag()): - print >>sys.stderr, ( 'Entry "%s" duplicates tag number ' - '%d from "%s" around line %d' ) % ( - entry.Name(), entry.Tag(), - self._tags[entry.Tag()], line_count) - sys.exit(1) - self._entries.append(entry) - self._tags[entry.Tag()] = entry.Name() - print >>sys.stderr, ' Added entry: %s' % entry.Name() - - def Name(self): - return self._name - - def EntryTagName(self, entry): - """Creates the name inside an enumeration for distinguishing data - types.""" - name = "%s_%s" % (self._name, entry.Name()) - return name.upper() - - def PrintIdented(self, file, ident, code): - """Takes an array, add indentation to each entry and prints it.""" - for entry in code: - print >>file, '%s%s' % (ident, entry) - - def PrintTags(self, file): - """Prints the tag definitions for a structure.""" - print >>file, '/* Tag definition for %s */' % self._name - print >>file, 'enum %s_ {' % self._name.lower() - for entry in self._entries: - print >>file, ' %s=%d,' % (self.EntryTagName(entry), - entry.Tag()) - print >>file, ' %s_MAX_TAGS' % (self._name.upper()) - print >>file, '};\n' - - def PrintForwardDeclaration(self, file): - print >>file, 'struct %s;' % self._name - - def PrintDeclaration(self, file): - print >>file, '/* Structure declaration for %s */' % self._name - print >>file, 'struct %s_access_ {' % self._name - for entry in self._entries: - dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name()) - dcl.extend( - entry.GetDeclaration('(*%s_get)' % entry.Name())) - if entry.Array(): - dcl.extend( - entry.AddDeclaration('(*%s_add)' % entry.Name())) - self.PrintIdented(file, ' ', dcl) - print >>file, '};\n' - - print >>file, 'struct %s {' % self._name - print >>file, ' struct %s_access_ *base;\n' % self._name - for entry in self._entries: - dcl = entry.Declaration() - self.PrintIdented(file, ' ', dcl) - print >>file, '' - for entry in self._entries: - print >>file, ' ev_uint8_t %s_set;' % entry.Name() - print >>file, '};\n' - - print >>file, \ -"""struct %(name)s *%(name)s_new(void); -void %(name)s_free(struct %(name)s *); -void %(name)s_clear(struct %(name)s *); -void %(name)s_marshal(struct evbuffer *, const struct %(name)s *); -int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *); -int %(name)s_complete(struct %(name)s *); -void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t, - const struct %(name)s *); -int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t, - struct %(name)s *);""" % { 'name' : self._name } - - - # Write a setting function of every variable - for entry in self._entries: - self.PrintIdented(file, '', entry.AssignDeclaration( - entry.AssignFuncName())) - self.PrintIdented(file, '', entry.GetDeclaration( - entry.GetFuncName())) - if entry.Array(): - self.PrintIdented(file, '', entry.AddDeclaration( - entry.AddFuncName())) - - print >>file, '/* --- %s done --- */\n' % self._name - - def PrintCode(self, file): - print >>file, ('/*\n' - ' * Implementation of %s\n' - ' */\n') % self._name - - print >>file, \ - 'static struct %(name)s_access_ __%(name)s_base = {' % \ - { 'name' : self._name } - for entry in self._entries: - self.PrintIdented(file, ' ', entry.CodeBase()) - print >>file, '};\n' - - # Creation - print >>file, ( - 'struct %(name)s *\n' - '%(name)s_new(void)\n' - '{\n' - ' struct %(name)s *tmp;\n' - ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n' - ' event_warn("%%s: malloc", __func__);\n' - ' return (NULL);\n' - ' }\n' - ' tmp->base = &__%(name)s_base;\n') % { 'name' : self._name } - - for entry in self._entries: - self.PrintIdented(file, ' ', entry.CodeNew('tmp')) - print >>file, ' tmp->%s_set = 0;\n' % entry.Name() - - print >>file, ( - ' return (tmp);\n' - '}\n') - - # Adding - for entry in self._entries: - if entry.Array(): - self.PrintIdented(file, '', entry.CodeAdd()) - print >>file, '' - - # Assigning - for entry in self._entries: - self.PrintIdented(file, '', entry.CodeAssign()) - print >>file, '' - - # Getting - for entry in self._entries: - self.PrintIdented(file, '', entry.CodeGet()) - print >>file, '' - - # Clearing - print >>file, ( 'void\n' - '%(name)s_clear(struct %(name)s *tmp)\n' - '{' - ) % { 'name' : self._name } - for entry in self._entries: - self.PrintIdented(file, ' ', entry.CodeClear('tmp')) - - print >>file, '}\n' - - # Freeing - print >>file, ( 'void\n' - '%(name)s_free(struct %(name)s *tmp)\n' - '{' - ) % { 'name' : self._name } - - for entry in self._entries: - self.PrintIdented(file, ' ', entry.CodeFree('tmp')) - - print >>file, (' free(tmp);\n' - '}\n') - - # Marshaling - print >>file, ('void\n' - '%(name)s_marshal(struct evbuffer *evbuf, ' - 'const struct %(name)s *tmp)' - '{') % { 'name' : self._name } - for entry in self._entries: - indent = ' ' - # Optional entries do not have to be set - if entry.Optional(): - indent += ' ' - print >>file, ' if (tmp->%s_set) {' % entry.Name() - self.PrintIdented( - file, indent, - entry.CodeMarshal('evbuf', self.EntryTagName(entry), 'tmp')) - if entry.Optional(): - print >>file, ' }' - - print >>file, '}\n' - - # Unmarshaling - print >>file, ('int\n' - '%(name)s_unmarshal(struct %(name)s *tmp, ' - ' struct evbuffer *evbuf)\n' - '{\n' - ' ev_uint32_t tag;\n' - ' while (EVBUFFER_LENGTH(evbuf) > 0) {\n' - ' if (evtag_peek(evbuf, &tag) == -1)\n' - ' return (-1);\n' - ' switch (tag) {\n' - ) % { 'name' : self._name } - for entry in self._entries: - print >>file, ' case %s:\n' % self.EntryTagName(entry) - if not entry.Array(): - print >>file, ( - ' if (tmp->%s_set)\n' - ' return (-1);' - ) % (entry.Name()) - - self.PrintIdented( - file, ' ', - entry.CodeUnmarshal('evbuf', - self.EntryTagName(entry), 'tmp')) - - print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() + - ' break;\n' ) - print >>file, ( ' default:\n' - ' return -1;\n' - ' }\n' - ' }\n' ) - # Check if it was decoded completely - print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n' - ' return (-1);' - ) % { 'name' : self._name } - - # Successfully decoded - print >>file, ( ' return (0);\n' - '}\n') - - # Checking if a structure has all the required data - print >>file, ( - 'int\n' - '%(name)s_complete(struct %(name)s *msg)\n' - '{' ) % { 'name' : self._name } - for entry in self._entries: - self.PrintIdented( - file, ' ', - entry.CodeComplete('msg')) - print >>file, ( - ' return (0);\n' - '}\n' ) - - # Complete message unmarshaling - print >>file, ( - 'int\n' - 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, ' - 'ev_uint32_t need_tag, struct %(name)s *msg)\n' - '{\n' - ' ev_uint32_t tag;\n' - ' int res = -1;\n' - '\n' - ' struct evbuffer *tmp = evbuffer_new();\n' - '\n' - ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1' - ' || tag != need_tag)\n' - ' goto error;\n' - '\n' - ' if (%(name)s_unmarshal(msg, tmp) == -1)\n' - ' goto error;\n' - '\n' - ' res = 0;\n' - '\n' - ' error:\n' - ' evbuffer_free(tmp);\n' - ' return (res);\n' - '}\n' ) % { 'name' : self._name } - - # Complete message marshaling - print >>file, ( - 'void\n' - 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, ' - 'const struct %(name)s *msg)\n' - '{\n' - ' struct evbuffer *_buf = evbuffer_new();\n' - ' assert(_buf != NULL);\n' - ' evbuffer_drain(_buf, -1);\n' - ' %(name)s_marshal(_buf, msg);\n' - ' evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), ' - 'EVBUFFER_LENGTH(_buf));\n' - ' evbuffer_free(_buf);\n' - '}\n' ) % { 'name' : self._name } - -class Entry: - def __init__(self, type, name, tag): - self._type = type - self._name = name - self._tag = int(tag) - self._ctype = type - self._optional = 0 - self._can_be_array = 0 - self._array = 0 - self._line_count = -1 - self._struct = None - self._refname = None - - def GetTranslation(self): - return { "parent_name" : self._struct.Name(), - "name" : self._name, - "ctype" : self._ctype, - "refname" : self._refname - } - - def SetStruct(self, struct): - self._struct = struct - - def LineCount(self): - assert self._line_count != -1 - return self._line_count - - def SetLineCount(self, number): - self._line_count = number - - def Array(self): - return self._array - - def Optional(self): - return self._optional - - def Tag(self): - return self._tag - - def Name(self): - return self._name - - def Type(self): - return self._type - - def MakeArray(self, yes=1): - self._array = yes - - def MakeOptional(self): - self._optional = 1 - - def GetFuncName(self): - return '%s_%s_get' % (self._struct.Name(), self._name) - - def GetDeclaration(self, funcname): - code = [ 'int %s(struct %s *, %s *);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def CodeGet(self): - code = ( - 'int', - '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, ' - '%(ctype)s *value)', - '{', - ' if (msg->%(name)s_set != 1)', - ' return (-1);', - ' *value = msg->%(name)s_data;', - ' return (0);', - '}' ) - code = '\n'.join(code) - code = code % self.GetTranslation() - return code.split('\n') - - def AssignFuncName(self): - return '%s_%s_assign' % (self._struct.Name(), self._name) - - def AddFuncName(self): - return '%s_%s_add' % (self._struct.Name(), self._name) - - def AssignDeclaration(self, funcname): - code = [ 'int %s(struct %s *, const %s);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def CodeAssign(self): - code = [ 'int', - '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,' - ' const %(ctype)s value)', - '{', - ' msg->%(name)s_set = 1;', - ' msg->%(name)s_data = value;', - ' return (0);', - '}' ] - code = '\n'.join(code) - code = code % self.GetTranslation() - return code.split('\n') - - def CodeClear(self, structname): - code = [ '%s->%s_set = 0;' % (structname, self.Name()) ] - - return code - - def CodeComplete(self, structname): - if self.Optional(): - return [] - - code = [ 'if (!%s->%s_set)' % (structname, self.Name()), - ' return (-1);' ] - - return code - - def CodeFree(self, name): - return [] - - def CodeBase(self): - code = [ - '%(parent_name)s_%(name)s_assign,', - '%(parent_name)s_%(name)s_get,' - ] - if self.Array(): - code.append('%(parent_name)s_%(name)s_add,') - - code = '\n'.join(code) - code = code % self.GetTranslation() - return code.split('\n') - - def Verify(self): - if self.Array() and not self._can_be_array: - print >>sys.stderr, ( - 'Entry "%s" cannot be created as an array ' - 'around line %d' ) % (self._name, self.LineCount()) - sys.exit(1) - if not self._struct: - print >>sys.stderr, ( - 'Entry "%s" does not know which struct it belongs to ' - 'around line %d' ) % (self._name, self.LineCount()) - sys.exit(1) - if self._optional and self._array: - print >>sys.stderr, ( 'Entry "%s" has illegal combination of ' - 'optional and array around line %d' ) % ( - self._name, self.LineCount() ) - sys.exit(1) - -class EntryBytes(Entry): - def __init__(self, type, name, tag, length): - # Init base class - Entry.__init__(self, type, name, tag) - - self._length = length - self._ctype = 'ev_uint8_t' - - def GetDeclaration(self, funcname): - code = [ 'int %s(struct %s *, %s **);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def AssignDeclaration(self, funcname): - code = [ 'int %s(struct %s *, const %s *);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def Declaration(self): - dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)] - - return dcl - - def CodeGet(self): - name = self._name - code = [ 'int', - '%s_%s_get(struct %s *msg, %s **value)' % ( - self._struct.Name(), name, - self._struct.Name(), self._ctype), - '{', - ' if (msg->%s_set != 1)' % name, - ' return (-1);', - ' *value = msg->%s_data;' % name, - ' return (0);', - '}' ] - return code - - def CodeAssign(self): - name = self._name - code = [ 'int', - '%s_%s_assign(struct %s *msg, const %s *value)' % ( - self._struct.Name(), name, - self._struct.Name(), self._ctype), - '{', - ' msg->%s_set = 1;' % name, - ' memcpy(msg->%s_data, value, %s);' % ( - name, self._length), - ' return (0);', - '}' ] - return code - - def CodeUnmarshal(self, buf, tag_name, var_name): - code = [ 'if (evtag_unmarshal_fixed(%s, %s, ' % (buf, tag_name) + - '%s->%s_data, ' % (var_name, self._name) + - 'sizeof(%s->%s_data)) == -1) {' % ( - var_name, self._name), - ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( - self._name ), - ' return (-1);', - '}' - ] - return code - - def CodeMarshal(self, buf, tag_name, var_name): - code = ['evtag_marshal(%s, %s, %s->%s_data, sizeof(%s->%s_data));' % ( - buf, tag_name, var_name, self._name, var_name, self._name )] - return code - - def CodeClear(self, structname): - code = [ '%s->%s_set = 0;' % (structname, self.Name()), - 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( - structname, self._name, structname, self._name)] - - return code - - def CodeNew(self, name): - code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( - name, self._name, name, self._name)] - return code - - def Verify(self): - if not self._length: - print >>sys.stderr, 'Entry "%s" needs a length around line %d' % ( - self._name, self.LineCount() ) - sys.exit(1) - - Entry.Verify(self) - -class EntryInt(Entry): - def __init__(self, type, name, tag): - # Init base class - Entry.__init__(self, type, name, tag) - - self._ctype = 'ev_uint32_t' - - def CodeUnmarshal(self, buf, tag_name, var_name): - code = ['if (evtag_unmarshal_int(%s, %s, &%s->%s_data) == -1) {' % ( - buf, tag_name, var_name, self._name), - ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( - self._name ), - ' return (-1);', - '}' ] - return code - - def CodeMarshal(self, buf, tag_name, var_name): - code = ['evtag_marshal_int(%s, %s, %s->%s_data);' % ( - buf, tag_name, var_name, self._name)] - return code - - def Declaration(self): - dcl = ['ev_uint32_t %s_data;' % self._name] - - return dcl - - def CodeNew(self, name): - code = ['%s->%s_data = 0;' % (name, self._name)] - return code - -class EntryString(Entry): - def __init__(self, type, name, tag): - # Init base class - Entry.__init__(self, type, name, tag) - - self._ctype = 'char *' - - def CodeAssign(self): - name = self._name - code = """int -%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, - const %(ctype)s value) -{ - if (msg->%(name)s_data != NULL) - free(msg->%(name)s_data); - if ((msg->%(name)s_data = strdup(value)) == NULL) - return (-1); - msg->%(name)s_set = 1; - return (0); -}""" % self.GetTranslation() - - return code.split('\n') - - def CodeUnmarshal(self, buf, tag_name, var_name): - code = ['if (evtag_unmarshal_string(%s, %s, &%s->%s_data) == -1) {' % ( - buf, tag_name, var_name, self._name), - ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( - self._name ), - ' return (-1);', - '}' - ] - return code - - def CodeMarshal(self, buf, tag_name, var_name): - code = ['evtag_marshal_string(%s, %s, %s->%s_data);' % ( - buf, tag_name, var_name, self._name)] - return code - - def CodeClear(self, structname): - code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), - ' free (%s->%s_data);' % (structname, self.Name()), - ' %s->%s_data = NULL;' % (structname, self.Name()), - ' %s->%s_set = 0;' % (structname, self.Name()), - '}' - ] - - return code - - def CodeNew(self, name): - code = ['%s->%s_data = NULL;' % (name, self._name)] - return code - - def CodeFree(self, name): - code = ['if (%s->%s_data != NULL)' % (name, self._name), - ' free (%s->%s_data); ' % (name, self._name)] - - return code - - def Declaration(self): - dcl = ['char *%s_data;' % self._name] - - return dcl - -class EntryStruct(Entry): - def __init__(self, type, name, tag, refname): - # Init base class - Entry.__init__(self, type, name, tag) - - self._can_be_array = 1 - self._refname = refname - self._ctype = 'struct %s*' % refname - - def CodeGet(self): - name = self._name - code = [ 'int', - '%s_%s_get(struct %s *msg, %s *value)' % ( - self._struct.Name(), name, - self._struct.Name(), self._ctype), - '{', - ' if (msg->%s_set != 1) {' % name, - ' msg->%s_data = %s_new();' % (name, self._refname), - ' if (msg->%s_data == NULL)' % name, - ' return (-1);', - ' msg->%s_set = 1;' % name, - ' }', - ' *value = msg->%s_data;' % name, - ' return (0);', - '}' ] - return code - - def CodeAssign(self): - name = self._name - code = """int -%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, - const %(ctype)s value) -{ - struct evbuffer *tmp = NULL; - if (msg->%(name)s_set) { - %(refname)s_clear(msg->%(name)s_data); - msg->%(name)s_set = 0; - } else { - msg->%(name)s_data = %(refname)s_new(); - if (msg->%(name)s_data == NULL) { - event_warn("%%s: %(refname)s_new()", __func__); - goto error; - } - } - if ((tmp = evbuffer_new()) == NULL) { - event_warn("%%s: evbuffer_new()", __func__); - goto error; - } - %(refname)s_marshal(tmp, value); - if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) { - event_warnx("%%s: %(refname)s_unmarshal", __func__); - goto error; - } - msg->%(name)s_set = 1; - evbuffer_free(tmp); - return (0); - error: - if (tmp != NULL) - evbuffer_free(tmp); - if (msg->%(name)s_data != NULL) { - %(refname)s_free(msg->%(name)s_data); - msg->%(name)s_data = NULL; - } - return (-1); -}""" % self.GetTranslation() - return code.split('\n') - - def CodeComplete(self, structname): - if self.Optional(): - code = [ 'if (%s->%s_set && %s_complete(%s->%s_data) == -1)' % ( - structname, self.Name(), - self._refname, structname, self.Name()), - ' return (-1);' ] - else: - code = [ 'if (%s_complete(%s->%s_data) == -1)' % ( - self._refname, structname, self.Name()), - ' return (-1);' ] - - return code - - def CodeUnmarshal(self, buf, tag_name, var_name): - code = ['%s->%s_data = %s_new();' % ( - var_name, self._name, self._refname), - 'if (%s->%s_data == NULL)' % (var_name, self._name), - ' return (-1);', - 'if (evtag_unmarshal_%s(%s, %s, %s->%s_data) == -1) {' % ( - self._refname, buf, tag_name, var_name, self._name), - ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( - self._name ), - ' return (-1);', - '}' - ] - return code - - def CodeMarshal(self, buf, tag_name, var_name): - code = ['evtag_marshal_%s(%s, %s, %s->%s_data);' % ( - self._refname, buf, tag_name, var_name, self._name)] - return code - - def CodeClear(self, structname): - code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), - ' %s_free(%s->%s_data);' % ( - self._refname, structname, self.Name()), - ' %s->%s_data = NULL;' % (structname, self.Name()), - ' %s->%s_set = 0;' % (structname, self.Name()), - '}' - ] - - return code - - def CodeNew(self, name): - code = ['%s->%s_data = NULL;' % (name, self._name)] - return code - - def CodeFree(self, name): - code = ['if (%s->%s_data != NULL)' % (name, self._name), - ' %s_free(%s->%s_data); ' % ( - self._refname, name, self._name)] - - return code - - def Declaration(self): - dcl = ['%s %s_data;' % (self._ctype, self._name)] - - return dcl - -class EntryVarBytes(Entry): - def __init__(self, type, name, tag): - # Init base class - Entry.__init__(self, type, name, tag) - - self._ctype = 'ev_uint8_t *' - - def GetDeclaration(self, funcname): - code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def AssignDeclaration(self, funcname): - code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def CodeAssign(self): - name = self._name - code = [ 'int', - '%s_%s_assign(struct %s *msg, ' - 'const %s value, ev_uint32_t len)' % ( - self._struct.Name(), name, - self._struct.Name(), self._ctype), - '{', - ' if (msg->%s_data != NULL)' % name, - ' free (msg->%s_data);' % name, - ' msg->%s_data = malloc(len);' % name, - ' if (msg->%s_data == NULL)' % name, - ' return (-1);', - ' msg->%s_set = 1;' % name, - ' msg->%s_length = len;' % name, - ' memcpy(msg->%s_data, value, len);' % name, - ' return (0);', - '}' ] - return code - - def CodeGet(self): - name = self._name - code = [ 'int', - '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % ( - self._struct.Name(), name, - self._struct.Name(), self._ctype), - '{', - ' if (msg->%s_set != 1)' % name, - ' return (-1);', - ' *value = msg->%s_data;' % name, - ' *plen = msg->%s_length;' % name, - ' return (0);', - '}' ] - return code - - def CodeUnmarshal(self, buf, tag_name, var_name): - code = ['if (evtag_payload_length(%s, &%s->%s_length) == -1)' % ( - buf, var_name, self._name), - ' return (-1);', - # We do not want DoS opportunities - 'if (%s->%s_length > EVBUFFER_LENGTH(%s))' % ( - var_name, self._name, buf), - ' return (-1);', - 'if ((%s->%s_data = malloc(%s->%s_length)) == NULL)' % ( - var_name, self._name, var_name, self._name), - ' return (-1);', - 'if (evtag_unmarshal_fixed(%s, %s, %s->%s_data, ' - '%s->%s_length) == -1) {' % ( - buf, tag_name, var_name, self._name, var_name, self._name), - ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( - self._name ), - ' return (-1);', - '}' - ] - return code - - def CodeMarshal(self, buf, tag_name, var_name): - code = ['evtag_marshal(%s, %s, %s->%s_data, %s->%s_length);' % ( - buf, tag_name, var_name, self._name, var_name, self._name)] - return code - - def CodeClear(self, structname): - code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), - ' free (%s->%s_data);' % (structname, self.Name()), - ' %s->%s_data = NULL;' % (structname, self.Name()), - ' %s->%s_length = 0;' % (structname, self.Name()), - ' %s->%s_set = 0;' % (structname, self.Name()), - '}' - ] - - return code - - def CodeNew(self, name): - code = ['%s->%s_data = NULL;' % (name, self._name), - '%s->%s_length = 0;' % (name, self._name) ] - return code - - def CodeFree(self, name): - code = ['if (%s->%s_data != NULL)' % (name, self._name), - ' free (%s->%s_data); ' % (name, self._name)] - - return code - - def Declaration(self): - dcl = ['ev_uint8_t *%s_data;' % self._name, - 'ev_uint32_t %s_length;' % self._name] - - return dcl - -class EntryArray(Entry): - def __init__(self, entry): - # Init base class - Entry.__init__(self, entry._type, entry._name, entry._tag) - - self._entry = entry - self._refname = entry._refname - self._ctype = 'struct %s *' % self._refname - - def GetDeclaration(self, funcname): - """Allows direct access to elements of the array.""" - translate = self.GetTranslation() - translate["funcname"] = funcname - code = [ - 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' % - translate ] - return code - - def AssignDeclaration(self, funcname): - code = [ 'int %s(struct %s *, int, const %s);' % ( - funcname, self._struct.Name(), self._ctype ) ] - return code - - def AddDeclaration(self, funcname): - code = [ '%s %s(struct %s *);' % ( - self._ctype, funcname, self._struct.Name() ) ] - return code - - def CodeGet(self): - code = """int -%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset, - %(ctype)s *value) -{ - if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length) - return (-1); - *value = msg->%(name)s_data[offset]; - return (0); -}""" % self.GetTranslation() - - return code.split('\n') - - def CodeAssign(self): - code = """int -%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off, - const %(ctype)s value) -{ - struct evbuffer *tmp = NULL; - if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length) - return (-1); - %(refname)s_clear(msg->%(name)s_data[off]); - if ((tmp = evbuffer_new()) == NULL) { - event_warn("%%s: evbuffer_new()", __func__); - goto error; - } - %(refname)s_marshal(tmp, value); - if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) { - event_warnx("%%s: %(refname)s_unmarshal", __func__); - goto error; - } - evbuffer_free(tmp); - return (0); -error: - if (tmp != NULL) - evbuffer_free(tmp); - %(refname)s_clear(msg->%(name)s_data[off]); - return (-1); -}""" % self.GetTranslation() - - return code.split('\n') - - def CodeAdd(self): - code = \ -"""%(ctype)s -%(parent_name)s_%(name)s_add(struct %(parent_name)s *msg) -{ - if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) { - int tobe_allocated = msg->%(name)s_num_allocated; - %(ctype)s* new_data = NULL; - tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; - new_data = (%(ctype)s*) realloc(msg->%(name)s_data, - tobe_allocated * sizeof(%(ctype)s)); - if (new_data == NULL) - goto error; - msg->%(name)s_data = new_data; - msg->%(name)s_num_allocated = tobe_allocated; - } - msg->%(name)s_data[msg->%(name)s_length - 1] = %(refname)s_new(); - if (msg->%(name)s_data[msg->%(name)s_length - 1] == NULL) - goto error; - msg->%(name)s_set = 1; - return (msg->%(name)s_data[msg->%(name)s_length - 1]); -error: - --msg->%(name)s_length; - return (NULL); -} - """ % self.GetTranslation() - - return code.split('\n') - - def CodeComplete(self, structname): - code = [] - translate = self.GetTranslation() - - if self.Optional(): - code.append( 'if (%(structname)s->%(name)s_set)' % translate) - - translate["structname"] = structname - tmp = """{ - int i; - for (i = 0; i < %(structname)s->%(name)s_length; ++i) { - if (%(refname)s_complete(%(structname)s->%(name)s_data[i]) == -1) - return (-1); - } -}""" % translate - code.extend(tmp.split('\n')) - - return code - - def CodeUnmarshal(self, buf, tag_name, var_name): - translate = self.GetTranslation() - translate["var_name"] = var_name - translate["buf"] = buf - translate["tag_name"] = tag_name - code = """if (%(parent_name)s_%(name)s_add(%(var_name)s) == NULL) - return (-1); -if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag_name)s, - %(var_name)s->%(name)s_data[%(var_name)s->%(name)s_length - 1]) == -1) { - --%(var_name)s->%(name)s_length; - event_warnx("%%s: failed to unmarshal %(name)s", __func__); - return (-1); -}""" % translate - - return code.split('\n') - - def CodeMarshal(self, buf, tag_name, var_name): - code = ['{', - ' int i;', - ' for (i = 0; i < %s->%s_length; ++i) {' % ( - var_name, self._name), - ' evtag_marshal_%s(%s, %s, %s->%s_data[i]);' % ( - self._refname, buf, tag_name, var_name, self._name), - ' }', - '}' - ] - return code - - def CodeClear(self, structname): - code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), - ' int i;', - ' for (i = 0; i < %s->%s_length; ++i) {' % ( - structname, self.Name()), - ' %s_free(%s->%s_data[i]);' % ( - self._refname, structname, self.Name()), - ' }', - ' free(%s->%s_data);' % (structname, self.Name()), - ' %s->%s_data = NULL;' % (structname, self.Name()), - ' %s->%s_set = 0;' % (structname, self.Name()), - ' %s->%s_length = 0;' % (structname, self.Name()), - ' %s->%s_num_allocated = 0;' % (structname, self.Name()), - '}' - ] - - return code - - def CodeNew(self, name): - code = ['%s->%s_data = NULL;' % (name, self._name), - '%s->%s_length = 0;' % (name, self._name), - '%s->%s_num_allocated = 0;' % (name, self._name)] - return code - - def CodeFree(self, name): - code = ['if (%s->%s_data != NULL) {' % (name, self._name), - ' int i;', - ' for (i = 0; i < %s->%s_length; ++i) {' % ( - name, self._name), - ' %s_free(%s->%s_data[i]); ' % ( - self._refname, name, self._name), - ' %s->%s_data[i] = NULL;' % (name, self._name), - ' }', - ' free(%s->%s_data);' % (name, self._name), - ' %s->%s_data = NULL;' % (name, self._name), - ' %s->%s_length = 0;' % (name, self._name), - ' %s->%s_num_allocated = 0;' % (name, self._name), - '}' - ] - - return code - - def Declaration(self): - dcl = ['struct %s **%s_data;' % (self._refname, self._name), - 'int %s_length;' % self._name, - 'int %s_num_allocated;' % self._name ] - - return dcl - -def NormalizeLine(line): - global white - global cppcomment - - line = cppcomment.sub('', line) - line = line.strip() - line = white.sub(' ', line) - - return line - -def ProcessOneEntry(newstruct, entry): - optional = 0 - array = 0 - entry_type = '' - name = '' - tag = '' - tag_set = None - separator = '' - fixed_length = '' - - tokens = entry.split(' ') - while tokens: - token = tokens[0] - tokens = tokens[1:] - - if not entry_type: - if not optional and token == 'optional': - optional = 1 - continue - - if not array and token == 'array': - array = 1 - continue - - if not entry_type: - entry_type = token - continue - - if not name: - res = re.match(r'^([^\[\]]+)(\[.*\])?$', token) - if not res: - print >>sys.stderr, 'Cannot parse name: \"%s\" around %d' % ( - entry, line_count) - sys.exit(1) - name = res.group(1) - fixed_length = res.group(2) - if fixed_length: - fixed_length = fixed_length[1:-1] - continue - - if not separator: - separator = token - if separator != '=': - print >>sys.stderr, 'Expected "=" after name \"%s\" got %s' % ( - name, token) - sys.exit(1) - continue - - if not tag_set: - tag_set = 1 - if not re.match(r'^(0x)?[0-9]+$', token): - print >>sys.stderr, 'Expected tag number: \"%s\"' % entry - sys.exit(1) - tag = int(token, 0) - continue - - print >>sys.stderr, 'Cannot parse \"%s\"' % entry - sys.exit(1) - - if not tag_set: - print >>sys.stderr, 'Need tag number: \"%s\"' % entry - sys.exit(1) - - # Create the right entry - if entry_type == 'bytes': - if fixed_length: - newentry = EntryBytes(entry_type, name, tag, fixed_length) - else: - newentry = EntryVarBytes(entry_type, name, tag) - elif entry_type == 'int' and not fixed_length: - newentry = EntryInt(entry_type, name, tag) - elif entry_type == 'string' and not fixed_length: - newentry = EntryString(entry_type, name, tag) - else: - res = re.match(r'^struct\[(%s)\]$' % _STRUCT_RE, - entry_type, re.IGNORECASE) - if res: - # References another struct defined in our file - newentry = EntryStruct(entry_type, name, tag, res.group(1)) - else: - print >>sys.stderr, 'Bad type: "%s" in "%s"' % (entry_type, entry) - sys.exit(1) - - structs = [] - - if optional: - newentry.MakeOptional() - if array: - newentry.MakeArray() - - newentry.SetStruct(newstruct) - newentry.SetLineCount(line_count) - newentry.Verify() - - if array: - # We need to encapsulate this entry into a struct - newname = newentry.Name()+ '_array' - - # Now borgify the new entry. - newentry = EntryArray(newentry) - newentry.SetStruct(newstruct) - newentry.SetLineCount(line_count) - newentry.MakeArray() - - newstruct.AddEntry(newentry) - - return structs - -def ProcessStruct(data): - tokens = data.split(' ') - - # First three tokens are: 'struct' 'name' '{' - newstruct = Struct(tokens[1]) - - inside = ' '.join(tokens[3:-1]) - - tokens = inside.split(';') - - structs = [] - - for entry in tokens: - entry = NormalizeLine(entry) - if not entry: - continue - - # It's possible that new structs get defined in here - structs.extend(ProcessOneEntry(newstruct, entry)) - - structs.append(newstruct) - return structs - -def GetNextStruct(file): - global line_count - global cppdirect - - got_struct = 0 - - processed_lines = [] - - have_c_comment = 0 - data = '' - while 1: - line = file.readline() - if not line: - break - - line_count += 1 - line = line[:-1] - - if not have_c_comment and re.search(r'/\*', line): - if re.search(r'/\*.*\*/', line): - line = re.sub(r'/\*.*\*/', '', line) - else: - line = re.sub(r'/\*.*$', '', line) - have_c_comment = 1 - - if have_c_comment: - if not re.search(r'\*/', line): - continue - have_c_comment = 0 - line = re.sub(r'^.*\*/', '', line) - - line = NormalizeLine(line) - - if not line: - continue - - if not got_struct: - if re.match(r'#include ["<].*[>"]', line): - cppdirect.append(line) - continue - - if re.match(r'^#(if( |def)|endif)', line): - cppdirect.append(line) - continue - - if re.match(r'^#define', line): - headerdirect.append(line) - continue - - if not re.match(r'^struct %s {$' % _STRUCT_RE, - line, re.IGNORECASE): - print >>sys.stderr, 'Missing struct on line %d: %s' % ( - line_count, line) - sys.exit(1) - else: - got_struct = 1 - data += line - continue - - # We are inside the struct - tokens = line.split('}') - if len(tokens) == 1: - data += ' ' + line - continue - - if len(tokens[1]): - print >>sys.stderr, 'Trailing garbage after struct on line %d' % ( - line_count ) - sys.exit(1) - - # We found the end of the struct - data += ' %s}' % tokens[0] - break - - # Remove any comments, that might be in there - data = re.sub(r'/\*.*\*/', '', data) - - return data - - -def Parse(file): - """ - Parses the input file and returns C code and corresponding header file. - """ - - entities = [] - - while 1: - # Just gets the whole struct nicely formatted - data = GetNextStruct(file) - - if not data: - break - - entities.extend(ProcessStruct(data)) - - return entities - -def GuardName(name): - name = '_'.join(name.split('.')) - name = '_'.join(name.split('/')) - guard = '_'+name.upper()+'_' - - return guard - -def HeaderPreamble(name): - guard = GuardName(name) - pre = ( - '/*\n' - ' * Automatically generated from %s\n' - ' */\n\n' - '#ifndef %s\n' - '#define %s\n\n' ) % ( - name, guard, guard) - - # insert stdint.h - let's hope everyone has it - pre += ( - '#include <event-config.h>\n' - '#ifdef _EVENT_HAVE_STDINT_H\n' - '#include <stdint.h>\n' - '#endif\n' ) - - for statement in headerdirect: - pre += '%s\n' % statement - if headerdirect: - pre += '\n' - - pre += ( - '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n' - '#ifdef __GNUC__\n' - '#define EVTAG_ASSIGN(msg, member, args...) ' - '(*(msg)->base->member##_assign)(msg, ## args)\n' - '#define EVTAG_GET(msg, member, args...) ' - '(*(msg)->base->member##_get)(msg, ## args)\n' - '#else\n' - '#define EVTAG_ASSIGN(msg, member, ...) ' - '(*(msg)->base->member##_assign)(msg, ## __VA_ARGS__)\n' - '#define EVTAG_GET(msg, member, ...) ' - '(*(msg)->base->member##_get)(msg, ## __VA_ARGS__)\n' - '#endif\n' - '#define EVTAG_ADD(msg, member) (*(msg)->base->member##_add)(msg)\n' - '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n' - ) - - return pre - - -def HeaderPostamble(name): - guard = GuardName(name) - return '#endif /* %s */' % guard - -def BodyPreamble(name): - global _NAME - global _VERSION - - header_file = '.'.join(name.split('.')[:-1]) + '.gen.h' - - pre = ( '/*\n' - ' * Automatically generated from %s\n' - ' * by %s/%s. DO NOT EDIT THIS FILE.\n' - ' */\n\n' ) % (name, _NAME, _VERSION) - pre += ( '#include <sys/types.h>\n' - '#ifdef _EVENT_HAVE_SYS_TIME_H\n' - '#include <sys/time.h>\n' - '#endif\n' - '#include <stdlib.h>\n' - '#include <string.h>\n' - '#include <assert.h>\n' - '#define EVENT_NO_STRUCT\n' - '#include <event.h>\n\n' - '#ifdef _EVENT___func__\n' - '#define __func__ _EVENT___func__\n' - '#endif\n' ) - - for statement in cppdirect: - pre += '%s\n' % statement - - pre += '\n#include "%s"\n\n' % header_file - - pre += 'void event_err(int eval, const char *fmt, ...);\n' - pre += 'void event_warn(const char *fmt, ...);\n' - pre += 'void event_errx(int eval, const char *fmt, ...);\n' - pre += 'void event_warnx(const char *fmt, ...);\n\n' - - return pre - -def main(argv): - if len(argv) < 2 or not argv[1]: - print >>sys.stderr, 'Need RPC description file as first argument.' - sys.exit(1) - - filename = argv[1] - - ext = filename.split('.')[-1] - if ext != 'rpc': - print >>sys.stderr, 'Unrecognized file extension: %s' % ext - sys.exit(1) - - print >>sys.stderr, 'Reading \"%s\"' % filename - - fp = open(filename, 'r') - entities = Parse(fp) - fp.close() - - header_file = '.'.join(filename.split('.')[:-1]) + '.gen.h' - impl_file = '.'.join(filename.split('.')[:-1]) + '.gen.c' - - print >>sys.stderr, '... creating "%s"' % header_file - header_fp = open(header_file, 'w') - print >>header_fp, HeaderPreamble(filename) - - # Create forward declarations: allows other structs to reference - # each other - for entry in entities: - entry.PrintForwardDeclaration(header_fp) - print >>header_fp, '' - - for entry in entities: - entry.PrintTags(header_fp) - entry.PrintDeclaration(header_fp) - print >>header_fp, HeaderPostamble(filename) - header_fp.close() - - print >>sys.stderr, '... creating "%s"' % impl_file - impl_fp = open(impl_file, 'w') - print >>impl_fp, BodyPreamble(filename) - for entry in entities: - entry.PrintCode(impl_fp) - impl_fp.close() - -if __name__ == '__main__': - main(sys.argv)
diff --git a/third_party/libevent/evport.c b/third_party/libevent/evport.c deleted file mode 100644 index 1f5ebc41..0000000 --- a/third_party/libevent/evport.c +++ /dev/null
@@ -1,519 +0,0 @@ -/* - * Submitted by David Pacheco (dp.spambait@gmail.com) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 2007 Sun Microsystems. All rights reserved. - * Use is subject to license terms. - */ - -/* - * evport.c: event backend using Solaris 10 event ports. See port_create(3C). - * This implementation is loosely modeled after the one used for select(2) (in - * select.c). - * - * The outstanding events are tracked in a data structure called evport_data. - * Each entry in the ed_fds array corresponds to a file descriptor, and contains - * pointers to the read and write events that correspond to that fd. (That is, - * when the file is readable, the "read" event should handle it, etc.) - * - * evport_add and evport_del update this data structure. evport_dispatch uses it - * to determine where to callback when an event occurs (which it gets from - * port_getn). - * - * Helper functions are used: grow() grows the file descriptor array as - * necessary when large fd's come in. reassociate() takes care of maintaining - * the proper file-descriptor/event-port associations. - * - * As in the select(2) implementation, signals are handled by evsignal. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/time.h> -#include <assert.h> -#include <sys/queue.h> -#include <errno.h> -#include <poll.h> -#include <port.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#ifdef CHECK_INVARIANTS -#include <assert.h> -#endif - -#include "event.h" -#include "event-internal.h" -#include "log.h" -#include "evsignal.h" - - -/* - * Default value for ed_nevents, which is the maximum file descriptor number we - * can handle. If an event comes in for a file descriptor F > nevents, we will - * grow the array of file descriptors, doubling its size. - */ -#define DEFAULT_NFDS 16 - - -/* - * EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on - * any particular call. You can speed things up by increasing this, but it will - * (obviously) require more memory. - */ -#define EVENTS_PER_GETN 8 - -/* - * Per-file-descriptor information about what events we're subscribed to. These - * fields are NULL if no event is subscribed to either of them. - */ - -struct fd_info { - struct event* fdi_revt; /* the event responsible for the "read" */ - struct event* fdi_wevt; /* the event responsible for the "write" */ -}; - -#define FDI_HAS_READ(fdi) ((fdi)->fdi_revt != NULL) -#define FDI_HAS_WRITE(fdi) ((fdi)->fdi_wevt != NULL) -#define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi)) -#define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \ - (FDI_HAS_WRITE(fdi) ? POLLOUT : 0) - -struct evport_data { - int ed_port; /* event port for system events */ - int ed_nevents; /* number of allocated fdi's */ - struct fd_info *ed_fds; /* allocated fdi table */ - /* fdi's that we need to reassoc */ - int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */ -}; - -static void* evport_init (struct event_base *); -static int evport_add (void *, struct event *); -static int evport_del (void *, struct event *); -static int evport_dispatch (struct event_base *, void *, struct timeval *); -static void evport_dealloc (struct event_base *, void *); - -const struct eventop evportops = { - "evport", - evport_init, - evport_add, - evport_del, - evport_dispatch, - evport_dealloc, - 1 /* need reinit */ -}; - -/* - * Initialize the event port implementation. - */ - -static void* -evport_init(struct event_base *base) -{ - struct evport_data *evpd; - int i; - /* - * Disable event ports when this environment variable is set - */ - if (evutil_getenv("EVENT_NOEVPORT")) - return (NULL); - - if (!(evpd = calloc(1, sizeof(struct evport_data)))) - return (NULL); - - if ((evpd->ed_port = port_create()) == -1) { - free(evpd); - return (NULL); - } - - /* - * Initialize file descriptor structure - */ - evpd->ed_fds = calloc(DEFAULT_NFDS, sizeof(struct fd_info)); - if (evpd->ed_fds == NULL) { - close(evpd->ed_port); - free(evpd); - return (NULL); - } - evpd->ed_nevents = DEFAULT_NFDS; - for (i = 0; i < EVENTS_PER_GETN; i++) - evpd->ed_pending[i] = -1; - - evsignal_init(base); - - return (evpd); -} - -#ifdef CHECK_INVARIANTS -/* - * Checks some basic properties about the evport_data structure. Because it - * checks all file descriptors, this function can be expensive when the maximum - * file descriptor ever used is rather large. - */ - -static void -check_evportop(struct evport_data *evpd) -{ - assert(evpd); - assert(evpd->ed_nevents > 0); - assert(evpd->ed_port > 0); - assert(evpd->ed_fds > 0); - - /* - * Verify the integrity of the fd_info struct as well as the events to - * which it points (at least, that they're valid references and correct - * for their position in the structure). - */ - int i; - for (i = 0; i < evpd->ed_nevents; ++i) { - struct event *ev; - struct fd_info *fdi; - - fdi = &evpd->ed_fds[i]; - if ((ev = fdi->fdi_revt) != NULL) { - assert(ev->ev_fd == i); - } - if ((ev = fdi->fdi_wevt) != NULL) { - assert(ev->ev_fd == i); - } - } -} - -/* - * Verifies very basic integrity of a given port_event. - */ -static void -check_event(port_event_t* pevt) -{ - /* - * We've only registered for PORT_SOURCE_FD events. The only - * other thing we can legitimately receive is PORT_SOURCE_ALERT, - * but since we're not using port_alert either, we can assume - * PORT_SOURCE_FD. - */ - assert(pevt->portev_source == PORT_SOURCE_FD); - assert(pevt->portev_user == NULL); -} - -#else -#define check_evportop(epop) -#define check_event(pevt) -#endif /* CHECK_INVARIANTS */ - -/* - * Doubles the size of the allocated file descriptor array. - */ -static int -grow(struct evport_data *epdp, int factor) -{ - struct fd_info *tmp; - int oldsize = epdp->ed_nevents; - int newsize = factor * oldsize; - assert(factor > 1); - - check_evportop(epdp); - - tmp = realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize); - if (NULL == tmp) - return -1; - epdp->ed_fds = tmp; - memset((char*) (epdp->ed_fds + oldsize), 0, - (newsize - oldsize)*sizeof(struct fd_info)); - epdp->ed_nevents = newsize; - - check_evportop(epdp); - - return 0; -} - - -/* - * (Re)associates the given file descriptor with the event port. The OS events - * are specified (implicitly) from the fd_info struct. - */ -static int -reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd) -{ - int sysevents = FDI_TO_SYSEVENTS(fdip); - - if (sysevents != 0) { - if (port_associate(epdp->ed_port, PORT_SOURCE_FD, - fd, sysevents, NULL) == -1) { - event_warn("port_associate"); - return (-1); - } - } - - check_evportop(epdp); - - return (0); -} - -/* - * Main event loop - polls port_getn for some number of events, and processes - * them. - */ - -static int -evport_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - int i, res; - struct evport_data *epdp = arg; - port_event_t pevtlist[EVENTS_PER_GETN]; - - /* - * port_getn will block until it has at least nevents events. It will - * also return how many it's given us (which may be more than we asked - * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in - * nevents. - */ - int nevents = 1; - - /* - * We have to convert a struct timeval to a struct timespec - * (only difference is nanoseconds vs. microseconds). If no time-based - * events are active, we should wait for I/O (and tv == NULL). - */ - struct timespec ts; - struct timespec *ts_p = NULL; - if (tv != NULL) { - ts.tv_sec = tv->tv_sec; - ts.tv_nsec = tv->tv_usec * 1000; - ts_p = &ts; - } - - /* - * Before doing anything else, we need to reassociate the events we hit - * last time which need reassociation. See comment at the end of the - * loop below. - */ - for (i = 0; i < EVENTS_PER_GETN; ++i) { - struct fd_info *fdi = NULL; - if (epdp->ed_pending[i] != -1) { - fdi = &(epdp->ed_fds[epdp->ed_pending[i]]); - } - - if (fdi != NULL && FDI_HAS_EVENTS(fdi)) { - int fd = FDI_HAS_READ(fdi) ? fdi->fdi_revt->ev_fd : - fdi->fdi_wevt->ev_fd; - reassociate(epdp, fdi, fd); - epdp->ed_pending[i] = -1; - } - } - - if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN, - (unsigned int *) &nevents, ts_p)) == -1) { - if (errno == EINTR || errno == EAGAIN) { - evsignal_process(base); - return (0); - } else if (errno == ETIME) { - if (nevents == 0) - return (0); - } else { - event_warn("port_getn"); - return (-1); - } - } else if (base->sig.evsignal_caught) { - evsignal_process(base); - } - - event_debug(("%s: port_getn reports %d events", __func__, nevents)); - - for (i = 0; i < nevents; ++i) { - struct event *ev; - struct fd_info *fdi; - port_event_t *pevt = &pevtlist[i]; - int fd = (int) pevt->portev_object; - - check_evportop(epdp); - check_event(pevt); - epdp->ed_pending[i] = fd; - - /* - * Figure out what kind of event it was - * (because we have to pass this to the callback) - */ - res = 0; - if (pevt->portev_events & POLLIN) - res |= EV_READ; - if (pevt->portev_events & POLLOUT) - res |= EV_WRITE; - - /* - * Check for the error situations or a hangup situation - */ - if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL)) - res |= EV_READ|EV_WRITE; - - assert(epdp->ed_nevents > fd); - fdi = &(epdp->ed_fds[fd]); - - /* - * We now check for each of the possible events (READ - * or WRITE). Then, we activate the event (which will - * cause its callback to be executed). - */ - - if ((res & EV_READ) && ((ev = fdi->fdi_revt) != NULL)) { - event_active(ev, res, 1); - } - - if ((res & EV_WRITE) && ((ev = fdi->fdi_wevt) != NULL)) { - event_active(ev, res, 1); - } - } /* end of all events gotten */ - - check_evportop(epdp); - - return (0); -} - - -/* - * Adds the given event (so that you will be notified when it happens via - * the callback function). - */ - -static int -evport_add(void *arg, struct event *ev) -{ - struct evport_data *evpd = arg; - struct fd_info *fdi; - int factor; - - check_evportop(evpd); - - /* - * Delegate, if it's not ours to handle. - */ - if (ev->ev_events & EV_SIGNAL) - return (evsignal_add(ev)); - - /* - * If necessary, grow the file descriptor info table - */ - - factor = 1; - while (ev->ev_fd >= factor * evpd->ed_nevents) - factor *= 2; - - if (factor > 1) { - if (-1 == grow(evpd, factor)) { - return (-1); - } - } - - fdi = &evpd->ed_fds[ev->ev_fd]; - if (ev->ev_events & EV_READ) - fdi->fdi_revt = ev; - if (ev->ev_events & EV_WRITE) - fdi->fdi_wevt = ev; - - return reassociate(evpd, fdi, ev->ev_fd); -} - -/* - * Removes the given event from the list of events to wait for. - */ - -static int -evport_del(void *arg, struct event *ev) -{ - struct evport_data *evpd = arg; - struct fd_info *fdi; - int i; - int associated = 1; - - check_evportop(evpd); - - /* - * Delegate, if it's not ours to handle - */ - if (ev->ev_events & EV_SIGNAL) { - return (evsignal_del(ev)); - } - - if (evpd->ed_nevents < ev->ev_fd) { - return (-1); - } - - for (i = 0; i < EVENTS_PER_GETN; ++i) { - if (evpd->ed_pending[i] == ev->ev_fd) { - associated = 0; - break; - } - } - - fdi = &evpd->ed_fds[ev->ev_fd]; - if (ev->ev_events & EV_READ) - fdi->fdi_revt = NULL; - if (ev->ev_events & EV_WRITE) - fdi->fdi_wevt = NULL; - - if (associated) { - if (!FDI_HAS_EVENTS(fdi) && - port_dissociate(evpd->ed_port, PORT_SOURCE_FD, - ev->ev_fd) == -1) { - /* - * Ignre EBADFD error the fd could have been closed - * before event_del() was called. - */ - if (errno != EBADFD) { - event_warn("port_dissociate"); - return (-1); - } - } else { - if (FDI_HAS_EVENTS(fdi)) { - return (reassociate(evpd, fdi, ev->ev_fd)); - } - } - } else { - if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL) { - evpd->ed_pending[i] = -1; - } - } - return 0; -} - - -static void -evport_dealloc(struct event_base *base, void *arg) -{ - struct evport_data *evpd = arg; - - evsignal_dealloc(base); - - close(evpd->ed_port); - - if (evpd->ed_fds) - free(evpd->ed_fds); - free(evpd); -}
diff --git a/third_party/libevent/evsignal.h b/third_party/libevent/evsignal.h deleted file mode 100644 index 076cd8da..0000000 --- a/third_party/libevent/evsignal.h +++ /dev/null
@@ -1,52 +0,0 @@ -/* - * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _EVSIGNAL_H_ -#define _EVSIGNAL_H_ - -typedef void (*ev_sighandler_t)(int); - -struct evsignal_info { - struct event ev_signal; - int ev_signal_pair[2]; - int ev_signal_added; - volatile sig_atomic_t evsignal_caught; - struct event_list evsigevents[NSIG]; - sig_atomic_t evsigcaught[NSIG]; -#ifdef HAVE_SIGACTION - struct sigaction **sh_old; -#else - ev_sighandler_t **sh_old; -#endif - int sh_old_max; -}; -int evsignal_init(struct event_base *); -void evsignal_process(struct event_base *); -int evsignal_add(struct event *); -int evsignal_del(struct event *); -void evsignal_dealloc(struct event_base *); - -#endif /* _EVSIGNAL_H_ */
diff --git a/third_party/libevent/evutil.c b/third_party/libevent/evutil.c deleted file mode 100644 index cc6d0f4..0000000 --- a/third_party/libevent/evutil.c +++ /dev/null
@@ -1,284 +0,0 @@ -/* - * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#include <winsock2.h> -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -#endif - -#include <sys/types.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#include <errno.h> -#if defined WIN32 && !defined(HAVE_GETTIMEOFDAY_H) -#include <sys/timeb.h> -#endif -#include <stdio.h> -#include <signal.h> - -#include <sys/queue.h> -#include "event.h" -#include "event-internal.h" -#include "evutil.h" -#include "log.h" - -int -evutil_socketpair(int family, int type, int protocol, int fd[2]) -{ -#ifndef WIN32 - return socketpair(family, type, protocol, fd); -#else - /* This code is originally from Tor. Used with permission. */ - - /* This socketpair does not work when localhost is down. So - * it's really not the same thing at all. But it's close enough - * for now, and really, when localhost is down sometimes, we - * have other problems too. - */ - int listener = -1; - int connector = -1; - int acceptor = -1; - struct sockaddr_in listen_addr; - struct sockaddr_in connect_addr; - int size; - int saved_errno = -1; - - if (protocol -#ifdef AF_UNIX - || family != AF_UNIX -#endif - ) { - EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT); - return -1; - } - if (!fd) { - EVUTIL_SET_SOCKET_ERROR(WSAEINVAL); - return -1; - } - - listener = socket(AF_INET, type, 0); - if (listener < 0) - return -1; - memset(&listen_addr, 0, sizeof(listen_addr)); - listen_addr.sin_family = AF_INET; - listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - listen_addr.sin_port = 0; /* kernel chooses port. */ - if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) - == -1) - goto tidy_up_and_fail; - if (listen(listener, 1) == -1) - goto tidy_up_and_fail; - - connector = socket(AF_INET, type, 0); - if (connector < 0) - goto tidy_up_and_fail; - /* We want to find out the port number to connect to. */ - size = sizeof(connect_addr); - if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) - goto tidy_up_and_fail; - if (size != sizeof (connect_addr)) - goto abort_tidy_up_and_fail; - if (connect(connector, (struct sockaddr *) &connect_addr, - sizeof(connect_addr)) == -1) - goto tidy_up_and_fail; - - size = sizeof(listen_addr); - acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); - if (acceptor < 0) - goto tidy_up_and_fail; - if (size != sizeof(listen_addr)) - goto abort_tidy_up_and_fail; - EVUTIL_CLOSESOCKET(listener); - /* Now check we are talking to ourself by matching port and host on the - two sockets. */ - if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) - goto tidy_up_and_fail; - if (size != sizeof (connect_addr) - || listen_addr.sin_family != connect_addr.sin_family - || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr - || listen_addr.sin_port != connect_addr.sin_port) - goto abort_tidy_up_and_fail; - fd[0] = connector; - fd[1] = acceptor; - - return 0; - - abort_tidy_up_and_fail: - saved_errno = WSAECONNABORTED; - tidy_up_and_fail: - if (saved_errno < 0) - saved_errno = WSAGetLastError(); - if (listener != -1) - EVUTIL_CLOSESOCKET(listener); - if (connector != -1) - EVUTIL_CLOSESOCKET(connector); - if (acceptor != -1) - EVUTIL_CLOSESOCKET(acceptor); - - EVUTIL_SET_SOCKET_ERROR(saved_errno); - return -1; -#endif -} - -int -evutil_make_socket_nonblocking(int fd) -{ -#ifdef WIN32 - { - unsigned long nonblocking = 1; - ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking); - } -#else - { - int flags; - if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) { - event_warn("fcntl(%d, F_GETFL)", fd); - return -1; - } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { - event_warn("fcntl(%d, F_SETFL)", fd); - return -1; - } - } -#endif - return 0; -} - -ev_int64_t -evutil_strtoll(const char *s, char **endptr, int base) -{ -#ifdef HAVE_STRTOLL - return (ev_int64_t)strtoll(s, endptr, base); -#elif SIZEOF_LONG == 8 - return (ev_int64_t)strtol(s, endptr, base); -#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 - /* XXXX on old versions of MS APIs, we only support base - * 10. */ - ev_int64_t r; - if (base != 10) - return 0; - r = (ev_int64_t) _atoi64(s); - while (isspace(*s)) - ++s; - while (isdigit(*s)) - ++s; - if (endptr) - *endptr = (char*) s; - return r; -#elif defined(WIN32) - return (ev_int64_t) _strtoi64(s, endptr, base); -#else -#error "I don't know how to parse 64-bit integers." -#endif -} - -#ifndef _EVENT_HAVE_GETTIMEOFDAY -int -evutil_gettimeofday(struct timeval *tv, struct timezone *tz) -{ - struct _timeb tb; - - if(tv == NULL) - return -1; - - _ftime(&tb); - tv->tv_sec = (long) tb.time; - tv->tv_usec = ((int) tb.millitm) * 1000; - return 0; -} -#endif - -int -evutil_snprintf(char *buf, size_t buflen, const char *format, ...) -{ - int r; - va_list ap; - va_start(ap, format); - r = evutil_vsnprintf(buf, buflen, format, ap); - va_end(ap); - return r; -} - -int -evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) -{ -#ifdef _MSC_VER - int r = _vsnprintf(buf, buflen, format, ap); - buf[buflen-1] = '\0'; - if (r >= 0) - return r; - else - return _vscprintf(format, ap); -#else - int r = vsnprintf(buf, buflen, format, ap); - buf[buflen-1] = '\0'; - return r; -#endif -} - -static int -evutil_issetugid(void) -{ -#ifdef _EVENT_HAVE_ISSETUGID - return issetugid(); -#else - -#ifdef _EVENT_HAVE_GETEUID - if (getuid() != geteuid()) - return 1; -#endif -#ifdef _EVENT_HAVE_GETEGID - if (getgid() != getegid()) - return 1; -#endif - return 0; -#endif -} - -const char * -evutil_getenv(const char *varname) -{ - if (evutil_issetugid()) - return NULL; - - return getenv(varname); -}
diff --git a/third_party/libevent/evutil.h b/third_party/libevent/evutil.h deleted file mode 100644 index 8b664b9..0000000 --- a/third_party/libevent/evutil.h +++ /dev/null
@@ -1,186 +0,0 @@ -/* - * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _EVUTIL_H_ -#define _EVUTIL_H_ - -/** @file evutil.h - - Common convenience functions for cross-platform portability and - related socket manipulations. - - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "event-config.h" -#ifdef _EVENT_HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef _EVENT_HAVE_STDINT_H -#include <stdint.h> -#elif defined(_EVENT_HAVE_INTTYPES_H) -#include <inttypes.h> -#endif -#ifdef _EVENT_HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#include <stdarg.h> - -#ifdef _EVENT_HAVE_UINT64_T -#define ev_uint64_t uint64_t -#define ev_int64_t int64_t -#elif defined(WIN32) -#define ev_uint64_t unsigned __int64 -#define ev_int64_t signed __int64 -#elif _EVENT_SIZEOF_LONG_LONG == 8 -#define ev_uint64_t unsigned long long -#define ev_int64_t long long -#elif _EVENT_SIZEOF_LONG == 8 -#define ev_uint64_t unsigned long -#define ev_int64_t long -#else -#error "No way to define ev_uint64_t" -#endif - -#ifdef _EVENT_HAVE_UINT32_T -#define ev_uint32_t uint32_t -#elif defined(WIN32) -#define ev_uint32_t unsigned int -#elif _EVENT_SIZEOF_LONG == 4 -#define ev_uint32_t unsigned long -#elif _EVENT_SIZEOF_INT == 4 -#define ev_uint32_t unsigned int -#else -#error "No way to define ev_uint32_t" -#endif - -#ifdef _EVENT_HAVE_UINT16_T -#define ev_uint16_t uint16_t -#elif defined(WIN32) -#define ev_uint16_t unsigned short -#elif _EVENT_SIZEOF_INT == 2 -#define ev_uint16_t unsigned int -#elif _EVENT_SIZEOF_SHORT == 2 -#define ev_uint16_t unsigned short -#else -#error "No way to define ev_uint16_t" -#endif - -#ifdef _EVENT_HAVE_UINT8_T -#define ev_uint8_t uint8_t -#else -#define ev_uint8_t unsigned char -#endif - -int evutil_socketpair(int d, int type, int protocol, int sv[2]); -int evutil_make_socket_nonblocking(int sock); -#ifdef WIN32 -#define EVUTIL_CLOSESOCKET(s) closesocket(s) -#else -#define EVUTIL_CLOSESOCKET(s) close(s) -#endif - -#ifdef WIN32 -#define EVUTIL_SOCKET_ERROR() WSAGetLastError() -#define EVUTIL_SET_SOCKET_ERROR(errcode) \ - do { WSASetLastError(errcode); } while (0) -#else -#define EVUTIL_SOCKET_ERROR() (errno) -#define EVUTIL_SET_SOCKET_ERROR(errcode) \ - do { errno = (errcode); } while (0) -#endif - -/* - * Manipulation functions for struct timeval - */ -#ifdef _EVENT_HAVE_TIMERADD -#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp)) -#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp)) -#else -#define evutil_timeradd(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ - if ((vvp)->tv_usec >= 1000000) { \ - (vvp)->tv_sec++; \ - (vvp)->tv_usec -= 1000000; \ - } \ - } while (0) -#define evutil_timersub(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ - if ((vvp)->tv_usec < 0) { \ - (vvp)->tv_sec--; \ - (vvp)->tv_usec += 1000000; \ - } \ - } while (0) -#endif /* !_EVENT_HAVE_HAVE_TIMERADD */ - -#ifdef _EVENT_HAVE_TIMERCLEAR -#define evutil_timerclear(tvp) timerclear(tvp) -#else -#define evutil_timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 -#endif - -#define evutil_timercmp(tvp, uvp, cmp) \ - (((tvp)->tv_sec == (uvp)->tv_sec) ? \ - ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ - ((tvp)->tv_sec cmp (uvp)->tv_sec)) - -#ifdef _EVENT_HAVE_TIMERISSET -#define evutil_timerisset(tvp) timerisset(tvp) -#else -#define evutil_timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#endif - - -/* big-int related functions */ -ev_int64_t evutil_strtoll(const char *s, char **endptr, int base); - - -#ifdef _EVENT_HAVE_GETTIMEOFDAY -#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz)) -#else -struct timezone; -int evutil_gettimeofday(struct timeval *tv, struct timezone *tz); -#endif - -int evutil_snprintf(char *buf, size_t buflen, const char *format, ...) -#ifdef __GNUC__ - __attribute__((format(printf, 3, 4))) -#endif - ; -int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap); - -#ifdef __cplusplus -} -#endif - -#endif /* _EVUTIL_H_ */
diff --git a/third_party/libevent/freebsd/config.h b/third_party/libevent/freebsd/config.h deleted file mode 100644 index 4fe3d6be..0000000 --- a/third_party/libevent/freebsd/config.h +++ /dev/null
@@ -1,266 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -/* #undef HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `kqueue' function. */ -#define HAVE_KQUEUE 1 - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -/* #undef HAVE_LIBNSL */ - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -/* #undef HAVE_LIBRESOLV */ - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -#define HAVE_SYS_EVENT_H 1 - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -#define HAVE_WORKING_KQUEUE 1 - -/* Name of package */ -#define PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "1.4.13-stable" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef __func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef socklen_t */
diff --git a/third_party/libevent/freebsd/event-config.h b/third_party/libevent/freebsd/event-config.h deleted file mode 100644 index be1eae4..0000000 --- a/third_party/libevent/freebsd/event-config.h +++ /dev/null
@@ -1,284 +0,0 @@ -/* event-config.h - * Generated by autoconf; post-processed by libevent. - * Do not edit this file. - * Do not rely on macros in this file existing in later versions. - */ -#ifndef _EVENT_CONFIG_H_ -#define _EVENT_CONFIG_H_ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define _EVENT_HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef _EVENT_HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define _EVENT_HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef _EVENT_HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef _EVENT_HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -/* #undef _EVENT_HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define _EVENT_HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define _EVENT_HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define _EVENT_HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define _EVENT_HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define _EVENT_HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define _EVENT_HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define _EVENT_HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define _EVENT_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define _EVENT_HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define _EVENT_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define _EVENT_HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `kqueue' function. */ -#define _EVENT_HAVE_KQUEUE 1 - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -/* #undef _EVENT_HAVE_LIBNSL */ - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -/* #undef _EVENT_HAVE_LIBRESOLV */ - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define _EVENT_HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef _EVENT_HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define _EVENT_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef _EVENT_HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define _EVENT_HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define _EVENT_HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef _EVENT_HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef _EVENT_HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define _EVENT_HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define _EVENT_HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define _EVENT_HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define _EVENT_HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define _EVENT_HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define _EVENT_HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define _EVENT_HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define _EVENT_HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define _EVENT_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define _EVENT_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define _EVENT_HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define _EVENT_HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define _EVENT_HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define _EVENT_HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -#define _EVENT_HAVE_SYS_EVENT_H 1 - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define _EVENT_HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define _EVENT_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define _EVENT_HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define _EVENT_HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define _EVENT_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define _EVENT_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define _EVENT_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define _EVENT_HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define _EVENT_HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define _EVENT_HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define _EVENT_HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define _EVENT_HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define _EVENT_HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define _EVENT_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define _EVENT_HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -#define _EVENT_HAVE_WORKING_KQUEUE 1 - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define _EVENT_LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define _EVENT_NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define _EVENT_PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define _EVENT_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _EVENT_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define _EVENT_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define _EVENT_PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define _EVENT_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _EVENT_PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define _EVENT_SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define _EVENT_SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define _EVENT_STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define _EVENT_TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define _EVENT_VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef _EVENT___func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef _EVENT_const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef _EVENT___cplusplus -/* #undef _EVENT_inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef _EVENT_pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef _EVENT_size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef _EVENT_socklen_t */ -#endif
diff --git a/third_party/libevent/kqueue.c b/third_party/libevent/kqueue.c deleted file mode 100644 index 3c2ffd5..0000000 --- a/third_party/libevent/kqueue.c +++ /dev/null
@@ -1,433 +0,0 @@ -/* $OpenBSD: kqueue.c,v 1.5 2002/07/10 14:41:31 art Exp $ */ - -/* - * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _GNU_SOURCE 1 - -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#include <sys/queue.h> -#include <sys/event.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <assert.h> -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -/* Some platforms apparently define the udata field of struct kevent as - * intptr_t, whereas others define it as void*. There doesn't seem to be an - * easy way to tell them apart via autoconf, so we need to use OS macros. */ -#if defined(HAVE_INTTYPES_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__darwin__) && !defined(__APPLE__) -#define PTR_TO_UDATA(x) ((intptr_t)(x)) -#else -#define PTR_TO_UDATA(x) (x) -#endif - -#include "event.h" -#include "event-internal.h" -#include "log.h" -#include "evsignal.h" - -#define EVLIST_X_KQINKERNEL 0x1000 - -#define NEVENT 64 - -struct kqop { - struct kevent *changes; - int nchanges; - struct kevent *events; - struct event_list evsigevents[NSIG]; - int nevents; - int kq; - pid_t pid; -}; - -static void *kq_init (struct event_base *); -static int kq_add (void *, struct event *); -static int kq_del (void *, struct event *); -static int kq_dispatch (struct event_base *, void *, struct timeval *); -static int kq_insert (struct kqop *, struct kevent *); -static void kq_dealloc (struct event_base *, void *); - -const struct eventop kqops = { - "kqueue", - kq_init, - kq_add, - kq_del, - kq_dispatch, - kq_dealloc, - 1 /* need reinit */ -}; - -static void * -kq_init(struct event_base *base) -{ - int i, kq; - struct kqop *kqueueop; - - /* Disable kqueue when this environment variable is set */ - if (evutil_getenv("EVENT_NOKQUEUE")) - return (NULL); - - if (!(kqueueop = calloc(1, sizeof(struct kqop)))) - return (NULL); - - /* Initalize the kernel queue */ - - if ((kq = kqueue()) == -1) { - event_warn("kqueue"); - free (kqueueop); - return (NULL); - } - - kqueueop->kq = kq; - - kqueueop->pid = getpid(); - - /* Initalize fields */ - kqueueop->changes = malloc(NEVENT * sizeof(struct kevent)); - if (kqueueop->changes == NULL) { - free (kqueueop); - return (NULL); - } - kqueueop->events = malloc(NEVENT * sizeof(struct kevent)); - if (kqueueop->events == NULL) { - free (kqueueop->changes); - free (kqueueop); - return (NULL); - } - kqueueop->nevents = NEVENT; - - /* we need to keep track of multiple events per signal */ - for (i = 0; i < NSIG; ++i) { - TAILQ_INIT(&kqueueop->evsigevents[i]); - } - - return (kqueueop); -} - -static int -kq_insert(struct kqop *kqop, struct kevent *kev) -{ - int nevents = kqop->nevents; - - if (kqop->nchanges == nevents) { - struct kevent *newchange; - struct kevent *newresult; - - nevents *= 2; - - newchange = realloc(kqop->changes, - nevents * sizeof(struct kevent)); - if (newchange == NULL) { - event_warn("%s: malloc", __func__); - return (-1); - } - kqop->changes = newchange; - - newresult = realloc(kqop->events, - nevents * sizeof(struct kevent)); - - /* - * If we fail, we don't have to worry about freeing, - * the next realloc will pick it up. - */ - if (newresult == NULL) { - event_warn("%s: malloc", __func__); - return (-1); - } - kqop->events = newresult; - - kqop->nevents = nevents; - } - - memcpy(&kqop->changes[kqop->nchanges++], kev, sizeof(struct kevent)); - - event_debug(("%s: fd %d %s%s", - __func__, (int)kev->ident, - kev->filter == EVFILT_READ ? "EVFILT_READ" : "EVFILT_WRITE", - kev->flags == EV_DELETE ? " (del)" : "")); - - return (0); -} - -static void -kq_sighandler(int sig) -{ - /* Do nothing here */ -} - -static int -kq_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - struct kqop *kqop = arg; - struct kevent *changes = kqop->changes; - struct kevent *events = kqop->events; - struct event *ev; - struct timespec ts, *ts_p = NULL; - int i, res; - - if (tv != NULL) { - TIMEVAL_TO_TIMESPEC(tv, &ts); - ts_p = &ts; - } - - res = kevent(kqop->kq, changes, kqop->nchanges, - events, kqop->nevents, ts_p); - kqop->nchanges = 0; - if (res == -1) { - if (errno != EINTR) { - event_warn("kevent"); - return (-1); - } - - return (0); - } - - event_debug(("%s: kevent reports %d", __func__, res)); - - for (i = 0; i < res; i++) { - int which = 0; - - if (events[i].flags & EV_ERROR) { - /* - * Error messages that can happen, when a delete fails. - * EBADF happens when the file discriptor has been - * closed, - * ENOENT when the file discriptor was closed and - * then reopened. - * EINVAL for some reasons not understood; EINVAL - * should not be returned ever; but FreeBSD does :-\ - * An error is also indicated when a callback deletes - * an event we are still processing. In that case - * the data field is set to ENOENT. - */ - if (events[i].data == EBADF || - events[i].data == EINVAL || - events[i].data == ENOENT) - continue; - errno = events[i].data; - return (-1); - } - - if (events[i].filter == EVFILT_READ) { - which |= EV_READ; - } else if (events[i].filter == EVFILT_WRITE) { - which |= EV_WRITE; - } else if (events[i].filter == EVFILT_SIGNAL) { - which |= EV_SIGNAL; - } - - if (!which) - continue; - - if (events[i].filter == EVFILT_SIGNAL) { - struct event_list *head = - (struct event_list *)events[i].udata; - TAILQ_FOREACH(ev, head, ev_signal_next) { - event_active(ev, which, events[i].data); - } - } else { - ev = (struct event *)events[i].udata; - - if (!(ev->ev_events & EV_PERSIST)) - ev->ev_flags &= ~EVLIST_X_KQINKERNEL; - - event_active(ev, which, 1); - } - } - - return (0); -} - - -static int -kq_add(void *arg, struct event *ev) -{ - struct kqop *kqop = arg; - struct kevent kev; - - if (ev->ev_events & EV_SIGNAL) { - int nsignal = EVENT_SIGNAL(ev); - - assert(nsignal >= 0 && nsignal < NSIG); - if (TAILQ_EMPTY(&kqop->evsigevents[nsignal])) { - struct timespec timeout = { 0, 0 }; - - memset(&kev, 0, sizeof(kev)); - kev.ident = nsignal; - kev.filter = EVFILT_SIGNAL; - kev.flags = EV_ADD; - kev.udata = PTR_TO_UDATA(&kqop->evsigevents[nsignal]); - - /* Be ready for the signal if it is sent any - * time between now and the next call to - * kq_dispatch. */ - if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) - return (-1); - - if (_evsignal_set_handler(ev->ev_base, nsignal, - kq_sighandler) == -1) - return (-1); - } - - TAILQ_INSERT_TAIL(&kqop->evsigevents[nsignal], ev, - ev_signal_next); - ev->ev_flags |= EVLIST_X_KQINKERNEL; - return (0); - } - - if (ev->ev_events & EV_READ) { - memset(&kev, 0, sizeof(kev)); - kev.ident = ev->ev_fd; - kev.filter = EVFILT_READ; -#ifdef NOTE_EOF - /* Make it behave like select() and poll() */ - kev.fflags = NOTE_EOF; -#endif - kev.flags = EV_ADD; - if (!(ev->ev_events & EV_PERSIST)) - kev.flags |= EV_ONESHOT; - kev.udata = PTR_TO_UDATA(ev); - - if (kq_insert(kqop, &kev) == -1) - return (-1); - - ev->ev_flags |= EVLIST_X_KQINKERNEL; - } - - if (ev->ev_events & EV_WRITE) { - memset(&kev, 0, sizeof(kev)); - kev.ident = ev->ev_fd; - kev.filter = EVFILT_WRITE; - kev.flags = EV_ADD; - if (!(ev->ev_events & EV_PERSIST)) - kev.flags |= EV_ONESHOT; - kev.udata = PTR_TO_UDATA(ev); - - if (kq_insert(kqop, &kev) == -1) - return (-1); - - ev->ev_flags |= EVLIST_X_KQINKERNEL; - } - - return (0); -} - -static int -kq_del(void *arg, struct event *ev) -{ - struct kqop *kqop = arg; - struct kevent kev; - - if (!(ev->ev_flags & EVLIST_X_KQINKERNEL)) - return (0); - - if (ev->ev_events & EV_SIGNAL) { - int nsignal = EVENT_SIGNAL(ev); - struct timespec timeout = { 0, 0 }; - - assert(nsignal >= 0 && nsignal < NSIG); - TAILQ_REMOVE(&kqop->evsigevents[nsignal], ev, ev_signal_next); - if (TAILQ_EMPTY(&kqop->evsigevents[nsignal])) { - memset(&kev, 0, sizeof(kev)); - kev.ident = nsignal; - kev.filter = EVFILT_SIGNAL; - kev.flags = EV_DELETE; - - /* Because we insert signal events - * immediately, we need to delete them - * immediately, too */ - if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) - return (-1); - - if (_evsignal_restore_handler(ev->ev_base, - nsignal) == -1) - return (-1); - } - - ev->ev_flags &= ~EVLIST_X_KQINKERNEL; - return (0); - } - - if (ev->ev_events & EV_READ) { - memset(&kev, 0, sizeof(kev)); - kev.ident = ev->ev_fd; - kev.filter = EVFILT_READ; - kev.flags = EV_DELETE; - - if (kq_insert(kqop, &kev) == -1) - return (-1); - - ev->ev_flags &= ~EVLIST_X_KQINKERNEL; - } - - if (ev->ev_events & EV_WRITE) { - memset(&kev, 0, sizeof(kev)); - kev.ident = ev->ev_fd; - kev.filter = EVFILT_WRITE; - kev.flags = EV_DELETE; - - if (kq_insert(kqop, &kev) == -1) - return (-1); - - ev->ev_flags &= ~EVLIST_X_KQINKERNEL; - } - - return (0); -} - -static void -kq_dealloc(struct event_base *base, void *arg) -{ - struct kqop *kqop = arg; - - evsignal_dealloc(base); - - if (kqop->changes) - free(kqop->changes); - if (kqop->events) - free(kqop->events); - if (kqop->kq >= 0 && kqop->pid == getpid()) - close(kqop->kq); - - memset(kqop, 0, sizeof(struct kqop)); - free(kqop); -}
diff --git a/third_party/libevent/linux/config.h b/third_party/libevent/linux/config.h deleted file mode 100644 index c01ceb5..0000000 --- a/third_party/libevent/linux/config.h +++ /dev/null
@@ -1,266 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -#define HAVE_EPOLL 1 - -/* Define to 1 if you have the `epoll_ctl' function. */ -#define HAVE_EPOLL_CTL 1 - -/* Define if your system supports event ports */ -/* #undef HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -/* #undef HAVE_STRLCPY */ - -/* Define to 1 if you have the `strsep' function. */ -#define HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -#define HAVE_SYS_EPOLL_H 1 - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -/* #undef HAVE_WORKING_KQUEUE */ - -/* Name of package */ -#define PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "1.4.13-stable" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef __func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef socklen_t */
diff --git a/third_party/libevent/linux/event-config.h b/third_party/libevent/linux/event-config.h deleted file mode 100644 index 2203253..0000000 --- a/third_party/libevent/linux/event-config.h +++ /dev/null
@@ -1,284 +0,0 @@ -/* event-config.h - * Generated by autoconf; post-processed by libevent. - * Do not edit this file. - * Do not rely on macros in this file existing in later versions. - */ -#ifndef _EVENT_CONFIG_H_ -#define _EVENT_CONFIG_H_ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define _EVENT_HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -/* #undef _EVENT_HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define _EVENT_HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -#define _EVENT_HAVE_EPOLL 1 - -/* Define to 1 if you have the `epoll_ctl' function. */ -#define _EVENT_HAVE_EPOLL_CTL 1 - -/* Define if your system supports event ports */ -/* #undef _EVENT_HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define _EVENT_HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define _EVENT_HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define _EVENT_HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define _EVENT_HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define _EVENT_HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define _EVENT_HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define _EVENT_HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define _EVENT_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define _EVENT_HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define _EVENT_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -/* #undef _EVENT_HAVE_ISSETUGID */ - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef _EVENT_HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define _EVENT_HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define _EVENT_HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define _EVENT_HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef _EVENT_HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define _EVENT_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef _EVENT_HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define _EVENT_HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define _EVENT_HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef _EVENT_HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef _EVENT_HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define _EVENT_HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define _EVENT_HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define _EVENT_HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define _EVENT_HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define _EVENT_HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define _EVENT_HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define _EVENT_HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define _EVENT_HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define _EVENT_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define _EVENT_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -/* #undef _EVENT_HAVE_STRLCPY */ - -/* Define to 1 if you have the `strsep' function. */ -#define _EVENT_HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define _EVENT_HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define _EVENT_HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -#define _EVENT_HAVE_SYS_EPOLL_H 1 - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define _EVENT_HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define _EVENT_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define _EVENT_HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define _EVENT_HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define _EVENT_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define _EVENT_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define _EVENT_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define _EVENT_HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define _EVENT_HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define _EVENT_HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define _EVENT_HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define _EVENT_HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define _EVENT_HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define _EVENT_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define _EVENT_HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -/* #undef _EVENT_HAVE_WORKING_KQUEUE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define _EVENT_LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define _EVENT_NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define _EVENT_PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define _EVENT_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _EVENT_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define _EVENT_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define _EVENT_PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define _EVENT_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _EVENT_PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define _EVENT_SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG 8 - -/* The size of `long long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define _EVENT_SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define _EVENT_STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define _EVENT_TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define _EVENT_VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef _EVENT___func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef _EVENT_const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef _EVENT___cplusplus -/* #undef _EVENT_inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef _EVENT_pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef _EVENT_size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef _EVENT_socklen_t */ -#endif
diff --git a/third_party/libevent/log.c b/third_party/libevent/log.c deleted file mode 100644 index 48ebb269..0000000 --- a/third_party/libevent/log.c +++ /dev/null
@@ -1,187 +0,0 @@ -/* $OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ - -/* - * log.c - * - * Based on err.c, which was adapted from OpenBSD libc *err* *warn* code. - * - * Copyright (c) 2005 Nick Mathewson <nickm@freehaven.net> - * - * Copyright (c) 2000 Dug Song <dugsong@monkey.org> - * - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -#endif -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include "event.h" - -#include "log.h" -#include "evutil.h" - -static void _warn_helper(int severity, int log_errno, const char *fmt, - va_list ap); -static void event_log(int severity, const char *msg); - -void -event_err(int eval, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - _warn_helper(_EVENT_LOG_ERR, errno, fmt, ap); - va_end(ap); - exit(eval); -} - -void -event_warn(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - _warn_helper(_EVENT_LOG_WARN, errno, fmt, ap); - va_end(ap); -} - -void -event_errx(int eval, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - _warn_helper(_EVENT_LOG_ERR, -1, fmt, ap); - va_end(ap); - exit(eval); -} - -void -event_warnx(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - _warn_helper(_EVENT_LOG_WARN, -1, fmt, ap); - va_end(ap); -} - -void -event_msgx(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - _warn_helper(_EVENT_LOG_MSG, -1, fmt, ap); - va_end(ap); -} - -void -_event_debugx(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - _warn_helper(_EVENT_LOG_DEBUG, -1, fmt, ap); - va_end(ap); -} - -static void -_warn_helper(int severity, int log_errno, const char *fmt, va_list ap) -{ - char buf[1024]; - size_t len; - - if (fmt != NULL) - evutil_vsnprintf(buf, sizeof(buf), fmt, ap); - else - buf[0] = '\0'; - - if (log_errno >= 0) { - len = strlen(buf); - if (len < sizeof(buf) - 3) { - evutil_snprintf(buf + len, sizeof(buf) - len, ": %s", - strerror(log_errno)); - } - } - - event_log(severity, buf); -} - -static event_log_cb log_fn = NULL; - -void -event_set_log_callback(event_log_cb cb) -{ - log_fn = cb; -} - -static void -event_log(int severity, const char *msg) -{ - if (log_fn) - log_fn(severity, msg); - else { - const char *severity_str; - switch (severity) { - case _EVENT_LOG_DEBUG: - severity_str = "debug"; - break; - case _EVENT_LOG_MSG: - severity_str = "msg"; - break; - case _EVENT_LOG_WARN: - severity_str = "warn"; - break; - case _EVENT_LOG_ERR: - severity_str = "err"; - break; - default: - severity_str = "???"; - break; - } - (void)fprintf(stderr, "[%s] %s\n", severity_str, msg); - } -}
diff --git a/third_party/libevent/log.h b/third_party/libevent/log.h deleted file mode 100644 index 7bc6632b..0000000 --- a/third_party/libevent/log.h +++ /dev/null
@@ -1,51 +0,0 @@ -/* - * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _LOG_H_ -#define _LOG_H_ - -#ifdef __GNUC__ -#define EV_CHECK_FMT(a,b) __attribute__((format(printf, a, b))) -#else -#define EV_CHECK_FMT(a,b) -#endif - -void event_err(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3); -void event_warn(const char *fmt, ...) EV_CHECK_FMT(1,2); -void event_errx(int eval, const char *fmt, ...) EV_CHECK_FMT(2,3); -void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2); -void event_msgx(const char *fmt, ...) EV_CHECK_FMT(1,2); -void _event_debugx(const char *fmt, ...) EV_CHECK_FMT(1,2); - -#ifdef USE_DEBUG -#define event_debug(x) _event_debugx x -#else -#define event_debug(x) do {;} while (0) -#endif - -#undef EV_CHECK_FMT - -#endif
diff --git a/third_party/libevent/m4/.dummy b/third_party/libevent/m4/.dummy deleted file mode 100644 index a0a72d60..0000000 --- a/third_party/libevent/m4/.dummy +++ /dev/null
@@ -1 +0,0 @@ -(This dummy file exists so that git will create the m4 directory)
diff --git a/third_party/libevent/mac/config.h b/third_party/libevent/mac/config.h deleted file mode 100644 index f73f0c63..0000000 --- a/third_party/libevent/mac/config.h +++ /dev/null
@@ -1,266 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -/* #undef DNS_USE_CPU_CLOCK_FOR_ID */ - -/* Define is no secure id variant is available */ -#define DNS_USE_GETTIMEOFDAY_FOR_ID 1 - -/* Define to 1 if you have the `clock_gettime' function. */ -/* #undef HAVE_CLOCK_GETTIME */ - -/* Define if /dev/poll is available */ -/* #undef HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -/* #undef HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `kqueue' function. */ -#define HAVE_KQUEUE 1 - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -/* #undef HAVE_LIBNSL */ - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -/* #undef HAVE_LIBRT */ - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -#define HAVE_SYS_EVENT_H 1 - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -#define HAVE_WORKING_KQUEUE 1 - -/* Name of package */ -#define PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "1.4.13-stable" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef __func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef socklen_t */
diff --git a/third_party/libevent/mac/event-config.h b/third_party/libevent/mac/event-config.h deleted file mode 100644 index 92e212d0..0000000 --- a/third_party/libevent/mac/event-config.h +++ /dev/null
@@ -1,284 +0,0 @@ -/* event-config.h - * Generated by autoconf; post-processed by libevent. - * Do not edit this file. - * Do not rely on macros in this file existing in later versions. - */ -#ifndef _EVENT_CONFIG_H_ -#define _EVENT_CONFIG_H_ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -/* #undef _EVENT_DNS_USE_CPU_CLOCK_FOR_ID */ - -/* Define is no secure id variant is available */ -#define _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID 1 - -/* Define to 1 if you have the `clock_gettime' function. */ -/* #undef _EVENT_HAVE_CLOCK_GETTIME */ - -/* Define if /dev/poll is available */ -/* #undef _EVENT_HAVE_DEVPOLL */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define _EVENT_HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef _EVENT_HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef _EVENT_HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -/* #undef _EVENT_HAVE_EVENT_PORTS */ - -/* Define to 1 if you have the `fcntl' function. */ -#define _EVENT_HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define _EVENT_HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define _EVENT_HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define _EVENT_HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define _EVENT_HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define _EVENT_HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define _EVENT_HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define _EVENT_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define _EVENT_HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define _EVENT_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define _EVENT_HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `kqueue' function. */ -#define _EVENT_HAVE_KQUEUE 1 - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -/* #undef _EVENT_HAVE_LIBNSL */ - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define _EVENT_HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -/* #undef _EVENT_HAVE_LIBRT */ - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef _EVENT_HAVE_LIBSOCKET */ - -/* Define to 1 if you have the <memory.h> header file. */ -#define _EVENT_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef _EVENT_HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define _EVENT_HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define _EVENT_HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -/* #undef _EVENT_HAVE_PORT_CREATE */ - -/* Define to 1 if you have the <port.h> header file. */ -/* #undef _EVENT_HAVE_PORT_H */ - -/* Define to 1 if you have the `select' function. */ -#define _EVENT_HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define _EVENT_HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define _EVENT_HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define _EVENT_HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define _EVENT_HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define _EVENT_HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define _EVENT_HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define _EVENT_HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define _EVENT_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define _EVENT_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define _EVENT_HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define _EVENT_HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define _EVENT_HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define _EVENT_HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */ - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -#define _EVENT_HAVE_SYS_EVENT_H 1 - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define _EVENT_HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define _EVENT_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define _EVENT_HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define _EVENT_HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define _EVENT_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define _EVENT_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define _EVENT_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define _EVENT_HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define _EVENT_HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define _EVENT_HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define _EVENT_HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define _EVENT_HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define _EVENT_HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define _EVENT_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define _EVENT_HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -#define _EVENT_HAVE_WORKING_KQUEUE 1 - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define _EVENT_LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define _EVENT_NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define _EVENT_PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define _EVENT_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _EVENT_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define _EVENT_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define _EVENT_PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define _EVENT_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _EVENT_PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define _EVENT_SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define _EVENT_SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define _EVENT_STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define _EVENT_TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define _EVENT_VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef _EVENT___func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef _EVENT_const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef _EVENT___cplusplus -/* #undef _EVENT_inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef _EVENT_pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef _EVENT_size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef _EVENT_socklen_t */ -#endif
diff --git a/third_party/libevent/min_heap.h b/third_party/libevent/min_heap.h deleted file mode 100644 index 14d8e37..0000000 --- a/third_party/libevent/min_heap.h +++ /dev/null
@@ -1,149 +0,0 @@ -/* - * Copyright (c) 2006 Maxim Yegorushkin <maxim.yegorushkin@gmail.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _MIN_HEAP_H_ -#define _MIN_HEAP_H_ - -#include "event.h" -#include "evutil.h" - -typedef struct min_heap -{ - struct event** p; - unsigned n, a; -} min_heap_t; - -static inline void min_heap_ctor(min_heap_t* s); -static inline void min_heap_dtor(min_heap_t* s); -static inline void min_heap_elem_init(struct event* e); -static inline int min_heap_elem_greater(struct event *a, struct event *b); -static inline int min_heap_empty(min_heap_t* s); -static inline unsigned min_heap_size(min_heap_t* s); -static inline struct event* min_heap_top(min_heap_t* s); -static inline int min_heap_reserve(min_heap_t* s, unsigned n); -static inline int min_heap_push(min_heap_t* s, struct event* e); -static inline struct event* min_heap_pop(min_heap_t* s); -static inline int min_heap_erase(min_heap_t* s, struct event* e); -static inline void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e); -static inline void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e); - -int min_heap_elem_greater(struct event *a, struct event *b) -{ - return evutil_timercmp(&a->ev_timeout, &b->ev_timeout, >); -} - -void min_heap_ctor(min_heap_t* s) { s->p = 0; s->n = 0; s->a = 0; } -void min_heap_dtor(min_heap_t* s) { if(s->p) free(s->p); } -void min_heap_elem_init(struct event* e) { e->min_heap_idx = -1; } -int min_heap_empty(min_heap_t* s) { return 0u == s->n; } -unsigned min_heap_size(min_heap_t* s) { return s->n; } -struct event* min_heap_top(min_heap_t* s) { return s->n ? *s->p : 0; } - -int min_heap_push(min_heap_t* s, struct event* e) -{ - if(min_heap_reserve(s, s->n + 1)) - return -1; - min_heap_shift_up_(s, s->n++, e); - return 0; -} - -struct event* min_heap_pop(min_heap_t* s) -{ - if(s->n) - { - struct event* e = *s->p; - min_heap_shift_down_(s, 0u, s->p[--s->n]); - e->min_heap_idx = -1; - return e; - } - return 0; -} - -int min_heap_erase(min_heap_t* s, struct event* e) -{ - if(((unsigned int)-1) != e->min_heap_idx) - { - struct event *last = s->p[--s->n]; - unsigned parent = (e->min_heap_idx - 1) / 2; - /* we replace e with the last element in the heap. We might need to - shift it upward if it is less than its parent, or downward if it is - greater than one or both its children. Since the children are known - to be less than the parent, it can't need to shift both up and - down. */ - if (e->min_heap_idx > 0 && min_heap_elem_greater(s->p[parent], last)) - min_heap_shift_up_(s, e->min_heap_idx, last); - else - min_heap_shift_down_(s, e->min_heap_idx, last); - e->min_heap_idx = -1; - return 0; - } - return -1; -} - -int min_heap_reserve(min_heap_t* s, unsigned n) -{ - if(s->a < n) - { - struct event** p; - unsigned a = s->a ? s->a * 2 : 8; - if(a < n) - a = n; - if(!(p = (struct event**)realloc(s->p, a * sizeof *p))) - return -1; - s->p = p; - s->a = a; - } - return 0; -} - -void min_heap_shift_up_(min_heap_t* s, unsigned hole_index, struct event* e) -{ - unsigned parent = (hole_index - 1) / 2; - while(hole_index && min_heap_elem_greater(s->p[parent], e)) - { - (s->p[hole_index] = s->p[parent])->min_heap_idx = hole_index; - hole_index = parent; - parent = (hole_index - 1) / 2; - } - (s->p[hole_index] = e)->min_heap_idx = hole_index; -} - -void min_heap_shift_down_(min_heap_t* s, unsigned hole_index, struct event* e) -{ - unsigned min_child = 2 * (hole_index + 1); - while(min_child <= s->n) - { - min_child -= min_child == s->n || min_heap_elem_greater(s->p[min_child], s->p[min_child - 1]); - if(!(min_heap_elem_greater(e, s->p[min_child]))) - break; - (s->p[hole_index] = s->p[min_child])->min_heap_idx = hole_index; - hole_index = min_child; - min_child = 2 * (hole_index + 1); - } - min_heap_shift_up_(s, hole_index, e); -} - -#endif /* _MIN_HEAP_H_ */
diff --git a/third_party/libevent/poll.c b/third_party/libevent/poll.c deleted file mode 100644 index 2aa245b..0000000 --- a/third_party/libevent/poll.c +++ /dev/null
@@ -1,379 +0,0 @@ -/* $OpenBSD: poll.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ - -/* - * Copyright 2000-2003 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#include <sys/queue.h> -#include <poll.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#ifdef CHECK_INVARIANTS -#include <assert.h> -#endif - -#include "event.h" -#include "event-internal.h" -#include "evsignal.h" -#include "log.h" - -struct pollop { - int event_count; /* Highest number alloc */ - int nfds; /* Size of event_* */ - int fd_count; /* Size of idxplus1_by_fd */ - struct pollfd *event_set; - struct event **event_r_back; - struct event **event_w_back; - int *idxplus1_by_fd; /* Index into event_set by fd; we add 1 so - * that 0 (which is easy to memset) can mean - * "no entry." */ -}; - -static void *poll_init (struct event_base *); -static int poll_add (void *, struct event *); -static int poll_del (void *, struct event *); -static int poll_dispatch (struct event_base *, void *, struct timeval *); -static void poll_dealloc (struct event_base *, void *); - -const struct eventop pollops = { - "poll", - poll_init, - poll_add, - poll_del, - poll_dispatch, - poll_dealloc, - 0 -}; - -static void * -poll_init(struct event_base *base) -{ - struct pollop *pollop; - - /* Disable poll when this environment variable is set */ - if (evutil_getenv("EVENT_NOPOLL")) - return (NULL); - - if (!(pollop = calloc(1, sizeof(struct pollop)))) - return (NULL); - - evsignal_init(base); - - return (pollop); -} - -#ifdef CHECK_INVARIANTS -static void -poll_check_ok(struct pollop *pop) -{ - int i, idx; - struct event *ev; - - for (i = 0; i < pop->fd_count; ++i) { - idx = pop->idxplus1_by_fd[i]-1; - if (idx < 0) - continue; - assert(pop->event_set[idx].fd == i); - if (pop->event_set[idx].events & POLLIN) { - ev = pop->event_r_back[idx]; - assert(ev); - assert(ev->ev_events & EV_READ); - assert(ev->ev_fd == i); - } - if (pop->event_set[idx].events & POLLOUT) { - ev = pop->event_w_back[idx]; - assert(ev); - assert(ev->ev_events & EV_WRITE); - assert(ev->ev_fd == i); - } - } - for (i = 0; i < pop->nfds; ++i) { - struct pollfd *pfd = &pop->event_set[i]; - assert(pop->idxplus1_by_fd[pfd->fd] == i+1); - } -} -#else -#define poll_check_ok(pop) -#endif - -static int -poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - int res, i, j, msec = -1, nfds; - struct pollop *pop = arg; - - poll_check_ok(pop); - - if (tv != NULL) - msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; - - nfds = pop->nfds; - res = poll(pop->event_set, nfds, msec); - - if (res == -1) { - if (errno != EINTR) { - event_warn("poll"); - return (-1); - } - - evsignal_process(base); - return (0); - } else if (base->sig.evsignal_caught) { - evsignal_process(base); - } - - event_debug(("%s: poll reports %d", __func__, res)); - - if (res == 0 || nfds == 0) - return (0); - - i = random() % nfds; - for (j = 0; j < nfds; j++) { - struct event *r_ev = NULL, *w_ev = NULL; - int what; - if (++i == nfds) - i = 0; - what = pop->event_set[i].revents; - - if (!what) - continue; - - res = 0; - - /* If the file gets closed notify */ - if (what & (POLLHUP|POLLERR)) - what |= POLLIN|POLLOUT; - if (what & POLLIN) { - res |= EV_READ; - r_ev = pop->event_r_back[i]; - } - if (what & POLLOUT) { - res |= EV_WRITE; - w_ev = pop->event_w_back[i]; - } - if (res == 0) - continue; - - if (r_ev && (res & r_ev->ev_events)) { - event_active(r_ev, res & r_ev->ev_events, 1); - } - if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { - event_active(w_ev, res & w_ev->ev_events, 1); - } - } - - return (0); -} - -static int -poll_add(void *arg, struct event *ev) -{ - struct pollop *pop = arg; - struct pollfd *pfd = NULL; - int i; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_add(ev)); - if (!(ev->ev_events & (EV_READ|EV_WRITE))) - return (0); - - poll_check_ok(pop); - if (pop->nfds + 1 >= pop->event_count) { - struct pollfd *tmp_event_set; - struct event **tmp_event_r_back; - struct event **tmp_event_w_back; - int tmp_event_count; - - if (pop->event_count < 32) - tmp_event_count = 32; - else - tmp_event_count = pop->event_count * 2; - - /* We need more file descriptors */ - tmp_event_set = realloc(pop->event_set, - tmp_event_count * sizeof(struct pollfd)); - if (tmp_event_set == NULL) { - event_warn("realloc"); - return (-1); - } - pop->event_set = tmp_event_set; - - tmp_event_r_back = realloc(pop->event_r_back, - tmp_event_count * sizeof(struct event *)); - if (tmp_event_r_back == NULL) { - /* event_set overallocated; that's okay. */ - event_warn("realloc"); - return (-1); - } - pop->event_r_back = tmp_event_r_back; - - tmp_event_w_back = realloc(pop->event_w_back, - tmp_event_count * sizeof(struct event *)); - if (tmp_event_w_back == NULL) { - /* event_set and event_r_back overallocated; that's - * okay. */ - event_warn("realloc"); - return (-1); - } - pop->event_w_back = tmp_event_w_back; - - pop->event_count = tmp_event_count; - } - if (ev->ev_fd >= pop->fd_count) { - int *tmp_idxplus1_by_fd; - int new_count; - if (pop->fd_count < 32) - new_count = 32; - else - new_count = pop->fd_count * 2; - while (new_count <= ev->ev_fd) - new_count *= 2; - tmp_idxplus1_by_fd = - realloc(pop->idxplus1_by_fd, new_count * sizeof(int)); - if (tmp_idxplus1_by_fd == NULL) { - event_warn("realloc"); - return (-1); - } - pop->idxplus1_by_fd = tmp_idxplus1_by_fd; - memset(pop->idxplus1_by_fd + pop->fd_count, - 0, sizeof(int)*(new_count - pop->fd_count)); - pop->fd_count = new_count; - } - - i = pop->idxplus1_by_fd[ev->ev_fd] - 1; - if (i >= 0) { - pfd = &pop->event_set[i]; - } else { - i = pop->nfds++; - pfd = &pop->event_set[i]; - pfd->events = 0; - pfd->fd = ev->ev_fd; - pop->event_w_back[i] = pop->event_r_back[i] = NULL; - pop->idxplus1_by_fd[ev->ev_fd] = i + 1; - } - - pfd->revents = 0; - if (ev->ev_events & EV_WRITE) { - pfd->events |= POLLOUT; - pop->event_w_back[i] = ev; - } - if (ev->ev_events & EV_READ) { - pfd->events |= POLLIN; - pop->event_r_back[i] = ev; - } - poll_check_ok(pop); - - return (0); -} - -/* - * Nothing to be done here. - */ - -static int -poll_del(void *arg, struct event *ev) -{ - struct pollop *pop = arg; - struct pollfd *pfd = NULL; - int i; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_del(ev)); - - if (!(ev->ev_events & (EV_READ|EV_WRITE))) - return (0); - - poll_check_ok(pop); - i = pop->idxplus1_by_fd[ev->ev_fd] - 1; - if (i < 0) - return (-1); - - /* Do we still want to read or write? */ - pfd = &pop->event_set[i]; - if (ev->ev_events & EV_READ) { - pfd->events &= ~POLLIN; - pop->event_r_back[i] = NULL; - } - if (ev->ev_events & EV_WRITE) { - pfd->events &= ~POLLOUT; - pop->event_w_back[i] = NULL; - } - poll_check_ok(pop); - if (pfd->events) - /* Another event cares about that fd. */ - return (0); - - /* Okay, so we aren't interested in that fd anymore. */ - pop->idxplus1_by_fd[ev->ev_fd] = 0; - - --pop->nfds; - if (i != pop->nfds) { - /* - * Shift the last pollfd down into the now-unoccupied - * position. - */ - memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], - sizeof(struct pollfd)); - pop->event_r_back[i] = pop->event_r_back[pop->nfds]; - pop->event_w_back[i] = pop->event_w_back[pop->nfds]; - pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1; - } - - poll_check_ok(pop); - return (0); -} - -static void -poll_dealloc(struct event_base *base, void *arg) -{ - struct pollop *pop = arg; - - evsignal_dealloc(base); - if (pop->event_set) - free(pop->event_set); - if (pop->event_r_back) - free(pop->event_r_back); - if (pop->event_w_back) - free(pop->event_w_back); - if (pop->idxplus1_by_fd) - free(pop->idxplus1_by_fd); - - memset(pop, 0, sizeof(struct pollop)); - free(pop); -}
diff --git a/third_party/libevent/sample/Makefile.am b/third_party/libevent/sample/Makefile.am deleted file mode 100644 index 2f4e26e..0000000 --- a/third_party/libevent/sample/Makefile.am +++ /dev/null
@@ -1,14 +0,0 @@ -AUTOMAKE_OPTIONS = foreign no-dependencies - -LDADD = ../libevent.la -AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat - -noinst_PROGRAMS = event-test time-test signal-test - -event_test_sources = event-test.c -time_test_sources = time-test.c -signal_test_sources = signal-test.c - -verify: - -DISTCLEANFILES = *~
diff --git a/third_party/libevent/sample/event-test.c b/third_party/libevent/sample/event-test.c deleted file mode 100644 index 0a439ce..0000000 --- a/third_party/libevent/sample/event-test.c +++ /dev/null
@@ -1,139 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifndef WIN32 -#include <sys/queue.h> -#include <unistd.h> -#include <sys/time.h> -#else -#include <windows.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <event.h> - -static void -fifo_read(int fd, short event, void *arg) -{ - char buf[255]; - int len; - struct event *ev = arg; -#ifdef WIN32 - DWORD dwBytesRead; -#endif - - /* Reschedule this event */ - event_add(ev, NULL); - - fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", - fd, event, arg); -#ifdef WIN32 - len = ReadFile((HANDLE)fd, buf, sizeof(buf) - 1, &dwBytesRead, NULL); - - // Check for end of file. - if(len && dwBytesRead == 0) { - fprintf(stderr, "End Of File"); - event_del(ev); - return; - } - - buf[dwBytesRead] = '\0'; -#else - len = read(fd, buf, sizeof(buf) - 1); - - if (len == -1) { - perror("read"); - return; - } else if (len == 0) { - fprintf(stderr, "Connection closed\n"); - return; - } - - buf[len] = '\0'; -#endif - fprintf(stdout, "Read: %s\n", buf); -} - -int -main (int argc, char **argv) -{ - struct event evfifo; -#ifdef WIN32 - HANDLE socket; - // Open a file. - socket = CreateFileA("test.txt", // open File - GENERIC_READ, // open for reading - 0, // do not share - NULL, // no security - OPEN_EXISTING, // existing file only - FILE_ATTRIBUTE_NORMAL, // normal file - NULL); // no attr. template - - if(socket == INVALID_HANDLE_VALUE) - return 1; - -#else - struct stat st; - const char *fifo = "event.fifo"; - int socket; - - if (lstat (fifo, &st) == 0) { - if ((st.st_mode & S_IFMT) == S_IFREG) { - errno = EEXIST; - perror("lstat"); - exit (1); - } - } - - unlink (fifo); - if (mkfifo (fifo, 0600) == -1) { - perror("mkfifo"); - exit (1); - } - - /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */ -#ifdef __linux - socket = open (fifo, O_RDWR | O_NONBLOCK, 0); -#else - socket = open (fifo, O_RDONLY | O_NONBLOCK, 0); -#endif - - if (socket == -1) { - perror("open"); - exit (1); - } - - fprintf(stderr, "Write data to %s\n", fifo); -#endif - /* Initalize the event library */ - event_init(); - - /* Initalize one event */ -#ifdef WIN32 - event_set(&evfifo, (int)socket, EV_READ, fifo_read, &evfifo); -#else - event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo); -#endif - - /* Add it to the active events, without a timeout */ - event_add(&evfifo, NULL); - - event_dispatch(); -#ifdef WIN32 - CloseHandle(socket); -#endif - return (0); -} -
diff --git a/third_party/libevent/sample/signal-test.c b/third_party/libevent/sample/signal-test.c deleted file mode 100644 index 5a5a303..0000000 --- a/third_party/libevent/sample/signal-test.c +++ /dev/null
@@ -1,65 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o signal-test \ - * signal-test.c -L/usr/local/lib -levent - */ - -#include <sys/types.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/stat.h> -#ifndef WIN32 -#include <sys/queue.h> -#include <unistd.h> -#include <sys/time.h> -#else -#include <windows.h> -#endif -#include <signal.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <event.h> - -int called = 0; - -static void -signal_cb(int fd, short event, void *arg) -{ - struct event *signal = arg; - - printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal)); - - if (called >= 2) - event_del(signal); - - called++; -} - -int -main (int argc, char **argv) -{ - struct event signal_int; - - /* Initalize the event library */ - struct event_base* base = event_base_new(); - - /* Initalize one event */ - event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signal_cb, - &signal_int); - event_base_set(base, &signal_int); - - event_add(&signal_int, NULL); - - event_base_dispatch(base); - event_base_free(base); - - return (0); -} -
diff --git a/third_party/libevent/sample/time-test.c b/third_party/libevent/sample/time-test.c deleted file mode 100644 index 069d4f8f..0000000 --- a/third_party/libevent/sample/time-test.c +++ /dev/null
@@ -1,70 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent - */ - -#include <sys/types.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/stat.h> -#ifndef WIN32 -#include <sys/queue.h> -#include <unistd.h> -#endif -#include <time.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <event.h> -#include <evutil.h> - -int lasttime; - -static void -timeout_cb(int fd, short event, void *arg) -{ - struct timeval tv; - struct event *timeout = arg; - int newtime = time(NULL); - - printf("%s: called at %d: %d\n", __func__, newtime, - newtime - lasttime); - lasttime = newtime; - - evutil_timerclear(&tv); - tv.tv_sec = 2; - event_add(timeout, &tv); -} - -int -main (int argc, char **argv) -{ - struct event timeout; - struct timeval tv; - - /* Initalize the event library */ - event_init(); - - /* Initalize one event */ - evtimer_set(&timeout, timeout_cb, &timeout); - - evutil_timerclear(&tv); - tv.tv_sec = 2; - event_add(&timeout, &tv); - - lasttime = time(NULL); - - event_dispatch(); - - return (0); -} -
diff --git a/third_party/libevent/select.c b/third_party/libevent/select.c deleted file mode 100644 index 3f733313..0000000 --- a/third_party/libevent/select.c +++ /dev/null
@@ -1,364 +0,0 @@ -/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ - -/* - * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#else -#include <sys/_libevent_time.h> -#endif -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif -#include <sys/queue.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#ifdef CHECK_INVARIANTS -#include <assert.h> -#endif - -#include "event.h" -#include "evutil.h" -#include "event-internal.h" -#include "evsignal.h" -#include "log.h" - -#ifndef howmany -#define howmany(x, y) (((x)+((y)-1))/(y)) -#endif - -#ifndef _EVENT_HAVE_FD_MASK -/* This type is mandatory, but Android doesn't define it. */ -#undef NFDBITS -#define NFDBITS (sizeof(long)*8) -typedef unsigned long fd_mask; -#endif - -struct selectop { - int event_fds; /* Highest fd in fd set */ - int event_fdsz; - fd_set *event_readset_in; - fd_set *event_writeset_in; - fd_set *event_readset_out; - fd_set *event_writeset_out; - struct event **event_r_by_fd; - struct event **event_w_by_fd; -}; - -static void *select_init (struct event_base *); -static int select_add (void *, struct event *); -static int select_del (void *, struct event *); -static int select_dispatch (struct event_base *, void *, struct timeval *); -static void select_dealloc (struct event_base *, void *); - -const struct eventop selectops = { - "select", - select_init, - select_add, - select_del, - select_dispatch, - select_dealloc, - 0 -}; - -static int select_resize(struct selectop *sop, int fdsz); - -static void * -select_init(struct event_base *base) -{ - struct selectop *sop; - - /* Disable select when this environment variable is set */ - if (evutil_getenv("EVENT_NOSELECT")) - return (NULL); - - if (!(sop = calloc(1, sizeof(struct selectop)))) - return (NULL); - - select_resize(sop, howmany(32 + 1, NFDBITS)*sizeof(fd_mask)); - - evsignal_init(base); - - return (sop); -} - -#ifdef CHECK_INVARIANTS -static void -check_selectop(struct selectop *sop) -{ - int i; - for (i = 0; i <= sop->event_fds; ++i) { - if (FD_ISSET(i, sop->event_readset_in)) { - assert(sop->event_r_by_fd[i]); - assert(sop->event_r_by_fd[i]->ev_events & EV_READ); - assert(sop->event_r_by_fd[i]->ev_fd == i); - } else { - assert(! sop->event_r_by_fd[i]); - } - if (FD_ISSET(i, sop->event_writeset_in)) { - assert(sop->event_w_by_fd[i]); - assert(sop->event_w_by_fd[i]->ev_events & EV_WRITE); - assert(sop->event_w_by_fd[i]->ev_fd == i); - } else { - assert(! sop->event_w_by_fd[i]); - } - } - -} -#else -#define check_selectop(sop) do { (void) sop; } while (0) -#endif - -static int -select_dispatch(struct event_base *base, void *arg, struct timeval *tv) -{ - int res, i, j; - struct selectop *sop = arg; - - check_selectop(sop); - - memcpy(sop->event_readset_out, sop->event_readset_in, - sop->event_fdsz); - memcpy(sop->event_writeset_out, sop->event_writeset_in, - sop->event_fdsz); - - res = select(sop->event_fds + 1, sop->event_readset_out, - sop->event_writeset_out, NULL, tv); - - check_selectop(sop); - - if (res == -1) { - if (errno != EINTR) { - event_warn("select"); - return (-1); - } - - evsignal_process(base); - return (0); - } else if (base->sig.evsignal_caught) { - evsignal_process(base); - } - - event_debug(("%s: select reports %d", __func__, res)); - - check_selectop(sop); - i = random() % (sop->event_fds+1); - for (j = 0; j <= sop->event_fds; ++j) { - struct event *r_ev = NULL, *w_ev = NULL; - if (++i >= sop->event_fds+1) - i = 0; - - res = 0; - if (FD_ISSET(i, sop->event_readset_out)) { - r_ev = sop->event_r_by_fd[i]; - res |= EV_READ; - } - if (FD_ISSET(i, sop->event_writeset_out)) { - w_ev = sop->event_w_by_fd[i]; - res |= EV_WRITE; - } - if (r_ev && (res & r_ev->ev_events)) { - event_active(r_ev, res & r_ev->ev_events, 1); - } - if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { - event_active(w_ev, res & w_ev->ev_events, 1); - } - } - check_selectop(sop); - - return (0); -} - - -static int -select_resize(struct selectop *sop, int fdsz) -{ - int n_events, n_events_old; - - fd_set *readset_in = NULL; - fd_set *writeset_in = NULL; - fd_set *readset_out = NULL; - fd_set *writeset_out = NULL; - struct event **r_by_fd = NULL; - struct event **w_by_fd = NULL; - - n_events = (fdsz/sizeof(fd_mask)) * NFDBITS; - n_events_old = (sop->event_fdsz/sizeof(fd_mask)) * NFDBITS; - - if (sop->event_readset_in) - check_selectop(sop); - - if ((readset_in = realloc(sop->event_readset_in, fdsz)) == NULL) - goto error; - sop->event_readset_in = readset_in; - if ((readset_out = realloc(sop->event_readset_out, fdsz)) == NULL) - goto error; - sop->event_readset_out = readset_out; - if ((writeset_in = realloc(sop->event_writeset_in, fdsz)) == NULL) - goto error; - sop->event_writeset_in = writeset_in; - if ((writeset_out = realloc(sop->event_writeset_out, fdsz)) == NULL) - goto error; - sop->event_writeset_out = writeset_out; - if ((r_by_fd = realloc(sop->event_r_by_fd, - n_events*sizeof(struct event*))) == NULL) - goto error; - sop->event_r_by_fd = r_by_fd; - if ((w_by_fd = realloc(sop->event_w_by_fd, - n_events * sizeof(struct event*))) == NULL) - goto error; - sop->event_w_by_fd = w_by_fd; - - memset((char *)sop->event_readset_in + sop->event_fdsz, 0, - fdsz - sop->event_fdsz); - memset((char *)sop->event_writeset_in + sop->event_fdsz, 0, - fdsz - sop->event_fdsz); - memset(sop->event_r_by_fd + n_events_old, 0, - (n_events-n_events_old) * sizeof(struct event*)); - memset(sop->event_w_by_fd + n_events_old, 0, - (n_events-n_events_old) * sizeof(struct event*)); - - sop->event_fdsz = fdsz; - check_selectop(sop); - - return (0); - - error: - event_warn("malloc"); - return (-1); -} - - -static int -select_add(void *arg, struct event *ev) -{ - struct selectop *sop = arg; - - if (ev->ev_events & EV_SIGNAL) - return (evsignal_add(ev)); - - check_selectop(sop); - /* - * Keep track of the highest fd, so that we can calculate the size - * of the fd_sets for select(2) - */ - if (sop->event_fds < ev->ev_fd) { - int fdsz = sop->event_fdsz; - - if (fdsz < sizeof(fd_mask)) - fdsz = sizeof(fd_mask); - - while (fdsz < - (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask))) - fdsz *= 2; - - if (fdsz != sop->event_fdsz) { - if (select_resize(sop, fdsz)) { - check_selectop(sop); - return (-1); - } - } - - sop->event_fds = ev->ev_fd; - } - - if (ev->ev_events & EV_READ) { - FD_SET(ev->ev_fd, sop->event_readset_in); - sop->event_r_by_fd[ev->ev_fd] = ev; - } - if (ev->ev_events & EV_WRITE) { - FD_SET(ev->ev_fd, sop->event_writeset_in); - sop->event_w_by_fd[ev->ev_fd] = ev; - } - check_selectop(sop); - - return (0); -} - -/* - * Nothing to be done here. - */ - -static int -select_del(void *arg, struct event *ev) -{ - struct selectop *sop = arg; - - check_selectop(sop); - if (ev->ev_events & EV_SIGNAL) - return (evsignal_del(ev)); - - if (sop->event_fds < ev->ev_fd) { - check_selectop(sop); - return (0); - } - - if (ev->ev_events & EV_READ) { - FD_CLR(ev->ev_fd, sop->event_readset_in); - sop->event_r_by_fd[ev->ev_fd] = NULL; - } - - if (ev->ev_events & EV_WRITE) { - FD_CLR(ev->ev_fd, sop->event_writeset_in); - sop->event_w_by_fd[ev->ev_fd] = NULL; - } - - check_selectop(sop); - return (0); -} - -static void -select_dealloc(struct event_base *base, void *arg) -{ - struct selectop *sop = arg; - - evsignal_dealloc(base); - if (sop->event_readset_in) - free(sop->event_readset_in); - if (sop->event_writeset_in) - free(sop->event_writeset_in); - if (sop->event_readset_out) - free(sop->event_readset_out); - if (sop->event_writeset_out) - free(sop->event_writeset_out); - if (sop->event_r_by_fd) - free(sop->event_r_by_fd); - if (sop->event_w_by_fd) - free(sop->event_w_by_fd); - - memset(sop, 0, sizeof(struct selectop)); - free(sop); -}
diff --git a/third_party/libevent/signal.c b/third_party/libevent/signal.c deleted file mode 100644 index b8d51ab..0000000 --- a/third_party/libevent/signal.c +++ /dev/null
@@ -1,377 +0,0 @@ -/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ - -/* - * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -#endif -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/queue.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <errno.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <assert.h> - -#include "event.h" -#include "event-internal.h" -#include "evsignal.h" -#include "evutil.h" -#include "log.h" - -struct event_base *evsignal_base = NULL; - -static void evsignal_handler(int sig); - -#ifdef WIN32 -#define error_is_eagain(err) \ - ((err) == EAGAIN || (err) == WSAEWOULDBLOCK) -#else -#define error_is_eagain(err) ((err) == EAGAIN) -#endif - -/* Callback for when the signal handler write a byte to our signaling socket */ -static void -evsignal_cb(int fd, short what, void *arg) -{ - static char signals[1]; -#ifdef WIN32 - SSIZE_T n; -#else - ssize_t n; -#endif - - n = recv(fd, signals, sizeof(signals), 0); - if (n == -1) { - int err = EVUTIL_SOCKET_ERROR(); - if (! error_is_eagain(err)) - event_err(1, "%s: read", __func__); - } -} - -#ifdef HAVE_SETFD -#define FD_CLOSEONEXEC(x) do { \ - if (fcntl(x, F_SETFD, 1) == -1) \ - event_warn("fcntl(%d, F_SETFD)", x); \ -} while (0) -#else -#define FD_CLOSEONEXEC(x) -#endif - -int -evsignal_init(struct event_base *base) -{ - int i; - - /* - * Our signal handler is going to write to one end of the socket - * pair to wake up our event loop. The event loop then scans for - * signals that got delivered. - */ - if (evutil_socketpair( - AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { -#ifdef WIN32 - /* Make this nonfatal on win32, where sometimes people - have localhost firewalled. */ - event_warn("%s: socketpair", __func__); -#else - event_err(1, "%s: socketpair", __func__); -#endif - return -1; - } - - FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]); - FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]); - base->sig.sh_old = NULL; - base->sig.sh_old_max = 0; - base->sig.evsignal_caught = 0; - memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); - /* initialize the queues for all events */ - for (i = 0; i < NSIG; ++i) - TAILQ_INIT(&base->sig.evsigevents[i]); - - evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); - evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]); - - event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], - EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal); - base->sig.ev_signal.ev_base = base; - base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; - - return 0; -} - -/* Helper: set the signal handler for evsignal to handler in base, so that - * we can restore the original handler when we clear the current one. */ -int -_evsignal_set_handler(struct event_base *base, - int evsignal, void (*handler)(int)) -{ -#ifdef HAVE_SIGACTION - struct sigaction sa; -#else - ev_sighandler_t sh; -#endif - struct evsignal_info *sig = &base->sig; - void *p; - - /* - * resize saved signal handler array up to the highest signal number. - * a dynamic array is used to keep footprint on the low side. - */ - if (evsignal >= sig->sh_old_max) { - int new_max = evsignal + 1; - event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing", - __func__, evsignal, sig->sh_old_max)); - p = realloc(sig->sh_old, new_max * sizeof(*sig->sh_old)); - if (p == NULL) { - event_warn("realloc"); - return (-1); - } - - memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old), - 0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old)); - - sig->sh_old_max = new_max; - sig->sh_old = p; - } - - /* allocate space for previous handler out of dynamic array */ - sig->sh_old[evsignal] = malloc(sizeof *sig->sh_old[evsignal]); - if (sig->sh_old[evsignal] == NULL) { - event_warn("malloc"); - return (-1); - } - - /* save previous handler and setup new handler */ -#ifdef HAVE_SIGACTION - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = handler; - sa.sa_flags |= SA_RESTART; - sigfillset(&sa.sa_mask); - - if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) { - event_warn("sigaction"); - free(sig->sh_old[evsignal]); - sig->sh_old[evsignal] = NULL; - return (-1); - } -#else - if ((sh = signal(evsignal, handler)) == SIG_ERR) { - event_warn("signal"); - free(sig->sh_old[evsignal]); - sig->sh_old[evsignal] = NULL; - return (-1); - } - *sig->sh_old[evsignal] = sh; -#endif - - return (0); -} - -int -evsignal_add(struct event *ev) -{ - int evsignal; - struct event_base *base = ev->ev_base; - struct evsignal_info *sig = &ev->ev_base->sig; - - if (ev->ev_events & (EV_READ|EV_WRITE)) - event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); - evsignal = EVENT_SIGNAL(ev); - assert(evsignal >= 0 && evsignal < NSIG); - if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) { - event_debug(("%s: %p: changing signal handler", __func__, ev)); - if (_evsignal_set_handler( - base, evsignal, evsignal_handler) == -1) - return (-1); - - /* catch signals if they happen quickly */ - evsignal_base = base; - - if (!sig->ev_signal_added) { - if (event_add(&sig->ev_signal, NULL)) - return (-1); - sig->ev_signal_added = 1; - } - } - - /* multiple events may listen to the same signal */ - TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next); - - return (0); -} - -int -_evsignal_restore_handler(struct event_base *base, int evsignal) -{ - int ret = 0; - struct evsignal_info *sig = &base->sig; -#ifdef HAVE_SIGACTION - struct sigaction *sh; -#else - ev_sighandler_t *sh; -#endif - - /* restore previous handler */ - sh = sig->sh_old[evsignal]; - sig->sh_old[evsignal] = NULL; -#ifdef HAVE_SIGACTION - if (sigaction(evsignal, sh, NULL) == -1) { - event_warn("sigaction"); - ret = -1; - } -#else - if (signal(evsignal, *sh) == SIG_ERR) { - event_warn("signal"); - ret = -1; - } -#endif - free(sh); - - return ret; -} - -int -evsignal_del(struct event *ev) -{ - struct event_base *base = ev->ev_base; - struct evsignal_info *sig = &base->sig; - int evsignal = EVENT_SIGNAL(ev); - - assert(evsignal >= 0 && evsignal < NSIG); - - /* multiple events may listen to the same signal */ - TAILQ_REMOVE(&sig->evsigevents[evsignal], ev, ev_signal_next); - - if (!TAILQ_EMPTY(&sig->evsigevents[evsignal])) - return (0); - - event_debug(("%s: %p: restoring signal handler", __func__, ev)); - - return (_evsignal_restore_handler(ev->ev_base, EVENT_SIGNAL(ev))); -} - -static void -evsignal_handler(int sig) -{ - int save_errno = errno; - - if (evsignal_base == NULL) { - event_warn( - "%s: received signal %d, but have no base configured", - __func__, sig); - return; - } - - evsignal_base->sig.evsigcaught[sig]++; - evsignal_base->sig.evsignal_caught = 1; - -#ifndef HAVE_SIGACTION - signal(sig, evsignal_handler); -#endif - - /* Wake up our notification mechanism */ - send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0); - errno = save_errno; -} - -void -evsignal_process(struct event_base *base) -{ - struct evsignal_info *sig = &base->sig; - struct event *ev, *next_ev; - sig_atomic_t ncalls; - int i; - - base->sig.evsignal_caught = 0; - for (i = 1; i < NSIG; ++i) { - ncalls = sig->evsigcaught[i]; - if (ncalls == 0) - continue; - sig->evsigcaught[i] -= ncalls; - - for (ev = TAILQ_FIRST(&sig->evsigevents[i]); - ev != NULL; ev = next_ev) { - next_ev = TAILQ_NEXT(ev, ev_signal_next); - if (!(ev->ev_events & EV_PERSIST)) - event_del(ev); - event_active(ev, EV_SIGNAL, ncalls); - } - - } -} - -void -evsignal_dealloc(struct event_base *base) -{ - int i = 0; - if (base->sig.ev_signal_added) { - event_del(&base->sig.ev_signal); - base->sig.ev_signal_added = 0; - } - for (i = 0; i < NSIG; ++i) { - if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL) - _evsignal_restore_handler(base, i); - } - - if (base->sig.ev_signal_pair[0] != -1) { - EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]); - base->sig.ev_signal_pair[0] = -1; - } - if (base->sig.ev_signal_pair[1] != -1) { - EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]); - base->sig.ev_signal_pair[1] = -1; - } - base->sig.sh_old_max = 0; - - /* per index frees are handled in evsig_del() */ - if (base->sig.sh_old) { - free(base->sig.sh_old); - base->sig.sh_old = NULL; - } -}
diff --git a/third_party/libevent/solaris/config.h b/third_party/libevent/solaris/config.h deleted file mode 100644 index 4dd40eb..0000000 --- a/third_party/libevent/solaris/config.h +++ /dev/null
@@ -1,266 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -#define HAVE_DEVPOLL 1 - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -#define HAVE_EVENT_PORTS 1 - -/* Define to 1 if you have the `fcntl' function. */ -#define HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -#define HAVE_LIBSOCKET 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -#define HAVE_PORT_CREATE 1 - -/* Define to 1 if you have the <port.h> header file. */ -#define HAVE_PORT_H 1 - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -#define HAVE_SYS_DEVPOLL_H 1 - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -/* #undef HAVE_WORKING_KQUEUE */ - -/* Name of package */ -#define PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define VERSION "1.4.13-stable" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef __func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef socklen_t */
diff --git a/third_party/libevent/solaris/event-config.h b/third_party/libevent/solaris/event-config.h deleted file mode 100644 index afabe2f4..0000000 --- a/third_party/libevent/solaris/event-config.h +++ /dev/null
@@ -1,284 +0,0 @@ -/* event-config.h - * Generated by autoconf; post-processed by libevent. - * Do not edit this file. - * Do not rely on macros in this file existing in later versions. - */ -#ifndef _EVENT_CONFIG_H_ -#define _EVENT_CONFIG_H_ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -/* Define if clock_gettime is available in libc */ -#define _EVENT_DNS_USE_CPU_CLOCK_FOR_ID 1 - -/* Define is no secure id variant is available */ -/* #undef _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID */ - -/* Define to 1 if you have the `clock_gettime' function. */ -#define _EVENT_HAVE_CLOCK_GETTIME 1 - -/* Define if /dev/poll is available */ -#define _EVENT_HAVE_DEVPOLL 1 - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define _EVENT_HAVE_DLFCN_H 1 - -/* Define if your system supports the epoll system calls */ -/* #undef _EVENT_HAVE_EPOLL */ - -/* Define to 1 if you have the `epoll_ctl' function. */ -/* #undef _EVENT_HAVE_EPOLL_CTL */ - -/* Define if your system supports event ports */ -#define _EVENT_HAVE_EVENT_PORTS 1 - -/* Define to 1 if you have the `fcntl' function. */ -#define _EVENT_HAVE_FCNTL 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define _EVENT_HAVE_FCNTL_H 1 - -/* Define to 1 if the system has the type `fd_mask'. */ -#define _EVENT_HAVE_FD_MASK 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define _EVENT_HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `getegid' function. */ -#define _EVENT_HAVE_GETEGID 1 - -/* Define to 1 if you have the `geteuid' function. */ -#define _EVENT_HAVE_GETEUID 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define _EVENT_HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `gettimeofday' function. */ -#define _EVENT_HAVE_GETTIMEOFDAY 1 - -/* Define to 1 if you have the `inet_ntop' function. */ -#define _EVENT_HAVE_INET_NTOP 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define _EVENT_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `issetugid' function. */ -#define _EVENT_HAVE_ISSETUGID 1 - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef _EVENT_HAVE_KQUEUE */ - -/* Define to 1 if you have the `nsl' library (-lnsl). */ -#define _EVENT_HAVE_LIBNSL 1 - -/* Define to 1 if you have the `resolv' library (-lresolv). */ -#define _EVENT_HAVE_LIBRESOLV 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -#define _EVENT_HAVE_LIBRT 1 - -/* Define to 1 if you have the `socket' library (-lsocket). */ -#define _EVENT_HAVE_LIBSOCKET 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define _EVENT_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <netinet/in6.h> header file. */ -/* #undef _EVENT_HAVE_NETINET_IN6_H */ - -/* Define to 1 if you have the `poll' function. */ -#define _EVENT_HAVE_POLL 1 - -/* Define to 1 if you have the <poll.h> header file. */ -#define _EVENT_HAVE_POLL_H 1 - -/* Define to 1 if you have the `port_create' function. */ -#define _EVENT_HAVE_PORT_CREATE 1 - -/* Define to 1 if you have the <port.h> header file. */ -#define _EVENT_HAVE_PORT_H 1 - -/* Define to 1 if you have the `select' function. */ -#define _EVENT_HAVE_SELECT 1 - -/* Define if F_SETFD is defined in <fcntl.h> */ -#define _EVENT_HAVE_SETFD 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define _EVENT_HAVE_SIGACTION 1 - -/* Define to 1 if you have the `signal' function. */ -#define _EVENT_HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define _EVENT_HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define _EVENT_HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define _EVENT_HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define _EVENT_HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define _EVENT_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define _EVENT_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define _EVENT_HAVE_STRLCPY 1 - -/* Define to 1 if you have the `strsep' function. */ -#define _EVENT_HAVE_STRSEP 1 - -/* Define to 1 if you have the `strtok_r' function. */ -#define _EVENT_HAVE_STRTOK_R 1 - -/* Define to 1 if you have the `strtoll' function. */ -#define _EVENT_HAVE_STRTOLL 1 - -/* Define to 1 if the system has the type `struct in6_addr'. */ -#define _EVENT_HAVE_STRUCT_IN6_ADDR 1 - -/* Define to 1 if you have the <sys/devpoll.h> header file. */ -#define _EVENT_HAVE_SYS_DEVPOLL_H 1 - -/* Define to 1 if you have the <sys/epoll.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EPOLL_H */ - -/* Define to 1 if you have the <sys/event.h> header file. */ -/* #undef _EVENT_HAVE_SYS_EVENT_H */ - -/* Define to 1 if you have the <sys/ioctl.h> header file. */ -#define _EVENT_HAVE_SYS_IOCTL_H 1 - -/* Define to 1 if you have the <sys/param.h> header file. */ -#define _EVENT_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/queue.h> header file. */ -#define _EVENT_HAVE_SYS_QUEUE_H 1 - -/* Define to 1 if you have the <sys/select.h> header file. */ -#define _EVENT_HAVE_SYS_SELECT_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -#define _EVENT_HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define _EVENT_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/time.h> header file. */ -#define _EVENT_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define _EVENT_HAVE_SYS_TYPES_H 1 - -/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */ -#define _EVENT_HAVE_TAILQFOREACH 1 - -/* Define if timeradd is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERADD 1 - -/* Define if timerclear is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCLEAR 1 - -/* Define if timercmp is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERCMP 1 - -/* Define if timerisset is defined in <sys/time.h> */ -#define _EVENT_HAVE_TIMERISSET 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define _EVENT_HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define _EVENT_HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define _EVENT_HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define _EVENT_HAVE_UINT8_T 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define _EVENT_HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vasprintf' function. */ -#define _EVENT_HAVE_VASPRINTF 1 - -/* Define if kqueue works correctly with pipes */ -/* #undef _EVENT_HAVE_WORKING_KQUEUE */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define _EVENT_LT_OBJDIR ".libs/" - -/* Numeric representation of the version */ -#define _EVENT_NUMERIC_VERSION 0x01040f00 - -/* Name of package */ -#define _EVENT_PACKAGE "libevent" - -/* Define to the address where bug reports for this package should be sent. */ -#define _EVENT_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _EVENT_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define _EVENT_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define _EVENT_PACKAGE_TARNAME "" - -/* Define to the home page for this package. */ -#define _EVENT_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _EVENT_PACKAGE_VERSION "" - -/* The size of `int', as computed by sizeof. */ -#define _EVENT_SIZEOF_INT 4 - -/* The size of `long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG 4 - -/* The size of `long long', as computed by sizeof. */ -#define _EVENT_SIZEOF_LONG_LONG 8 - -/* The size of `short', as computed by sizeof. */ -#define _EVENT_SIZEOF_SHORT 2 - -/* Define to 1 if you have the ANSI C header files. */ -#define _EVENT_STDC_HEADERS 1 - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -#define _EVENT_TIME_WITH_SYS_TIME 1 - -/* Version number of package */ -#define _EVENT_VERSION "1.4.15" - -/* Define to appropriate substitue if compiler doesnt have __func__ */ -/* #undef _EVENT___func__ */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef _EVENT_const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef _EVENT___cplusplus -/* #undef _EVENT_inline */ -#endif - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef _EVENT_pid_t */ - -/* Define to `unsigned int' if <sys/types.h> does not define. */ -/* #undef _EVENT_size_t */ - -/* Define to unsigned int if you dont have it */ -/* #undef _EVENT_socklen_t */ -#endif
diff --git a/third_party/libevent/stamp-h.in b/third_party/libevent/stamp-h.in deleted file mode 100644 index 9788f70..0000000 --- a/third_party/libevent/stamp-h.in +++ /dev/null
@@ -1 +0,0 @@ -timestamp
diff --git a/third_party/libevent/strlcpy-internal.h b/third_party/libevent/strlcpy-internal.h deleted file mode 100644 index 22b5f61d..0000000 --- a/third_party/libevent/strlcpy-internal.h +++ /dev/null
@@ -1,23 +0,0 @@ -#ifndef _STRLCPY_INTERNAL_H_ -#define _STRLCPY_INTERNAL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#ifndef HAVE_STRLCPY -#include <string.h> -size_t _event_strlcpy(char *dst, const char *src, size_t siz); -#define strlcpy _event_strlcpy -#endif - -#ifdef __cplusplus -} -#endif - -#endif -
diff --git a/third_party/libevent/strlcpy.c b/third_party/libevent/strlcpy.c deleted file mode 100644 index 149fee5..0000000 --- a/third_party/libevent/strlcpy.c +++ /dev/null
@@ -1,73 +0,0 @@ -/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#ifndef HAVE_STRLCPY -#include "strlcpy-internal.h" - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -_event_strlcpy(char *dst, const char *src, size_t siz) -{ - register char *d = dst; - register const char *s = src; - register size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} -#endif
diff --git a/third_party/libevent/test/Makefile.am b/third_party/libevent/test/Makefile.am deleted file mode 100644 index 3558d02..0000000 --- a/third_party/libevent/test/Makefile.am +++ /dev/null
@@ -1,35 +0,0 @@ -AUTOMAKE_OPTIONS = foreign no-dependencies - -AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat - -EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c - -noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench - -BUILT_SOURCES = regress.gen.c regress.gen.h -test_init_SOURCES = test-init.c -test_init_LDADD = ../libevent_core.la -test_eof_SOURCES = test-eof.c -test_eof_LDADD = ../libevent_core.la -test_weof_SOURCES = test-weof.c -test_weof_LDADD = ../libevent_core.la -test_time_SOURCES = test-time.c -test_time_LDADD = ../libevent_core.la -regress_SOURCES = regress.c regress.h regress_http.c regress_dns.c \ - regress_rpc.c \ - regress.gen.c regress.gen.h -regress_LDADD = ../libevent.la -bench_SOURCES = bench.c -bench_LDADD = ../libevent.la - -regress.gen.c regress.gen.h: regress.rpc $(top_srcdir)/event_rpcgen.py - $(top_srcdir)/event_rpcgen.py $(srcdir)/regress.rpc || echo "No Python installed" - -DISTCLEANFILES = *~ - -test: test-init test-eof test-weof test-time regress - -verify: test - @$(srcdir)/test.sh - -bench test-init test-eof test-weof test-time: ../libevent.la
diff --git a/third_party/libevent/test/Makefile.nmake b/third_party/libevent/test/Makefile.nmake deleted file mode 100644 index 320abe7..0000000 --- a/third_party/libevent/test/Makefile.nmake +++ /dev/null
@@ -1,47 +0,0 @@ - -CFLAGS=/I.. /I../include /I../WIN32-Code /I../compat /DWIN32 /DHAVE_CONFIG_H - -CFLAGS=$(CFLAGS) /Ox /W3 /wd4996 /nologo - -REGRESS_OBJS=regress.obj regress_http.obj regress_dns.obj \ - regress_rpc.obj regress.gen.obj \ - -OTHER_OBJS=test-init.obj test-eof.obj test-weof.obj test-time.obj \ - bench.obj bench_cascade.obj bench_http.obj bench_httpclient.obj - -PROGRAMS=regress.exe \ - test-init.exe test-eof.exe test-weof.exe test-time.exe - -# Disabled for now: -# bench.exe bench_cascade.exe bench_http.exe bench_httpclient.exe - - -LIBS=..\libevent.lib ws2_32.lib advapi32.lib - -all: $(PROGRAMS) - -regress.exe: $(REGRESS_OBJS) - $(CC) $(CFLAGS) $(LIBS) $(REGRESS_OBJS) - -test-init.exe: test-init.obj - $(CC) $(CFLAGS) $(LIBS) test-init.obj -test-eof.exe: test-eof.obj - $(CC) $(CFLAGS) $(LIBS) test-eof.obj -test-weof.exe: test-weof.obj - $(CC) $(CFLAGS) $(LIBS) test-weof.obj -test-time.exe: test-time.obj - $(CC) $(CFLAGS) $(LIBS) test-time.obj - -bench.exe: bench.obj - $(CC) $(CFLAGS) $(LIBS) bench.obj -bench_cascade.exe: bench_cascade.obj - $(CC) $(CFLAGS) $(LIBS) bench_cascade.obj -bench_http.exe: bench_http.obj - $(CC) $(CFLAGS) $(LIBS) bench_http.obj -bench_httpclient.exe: bench_httpclient.obj - $(CC) $(CFLAGS) $(LIBS) bench_httpclient.obj - -clean: - -del $(REGRESS_OBJS) - -del $(OTHER_OBJS) - -del regress.exe
diff --git a/third_party/libevent/test/bench.c b/third_party/libevent/test/bench.c deleted file mode 100644 index c976932..0000000 --- a/third_party/libevent/test/bench.c +++ /dev/null
@@ -1,188 +0,0 @@ -/* - * Copyright 2003 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Mon 03/10/2003 - Modified by Davide Libenzi <davidel@xmailserver.org> - * - * Added chain event propagation to improve the sensitivity of - * the measure respect to the event loop efficency. - * - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#ifdef WIN32 -#include <windows.h> -#else -#include <sys/socket.h> -#include <signal.h> -#include <sys/resource.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <event.h> -#include <evutil.h> - - -static int count, writes, fired; -static int *pipes; -static int num_pipes, num_active, num_writes; -static struct event *events; - -static void -read_cb(int fd, short which, void *arg) -{ - long idx = (long) arg, widx = idx + 1; - u_char ch; - - count += read(fd, &ch, sizeof(ch)); - if (writes) { - if (widx >= num_pipes) - widx -= num_pipes; - write(pipes[2 * widx + 1], "e", 1); - writes--; - fired++; - } -} - -static struct timeval * -run_once(void) -{ - int *cp, space; - long i; - static struct timeval ts, te; - - for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { - event_del(&events[i]); - event_set(&events[i], cp[0], EV_READ | EV_PERSIST, read_cb, (void *) i); - event_add(&events[i], NULL); - } - - event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); - - fired = 0; - space = num_pipes / num_active; - space = space * 2; - for (i = 0; i < num_active; i++, fired++) - write(pipes[i * space + 1], "e", 1); - - count = 0; - writes = num_writes; - { int xcount = 0; - gettimeofday(&ts, NULL); - do { - event_loop(EVLOOP_ONCE | EVLOOP_NONBLOCK); - xcount++; - } while (count != fired); - gettimeofday(&te, NULL); - - if (xcount != count) fprintf(stderr, "Xcount: %d, Rcount: %d\n", xcount, count); - } - - evutil_timersub(&te, &ts, &te); - - return (&te); -} - -int -main (int argc, char **argv) -{ -#ifndef WIN32 - struct rlimit rl; -#endif - int i, c; - struct timeval *tv; - int *cp; - - num_pipes = 100; - num_active = 1; - num_writes = num_pipes; - while ((c = getopt(argc, argv, "n:a:w:")) != -1) { - switch (c) { - case 'n': - num_pipes = atoi(optarg); - break; - case 'a': - num_active = atoi(optarg); - break; - case 'w': - num_writes = atoi(optarg); - break; - default: - fprintf(stderr, "Illegal argument \"%c\"\n", c); - exit(1); - } - } - -#ifndef WIN32 - rl.rlim_cur = rl.rlim_max = num_pipes * 2 + 50; - if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { - perror("setrlimit"); - exit(1); - } -#endif - - events = calloc(num_pipes, sizeof(struct event)); - pipes = calloc(num_pipes * 2, sizeof(int)); - if (events == NULL || pipes == NULL) { - perror("malloc"); - exit(1); - } - - event_init(); - - for (cp = pipes, i = 0; i < num_pipes; i++, cp += 2) { -#ifdef USE_PIPES - if (pipe(cp) == -1) { -#else - if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, cp) == -1) { -#endif - perror("pipe"); - exit(1); - } - } - - for (i = 0; i < 25; i++) { - tv = run_once(); - if (tv == NULL) - exit(1); - fprintf(stdout, "%ld\n", - tv->tv_sec * 1000000L + tv->tv_usec); - } - - exit(0); -}
diff --git a/third_party/libevent/test/regress.c b/third_party/libevent/test/regress.c deleted file mode 100644 index cce7d7d..0000000 --- a/third_party/libevent/test/regress.c +++ /dev/null
@@ -1,1903 +0,0 @@ -/* - * Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef WIN32 -#include <winsock2.h> -#include <windows.h> -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/queue.h> -#ifndef WIN32 -#include <sys/socket.h> -#include <sys/wait.h> -#include <signal.h> -#include <unistd.h> -#include <netdb.h> -#endif -#include <assert.h> -#include <fcntl.h> -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "event.h" -#include "evutil.h" -#include "event-internal.h" -#include "log.h" - -#include "regress.h" -#ifndef WIN32 -#include "regress.gen.h" -#endif - -int pair[2]; -int test_ok; -static int called; -static char wbuf[4096]; -static char rbuf[4096]; -static int woff; -static int roff; -static int usepersist; -static struct timeval tset; -static struct timeval tcalled; -static struct event_base *global_base; - -#define TEST1 "this is a test" -#define SECONDS 1 - -#ifndef SHUT_WR -#define SHUT_WR 1 -#endif - -#ifdef WIN32 -#define write(fd,buf,len) send((fd),(buf),(len),0) -#define read(fd,buf,len) recv((fd),(buf),(len),0) -#endif - -static void -simple_read_cb(int fd, short event, void *arg) -{ - char buf[256]; - int len; - - if (arg == NULL) - return; - - len = read(fd, buf, sizeof(buf)); - - if (len) { - if (!called) { - if (event_add(arg, NULL) == -1) - exit(1); - } - } else if (called == 1) - test_ok = 1; - - called++; -} - -static void -simple_write_cb(int fd, short event, void *arg) -{ - int len; - - if (arg == NULL) - return; - - len = write(fd, TEST1, strlen(TEST1) + 1); - if (len == -1) - test_ok = 0; - else - test_ok = 1; -} - -static void -multiple_write_cb(int fd, short event, void *arg) -{ - struct event *ev = arg; - int len; - - len = 128; - if (woff + len >= sizeof(wbuf)) - len = sizeof(wbuf) - woff; - - len = write(fd, wbuf + woff, len); - if (len == -1) { - fprintf(stderr, "%s: write\n", __func__); - if (usepersist) - event_del(ev); - return; - } - - woff += len; - - if (woff >= sizeof(wbuf)) { - shutdown(fd, SHUT_WR); - if (usepersist) - event_del(ev); - return; - } - - if (!usepersist) { - if (event_add(ev, NULL) == -1) - exit(1); - } -} - -static void -multiple_read_cb(int fd, short event, void *arg) -{ - struct event *ev = arg; - int len; - - len = read(fd, rbuf + roff, sizeof(rbuf) - roff); - if (len == -1) - fprintf(stderr, "%s: read\n", __func__); - if (len <= 0) { - if (usepersist) - event_del(ev); - return; - } - - roff += len; - if (!usepersist) { - if (event_add(ev, NULL) == -1) - exit(1); - } -} - -static void -timeout_cb(int fd, short event, void *arg) -{ - struct timeval tv; - int diff; - - evutil_gettimeofday(&tcalled, NULL); - if (evutil_timercmp(&tcalled, &tset, >)) - evutil_timersub(&tcalled, &tset, &tv); - else - evutil_timersub(&tset, &tcalled, &tv); - - diff = tv.tv_sec*1000 + tv.tv_usec/1000 - SECONDS * 1000; - if (diff < 0) - diff = -diff; - - if (diff < 100) - test_ok = 1; -} - -#ifndef WIN32 -static void -signal_cb_sa(int sig) -{ - test_ok = 2; -} - -static void -signal_cb(int fd, short event, void *arg) -{ - struct event *ev = arg; - - signal_del(ev); - test_ok = 1; -} -#endif - -struct both { - struct event ev; - int nread; -}; - -static void -combined_read_cb(int fd, short event, void *arg) -{ - struct both *both = arg; - char buf[128]; - int len; - - len = read(fd, buf, sizeof(buf)); - if (len == -1) - fprintf(stderr, "%s: read\n", __func__); - if (len <= 0) - return; - - both->nread += len; - if (event_add(&both->ev, NULL) == -1) - exit(1); -} - -static void -combined_write_cb(int fd, short event, void *arg) -{ - struct both *both = arg; - char buf[128]; - int len; - - len = sizeof(buf); - if (len > both->nread) - len = both->nread; - - len = write(fd, buf, len); - if (len == -1) - fprintf(stderr, "%s: write\n", __func__); - if (len <= 0) { - shutdown(fd, SHUT_WR); - return; - } - - both->nread -= len; - if (event_add(&both->ev, NULL) == -1) - exit(1); -} - -/* Test infrastructure */ - -static int -setup_test(const char *name) -{ - - fprintf(stdout, "%s", name); - - if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { - fprintf(stderr, "%s: socketpair\n", __func__); - exit(1); - } - -#ifdef HAVE_FCNTL - if (fcntl(pair[0], F_SETFL, O_NONBLOCK) == -1) - fprintf(stderr, "fcntl(O_NONBLOCK)"); - - if (fcntl(pair[1], F_SETFL, O_NONBLOCK) == -1) - fprintf(stderr, "fcntl(O_NONBLOCK)"); -#endif - - test_ok = 0; - called = 0; - return (0); -} - -static int -cleanup_test(void) -{ -#ifndef WIN32 - close(pair[0]); - close(pair[1]); -#else - CloseHandle((HANDLE)pair[0]); - CloseHandle((HANDLE)pair[1]); -#endif - if (test_ok) - fprintf(stdout, "OK\n"); - else { - fprintf(stdout, "FAILED\n"); - exit(1); - } - test_ok = 0; - return (0); -} - -static void -test_registerfds(void) -{ - int i, j; - int pair[2]; - struct event read_evs[512]; - struct event write_evs[512]; - - struct event_base *base = event_base_new(); - - fprintf(stdout, "Testing register fds: "); - - for (i = 0; i < 512; ++i) { - if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { - /* run up to the limit of file descriptors */ - break; - } - event_set(&read_evs[i], pair[0], - EV_READ|EV_PERSIST, simple_read_cb, NULL); - event_base_set(base, &read_evs[i]); - event_add(&read_evs[i], NULL); - event_set(&write_evs[i], pair[1], - EV_WRITE|EV_PERSIST, simple_write_cb, NULL); - event_base_set(base, &write_evs[i]); - event_add(&write_evs[i], NULL); - - /* just loop once */ - event_base_loop(base, EVLOOP_ONCE); - } - - /* now delete everything */ - for (j = 0; j < i; ++j) { - event_del(&read_evs[j]); - event_del(&write_evs[j]); -#ifndef WIN32 - close(read_evs[j].ev_fd); - close(write_evs[j].ev_fd); -#else - CloseHandle((HANDLE)read_evs[j].ev_fd); - CloseHandle((HANDLE)write_evs[j].ev_fd); -#endif - - /* just loop once */ - event_base_loop(base, EVLOOP_ONCE); - } - - event_base_free(base); - - fprintf(stdout, "OK\n"); -} - -static void -test_simpleread(void) -{ - struct event ev; - - /* Very simple read test */ - setup_test("Simple read: "); - - write(pair[0], TEST1, strlen(TEST1)+1); - shutdown(pair[0], SHUT_WR); - - event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); - if (event_add(&ev, NULL) == -1) - exit(1); - event_dispatch(); - - cleanup_test(); -} - -static void -test_simplewrite(void) -{ - struct event ev; - - /* Very simple write test */ - setup_test("Simple write: "); - - event_set(&ev, pair[0], EV_WRITE, simple_write_cb, &ev); - if (event_add(&ev, NULL) == -1) - exit(1); - event_dispatch(); - - cleanup_test(); -} - -static void -test_multiple(void) -{ - struct event ev, ev2; - int i; - - /* Multiple read and write test */ - setup_test("Multiple read/write: "); - memset(rbuf, 0, sizeof(rbuf)); - for (i = 0; i < sizeof(wbuf); i++) - wbuf[i] = i; - - roff = woff = 0; - usepersist = 0; - - event_set(&ev, pair[0], EV_WRITE, multiple_write_cb, &ev); - if (event_add(&ev, NULL) == -1) - exit(1); - event_set(&ev2, pair[1], EV_READ, multiple_read_cb, &ev2); - if (event_add(&ev2, NULL) == -1) - exit(1); - event_dispatch(); - - if (roff == woff) - test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; - - cleanup_test(); -} - -static void -test_persistent(void) -{ - struct event ev, ev2; - int i; - - /* Multiple read and write test with persist */ - setup_test("Persist read/write: "); - memset(rbuf, 0, sizeof(rbuf)); - for (i = 0; i < sizeof(wbuf); i++) - wbuf[i] = i; - - roff = woff = 0; - usepersist = 1; - - event_set(&ev, pair[0], EV_WRITE|EV_PERSIST, multiple_write_cb, &ev); - if (event_add(&ev, NULL) == -1) - exit(1); - event_set(&ev2, pair[1], EV_READ|EV_PERSIST, multiple_read_cb, &ev2); - if (event_add(&ev2, NULL) == -1) - exit(1); - event_dispatch(); - - if (roff == woff) - test_ok = memcmp(rbuf, wbuf, sizeof(wbuf)) == 0; - - cleanup_test(); -} - -static void -test_combined(void) -{ - struct both r1, r2, w1, w2; - - setup_test("Combined read/write: "); - memset(&r1, 0, sizeof(r1)); - memset(&r2, 0, sizeof(r2)); - memset(&w1, 0, sizeof(w1)); - memset(&w2, 0, sizeof(w2)); - - w1.nread = 4096; - w2.nread = 8192; - - event_set(&r1.ev, pair[0], EV_READ, combined_read_cb, &r1); - event_set(&w1.ev, pair[0], EV_WRITE, combined_write_cb, &w1); - event_set(&r2.ev, pair[1], EV_READ, combined_read_cb, &r2); - event_set(&w2.ev, pair[1], EV_WRITE, combined_write_cb, &w2); - if (event_add(&r1.ev, NULL) == -1) - exit(1); - if (event_add(&w1.ev, NULL)) - exit(1); - if (event_add(&r2.ev, NULL)) - exit(1); - if (event_add(&w2.ev, NULL)) - exit(1); - - event_dispatch(); - - if (r1.nread == 8192 && r2.nread == 4096) - test_ok = 1; - - cleanup_test(); -} - -static void -test_simpletimeout(void) -{ - struct timeval tv; - struct event ev; - - setup_test("Simple timeout: "); - - tv.tv_usec = 0; - tv.tv_sec = SECONDS; - evtimer_set(&ev, timeout_cb, NULL); - evtimer_add(&ev, &tv); - - evutil_gettimeofday(&tset, NULL); - event_dispatch(); - - cleanup_test(); -} - -#ifndef WIN32 -extern struct event_base *current_base; - -static void -child_signal_cb(int fd, short event, void *arg) -{ - struct timeval tv; - int *pint = arg; - - *pint = 1; - - tv.tv_usec = 500000; - tv.tv_sec = 0; - event_loopexit(&tv); -} - -static void -test_fork(void) -{ - int status, got_sigchld = 0; - struct event ev, sig_ev; - pid_t pid; - - setup_test("After fork: "); - - write(pair[0], TEST1, strlen(TEST1)+1); - - event_set(&ev, pair[1], EV_READ, simple_read_cb, &ev); - if (event_add(&ev, NULL) == -1) - exit(1); - - signal_set(&sig_ev, SIGCHLD, child_signal_cb, &got_sigchld); - signal_add(&sig_ev, NULL); - - if ((pid = fork()) == 0) { - /* in the child */ - if (event_reinit(current_base) == -1) { - fprintf(stderr, "FAILED (reinit)\n"); - exit(1); - } - - signal_del(&sig_ev); - - called = 0; - - event_dispatch(); - - /* we do not send an EOF; simple_read_cb requires an EOF - * to set test_ok. we just verify that the callback was - * called. */ - exit(test_ok != 0 || called != 2 ? -2 : 76); - } - - /* wait for the child to read the data */ - sleep(1); - - write(pair[0], TEST1, strlen(TEST1)+1); - - if (waitpid(pid, &status, 0) == -1) { - fprintf(stderr, "FAILED (fork)\n"); - exit(1); - } - - if (WEXITSTATUS(status) != 76) { - fprintf(stderr, "FAILED (exit): %d\n", WEXITSTATUS(status)); - exit(1); - } - - /* test that the current event loop still works */ - write(pair[0], TEST1, strlen(TEST1)+1); - shutdown(pair[0], SHUT_WR); - - event_dispatch(); - - if (!got_sigchld) { - fprintf(stdout, "FAILED (sigchld)\n"); - exit(1); - } - - signal_del(&sig_ev); - - cleanup_test(); -} - -static void -test_simplesignal(void) -{ - struct event ev; - struct itimerval itv; - - setup_test("Simple signal: "); - signal_set(&ev, SIGALRM, signal_cb, &ev); - signal_add(&ev, NULL); - /* find bugs in which operations are re-ordered */ - signal_del(&ev); - signal_add(&ev, NULL); - - memset(&itv, 0, sizeof(itv)); - itv.it_value.tv_sec = 1; - if (setitimer(ITIMER_REAL, &itv, NULL) == -1) - goto skip_simplesignal; - - event_dispatch(); - skip_simplesignal: - if (signal_del(&ev) == -1) - test_ok = 0; - - cleanup_test(); -} - -static void -test_multiplesignal(void) -{ - struct event ev_one, ev_two; - struct itimerval itv; - - setup_test("Multiple signal: "); - - signal_set(&ev_one, SIGALRM, signal_cb, &ev_one); - signal_add(&ev_one, NULL); - - signal_set(&ev_two, SIGALRM, signal_cb, &ev_two); - signal_add(&ev_two, NULL); - - memset(&itv, 0, sizeof(itv)); - itv.it_value.tv_sec = 1; - if (setitimer(ITIMER_REAL, &itv, NULL) == -1) - goto skip_simplesignal; - - event_dispatch(); - - skip_simplesignal: - if (signal_del(&ev_one) == -1) - test_ok = 0; - if (signal_del(&ev_two) == -1) - test_ok = 0; - - cleanup_test(); -} - -static void -test_immediatesignal(void) -{ - struct event ev; - - test_ok = 0; - printf("Immediate signal: "); - signal_set(&ev, SIGUSR1, signal_cb, &ev); - signal_add(&ev, NULL); - raise(SIGUSR1); - event_loop(EVLOOP_NONBLOCK); - signal_del(&ev); - cleanup_test(); -} - -static void -test_signal_dealloc(void) -{ - /* make sure that signal_event is event_del'ed and pipe closed */ - struct event ev; - struct event_base *base = event_init(); - printf("Signal dealloc: "); - signal_set(&ev, SIGUSR1, signal_cb, &ev); - signal_add(&ev, NULL); - signal_del(&ev); - event_base_free(base); - /* If we got here without asserting, we're fine. */ - test_ok = 1; - cleanup_test(); -} - -static void -test_signal_pipeloss(void) -{ - /* make sure that the base1 pipe is closed correctly. */ - struct event_base *base1, *base2; - int pipe1; - test_ok = 0; - printf("Signal pipeloss: "); - base1 = event_init(); - pipe1 = base1->sig.ev_signal_pair[0]; - base2 = event_init(); - event_base_free(base2); - event_base_free(base1); - if (close(pipe1) != -1 || errno!=EBADF) { - /* fd must be closed, so second close gives -1, EBADF */ - printf("signal pipe not closed. "); - test_ok = 0; - } else { - test_ok = 1; - } - cleanup_test(); -} - -/* - * make two bases to catch signals, use both of them. this only works - * for event mechanisms that use our signal pipe trick. kqueue handles - * signals internally, and all interested kqueues get all the signals. - */ -static void -test_signal_switchbase(void) -{ - struct event ev1, ev2; - struct event_base *base1, *base2; - int is_kqueue; - test_ok = 0; - printf("Signal switchbase: "); - base1 = event_init(); - base2 = event_init(); - is_kqueue = !strcmp(event_get_method(),"kqueue"); - signal_set(&ev1, SIGUSR1, signal_cb, &ev1); - signal_set(&ev2, SIGUSR1, signal_cb, &ev2); - if (event_base_set(base1, &ev1) || - event_base_set(base2, &ev2) || - event_add(&ev1, NULL) || - event_add(&ev2, NULL)) { - fprintf(stderr, "%s: cannot set base, add\n", __func__); - exit(1); - } - - test_ok = 0; - /* can handle signal before loop is called */ - raise(SIGUSR1); - event_base_loop(base2, EVLOOP_NONBLOCK); - if (is_kqueue) { - if (!test_ok) - goto done; - test_ok = 0; - } - event_base_loop(base1, EVLOOP_NONBLOCK); - if (test_ok && !is_kqueue) { - test_ok = 0; - - /* set base1 to handle signals */ - event_base_loop(base1, EVLOOP_NONBLOCK); - raise(SIGUSR1); - event_base_loop(base1, EVLOOP_NONBLOCK); - event_base_loop(base2, EVLOOP_NONBLOCK); - } - done: - event_base_free(base1); - event_base_free(base2); - cleanup_test(); -} - -/* - * assert that a signal event removed from the event queue really is - * removed - with no possibility of it's parent handler being fired. - */ -static void -test_signal_assert(void) -{ - struct event ev; - struct event_base *base = event_init(); - test_ok = 0; - printf("Signal handler assert: "); - /* use SIGCONT so we don't kill ourselves when we signal to nowhere */ - signal_set(&ev, SIGCONT, signal_cb, &ev); - signal_add(&ev, NULL); - /* - * if signal_del() fails to reset the handler, it's current handler - * will still point to evsignal_handler(). - */ - signal_del(&ev); - - raise(SIGCONT); - /* only way to verify we were in evsignal_handler() */ - if (base->sig.evsignal_caught) - test_ok = 0; - else - test_ok = 1; - - event_base_free(base); - cleanup_test(); - return; -} - -/* - * assert that we restore our previous signal handler properly. - */ -static void -test_signal_restore(void) -{ - struct event ev; - struct event_base *base = event_init(); -#ifdef HAVE_SIGACTION - struct sigaction sa; -#endif - - test_ok = 0; - printf("Signal handler restore: "); -#ifdef HAVE_SIGACTION - sa.sa_handler = signal_cb_sa; - sa.sa_flags = 0x0; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGUSR1, &sa, NULL) == -1) - goto out; -#else - if (signal(SIGUSR1, signal_cb_sa) == SIG_ERR) - goto out; -#endif - signal_set(&ev, SIGUSR1, signal_cb, &ev); - signal_add(&ev, NULL); - signal_del(&ev); - - raise(SIGUSR1); - /* 1 == signal_cb, 2 == signal_cb_sa, we want our previous handler */ - if (test_ok != 2) - test_ok = 0; -out: - event_base_free(base); - cleanup_test(); - return; -} - -static void -signal_cb_swp(int sig, short event, void *arg) -{ - called++; - if (called < 5) - raise(sig); - else - event_loopexit(NULL); -} -static void -timeout_cb_swp(int fd, short event, void *arg) -{ - if (called == -1) { - struct timeval tv = {5, 0}; - - called = 0; - evtimer_add((struct event *)arg, &tv); - raise(SIGUSR1); - return; - } - test_ok = 0; - event_loopexit(NULL); -} - -static void -test_signal_while_processing(void) -{ - struct event_base *base = event_init(); - struct event ev, ev_timer; - struct timeval tv = {0, 0}; - - setup_test("Receiving a signal while processing other signal: "); - - called = -1; - test_ok = 1; - signal_set(&ev, SIGUSR1, signal_cb_swp, NULL); - signal_add(&ev, NULL); - evtimer_set(&ev_timer, timeout_cb_swp, &ev_timer); - evtimer_add(&ev_timer, &tv); - event_dispatch(); - - event_base_free(base); - cleanup_test(); - return; -} -#endif - -static void -test_free_active_base(void) -{ - struct event_base *base1; - struct event ev1; - setup_test("Free active base: "); - base1 = event_init(); - event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1); - event_base_set(base1, &ev1); - event_add(&ev1, NULL); - /* event_del(&ev1); */ - event_base_free(base1); - test_ok = 1; - cleanup_test(); -} - -static void -test_event_base_new(void) -{ - struct event_base *base; - struct event ev1; - setup_test("Event base new: "); - - write(pair[0], TEST1, strlen(TEST1)+1); - shutdown(pair[0], SHUT_WR); - - base = event_base_new(); - event_set(&ev1, pair[1], EV_READ, simple_read_cb, &ev1); - event_base_set(base, &ev1); - event_add(&ev1, NULL); - - event_base_dispatch(base); - - event_base_free(base); - test_ok = 1; - cleanup_test(); -} - -static void -test_loopexit(void) -{ - struct timeval tv, tv_start, tv_end; - struct event ev; - - setup_test("Loop exit: "); - - tv.tv_usec = 0; - tv.tv_sec = 60*60*24; - evtimer_set(&ev, timeout_cb, NULL); - evtimer_add(&ev, &tv); - - tv.tv_usec = 0; - tv.tv_sec = 1; - event_loopexit(&tv); - - evutil_gettimeofday(&tv_start, NULL); - event_dispatch(); - evutil_gettimeofday(&tv_end, NULL); - evutil_timersub(&tv_end, &tv_start, &tv_end); - - evtimer_del(&ev); - - if (tv.tv_sec < 2) - test_ok = 1; - - cleanup_test(); -} - -static void -test_loopexit_multiple(void) -{ - struct timeval tv; - struct event_base *base; - - setup_test("Loop Multiple exit: "); - - base = event_base_new(); - - tv.tv_usec = 0; - tv.tv_sec = 1; - event_base_loopexit(base, &tv); - - tv.tv_usec = 0; - tv.tv_sec = 2; - event_base_loopexit(base, &tv); - - event_base_dispatch(base); - - event_base_free(base); - - test_ok = 1; - - cleanup_test(); -} - -static void -break_cb(int fd, short events, void *arg) -{ - test_ok = 1; - event_loopbreak(); -} - -static void -fail_cb(int fd, short events, void *arg) -{ - test_ok = 0; -} - -static void -test_loopbreak(void) -{ - struct event ev1, ev2; - struct timeval tv; - - setup_test("Loop break: "); - - tv.tv_sec = 0; - tv.tv_usec = 0; - evtimer_set(&ev1, break_cb, NULL); - evtimer_add(&ev1, &tv); - evtimer_set(&ev2, fail_cb, NULL); - evtimer_add(&ev2, &tv); - - event_dispatch(); - - evtimer_del(&ev1); - evtimer_del(&ev2); - - cleanup_test(); -} - -static void -test_evbuffer(void) { - - struct evbuffer *evb = evbuffer_new(); - setup_test("Testing Evbuffer: "); - - evbuffer_add_printf(evb, "%s/%d", "hello", 1); - - if (EVBUFFER_LENGTH(evb) == 7 && - strcmp((char*)EVBUFFER_DATA(evb), "hello/1") == 0) - test_ok = 1; - - evbuffer_free(evb); - - cleanup_test(); -} - -static void -test_evbuffer_readln(void) -{ - struct evbuffer *evb = evbuffer_new(); - struct evbuffer *evb_tmp = evbuffer_new(); - const char *s; - char *cp = NULL; - size_t sz; - -#define tt_line_eq(content) \ - if (!cp || sz != strlen(content) || strcmp(cp, content)) { \ - fprintf(stdout, "FAILED\n"); \ - exit(1); \ - } -#define tt_assert(expression) \ - if (!(expression)) { \ - fprintf(stdout, "FAILED\n"); \ - exit(1); \ - } \ - - /* Test EOL_ANY. */ - fprintf(stdout, "Testing evbuffer_readln EOL_ANY: "); - - s = "complex silly newline\r\n\n\r\n\n\rmore\0\n"; - evbuffer_add(evb, s, strlen(s)+2); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); - tt_line_eq("complex silly newline"); - free(cp); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); - if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6)) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - if (evb->totallen == 0) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - s = "\nno newline"; - evbuffer_add(evb, s, strlen(s)); - free(cp); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); - tt_line_eq(""); - free(cp); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); - tt_assert(!cp); - evbuffer_drain(evb, EVBUFFER_LENGTH(evb)); - tt_assert(EVBUFFER_LENGTH(evb) == 0); - - fprintf(stdout, "OK\n"); - - /* Test EOL_CRLF */ - fprintf(stdout, "Testing evbuffer_readln EOL_CRLF: "); - - s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n"; - evbuffer_add(evb, s, strlen(s)); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); - tt_line_eq("Line with\rin the middle"); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); - tt_line_eq("Line with good crlf"); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); - tt_line_eq(""); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); - tt_line_eq("final"); - s = "x"; - evbuffer_add(evb, s, 1); - free(cp); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); - tt_assert(!cp); - - fprintf(stdout, "OK\n"); - - /* Test CRLF_STRICT */ - fprintf(stdout, "Testing evbuffer_readln CRLF_STRICT: "); - - s = " and a bad crlf\nand a good one\r\n\r\nMore\r"; - evbuffer_add(evb, s, strlen(s)); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq("x and a bad crlf\nand a good one"); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq(""); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_assert(!cp); - evbuffer_add(evb, "\n", 1); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq("More"); - free(cp); - tt_assert(EVBUFFER_LENGTH(evb) == 0); - - s = "An internal CR\r is not an eol\r\nNor is a lack of one"; - evbuffer_add(evb, s, strlen(s)); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq("An internal CR\r is not an eol"); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_assert(!cp); - - evbuffer_add(evb, "\r\n", 2); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq("Nor is a lack of one"); - free(cp); - tt_assert(EVBUFFER_LENGTH(evb) == 0); - - fprintf(stdout, "OK\n"); - - /* Test LF */ - fprintf(stdout, "Testing evbuffer_readln LF: "); - - s = "An\rand a nl\n\nText"; - evbuffer_add(evb, s, strlen(s)); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); - tt_line_eq("An\rand a nl"); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); - tt_line_eq(""); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); - tt_assert(!cp); - free(cp); - evbuffer_add(evb, "\n", 1); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); - tt_line_eq("Text"); - free(cp); - - fprintf(stdout, "OK\n"); - - /* Test CRLF_STRICT - across boundaries */ - fprintf(stdout, - "Testing evbuffer_readln CRLF_STRICT across boundaries: "); - - s = " and a bad crlf\nand a good one\r"; - evbuffer_add(evb_tmp, s, strlen(s)); - evbuffer_add_buffer(evb, evb_tmp); - s = "\n\r"; - evbuffer_add(evb_tmp, s, strlen(s)); - evbuffer_add_buffer(evb, evb_tmp); - s = "\nMore\r"; - evbuffer_add(evb_tmp, s, strlen(s)); - evbuffer_add_buffer(evb, evb_tmp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq(" and a bad crlf\nand a good one"); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq(""); - free(cp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_assert(!cp); - free(cp); - evbuffer_add(evb, "\n", 1); - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); - tt_line_eq("More"); - free(cp); cp = NULL; - if (EVBUFFER_LENGTH(evb) != 0) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - /* Test memory problem */ - fprintf(stdout, "Testing evbuffer_readln memory problem: "); - - s = "one line\ntwo line\nblue line"; - evbuffer_add(evb_tmp, s, strlen(s)); - evbuffer_add_buffer(evb, evb_tmp); - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); - tt_line_eq("one line"); - free(cp); cp = NULL; - - cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); - tt_line_eq("two line"); - free(cp); cp = NULL; - - fprintf(stdout, "OK\n"); - - test_ok = 1; - evbuffer_free(evb); - evbuffer_free(evb_tmp); - if (cp) free(cp); -} - -static void -test_evbuffer_find(void) -{ - u_char* p; - const char* test1 = "1234567890\r\n"; - const char* test2 = "1234567890\r"; -#define EVBUFFER_INITIAL_LENGTH 256 - char test3[EVBUFFER_INITIAL_LENGTH]; - unsigned int i; - struct evbuffer * buf = evbuffer_new(); - - /* make sure evbuffer_find doesn't match past the end of the buffer */ - fprintf(stdout, "Testing evbuffer_find 1: "); - evbuffer_add(buf, (u_char*)test1, strlen(test1)); - evbuffer_drain(buf, strlen(test1)); - evbuffer_add(buf, (u_char*)test2, strlen(test2)); - p = evbuffer_find(buf, (u_char*)"\r\n", 2); - if (p == NULL) { - fprintf(stdout, "OK\n"); - } else { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* - * drain the buffer and do another find; in r309 this would - * read past the allocated buffer causing a valgrind error. - */ - fprintf(stdout, "Testing evbuffer_find 2: "); - evbuffer_drain(buf, strlen(test2)); - for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i) - test3[i] = 'a'; - test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x'; - evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH); - p = evbuffer_find(buf, (u_char *)"xy", 2); - if (p == NULL) { - printf("OK\n"); - } else { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* simple test for match at end of allocated buffer */ - fprintf(stdout, "Testing evbuffer_find 3: "); - p = evbuffer_find(buf, (u_char *)"ax", 2); - if (p != NULL && strncmp((char*)p, "ax", 2) == 0) { - printf("OK\n"); - } else { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - evbuffer_free(buf); -} - -/* - * simple bufferevent test - */ - -static void -readcb(struct bufferevent *bev, void *arg) -{ - if (EVBUFFER_LENGTH(bev->input) == 8333) { - bufferevent_disable(bev, EV_READ); - test_ok++; - } -} - -static void -writecb(struct bufferevent *bev, void *arg) -{ - if (EVBUFFER_LENGTH(bev->output) == 0) - test_ok++; -} - -static void -errorcb(struct bufferevent *bev, short what, void *arg) -{ - test_ok = -2; -} - -static void -test_bufferevent(void) -{ - struct bufferevent *bev1, *bev2; - char buffer[8333]; - int i; - - setup_test("Bufferevent: "); - - bev1 = bufferevent_new(pair[0], readcb, writecb, errorcb, NULL); - bev2 = bufferevent_new(pair[1], readcb, writecb, errorcb, NULL); - - bufferevent_disable(bev1, EV_READ); - bufferevent_enable(bev2, EV_READ); - - for (i = 0; i < sizeof(buffer); i++) - buffer[i] = i; - - bufferevent_write(bev1, buffer, sizeof(buffer)); - - event_dispatch(); - - bufferevent_free(bev1); - bufferevent_free(bev2); - - if (test_ok != 2) - test_ok = 0; - - cleanup_test(); -} - -/* - * test watermarks and bufferevent - */ - -static void -wm_readcb(struct bufferevent *bev, void *arg) -{ - int len = EVBUFFER_LENGTH(bev->input); - static int nread; - - assert(len >= 10 && len <= 20); - - evbuffer_drain(bev->input, len); - - nread += len; - if (nread == 65000) { - bufferevent_disable(bev, EV_READ); - test_ok++; - } -} - -static void -wm_writecb(struct bufferevent *bev, void *arg) -{ - if (EVBUFFER_LENGTH(bev->output) == 0) - test_ok++; -} - -static void -wm_errorcb(struct bufferevent *bev, short what, void *arg) -{ - test_ok = -2; -} - -static void -test_bufferevent_watermarks(void) -{ - struct bufferevent *bev1, *bev2; - char buffer[65000]; - int i; - - setup_test("Bufferevent Watermarks: "); - - bev1 = bufferevent_new(pair[0], NULL, wm_writecb, wm_errorcb, NULL); - bev2 = bufferevent_new(pair[1], wm_readcb, NULL, wm_errorcb, NULL); - - bufferevent_disable(bev1, EV_READ); - bufferevent_enable(bev2, EV_READ); - - for (i = 0; i < sizeof(buffer); i++) - buffer[i] = i; - - bufferevent_write(bev1, buffer, sizeof(buffer)); - - /* limit the reading on the receiving bufferevent */ - bufferevent_setwatermark(bev2, EV_READ, 10, 20); - - event_dispatch(); - - bufferevent_free(bev1); - bufferevent_free(bev2); - - if (test_ok != 2) - test_ok = 0; - - cleanup_test(); -} - -struct test_pri_event { - struct event ev; - int count; -}; - -static void -test_priorities_cb(int fd, short what, void *arg) -{ - struct test_pri_event *pri = arg; - struct timeval tv; - - if (pri->count == 3) { - event_loopexit(NULL); - return; - } - - pri->count++; - - evutil_timerclear(&tv); - event_add(&pri->ev, &tv); -} - -static void -test_priorities(int npriorities) -{ - char buf[32]; - struct test_pri_event one, two; - struct timeval tv; - - evutil_snprintf(buf, sizeof(buf), "Testing Priorities %d: ", npriorities); - setup_test(buf); - - event_base_priority_init(global_base, npriorities); - - memset(&one, 0, sizeof(one)); - memset(&two, 0, sizeof(two)); - - timeout_set(&one.ev, test_priorities_cb, &one); - if (event_priority_set(&one.ev, 0) == -1) { - fprintf(stderr, "%s: failed to set priority", __func__); - exit(1); - } - - timeout_set(&two.ev, test_priorities_cb, &two); - if (event_priority_set(&two.ev, npriorities - 1) == -1) { - fprintf(stderr, "%s: failed to set priority", __func__); - exit(1); - } - - evutil_timerclear(&tv); - - if (event_add(&one.ev, &tv) == -1) - exit(1); - if (event_add(&two.ev, &tv) == -1) - exit(1); - - event_dispatch(); - - event_del(&one.ev); - event_del(&two.ev); - - if (npriorities == 1) { - if (one.count == 3 && two.count == 3) - test_ok = 1; - } else if (npriorities == 2) { - /* Two is called once because event_loopexit is priority 1 */ - if (one.count == 3 && two.count == 1) - test_ok = 1; - } else { - if (one.count == 3 && two.count == 0) - test_ok = 1; - } - - cleanup_test(); -} - -static void -test_multiple_cb(int fd, short event, void *arg) -{ - if (event & EV_READ) - test_ok |= 1; - else if (event & EV_WRITE) - test_ok |= 2; -} - -static void -test_multiple_events_for_same_fd(void) -{ - struct event e1, e2; - - setup_test("Multiple events for same fd: "); - - event_set(&e1, pair[0], EV_READ, test_multiple_cb, NULL); - event_add(&e1, NULL); - event_set(&e2, pair[0], EV_WRITE, test_multiple_cb, NULL); - event_add(&e2, NULL); - event_loop(EVLOOP_ONCE); - event_del(&e2); - write(pair[1], TEST1, strlen(TEST1)+1); - event_loop(EVLOOP_ONCE); - event_del(&e1); - - if (test_ok != 3) - test_ok = 0; - - cleanup_test(); -} - -int evtag_decode_int(uint32_t *pnumber, struct evbuffer *evbuf); -int evtag_encode_tag(struct evbuffer *evbuf, uint32_t number); -int evtag_decode_tag(uint32_t *pnumber, struct evbuffer *evbuf); - -static void -read_once_cb(int fd, short event, void *arg) -{ - char buf[256]; - int len; - - len = read(fd, buf, sizeof(buf)); - - if (called) { - test_ok = 0; - } else if (len) { - /* Assumes global pair[0] can be used for writing */ - write(pair[0], TEST1, strlen(TEST1)+1); - test_ok = 1; - } - - called++; -} - -static void -test_want_only_once(void) -{ - struct event ev; - struct timeval tv; - - /* Very simple read test */ - setup_test("Want read only once: "); - - write(pair[0], TEST1, strlen(TEST1)+1); - - /* Setup the loop termination */ - evutil_timerclear(&tv); - tv.tv_sec = 1; - event_loopexit(&tv); - - event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); - if (event_add(&ev, NULL) == -1) - exit(1); - event_dispatch(); - - cleanup_test(); -} - -#define TEST_MAX_INT 6 - -static void -evtag_int_test(void) -{ - struct evbuffer *tmp = evbuffer_new(); - uint32_t integers[TEST_MAX_INT] = { - 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 - }; - uint32_t integer; - int i; - - for (i = 0; i < TEST_MAX_INT; i++) { - int oldlen, newlen; - oldlen = EVBUFFER_LENGTH(tmp); - encode_int(tmp, integers[i]); - newlen = EVBUFFER_LENGTH(tmp); - fprintf(stdout, "\t\tencoded 0x%08x with %d bytes\n", - integers[i], newlen - oldlen); - } - - for (i = 0; i < TEST_MAX_INT; i++) { - if (evtag_decode_int(&integer, tmp) == -1) { - fprintf(stderr, "decode %d failed", i); - exit(1); - } - if (integer != integers[i]) { - fprintf(stderr, "got %x, wanted %x", - integer, integers[i]); - exit(1); - } - } - - if (EVBUFFER_LENGTH(tmp) != 0) { - fprintf(stderr, "trailing data"); - exit(1); - } - evbuffer_free(tmp); - - fprintf(stdout, "\t%s: OK\n", __func__); -} - -static void -evtag_fuzz(void) -{ - u_char buffer[4096]; - struct evbuffer *tmp = evbuffer_new(); - struct timeval tv; - int i, j; - - int not_failed = 0; - for (j = 0; j < 100; j++) { - for (i = 0; i < sizeof(buffer); i++) - buffer[i] = rand(); - evbuffer_drain(tmp, -1); - evbuffer_add(tmp, buffer, sizeof(buffer)); - - if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) - not_failed++; - } - - /* The majority of decodes should fail */ - if (not_failed >= 10) { - fprintf(stderr, "evtag_unmarshal should have failed"); - exit(1); - } - - /* Now insert some corruption into the tag length field */ - evbuffer_drain(tmp, -1); - evutil_timerclear(&tv); - tv.tv_sec = 1; - evtag_marshal_timeval(tmp, 0, &tv); - evbuffer_add(tmp, buffer, sizeof(buffer)); - - EVBUFFER_DATA(tmp)[1] = 0xff; - if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { - fprintf(stderr, "evtag_unmarshal_timeval should have failed"); - exit(1); - } - - evbuffer_free(tmp); - - fprintf(stdout, "\t%s: OK\n", __func__); -} - -static void -evtag_tag_encoding(void) -{ - struct evbuffer *tmp = evbuffer_new(); - uint32_t integers[TEST_MAX_INT] = { - 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 - }; - uint32_t integer; - int i; - - for (i = 0; i < TEST_MAX_INT; i++) { - int oldlen, newlen; - oldlen = EVBUFFER_LENGTH(tmp); - evtag_encode_tag(tmp, integers[i]); - newlen = EVBUFFER_LENGTH(tmp); - fprintf(stdout, "\t\tencoded 0x%08x with %d bytes\n", - integers[i], newlen - oldlen); - } - - for (i = 0; i < TEST_MAX_INT; i++) { - if (evtag_decode_tag(&integer, tmp) == -1) { - fprintf(stderr, "decode %d failed", i); - exit(1); - } - if (integer != integers[i]) { - fprintf(stderr, "got %x, wanted %x", - integer, integers[i]); - exit(1); - } - } - - if (EVBUFFER_LENGTH(tmp) != 0) { - fprintf(stderr, "trailing data"); - exit(1); - } - evbuffer_free(tmp); - - fprintf(stdout, "\t%s: OK\n", __func__); -} - -static void -evtag_test(void) -{ - fprintf(stdout, "Testing Tagging:\n"); - - evtag_init(); - evtag_int_test(); - evtag_fuzz(); - - evtag_tag_encoding(); - - fprintf(stdout, "OK\n"); -} - -#ifndef WIN32 -static void -rpc_test(void) -{ - struct msg *msg, *msg2; - struct kill *attack; - struct run *run; - struct evbuffer *tmp = evbuffer_new(); - struct timeval tv_start, tv_end; - uint32_t tag; - int i; - - fprintf(stdout, "Testing RPC: "); - - msg = msg_new(); - EVTAG_ASSIGN(msg, from_name, "niels"); - EVTAG_ASSIGN(msg, to_name, "phoenix"); - - if (EVTAG_GET(msg, attack, &attack) == -1) { - fprintf(stderr, "Failed to set kill message.\n"); - exit(1); - } - - EVTAG_ASSIGN(attack, weapon, "feather"); - EVTAG_ASSIGN(attack, action, "tickle"); - - evutil_gettimeofday(&tv_start, NULL); - for (i = 0; i < 1000; ++i) { - run = EVTAG_ADD(msg, run); - if (run == NULL) { - fprintf(stderr, "Failed to add run message.\n"); - exit(1); - } - EVTAG_ASSIGN(run, how, "very fast but with some data in it"); - EVTAG_ASSIGN(run, fixed_bytes, - (unsigned char*)"012345678901234567890123"); - } - - if (msg_complete(msg) == -1) { - fprintf(stderr, "Failed to make complete message.\n"); - exit(1); - } - - evtag_marshal_msg(tmp, 0xdeaf, msg); - - if (evtag_peek(tmp, &tag) == -1) { - fprintf(stderr, "Failed to peak tag.\n"); - exit (1); - } - - if (tag != 0xdeaf) { - fprintf(stderr, "Got incorrect tag: %0x.\n", tag); - exit (1); - } - - msg2 = msg_new(); - if (evtag_unmarshal_msg(tmp, 0xdeaf, msg2) == -1) { - fprintf(stderr, "Failed to unmarshal message.\n"); - exit(1); - } - - evutil_gettimeofday(&tv_end, NULL); - evutil_timersub(&tv_end, &tv_start, &tv_end); - fprintf(stderr, "(%.1f us/add) ", - (float)tv_end.tv_sec/(float)i * 1000000.0 + - tv_end.tv_usec / (float)i); - - if (!EVTAG_HAS(msg2, from_name) || - !EVTAG_HAS(msg2, to_name) || - !EVTAG_HAS(msg2, attack)) { - fprintf(stderr, "Missing data structures.\n"); - exit(1); - } - - if (EVTAG_LEN(msg2, run) != i) { - fprintf(stderr, "Wrong number of run messages.\n"); - exit(1); - } - - msg_free(msg); - msg_free(msg2); - - evbuffer_free(tmp); - - fprintf(stdout, "OK\n"); -} -#endif - -static void -test_evutil_strtoll(void) -{ - const char *s; - char *endptr; - setup_test("evutil_stroll: "); - test_ok = 0; - - if (evutil_strtoll("5000000000", NULL, 10) != ((ev_int64_t)5000000)*1000) - goto err; - if (evutil_strtoll("-5000000000", NULL, 10) != ((ev_int64_t)5000000)*-1000) - goto err; - s = " 99999stuff"; - if (evutil_strtoll(s, &endptr, 10) != (ev_int64_t)99999) - goto err; - if (endptr != s+6) - goto err; - if (evutil_strtoll("foo", NULL, 10) != 0) - goto err; - - test_ok = 1; - err: - cleanup_test(); -} - - -int -main (int argc, char **argv) -{ -#ifdef WIN32 - WORD wVersionRequested; - WSADATA wsaData; - int err; - - wVersionRequested = MAKEWORD( 2, 2 ); - - err = WSAStartup( wVersionRequested, &wsaData ); -#endif - -#ifndef WIN32 - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - return (1); -#endif - setvbuf(stdout, NULL, _IONBF, 0); - - /* Initalize the event library */ - global_base = event_init(); - - test_registerfds(); - - test_evutil_strtoll(); - - /* use the global event base and need to be called first */ - test_priorities(1); - test_priorities(2); - test_priorities(3); - - test_evbuffer(); - test_evbuffer_find(); - test_evbuffer_readln(); - - test_bufferevent(); - test_bufferevent_watermarks(); - - test_free_active_base(); - - test_event_base_new(); - - http_suite(); - -#ifndef WIN32 - rpc_suite(); -#endif - - dns_suite(); - -#ifndef WIN32 - test_fork(); -#endif - - test_simpleread(); - - test_simplewrite(); - - test_multiple(); - - test_persistent(); - - test_combined(); - - test_simpletimeout(); -#ifndef WIN32 - test_simplesignal(); - test_multiplesignal(); - test_immediatesignal(); -#endif - test_loopexit(); - test_loopbreak(); - - test_loopexit_multiple(); - - test_multiple_events_for_same_fd(); - - test_want_only_once(); - - evtag_test(); - -#ifndef WIN32 - rpc_test(); - - test_signal_dealloc(); - test_signal_pipeloss(); - test_signal_switchbase(); - test_signal_restore(); - test_signal_assert(); - test_signal_while_processing(); -#endif - - return (0); -} -
diff --git a/third_party/libevent/test/regress.h b/third_party/libevent/test/regress.h deleted file mode 100644 index 4060ff5c..0000000 --- a/third_party/libevent/test/regress.h +++ /dev/null
@@ -1,45 +0,0 @@ -/* - * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _REGRESS_H_ -#define _REGRESS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void http_suite(void); -void http_basic_test(void); - -void rpc_suite(void); - -void dns_suite(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _REGRESS_H_ */
diff --git a/third_party/libevent/test/regress.rpc b/third_party/libevent/test/regress.rpc deleted file mode 100644 index 65ca95de..0000000 --- a/third_party/libevent/test/regress.rpc +++ /dev/null
@@ -1,20 +0,0 @@ -/* tests data packing and unpacking */ - -struct msg { - string from_name = 1; - string to_name = 2; - optional struct[kill] attack = 3; - array struct[run] run = 4; -} - -struct kill { - string weapon = 0x10121; - string action = 2; - optional int how_often = 3; -} - -struct run { - string how = 1; - optional bytes some_bytes = 2; - bytes fixed_bytes[24] = 3; -}
diff --git a/third_party/libevent/test/regress_dns.c b/third_party/libevent/test/regress_dns.c deleted file mode 100644 index 129cdad..0000000 --- a/third_party/libevent/test/regress_dns.c +++ /dev/null
@@ -1,376 +0,0 @@ -/* - * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef WIN32 -#include <winsock2.h> -#include <windows.h> -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/queue.h> -#ifndef WIN32 -#include <sys/socket.h> -#include <signal.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <unistd.h> -#endif -#ifdef HAVE_NETINET_IN6_H -#include <netinet/in6.h> -#endif -#ifdef HAVE_NETDB_H -#include <netdb.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "event.h" -#include "evdns.h" -#include "log.h" - -static int dns_ok = 0; -static int dns_err = 0; - -void dns_suite(void); - -static void -dns_gethostbyname_cb(int result, char type, int count, int ttl, - void *addresses, void *arg) -{ - dns_ok = dns_err = 0; - - if (result == DNS_ERR_TIMEOUT) { - fprintf(stdout, "[Timed out] "); - dns_err = result; - goto out; - } - - if (result != DNS_ERR_NONE) { - fprintf(stdout, "[Error code %d] ", result); - goto out; - } - - fprintf(stderr, "type: %d, count: %d, ttl: %d: ", type, count, ttl); - - switch (type) { - case DNS_IPv6_AAAA: { -#if defined(HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) - struct in6_addr *in6_addrs = addresses; - char buf[INET6_ADDRSTRLEN+1]; - int i; - /* a resolution that's not valid does not help */ - if (ttl < 0) - goto out; - for (i = 0; i < count; ++i) { - const char *b = inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf)); - if (b) - fprintf(stderr, "%s ", b); - else - fprintf(stderr, "%s ", strerror(errno)); - } -#endif - break; - } - case DNS_IPv4_A: { - struct in_addr *in_addrs = addresses; - int i; - /* a resolution that's not valid does not help */ - if (ttl < 0) - goto out; - for (i = 0; i < count; ++i) - fprintf(stderr, "%s ", inet_ntoa(in_addrs[i])); - break; - } - case DNS_PTR: - /* may get at most one PTR */ - if (count != 1) - goto out; - - fprintf(stderr, "%s ", *(char **)addresses); - break; - default: - goto out; - } - - dns_ok = type; - -out: - event_loopexit(NULL); -} - -static void -dns_gethostbyname(void) -{ - fprintf(stdout, "Simple DNS resolve: "); - dns_ok = 0; - evdns_resolve_ipv4("www.monkey.org", 0, dns_gethostbyname_cb, NULL); - event_dispatch(); - - if (dns_ok == DNS_IPv4_A) { - fprintf(stdout, "OK\n"); - } else { - fprintf(stdout, "FAILED\n"); - exit(1); - } -} - -static void -dns_gethostbyname6(void) -{ - fprintf(stdout, "IPv6 DNS resolve: "); - dns_ok = 0; - evdns_resolve_ipv6("www.ietf.org", 0, dns_gethostbyname_cb, NULL); - event_dispatch(); - - if (dns_ok == DNS_IPv6_AAAA) { - fprintf(stdout, "OK\n"); - } else if (!dns_ok && dns_err == DNS_ERR_TIMEOUT) { - fprintf(stdout, "SKIPPED\n"); - } else { - fprintf(stdout, "FAILED (%d)\n", dns_ok); - exit(1); - } -} - -static void -dns_gethostbyaddr(void) -{ - struct in_addr in; - in.s_addr = htonl(0x7f000001ul); /* 127.0.0.1 */ - fprintf(stdout, "Simple reverse DNS resolve: "); - dns_ok = 0; - evdns_resolve_reverse(&in, 0, dns_gethostbyname_cb, NULL); - event_dispatch(); - - if (dns_ok == DNS_PTR) { - fprintf(stdout, "OK\n"); - } else { - fprintf(stdout, "FAILED\n"); - exit(1); - } -} - -static int n_server_responses = 0; - -static void -dns_server_request_cb(struct evdns_server_request *req, void *data) -{ - int i, r; - const char TEST_ARPA[] = "11.11.168.192.in-addr.arpa"; - for (i = 0; i < req->nquestions; ++i) { - struct in_addr ans; - ans.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ - if (req->questions[i]->type == EVDNS_TYPE_A && - req->questions[i]->dns_question_class == EVDNS_CLASS_INET && - !strcmp(req->questions[i]->name, "zz.example.com")) { - r = evdns_server_request_add_a_reply(req, "zz.example.com", - 1, &ans.s_addr, 12345); - if (r<0) - dns_ok = 0; - } else if (req->questions[i]->type == EVDNS_TYPE_AAAA && - req->questions[i]->dns_question_class == EVDNS_CLASS_INET && - !strcmp(req->questions[i]->name, "zz.example.com")) { - char addr6[17] = "abcdefghijklmnop"; - r = evdns_server_request_add_aaaa_reply(req, "zz.example.com", - 1, addr6, 123); - if (r<0) - dns_ok = 0; - } else if (req->questions[i]->type == EVDNS_TYPE_PTR && - req->questions[i]->dns_question_class == EVDNS_CLASS_INET && - !strcmp(req->questions[i]->name, TEST_ARPA)) { - r = evdns_server_request_add_ptr_reply(req, NULL, TEST_ARPA, - "ZZ.EXAMPLE.COM", 54321); - if (r<0) - dns_ok = 0; - } else { - fprintf(stdout, "Unexpected question %d %d \"%s\" ", - req->questions[i]->type, - req->questions[i]->dns_question_class, - req->questions[i]->name); - dns_ok = 0; - } - } - r = evdns_server_request_respond(req, 0); - if (r<0) { - fprintf(stdout, "Couldn't send reply. "); - dns_ok = 0; - } -} - -static void -dns_server_gethostbyname_cb(int result, char type, int count, int ttl, - void *addresses, void *arg) -{ - if (result != DNS_ERR_NONE) { - fprintf(stdout, "Unexpected result %d. ", result); - dns_ok = 0; - goto out; - } - if (count != 1) { - fprintf(stdout, "Unexpected answer count %d. ", count); - dns_ok = 0; - goto out; - } - switch (type) { - case DNS_IPv4_A: { - struct in_addr *in_addrs = addresses; - if (in_addrs[0].s_addr != htonl(0xc0a80b0bUL) || ttl != 12345) { - fprintf(stdout, "Bad IPv4 response \"%s\" %d. ", - inet_ntoa(in_addrs[0]), ttl); - dns_ok = 0; - goto out; - } - break; - } - case DNS_IPv6_AAAA: { -#if defined (HAVE_STRUCT_IN6_ADDR) && defined(HAVE_INET_NTOP) && defined(INET6_ADDRSTRLEN) - struct in6_addr *in6_addrs = addresses; - char buf[INET6_ADDRSTRLEN+1]; - if (memcmp(&in6_addrs[0].s6_addr, "abcdefghijklmnop", 16) - || ttl != 123) { - const char *b = inet_ntop(AF_INET6, &in6_addrs[0],buf,sizeof(buf)); - fprintf(stdout, "Bad IPv6 response \"%s\" %d. ", b, ttl); - dns_ok = 0; - goto out; - } -#endif - break; - } - case DNS_PTR: { - char **addrs = addresses; - if (strcmp(addrs[0], "ZZ.EXAMPLE.COM") || ttl != 54321) { - fprintf(stdout, "Bad PTR response \"%s\" %d. ", - addrs[0], ttl); - dns_ok = 0; - goto out; - } - break; - } - default: - fprintf(stdout, "Bad response type %d. ", type); - dns_ok = 0; - } - - out: - if (++n_server_responses == 3) { - event_loopexit(NULL); - } -} - -static void -dns_server(void) -{ - int sock; - struct sockaddr_in my_addr; - struct evdns_server_port *port; - struct in_addr resolve_addr; - - dns_ok = 1; - fprintf(stdout, "DNS server support: "); - - /* Add ourself as the only nameserver, and make sure we really are - * the only nameserver. */ - evdns_nameserver_ip_add("127.0.0.1:35353"); - if (evdns_count_nameservers() != 1) { - fprintf(stdout, "Couldn't set up.\n"); - exit(1); - } - - /* Now configure a nameserver port. */ - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) { - perror("socket"); - exit(1); - } -#ifdef WIN32 - { - u_long nonblocking = 1; - ioctlsocket(sock, FIONBIO, &nonblocking); - } -#else - fcntl(sock, F_SETFL, O_NONBLOCK); -#endif - memset(&my_addr, 0, sizeof(my_addr)); - my_addr.sin_family = AF_INET; - my_addr.sin_port = htons(35353); - my_addr.sin_addr.s_addr = htonl(0x7f000001UL); - if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { - perror("bind"); - exit (1); - } - port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); - - /* Send two queries. */ - evdns_resolve_ipv4("zz.example.com", DNS_QUERY_NO_SEARCH, - dns_server_gethostbyname_cb, NULL); - evdns_resolve_ipv6("zz.example.com", DNS_QUERY_NO_SEARCH, - dns_server_gethostbyname_cb, NULL); - resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ - evdns_resolve_reverse(&resolve_addr, 0, - dns_server_gethostbyname_cb, NULL); - - event_dispatch(); - - if (dns_ok) { - fprintf(stdout, "OK\n"); - } else { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - evdns_close_server_port(port); - evdns_shutdown(0); /* remove ourself as nameserver. */ -#ifdef WIN32 - closesocket(sock); -#else - close(sock); -#endif -} - -void -dns_suite(void) -{ - dns_server(); /* Do this before we call evdns_init. */ - - evdns_init(); - dns_gethostbyname(); - dns_gethostbyname6(); - dns_gethostbyaddr(); - - evdns_shutdown(0); -}
diff --git a/third_party/libevent/test/regress_http.c b/third_party/libevent/test/regress_http.c deleted file mode 100644 index 943b29d..0000000 --- a/third_party/libevent/test/regress_http.c +++ /dev/null
@@ -1,1744 +0,0 @@ -/* - * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef WIN32 -#include <winsock2.h> -#include <windows.h> -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/queue.h> -#ifndef WIN32 -#include <sys/socket.h> -#include <signal.h> -#include <unistd.h> -#include <netdb.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "event.h" -#include "evhttp.h" -#include "log.h" -#include "http-internal.h" - -extern int pair[]; -extern int test_ok; - -static struct evhttp *http; -/* set if a test needs to call loopexit on a base */ -static struct event_base *base; - -void http_suite(void); - -void http_basic_cb(struct evhttp_request *req, void *arg); -static void http_chunked_cb(struct evhttp_request *req, void *arg); -void http_post_cb(struct evhttp_request *req, void *arg); -void http_dispatcher_cb(struct evhttp_request *req, void *arg); -static void http_large_delay_cb(struct evhttp_request *req, void *arg); -static void http_badreq_cb(struct evhttp_request *req, void *arg); - -static struct evhttp * -http_setup(short *pport, struct event_base *base) -{ - int i; - struct evhttp *myhttp; - short port = -1; - - /* Try a few different ports */ - myhttp = evhttp_new(base); - for (i = 0; i < 50; ++i) { - if (evhttp_bind_socket(myhttp, "127.0.0.1", 8080 + i) != -1) { - port = 8080 + i; - break; - } - } - - if (port == -1) - event_errx(1, "Could not start web server"); - - /* Register a callback for certain types of requests */ - evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL); - evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, NULL); - evhttp_set_cb(myhttp, "/postit", http_post_cb, NULL); - evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, NULL); - evhttp_set_cb(myhttp, "/badrequest", http_badreq_cb, NULL); - evhttp_set_cb(myhttp, "/", http_dispatcher_cb, NULL); - - *pport = port; - return (myhttp); -} - -#ifndef NI_MAXSERV -#define NI_MAXSERV 1024 -#endif - -static int -http_connect(const char *address, u_short port) -{ - /* Stupid code for connecting */ -#ifdef WIN32 - struct hostent *he; - struct sockaddr_in sin; -#else - struct addrinfo ai, *aitop; - char strport[NI_MAXSERV]; -#endif - struct sockaddr *sa; - int slen; - int fd; - -#ifdef WIN32 - if (!(he = gethostbyname(address))) { - event_warn("gethostbyname"); - } - memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length); - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - slen = sizeof(struct sockaddr_in); - sa = (struct sockaddr*)&sin; -#else - memset(&ai, 0, sizeof (ai)); - ai.ai_family = AF_INET; - ai.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof (strport), "%d", port); - if (getaddrinfo(address, strport, &ai, &aitop) != 0) { - event_warn("getaddrinfo"); - return (-1); - } - sa = aitop->ai_addr; - slen = aitop->ai_addrlen; -#endif - - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd == -1) - event_err(1, "socket failed"); - - if (connect(fd, sa, slen) == -1) - event_err(1, "connect failed"); - -#ifndef WIN32 - freeaddrinfo(aitop); -#endif - - return (fd); -} - -static void -http_readcb(struct bufferevent *bev, void *arg) -{ - const char *what = "This is funny"; - - event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(bev->input))); - - if (evbuffer_find(bev->input, - (const unsigned char*) what, strlen(what)) != NULL) { - struct evhttp_request *req = evhttp_request_new(NULL, NULL); - enum message_read_status done; - - req->kind = EVHTTP_RESPONSE; - done = evhttp_parse_firstline(req, bev->input); - if (done != ALL_DATA_READ) - goto out; - - done = evhttp_parse_headers(req, bev->input); - if (done != ALL_DATA_READ) - goto out; - - if (done == 1 && - evhttp_find_header(req->input_headers, - "Content-Type") != NULL) - test_ok++; - - out: - evhttp_request_free(req); - bufferevent_disable(bev, EV_READ); - if (base) - event_base_loopexit(base, NULL); - else - event_loopexit(NULL); - } -} - -static void -http_writecb(struct bufferevent *bev, void *arg) -{ - if (EVBUFFER_LENGTH(bev->output) == 0) { - /* enable reading of the reply */ - bufferevent_enable(bev, EV_READ); - test_ok++; - } -} - -static void -http_errorcb(struct bufferevent *bev, short what, void *arg) -{ - test_ok = -2; - event_loopexit(NULL); -} - -void -http_basic_cb(struct evhttp_request *req, void *arg) -{ - struct evbuffer *evb = evbuffer_new(); - int empty = evhttp_find_header(req->input_headers, "Empty") != NULL; - event_debug(("%s: called\n", __func__)); - evbuffer_add_printf(evb, "This is funny"); - - /* For multi-line headers test */ - { - const char *multi = - evhttp_find_header(req->input_headers,"X-multi"); - if (multi) { - if (strcmp("END", multi + strlen(multi) - 3) == 0) - test_ok++; - if (evhttp_find_header(req->input_headers, "X-Last")) - test_ok++; - } - } - - /* injecting a bad content-length */ - if (evhttp_find_header(req->input_headers, "X-Negative")) - evhttp_add_header(req->output_headers, - "Content-Length", "-100"); - - /* allow sending of an empty reply */ - evhttp_send_reply(req, HTTP_OK, "Everything is fine", - !empty ? evb : NULL); - - evbuffer_free(evb); -} - -static char const* const CHUNKS[] = { - "This is funny", - "but not hilarious.", - "bwv 1052" -}; - -struct chunk_req_state { - struct evhttp_request *req; - int i; -}; - -static void -http_chunked_trickle_cb(int fd, short events, void *arg) -{ - struct evbuffer *evb = evbuffer_new(); - struct chunk_req_state *state = arg; - struct timeval when = { 0, 0 }; - - evbuffer_add_printf(evb, "%s", CHUNKS[state->i]); - evhttp_send_reply_chunk(state->req, evb); - evbuffer_free(evb); - - if (++state->i < sizeof(CHUNKS)/sizeof(CHUNKS[0])) { - event_once(-1, EV_TIMEOUT, - http_chunked_trickle_cb, state, &when); - } else { - evhttp_send_reply_end(state->req); - free(state); - } -} - -static void -http_chunked_cb(struct evhttp_request *req, void *arg) -{ - struct timeval when = { 0, 0 }; - struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state)); - event_debug(("%s: called\n", __func__)); - - memset(state, 0, sizeof(struct chunk_req_state)); - state->req = req; - - /* generate a chunked reply */ - evhttp_send_reply_start(req, HTTP_OK, "Everything is fine"); - - /* but trickle it across several iterations to ensure we're not - * assuming it comes all at once */ - event_once(-1, EV_TIMEOUT, http_chunked_trickle_cb, state, &when); -} - -static void -http_complete_write(int fd, short what, void *arg) -{ - struct bufferevent *bev = arg; - const char *http_request = "host\r\n" - "Connection: close\r\n" - "\r\n"; - bufferevent_write(bev, http_request, strlen(http_request)); -} - -static void -http_basic_test(void) -{ - struct timeval tv; - struct bufferevent *bev; - int fd; - const char *http_request; - short port = -1; - - test_ok = 0; - fprintf(stdout, "Testing Basic HTTP Server: "); - - http = http_setup(&port, NULL); - - /* bind to a second socket */ - if (evhttp_bind_socket(http, "127.0.0.1", port + 1) == -1) { - fprintf(stdout, "FAILED (bind)\n"); - exit(1); - } - - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_readcb, http_writecb, - http_errorcb, NULL); - - /* first half of the http request */ - http_request = - "GET /test HTTP/1.1\r\n" - "Host: some"; - - bufferevent_write(bev, http_request, strlen(http_request)); - timerclear(&tv); - tv.tv_usec = 10000; - event_once(-1, EV_TIMEOUT, http_complete_write, bev, &tv); - - event_dispatch(); - - if (test_ok != 3) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* connect to the second port */ - bufferevent_free(bev); - EVUTIL_CLOSESOCKET(fd); - - fd = http_connect("127.0.0.1", port + 1); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_readcb, http_writecb, - http_errorcb, NULL); - - http_request = - "GET /test HTTP/1.1\r\n" - "Host: somehost\r\n" - "Connection: close\r\n" - "\r\n"; - - bufferevent_write(bev, http_request, strlen(http_request)); - - event_dispatch(); - - bufferevent_free(bev); - EVUTIL_CLOSESOCKET(fd); - - evhttp_free(http); - - if (test_ok != 5) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -static void -http_badreq_cb(struct evhttp_request *req, void *arg) -{ - struct evbuffer *buf = evbuffer_new(); - - evhttp_add_header(req->output_headers, "Content-Type", "text/xml; charset=UTF-8"); - evbuffer_add_printf(buf, "Hello, %s!", "127.0.0.1"); - - evhttp_send_reply(req, HTTP_OK, "OK", buf); - evbuffer_free(buf); -} - -static void -http_badreq_errorcb(struct bufferevent *bev, short what, void *arg) -{ - event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg)); - /* ignore */ -} - -static void -http_badreq_readcb(struct bufferevent *bev, void *arg) -{ - const char *what = "Hello, 127.0.0.1"; - const char *bad_request = "400 Bad Request"; - - event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(bev->input))); - - if (evbuffer_find(bev->input, - (const unsigned char *) bad_request, strlen(bad_request)) != NULL) { - event_debug(("%s: bad request detected", __func__)); - test_ok = -10; - bufferevent_disable(bev, EV_READ); - event_loopexit(NULL); - return; - } - - if (evbuffer_find(bev->input, - (const unsigned char*) what, strlen(what)) != NULL) { - struct evhttp_request *req = evhttp_request_new(NULL, NULL); - enum message_read_status done; - - req->kind = EVHTTP_RESPONSE; - done = evhttp_parse_firstline(req, bev->input); - if (done != ALL_DATA_READ) - goto out; - - done = evhttp_parse_headers(req, bev->input); - if (done != ALL_DATA_READ) - goto out; - - if (done == 1 && - evhttp_find_header(req->input_headers, - "Content-Type") != NULL) - test_ok++; - - out: - evhttp_request_free(req); - evbuffer_drain(bev->input, EVBUFFER_LENGTH(bev->input)); - } - - shutdown(bev->ev_read.ev_fd, SHUT_WR); -} - -static void -http_badreq_successcb(int fd, short what, void *arg) -{ - event_debug(("%s: called (what=%04x, arg=%p)", __func__, what, arg)); - event_loopexit(NULL); -} - -static void -http_bad_request(void) -{ - struct timeval tv; - struct bufferevent *bev; - int fd; - const char *http_request; - short port = -1; - - test_ok = 0; - fprintf(stdout, "Testing \"Bad Request\" on connection close: "); - - http = http_setup(&port, NULL); - - /* bind to a second socket */ - if (evhttp_bind_socket(http, "127.0.0.1", port + 1) == -1) { - fprintf(stdout, "FAILED (bind)\n"); - exit(1); - } - - /* NULL request test */ - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_badreq_readcb, http_writecb, - http_badreq_errorcb, NULL); - bufferevent_enable(bev, EV_READ); - - /* real NULL request */ - http_request = ""; - - shutdown(fd, SHUT_WR); - timerclear(&tv); - tv.tv_usec = 10000; - event_once(-1, EV_TIMEOUT, http_badreq_successcb, bev, &tv); - - event_dispatch(); - - bufferevent_free(bev); - EVUTIL_CLOSESOCKET(fd); - - if (test_ok != 0) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* Second answer (BAD REQUEST) on connection close */ - - /* connect to the second port */ - fd = http_connect("127.0.0.1", port + 1); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_badreq_readcb, http_writecb, - http_badreq_errorcb, NULL); - bufferevent_enable(bev, EV_READ); - - /* first half of the http request */ - http_request = - "GET /badrequest HTTP/1.0\r\n" \ - "Connection: Keep-Alive\r\n" \ - "\r\n"; - - bufferevent_write(bev, http_request, strlen(http_request)); - - timerclear(&tv); - tv.tv_usec = 10000; - event_once(-1, EV_TIMEOUT, http_badreq_successcb, bev, &tv); - - event_dispatch(); - - evhttp_free(http); - - if (test_ok != 2) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); -} -static struct evhttp_connection *delayed_client; - -static void -http_delay_reply(int fd, short what, void *arg) -{ - struct evhttp_request *req = arg; - - evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL); - - ++test_ok; -} - -static void -http_large_delay_cb(struct evhttp_request *req, void *arg) -{ - struct timeval tv; - timerclear(&tv); - tv.tv_sec = 3; - - event_once(-1, EV_TIMEOUT, http_delay_reply, req, &tv); - - /* here we close the client connection which will cause an EOF */ - evhttp_connection_fail(delayed_client, EVCON_HTTP_EOF); -} - -void http_request_done(struct evhttp_request *, void *); -void http_request_empty_done(struct evhttp_request *, void *); - -static void -http_connection_test(int persistent) -{ - short port = -1; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - - test_ok = 0; - fprintf(stdout, "Testing Request Connection Pipeline %s: ", - persistent ? "(persistent)" : ""); - - http = http_setup(&port, NULL); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* - * At this point, we want to schedule a request to the HTTP - * server using our make request method. - */ - - req = evhttp_request_new(http_request_done, NULL); - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* try to make another request over the same connection */ - test_ok = 0; - - req = evhttp_request_new(http_request_done, NULL); - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - /* - * if our connections are not supposed to be persistent; request - * a close from the server. - */ - if (!persistent) - evhttp_add_header(req->output_headers, "Connection", "close"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - /* make another request: request empty reply */ - test_ok = 0; - - req = evhttp_request_new(http_request_empty_done, NULL); - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Empty", "itis"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - evhttp_connection_free(evcon); - evhttp_free(http); - - fprintf(stdout, "OK\n"); -} - -void -http_request_done(struct evhttp_request *req, void *arg) -{ - const char *what = "This is funny"; - - if (req->response_code != HTTP_OK) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -/* test date header and content length */ - -void -http_request_empty_done(struct evhttp_request *req, void *arg) -{ - if (req->response_code != HTTP_OK) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (evhttp_find_header(req->input_headers, "Date") == NULL) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - - if (evhttp_find_header(req->input_headers, "Content-Length") == NULL) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (strcmp(evhttp_find_header(req->input_headers, "Content-Length"), - "0")) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (EVBUFFER_LENGTH(req->input_buffer) != 0) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -/* - * HTTP DISPATCHER test - */ - -void -http_dispatcher_cb(struct evhttp_request *req, void *arg) -{ - - struct evbuffer *evb = evbuffer_new(); - event_debug(("%s: called\n", __func__)); - evbuffer_add_printf(evb, "DISPATCHER_TEST"); - - evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); - - evbuffer_free(evb); -} - -static void -http_dispatcher_test_done(struct evhttp_request *req, void *arg) -{ - const char *what = "DISPATCHER_TEST"; - - if (req->response_code != HTTP_OK) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { - fprintf(stderr, "FAILED (content type)\n"); - exit(1); - } - - if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) { - fprintf(stderr, "FAILED (length %zu vs %zu)\n", - EVBUFFER_LENGTH(req->input_buffer), strlen(what)); - exit(1); - } - - if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) { - fprintf(stderr, "FAILED (data)\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -static void -http_dispatcher_test(void) -{ - short port = -1; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - - test_ok = 0; - fprintf(stdout, "Testing HTTP Dispatcher: "); - - http = http_setup(&port, NULL); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* also bind to local host */ - evhttp_connection_set_local_address(evcon, "127.0.0.1"); - - /* - * At this point, we want to schedule an HTTP GET request - * server using our make request method. - */ - - req = evhttp_request_new(http_dispatcher_test_done, NULL); - if (req == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - evhttp_connection_free(evcon); - evhttp_free(http); - - if (test_ok != 1) { - fprintf(stdout, "FAILED: %d\n", test_ok); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -/* - * HTTP POST test. - */ - -void http_postrequest_done(struct evhttp_request *, void *); - -#define POST_DATA "Okay. Not really printf" - -static void -http_post_test(void) -{ - short port = -1; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - - test_ok = 0; - fprintf(stdout, "Testing HTTP POST Request: "); - - http = http_setup(&port, NULL); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* - * At this point, we want to schedule an HTTP POST request - * server using our make request method. - */ - - req = evhttp_request_new(http_postrequest_done, NULL); - if (req == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - evbuffer_add_printf(req->output_buffer, POST_DATA); - - if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - evhttp_connection_free(evcon); - evhttp_free(http); - - if (test_ok != 1) { - fprintf(stdout, "FAILED: %d\n", test_ok); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -void -http_post_cb(struct evhttp_request *req, void *arg) -{ - struct evbuffer *evb; - event_debug(("%s: called\n", __func__)); - - /* Yes, we are expecting a post request */ - if (req->type != EVHTTP_REQ_POST) { - fprintf(stdout, "FAILED (post type)\n"); - exit(1); - } - - if (EVBUFFER_LENGTH(req->input_buffer) != strlen(POST_DATA)) { - fprintf(stdout, "FAILED (length: %zu vs %zu)\n", - EVBUFFER_LENGTH(req->input_buffer), strlen(POST_DATA)); - exit(1); - } - - if (memcmp(EVBUFFER_DATA(req->input_buffer), POST_DATA, - strlen(POST_DATA))) { - fprintf(stdout, "FAILED (data)\n"); - fprintf(stdout, "Got :%s\n", EVBUFFER_DATA(req->input_buffer)); - fprintf(stdout, "Want:%s\n", POST_DATA); - exit(1); - } - - evb = evbuffer_new(); - evbuffer_add_printf(evb, "This is funny"); - - evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); - - evbuffer_free(evb); -} - -void -http_postrequest_done(struct evhttp_request *req, void *arg) -{ - const char *what = "This is funny"; - - if (req == NULL) { - fprintf(stderr, "FAILED (timeout)\n"); - exit(1); - } - - if (req->response_code != HTTP_OK) { - - fprintf(stderr, "FAILED (response code)\n"); - exit(1); - } - - if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { - fprintf(stderr, "FAILED (content type)\n"); - exit(1); - } - - if (EVBUFFER_LENGTH(req->input_buffer) != strlen(what)) { - fprintf(stderr, "FAILED (length %zu vs %zu)\n", - EVBUFFER_LENGTH(req->input_buffer), strlen(what)); - exit(1); - } - - if (memcmp(EVBUFFER_DATA(req->input_buffer), what, strlen(what)) != 0) { - fprintf(stderr, "FAILED (data)\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -static void -http_failure_readcb(struct bufferevent *bev, void *arg) -{ - const char *what = "400 Bad Request"; - if (evbuffer_find(bev->input, (const unsigned char*) what, strlen(what)) != NULL) { - test_ok = 2; - bufferevent_disable(bev, EV_READ); - event_loopexit(NULL); - } -} - -/* - * Testing that the HTTP server can deal with a malformed request. - */ -static void -http_failure_test(void) -{ - struct bufferevent *bev; - int fd; - const char *http_request; - short port = -1; - - test_ok = 0; - fprintf(stdout, "Testing Bad HTTP Request: "); - - http = http_setup(&port, NULL); - - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_failure_readcb, http_writecb, - http_errorcb, NULL); - - http_request = "illegal request\r\n"; - - bufferevent_write(bev, http_request, strlen(http_request)); - - event_dispatch(); - - bufferevent_free(bev); - EVUTIL_CLOSESOCKET(fd); - - evhttp_free(http); - - if (test_ok != 2) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -static void -close_detect_done(struct evhttp_request *req, void *arg) -{ - struct timeval tv; - if (req == NULL || req->response_code != HTTP_OK) { - - fprintf(stderr, "FAILED\n"); - exit(1); - } - - test_ok = 1; - - timerclear(&tv); - tv.tv_sec = 3; /* longer than the http time out */ - - event_loopexit(&tv); -} - -static void -close_detect_launch(int fd, short what, void *arg) -{ - struct evhttp_connection *evcon = arg; - struct evhttp_request *req; - - req = evhttp_request_new(close_detect_done, NULL); - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } -} - -static void -close_detect_cb(struct evhttp_request *req, void *arg) -{ - struct evhttp_connection *evcon = arg; - struct timeval tv; - - if (req != NULL && req->response_code != HTTP_OK) { - - fprintf(stderr, "FAILED\n"); - exit(1); - } - - timerclear(&tv); - tv.tv_sec = 3; /* longer than the http time out */ - - /* launch a new request on the persistent connection in 6 seconds */ - event_once(-1, EV_TIMEOUT, close_detect_launch, evcon, &tv); -} - - -static void -http_close_detection(int with_delay) -{ - short port = -1; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - - test_ok = 0; - fprintf(stdout, "Testing Connection Close Detection%s: ", - with_delay ? " (with delay)" : ""); - - http = http_setup(&port, NULL); - - /* 2 second timeout */ - evhttp_set_timeout(http, 2); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - delayed_client = evcon; - - /* - * At this point, we want to schedule a request to the HTTP - * server using our make request method. - */ - - req = evhttp_request_new(close_detect_cb, evcon); - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, - req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* at this point, the http server should have no connection */ - if (TAILQ_FIRST(&http->connections) != NULL) { - fprintf(stdout, "FAILED (left connections)\n"); - exit(1); - } - - evhttp_connection_free(evcon); - evhttp_free(http); - - fprintf(stdout, "OK\n"); -} - -static void -http_highport_test(void) -{ - int i = -1; - struct evhttp *myhttp = NULL; - - fprintf(stdout, "Testing HTTP Server with high port: "); - - /* Try a few different ports */ - for (i = 0; i < 50; ++i) { - myhttp = evhttp_start("127.0.0.1", 65535 - i); - if (myhttp != NULL) { - fprintf(stdout, "OK\n"); - evhttp_free(myhttp); - return; - } - } - - fprintf(stdout, "FAILED\n"); - exit(1); -} - -static void -http_bad_header_test(void) -{ - struct evkeyvalq headers; - - fprintf(stdout, "Testing HTTP Header filtering: "); - - TAILQ_INIT(&headers); - - if (evhttp_add_header(&headers, "One", "Two") != 0) - goto fail; - - if (evhttp_add_header(&headers, "One\r", "Two") != -1) - goto fail; - if (evhttp_add_header(&headers, "One", "Two") != 0) - goto fail; - if (evhttp_add_header(&headers, "One", "Two\r\n Three") != 0) - goto fail; - if (evhttp_add_header(&headers, "One\r", "Two") != -1) - goto fail; - if (evhttp_add_header(&headers, "One\n", "Two") != -1) - goto fail; - if (evhttp_add_header(&headers, "One", "Two\r") != -1) - goto fail; - if (evhttp_add_header(&headers, "One", "Two\n") != -1) - goto fail; - - evhttp_clear_headers(&headers); - - fprintf(stdout, "OK\n"); - return; -fail: - fprintf(stdout, "FAILED\n"); - exit(1); -} - -static int validate_header( - const struct evkeyvalq* headers, - const char *key, const char *value) -{ - const char *real_val = evhttp_find_header(headers, key); - if (real_val == NULL) - return (-1); - if (strcmp(real_val, value) != 0) - return (-1); - return (0); -} - -static void -http_parse_query_test(void) -{ - struct evkeyvalq headers; - - fprintf(stdout, "Testing HTTP query parsing: "); - - TAILQ_INIT(&headers); - - evhttp_parse_query("http://www.test.com/?q=test", &headers); - if (validate_header(&headers, "q", "test") != 0) - goto fail; - evhttp_clear_headers(&headers); - - evhttp_parse_query("http://www.test.com/?q=test&foo=bar", &headers); - if (validate_header(&headers, "q", "test") != 0) - goto fail; - if (validate_header(&headers, "foo", "bar") != 0) - goto fail; - evhttp_clear_headers(&headers); - - evhttp_parse_query("http://www.test.com/?q=test+foo", &headers); - if (validate_header(&headers, "q", "test foo") != 0) - goto fail; - evhttp_clear_headers(&headers); - - evhttp_parse_query("http://www.test.com/?q=test%0Afoo", &headers); - if (validate_header(&headers, "q", "test\nfoo") != 0) - goto fail; - evhttp_clear_headers(&headers); - - evhttp_parse_query("http://www.test.com/?q=test%0Dfoo", &headers); - if (validate_header(&headers, "q", "test\rfoo") != 0) - goto fail; - evhttp_clear_headers(&headers); - - fprintf(stdout, "OK\n"); - return; -fail: - fprintf(stdout, "FAILED\n"); - exit(1); -} - -static void -http_base_test(void) -{ - struct bufferevent *bev; - int fd; - const char *http_request; - short port = -1; - - test_ok = 0; - fprintf(stdout, "Testing HTTP Server Event Base: "); - - base = event_init(); - - /* - * create another bogus base - which is being used by all subsequen - * tests - yuck! - */ - event_init(); - - http = http_setup(&port, base); - - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_readcb, http_writecb, - http_errorcb, NULL); - bufferevent_base_set(base, bev); - - http_request = - "GET /test HTTP/1.1\r\n" - "Host: somehost\r\n" - "Connection: close\r\n" - "\r\n"; - - bufferevent_write(bev, http_request, strlen(http_request)); - - event_base_dispatch(base); - - bufferevent_free(bev); - EVUTIL_CLOSESOCKET(fd); - - evhttp_free(http); - - event_base_free(base); - base = NULL; - - if (test_ok != 2) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -/* - * the server is going to reply with chunked data. - */ - -static void -http_chunked_readcb(struct bufferevent *bev, void *arg) -{ - /* nothing here */ -} - -static void -http_chunked_errorcb(struct bufferevent *bev, short what, void *arg) -{ - if (!test_ok) - goto out; - - test_ok = -1; - - if ((what & EVBUFFER_EOF) != 0) { - struct evhttp_request *req = evhttp_request_new(NULL, NULL); - const char *header; - enum message_read_status done; - - req->kind = EVHTTP_RESPONSE; - done = evhttp_parse_firstline(req, EVBUFFER_INPUT(bev)); - if (done != ALL_DATA_READ) - goto out; - - done = evhttp_parse_headers(req, EVBUFFER_INPUT(bev)); - if (done != ALL_DATA_READ) - goto out; - - header = evhttp_find_header(req->input_headers, "Transfer-Encoding"); - if (header == NULL || strcmp(header, "chunked")) - goto out; - - header = evhttp_find_header(req->input_headers, "Connection"); - if (header == NULL || strcmp(header, "close")) - goto out; - - header = evbuffer_readline(EVBUFFER_INPUT(bev)); - if (header == NULL) - goto out; - /* 13 chars */ - if (strcmp(header, "d")) - goto out; - free((char*)header); - - if (strncmp((char *)EVBUFFER_DATA(EVBUFFER_INPUT(bev)), - "This is funny", 13)) - goto out; - - evbuffer_drain(EVBUFFER_INPUT(bev), 13 + 2); - - header = evbuffer_readline(EVBUFFER_INPUT(bev)); - if (header == NULL) - goto out; - /* 18 chars */ - if (strcmp(header, "12")) - goto out; - free((char *)header); - - if (strncmp((char *)EVBUFFER_DATA(EVBUFFER_INPUT(bev)), - "but not hilarious.", 18)) - goto out; - - evbuffer_drain(EVBUFFER_INPUT(bev), 18 + 2); - - header = evbuffer_readline(EVBUFFER_INPUT(bev)); - if (header == NULL) - goto out; - /* 8 chars */ - if (strcmp(header, "8")) - goto out; - free((char *)header); - - if (strncmp((char *)EVBUFFER_DATA(EVBUFFER_INPUT(bev)), - "bwv 1052.", 8)) - goto out; - - evbuffer_drain(EVBUFFER_INPUT(bev), 8 + 2); - - header = evbuffer_readline(EVBUFFER_INPUT(bev)); - if (header == NULL) - goto out; - /* 0 chars */ - if (strcmp(header, "0")) - goto out; - free((char *)header); - - test_ok = 2; - } - -out: - event_loopexit(NULL); -} - -static void -http_chunked_writecb(struct bufferevent *bev, void *arg) -{ - if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(bev)) == 0) { - /* enable reading of the reply */ - bufferevent_enable(bev, EV_READ); - test_ok++; - } -} - -static void -http_chunked_request_done(struct evhttp_request *req, void *arg) -{ - if (req->response_code != HTTP_OK) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (evhttp_find_header(req->input_headers, - "Transfer-Encoding") == NULL) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (EVBUFFER_LENGTH(req->input_buffer) != 13 + 18 + 8) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - if (strncmp((char *)EVBUFFER_DATA(req->input_buffer), - "This is funnybut not hilarious.bwv 1052", - 13 + 18 + 8)) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -static void -http_chunked_test(void) -{ - struct bufferevent *bev; - int fd; - const char *http_request; - short port = -1; - struct timeval tv_start, tv_end; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - int i; - - test_ok = 0; - fprintf(stdout, "Testing Chunked HTTP Reply: "); - - http = http_setup(&port, NULL); - - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, - http_chunked_readcb, http_chunked_writecb, - http_chunked_errorcb, NULL); - - http_request = - "GET /chunked HTTP/1.1\r\n" - "Host: somehost\r\n" - "Connection: close\r\n" - "\r\n"; - - bufferevent_write(bev, http_request, strlen(http_request)); - - evutil_gettimeofday(&tv_start, NULL); - - event_dispatch(); - - evutil_gettimeofday(&tv_end, NULL); - evutil_timersub(&tv_end, &tv_start, &tv_end); - - if (tv_end.tv_sec >= 1) { - fprintf(stdout, "FAILED (time)\n"); - exit (1); - } - - - if (test_ok != 2) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* now try again with the regular connection object */ - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* make two requests to check the keepalive behavior */ - for (i = 0; i < 2; i++) { - test_ok = 0; - req = evhttp_request_new(http_chunked_request_done, NULL); - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, - EVHTTP_REQ_GET, "/chunked") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - } - - evhttp_connection_free(evcon); - evhttp_free(http); - - fprintf(stdout, "OK\n"); -} - -static void -http_multi_line_header_test(void) -{ - struct bufferevent *bev; - int fd; - const char *http_start_request; - short port = -1; - - test_ok = 0; - fprintf(stdout, "Testing HTTP Server with multi line: "); - - http = http_setup(&port, NULL); - - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, http_readcb, http_writecb, - http_errorcb, NULL); - - http_start_request = - "GET /test HTTP/1.1\r\n" - "Host: somehost\r\n" - "Connection: close\r\n" - "X-Multi: aaaaaaaa\r\n" - " a\r\n" - "\tEND\r\n" - "X-Last: last\r\n" - "\r\n"; - - bufferevent_write(bev, http_start_request, strlen(http_start_request)); - - event_dispatch(); - - bufferevent_free(bev); - EVUTIL_CLOSESOCKET(fd); - - evhttp_free(http); - - if (test_ok != 4) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -static void -http_request_bad(struct evhttp_request *req, void *arg) -{ - if (req != NULL) { - fprintf(stderr, "FAILED\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -static void -http_negative_content_length_test(void) -{ - short port = -1; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - - test_ok = 0; - fprintf(stdout, "Testing HTTP Negative Content Length: "); - - http = http_setup(&port, NULL); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* - * At this point, we want to schedule a request to the HTTP - * server using our make request method. - */ - - req = evhttp_request_new(http_request_bad, NULL); - - /* Cause the response to have a negative content-length */ - evhttp_add_header(req->output_headers, "X-Negative", "makeitso"); - - /* We give ownership of the request to the connection */ - if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - event_dispatch(); - - evhttp_free(http); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); -} - -/* - * Testing client reset of server chunked connections - */ - -struct terminate_state { - struct evhttp_request *req; - struct bufferevent *bev; - int fd; -} terminate_state; - -static void -terminate_chunked_trickle_cb(int fd, short events, void *arg) -{ - struct terminate_state *state = arg; - struct evbuffer *evb = evbuffer_new(); - struct timeval tv; - - if (evhttp_request_get_connection(state->req) == NULL) { - test_ok = 1; - evhttp_request_free(state->req); - event_loopexit(NULL); - return; - } - - evbuffer_add_printf(evb, "%p", evb); - evhttp_send_reply_chunk(state->req, evb); - evbuffer_free(evb); - - tv.tv_sec = 0; - tv.tv_usec = 3000; - event_once(-1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv); -} - -static void -terminate_chunked_cb(struct evhttp_request *req, void *arg) -{ - struct terminate_state *state = arg; - struct timeval tv; - - state->req = req; - - evhttp_send_reply_start(req, HTTP_OK, "OK"); - - tv.tv_sec = 0; - tv.tv_usec = 3000; - event_once(-1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv); -} - -static void -terminate_chunked_client(int fd, short event, void *arg) -{ - struct terminate_state *state = arg; - bufferevent_free(state->bev); - EVUTIL_CLOSESOCKET(state->fd); -} - -static void -terminate_readcb(struct bufferevent *bev, void *arg) -{ - /* just drop the data */ - evbuffer_drain(bev->output, -1); -} - - -static void -http_terminate_chunked_test(void) -{ - struct bufferevent *bev = NULL; - struct timeval tv; - const char *http_request; - short port = -1; - int fd = -1; - - test_ok = 0; - fprintf(stdout, "Testing Terminated Chunked Connection: "); - - http = http_setup(&port, NULL); - evhttp_del_cb(http, "/test"); - evhttp_set_cb(http, "/test", terminate_chunked_cb, &terminate_state); - - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = bufferevent_new(fd, terminate_readcb, http_writecb, - http_errorcb, NULL); - - terminate_state.fd = fd; - terminate_state.bev = bev; - - /* first half of the http request */ - http_request = - "GET /test HTTP/1.1\r\n" - "Host: some\r\n\r\n"; - - bufferevent_write(bev, http_request, strlen(http_request)); - evutil_timerclear(&tv); - tv.tv_usec = 10000; - event_once(-1, EV_TIMEOUT, terminate_chunked_client, &terminate_state, - &tv); - - event_dispatch(); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - if (fd >= 0) - EVUTIL_CLOSESOCKET(fd); - if (http) - evhttp_free(http); -} - -void -http_suite(void) -{ - http_base_test(); - http_bad_header_test(); - http_parse_query_test(); - http_basic_test(); - http_connection_test(0 /* not-persistent */); - http_connection_test(1 /* persistent */); - http_close_detection(0 /* without delay */); - http_close_detection(1 /* with delay */); - http_bad_request(); - http_post_test(); - http_failure_test(); - http_highport_test(); - http_dispatcher_test(); - - http_multi_line_header_test(); - http_negative_content_length_test(); - - http_chunked_test(); - http_terminate_chunked_test(); -}
diff --git a/third_party/libevent/test/regress_rpc.c b/third_party/libevent/test/regress_rpc.c deleted file mode 100644 index 7609347..0000000 --- a/third_party/libevent/test/regress_rpc.c +++ /dev/null
@@ -1,631 +0,0 @@ -/* - * Copyright (c) 2003-2006 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef WIN32 -#include <winsock2.h> -#include <windows.h> -#endif - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <sys/queue.h> -#ifndef WIN32 -#include <sys/socket.h> -#include <signal.h> -#include <unistd.h> -#include <netdb.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <assert.h> - -#include "event.h" -#include "evhttp.h" -#include "log.h" -#include "evrpc.h" - -#include "regress.gen.h" - -void rpc_suite(void); - -extern int test_ok; - -static struct evhttp * -http_setup(short *pport) -{ - int i; - struct evhttp *myhttp; - short port = -1; - - /* Try a few different ports */ - for (i = 0; i < 50; ++i) { - myhttp = evhttp_start("127.0.0.1", 8080 + i); - if (myhttp != NULL) { - port = 8080 + i; - break; - } - } - - if (port == -1) - event_errx(1, "Could not start web server"); - - *pport = port; - return (myhttp); -} - -EVRPC_HEADER(Message, msg, kill); -EVRPC_HEADER(NeverReply, msg, kill); - -EVRPC_GENERATE(Message, msg, kill); -EVRPC_GENERATE(NeverReply, msg, kill); - -static int need_input_hook = 0; -static int need_output_hook = 0; - -static void -MessageCb(EVRPC_STRUCT(Message)* rpc, void *arg) -{ - struct kill* kill_reply = rpc->reply; - - if (need_input_hook) { - struct evhttp_request* req = EVRPC_REQUEST_HTTP(rpc); - const char *header = evhttp_find_header( - req->input_headers, "X-Hook"); - assert(strcmp(header, "input") == 0); - } - - /* we just want to fill in some non-sense */ - EVTAG_ASSIGN(kill_reply, weapon, "dagger"); - EVTAG_ASSIGN(kill_reply, action, "wave around like an idiot"); - - /* no reply to the RPC */ - EVRPC_REQUEST_DONE(rpc); -} - -static EVRPC_STRUCT(NeverReply) *saved_rpc; - -static void -NeverReplyCb(EVRPC_STRUCT(NeverReply)* rpc, void *arg) -{ - test_ok += 1; - saved_rpc = rpc; -} - -static void -rpc_setup(struct evhttp **phttp, short *pport, struct evrpc_base **pbase) -{ - short port; - struct evhttp *http = NULL; - struct evrpc_base *base = NULL; - - http = http_setup(&port); - base = evrpc_init(http); - - EVRPC_REGISTER(base, Message, msg, kill, MessageCb, NULL); - EVRPC_REGISTER(base, NeverReply, msg, kill, NeverReplyCb, NULL); - - *phttp = http; - *pport = port; - *pbase = base; - - need_input_hook = 0; - need_output_hook = 0; -} - -static void -rpc_teardown(struct evrpc_base *base) -{ - assert(EVRPC_UNREGISTER(base, Message) == 0); - assert(EVRPC_UNREGISTER(base, NeverReply) == 0); - - evrpc_free(base); -} - -static void -rpc_postrequest_failure(struct evhttp_request *req, void *arg) -{ - if (req->response_code != HTTP_SERVUNAVAIL) { - - fprintf(stderr, "FAILED (response code)\n"); - exit(1); - } - - test_ok = 1; - event_loopexit(NULL); -} - -/* - * Test a malformed payload submitted as an RPC - */ - -static void -rpc_basic_test(void) -{ - short port; - struct evhttp *http = NULL; - struct evrpc_base *base = NULL; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - - fprintf(stdout, "Testing Basic RPC Support: "); - - rpc_setup(&http, &port, &base); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* - * At this point, we want to schedule an HTTP POST request - * server using our make request method. - */ - - req = evhttp_request_new(rpc_postrequest_failure, NULL); - if (req == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - evbuffer_add_printf(req->output_buffer, "Some Nonsense"); - - if (evhttp_make_request(evcon, req, - EVHTTP_REQ_POST, - "/.rpc.Message") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - test_ok = 0; - - event_dispatch(); - - evhttp_connection_free(evcon); - - rpc_teardown(base); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - evhttp_free(http); -} - -static void -rpc_postrequest_done(struct evhttp_request *req, void *arg) -{ - struct kill* kill_reply = NULL; - - if (req->response_code != HTTP_OK) { - - fprintf(stderr, "FAILED (response code)\n"); - exit(1); - } - - kill_reply = kill_new(); - - if ((kill_unmarshal(kill_reply, req->input_buffer)) == -1) { - fprintf(stderr, "FAILED (unmarshal)\n"); - exit(1); - } - - kill_free(kill_reply); - - test_ok = 1; - event_loopexit(NULL); -} - -static void -rpc_basic_message(void) -{ - short port; - struct evhttp *http = NULL; - struct evrpc_base *base = NULL; - struct evhttp_connection *evcon = NULL; - struct evhttp_request *req = NULL; - struct msg *msg; - - fprintf(stdout, "Testing Good RPC Post: "); - - rpc_setup(&http, &port, &base); - - evcon = evhttp_connection_new("127.0.0.1", port); - if (evcon == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* - * At this point, we want to schedule an HTTP POST request - * server using our make request method. - */ - - req = evhttp_request_new(rpc_postrequest_done, NULL); - if (req == NULL) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - /* Add the information that we care about */ - evhttp_add_header(req->output_headers, "Host", "somehost"); - - /* set up the basic message */ - msg = msg_new(); - EVTAG_ASSIGN(msg, from_name, "niels"); - EVTAG_ASSIGN(msg, to_name, "tester"); - msg_marshal(req->output_buffer, msg); - msg_free(msg); - - if (evhttp_make_request(evcon, req, - EVHTTP_REQ_POST, - "/.rpc.Message") == -1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - test_ok = 0; - - event_dispatch(); - - evhttp_connection_free(evcon); - - rpc_teardown(base); - - if (test_ok != 1) { - fprintf(stdout, "FAILED\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - evhttp_free(http); -} - -static struct evrpc_pool * -rpc_pool_with_connection(short port) -{ - struct evhttp_connection *evcon; - struct evrpc_pool *pool; - - pool = evrpc_pool_new(NULL); - assert(pool != NULL); - - evcon = evhttp_connection_new("127.0.0.1", port); - assert(evcon != NULL); - - evrpc_pool_add_connection(pool, evcon); - - return (pool); -} - -static void -GotKillCb(struct evrpc_status *status, - struct msg *msg, struct kill *kill, void *arg) -{ - char *weapon; - char *action; - - if (need_output_hook) { - struct evhttp_request *req = status->http_req; - const char *header = evhttp_find_header( - req->input_headers, "X-Pool-Hook"); - assert(strcmp(header, "ran") == 0); - } - - if (status->error != EVRPC_STATUS_ERR_NONE) - goto done; - - if (EVTAG_GET(kill, weapon, &weapon) == -1) { - fprintf(stderr, "get weapon\n"); - goto done; - } - if (EVTAG_GET(kill, action, &action) == -1) { - fprintf(stderr, "get action\n"); - goto done; - } - - if (strcmp(weapon, "dagger")) - goto done; - - if (strcmp(action, "wave around like an idiot")) - goto done; - - test_ok += 1; - -done: - event_loopexit(NULL); -} - -static void -GotKillCbTwo(struct evrpc_status *status, - struct msg *msg, struct kill *kill, void *arg) -{ - char *weapon; - char *action; - - if (status->error != EVRPC_STATUS_ERR_NONE) - goto done; - - if (EVTAG_GET(kill, weapon, &weapon) == -1) { - fprintf(stderr, "get weapon\n"); - goto done; - } - if (EVTAG_GET(kill, action, &action) == -1) { - fprintf(stderr, "get action\n"); - goto done; - } - - if (strcmp(weapon, "dagger")) - goto done; - - if (strcmp(action, "wave around like an idiot")) - goto done; - - test_ok += 1; - -done: - if (test_ok == 2) - event_loopexit(NULL); -} - -static int -rpc_hook_add_header(struct evhttp_request *req, - struct evbuffer *evbuf, void *arg) -{ - const char *hook_type = arg; - if (strcmp("input", hook_type) == 0) - evhttp_add_header(req->input_headers, "X-Hook", hook_type); - else - evhttp_add_header(req->output_headers, "X-Hook", hook_type); - return (0); -} - -static int -rpc_hook_remove_header(struct evhttp_request *req, - struct evbuffer *evbuf, void *arg) -{ - const char *header = evhttp_find_header(req->input_headers, "X-Hook"); - assert(header != NULL); - assert(strcmp(header, arg) == 0); - evhttp_remove_header(req->input_headers, "X-Hook"); - evhttp_add_header(req->input_headers, "X-Pool-Hook", "ran"); - - return (0); -} - -static void -rpc_basic_client(void) -{ - short port; - struct evhttp *http = NULL; - struct evrpc_base *base = NULL; - struct evrpc_pool *pool = NULL; - struct msg *msg; - struct kill *kill; - - fprintf(stdout, "Testing RPC Client: "); - - rpc_setup(&http, &port, &base); - - need_input_hook = 1; - need_output_hook = 1; - - assert(evrpc_add_hook(base, EVRPC_INPUT, rpc_hook_add_header, (void*)"input") - != NULL); - assert(evrpc_add_hook(base, EVRPC_OUTPUT, rpc_hook_add_header, (void*)"output") - != NULL); - - pool = rpc_pool_with_connection(port); - - assert(evrpc_add_hook(pool, EVRPC_INPUT, rpc_hook_remove_header, (void*)"output")); - - /* set up the basic message */ - msg = msg_new(); - EVTAG_ASSIGN(msg, from_name, "niels"); - EVTAG_ASSIGN(msg, to_name, "tester"); - - kill = kill_new(); - - EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); - - test_ok = 0; - - event_dispatch(); - - if (test_ok != 1) { - fprintf(stdout, "FAILED (1)\n"); - exit(1); - } - - /* we do it twice to make sure that reuse works correctly */ - kill_clear(kill); - - EVRPC_MAKE_REQUEST(Message, pool, msg, kill, GotKillCb, NULL); - - event_dispatch(); - - rpc_teardown(base); - - if (test_ok != 2) { - fprintf(stdout, "FAILED (2)\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - msg_free(msg); - kill_free(kill); - - evrpc_pool_free(pool); - evhttp_free(http); -} - -/* - * We are testing that the second requests gets send over the same - * connection after the first RPCs completes. - */ -static void -rpc_basic_queued_client(void) -{ - short port; - struct evhttp *http = NULL; - struct evrpc_base *base = NULL; - struct evrpc_pool *pool = NULL; - struct msg *msg; - struct kill *kill_one, *kill_two; - - fprintf(stdout, "Testing RPC (Queued) Client: "); - - rpc_setup(&http, &port, &base); - - pool = rpc_pool_with_connection(port); - - /* set up the basic message */ - msg = msg_new(); - EVTAG_ASSIGN(msg, from_name, "niels"); - EVTAG_ASSIGN(msg, to_name, "tester"); - - kill_one = kill_new(); - kill_two = kill_new(); - - EVRPC_MAKE_REQUEST(Message, pool, msg, kill_one, GotKillCbTwo, NULL); - EVRPC_MAKE_REQUEST(Message, pool, msg, kill_two, GotKillCb, NULL); - - test_ok = 0; - - event_dispatch(); - - rpc_teardown(base); - - if (test_ok != 2) { - fprintf(stdout, "FAILED (1)\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - msg_free(msg); - kill_free(kill_one); - kill_free(kill_two); - - evrpc_pool_free(pool); - evhttp_free(http); -} - -static void -GotErrorCb(struct evrpc_status *status, - struct msg *msg, struct kill *kill, void *arg) -{ - if (status->error != EVRPC_STATUS_ERR_TIMEOUT) - goto done; - - /* should never be complete but just to check */ - if (kill_complete(kill) == 0) - goto done; - - test_ok += 1; - -done: - event_loopexit(NULL); -} - -static void -rpc_client_timeout(void) -{ - short port; - struct evhttp *http = NULL; - struct evrpc_base *base = NULL; - struct evrpc_pool *pool = NULL; - struct msg *msg; - struct kill *kill; - - fprintf(stdout, "Testing RPC Client Timeout: "); - - rpc_setup(&http, &port, &base); - - pool = rpc_pool_with_connection(port); - - /* set the timeout to 5 seconds */ - evrpc_pool_set_timeout(pool, 5); - - /* set up the basic message */ - msg = msg_new(); - EVTAG_ASSIGN(msg, from_name, "niels"); - EVTAG_ASSIGN(msg, to_name, "tester"); - - kill = kill_new(); - - EVRPC_MAKE_REQUEST(NeverReply, pool, msg, kill, GotErrorCb, NULL); - - test_ok = 0; - - event_dispatch(); - - /* free the saved RPC structure up */ - EVRPC_REQUEST_DONE(saved_rpc); - - rpc_teardown(base); - - if (test_ok != 2) { - fprintf(stdout, "FAILED (1)\n"); - exit(1); - } - - fprintf(stdout, "OK\n"); - - msg_free(msg); - kill_free(kill); - - evrpc_pool_free(pool); - evhttp_free(http); -} - -void -rpc_suite(void) -{ - rpc_basic_test(); - rpc_basic_message(); - rpc_basic_client(); - rpc_basic_queued_client(); - rpc_client_timeout(); -}
diff --git a/third_party/libevent/test/test-eof.c b/third_party/libevent/test/test-eof.c deleted file mode 100644 index 3264a7b..0000000 --- a/third_party/libevent/test/test-eof.c +++ /dev/null
@@ -1,86 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#ifdef WIN32 -#include <winsock2.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <errno.h> - -#include <event.h> -#include <evutil.h> - -int test_okay = 1; -int called = 0; - -static void -read_cb(int fd, short event, void *arg) -{ - char buf[256]; - int len; - - len = recv(fd, buf, sizeof(buf), 0); - - printf("%s: read %d%s\n", __func__, - len, len ? "" : " - means EOF"); - - if (len) { - if (!called) - event_add(arg, NULL); - } else if (called == 1) - test_okay = 0; - - called++; -} - -#ifndef SHUT_WR -#define SHUT_WR 1 -#endif - -int -main (int argc, char **argv) -{ - struct event ev; - const char *test = "test string"; - int pair[2]; - - if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) - return (1); - - - send(pair[0], test, strlen(test)+1, 0); - shutdown(pair[0], SHUT_WR); - - /* Initalize the event library */ - event_init(); - - /* Initalize one event */ - event_set(&ev, pair[1], EV_READ, read_cb, &ev); - - event_add(&ev, NULL); - - event_dispatch(); - - return (test_okay); -} -
diff --git a/third_party/libevent/test/test-init.c b/third_party/libevent/test/test-init.c deleted file mode 100644 index d60aa36..0000000 --- a/third_party/libevent/test/test-init.c +++ /dev/null
@@ -1,40 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#include <winsock2.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <errno.h> - -#include <event.h> - -int -main(int argc, char **argv) -{ - /* Initalize the event library */ - event_init(); - - return (0); -} -
diff --git a/third_party/libevent/test/test-time.c b/third_party/libevent/test/test-time.c deleted file mode 100644 index 703bc32..0000000 --- a/third_party/libevent/test/test-time.c +++ /dev/null
@@ -1,89 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#include <winsock2.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <errno.h> - -#include <event.h> - -int called = 0; - -#define NEVENT 20000 - -struct event *ev[NEVENT]; - -static int -rand_int(int n) -{ -#ifdef WIN32 - return (int)(rand() * n); -#else - return (int)(random() % n); -#endif -} - -static void -time_cb(int fd, short event, void *arg) -{ - struct timeval tv; - int i, j; - - called++; - - if (called < 10*NEVENT) { - for (i = 0; i < 10; i++) { - j = rand_int(NEVENT); - tv.tv_sec = 0; - tv.tv_usec = rand_int(50000); - if (tv.tv_usec % 2) - evtimer_add(ev[j], &tv); - else - evtimer_del(ev[j]); - } - } -} - -int -main (int argc, char **argv) -{ - struct timeval tv; - int i; - - /* Initalize the event library */ - event_init(); - - for (i = 0; i < NEVENT; i++) { - ev[i] = malloc(sizeof(struct event)); - - /* Initalize one event */ - evtimer_set(ev[i], time_cb, ev[i]); - tv.tv_sec = 0; - tv.tv_usec = rand_int(50000); - evtimer_add(ev[i], &tv); - } - - event_dispatch(); - - return (called < NEVENT); -} -
diff --git a/third_party/libevent/test/test-weof.c b/third_party/libevent/test/test-weof.c deleted file mode 100644 index 7fd6c8b..0000000 --- a/third_party/libevent/test/test-weof.c +++ /dev/null
@@ -1,84 +0,0 @@ -/* - * Compile with: - * cc -I/usr/local/include -o time-test time-test.c -L/usr/local/lib -levent - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -#ifdef WIN32 -#include <winsock2.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <signal.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <errno.h> - -#include <event.h> -#include <evutil.h> - -int pair[2]; -int test_okay = 1; -int called = 0; - -static void -write_cb(int fd, short event, void *arg) -{ - const char *test = "test string"; - int len; - - len = send(fd, test, strlen(test) + 1, 0); - - printf("%s: write %d%s\n", __func__, - len, len ? "" : " - means EOF"); - - if (len > 0) { - if (!called) - event_add(arg, NULL); - EVUTIL_CLOSESOCKET(pair[0]); - } else if (called == 1) - test_okay = 0; - - called++; -} - -int -main (int argc, char **argv) -{ - struct event ev; - -#ifndef WIN32 - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - return (1); -#endif - - if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) - return (1); - - /* Initalize the event library */ - event_init(); - - /* Initalize one event */ - event_set(&ev, pair[1], EV_WRITE, write_cb, &ev); - - event_add(&ev, NULL); - - event_dispatch(); - - return (test_okay); -} -
diff --git a/third_party/libevent/test/test.sh b/third_party/libevent/test/test.sh deleted file mode 100755 index 506a1988..0000000 --- a/third_party/libevent/test/test.sh +++ /dev/null
@@ -1,91 +0,0 @@ -#!/bin/sh - -setup () { - EVENT_NOKQUEUE=yes; export EVENT_NOKQUEUE - EVENT_NODEVPOLL=yes; export EVENT_NODEVPOLL - EVENT_NOPOLL=yes; export EVENT_NOPOLL - EVENT_NOSELECT=yes; export EVENT_NOSELECT - EVENT_NOEPOLL=yes; export EVENT_NOEPOLL - EVENT_NOEVPORT=yes; export EVENT_NOEVPORT -} - -test () { - if ./test-init 2>/dev/null ; - then - true - else - echo Skipping test - return - fi - -echo -n " test-eof: " -if ./test-eof >/dev/null ; -then - echo OKAY ; -else - echo FAILED ; -fi -echo -n " test-weof: " -if ./test-weof >/dev/null ; -then - echo OKAY ; -else - echo FAILED ; -fi -echo -n " test-time: " -if ./test-time >/dev/null ; -then - echo OKAY ; -else - echo FAILED ; -fi -echo -n " regress: " -if ./regress >/dev/null ; -then - echo OKAY ; -else - echo FAILED ; -fi -} - -echo "Running tests:" - -# Need to do this by hand? -setup -unset EVENT_NOKQUEUE -export EVENT_NOKQUEUE -echo "KQUEUE" -test - -setup -unset EVENT_NODEVPOLL -export EVENT_NODEVPOLL -echo "DEVPOLL" -test - -setup -unset EVENT_NOPOLL -export EVENT_NOPOLL -echo "POLL" -test - -setup -unset EVENT_NOSELECT -export EVENT_NOSELECT -echo "SELECT" -test - -setup -unset EVENT_NOEPOLL -export EVENT_NOEPOLL -echo "EPOLL" -test - -setup -unset EVENT_NOEVPORT -export EVENT_NOEVPORT -echo "EVPORT" -test - - -
diff --git a/third_party/libevent/whatsnew-14.txt b/third_party/libevent/whatsnew-14.txt deleted file mode 100644 index 769dda78..0000000 --- a/third_party/libevent/whatsnew-14.txt +++ /dev/null
@@ -1,167 +0,0 @@ -What's New In Libevent 1.4: - -0. About this document - - This document describes the key differences between Libevent 1.3 and - Libevent 1.4, from a user's point of view. It was most recently - updated based on features from libevent 1.4.2-rc. - -1. Packaging Issues. - -1.1. The great library division. - - The libevent source now builds two libraries: libevent_core and - libevent_extra. The libevent_core library includes event loops, - timers, buffer code, and various small compatibility functions. The - libevent_extra library includes code for HTTP, DNS, RPC, and so on. - Thus, if you're writing software that only uses libevent's event - loop, you should link against only the libevent_core library, - whereas if you're writing software that uses libevent's protocol - support as well, you need to link libevent_extra as well. - - For backward compatibility, libevent also builds a library called - "libevent" that includes everything. - -1.2. The event-config.h header - - Libevent configure script now builds two headers from its configure - script: config.h (which it uses internally) and event-config.h - (which it installs as a header file). All of the macros in - event-config.h are modified so that they're safe to include in other - projects. This allows libevent's header files (like event.h and - evutil.h) information about platform configuration. - - What does this mean for you? As of 1.4.x, it should never be - necessary to include extra files or define extra types before you - include event.h (or any other libevent header); event.h can now look - at the information in event-config.h and figure out what it needs to - include. - -1.3. Documentation - - Libevent now includes better doxygen documentation. It's not - perfect or complete, though; if you find a mistake, please let us - know. - -1.4. Libtool usage - - We now use libtool's library versioning support correctly. If we - don't mess this up, it means that binaries linked against old - version of libevent should continue working when we make changes to - libevent that don't break backward compatibility. - -1.5. Portability - - Libevent now builds with MSVC again. We've only tested it with MSVC - 2005, and the project files might not be right. Please let us know - if you run into any issues. - - Libevent now builds on platforms where /bin/sh is not bash. - - Libevent's regression test no longer requires Python to be - installed. - -2. New and Improved APIs: - - (This list includes functions that are new, functions whose behavior - has changed, and functions that were included in previous releases - but which never actually worked before.) - -2.1. Utility functions are defined in evutil.h - - Libevent now exposes a small set of functions for cross-platform - network programming in evutil.h, on the theory that they've been - useful enough to us that other people may likely want to use them - too. These are mainly workarounds for Windows issues for now: they - include evutil_socketpair (to fake socketpair on platforms that - don't have it) and evutil_make_socket_nonblocking (to make a socket - nonblocking in a cross-platform way. See the header for more - information. - -2.2. In the libevent core. - - The event_base_free() function now works. Previously, it would - crash with an assertion failure if there were events pending on a - base. Now, it simply deletes all the pending events and frees the - base. Be careful -- this might leak fds and memory associated with - the old events. To avoid leaks, you should still remove all the - events and free their resources before you delete the base. - - Libevent should now work properly with fork(). Just call - event_reinit() on your event base after the fork call, and it should - work okay. Please let us know about any bugs you find. - - There's a new event_base_new() function that acts just like - event_init(), but does not replace the default base. If you are - using multiple event bases in your code, you should just use - event_base_new() instead of event_init(), to avoid accidental bugs. - - There's new event_loopbreak() function to make a current event loop - stop exiting and return. Unlike event_loopexit, it stops subsequent - pending events from getting executed. This behavior is useful for - scripting languages to implement exceptions from inside callbacks. - - There's a new event_base_get_method() function, for use in place of - event_get_method() in multi-base applications. - -2.3. New in HTTP. - - There's an evhttp_connection_set_local_address() function you can - use to set the local address of an HTTP connection. - - HTTP/1.1 chunking now correctly ends chunks with '\r\n'. - -2.4. New in DNS - - Instead of picking your method for generating DNS transaction IDs at - startup, you can use evdns_set_transaction_id() to provide a - transaction ID function at runtime. - - The "class" field in evdns_server_request is now renamed to - dns_question_class, so that it won't break compilation under C++. - This uses some preprocessor hacks so that C code using the old name - won't break. Eventually, the old name will be deprecated entirely; - please don't use it. - -2.5. New in RPC - - There are now hooks on RPC input and output; can be used to - implement RPC independent processing such as compression or - authentication. - - RPC tags can now be up to 32 bits. This is wire-compatible, but - changes some of the types in the APIs. Please let us know if this - is problematic for you. - -3. Big bugfixes - - We've done a lot, with help from users on different platforms, to - make the different backends behave more similarly with respect to - signals and timeouts. The kqueue and solaris backends were the big - offenders previously, but they should be better now. Windows should - be better too, though it's likely that problems remain there. - - The libevent headers (though not the source files!) should now build - cleanly on C++. - - (For more bugfixes, see the ChangeLog file. These are only the - biggies.) - -4. Big performance improvements - - Libevent now uses a min-heap rather than a red-black tree to track - timeouts. This means that finding the next timeout to fire is now - O(1) instead of (lg n). - - The win32 select-based backend now uses a red-black tree to map - SOCKET handles to event structures. This changes the performance - characteristics of the event loop on win32 from O(n^2) to O(n lg n). - Not perfect, but better. - -5. Removed code and features - - The rtsig backend is now removed. It hasn't even compiled for a - while, and nobody seemed to miss it very much. All the platforms - that have rtsig seem to have a better option instead these days. - Please let us know if rtsig was crucial for you. -
diff --git a/third_party/libyuv b/third_party/libyuv index 307b951..192b8c2 160000 --- a/third_party/libyuv +++ b/third_party/libyuv
@@ -1 +1 @@ -Subproject commit 307b951229cc2eb756af09ea111f7be6ff065d4f +Subproject commit 192b8c2238cae1c26774962eb5b61ba90cd45210
diff --git a/third_party/lit/v3_0/BUILD.gn b/third_party/lit/v3_0/BUILD.gn index cfb067b..f279486e 100644 --- a/third_party/lit/v3_0/BUILD.gn +++ b/third_party/lit/v3_0/BUILD.gn
@@ -34,7 +34,6 @@ "//chrome/browser/resources/extensions:build_ts", "//chrome/browser/resources/family_link_user_internals:build_ts", "//chrome/browser/resources/feedback:build_ts", - "//chrome/browser/resources/internals/user_education:build_ts", "//chrome/browser/resources/intro:build_ts", "//chrome/browser/resources/key_value_pair_viewer_shared:build_ts", "//chrome/browser/resources/management:build_ts", @@ -59,6 +58,7 @@ "//chrome/browser/resources/signin/batch_upload:build_ts", "//chrome/browser/resources/signin/profile_picker:build_ts", "//chrome/browser/resources/tab_search:build_ts", + "//chrome/browser/resources/user_education_internals:build_ts", "//chrome/browser/resources/webui_gallery:build_ts", "//chrome/browser/resources/whats_new:build_ts", "//chrome/test/data/pdf:build_ts",
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src index 5f1326b..5dda257 160000 --- a/third_party/llvm-libc/src +++ b/third_party/llvm-libc/src
@@ -1 +1 @@ -Subproject commit 5f1326b036bfd81c2831089915545189d154426c +Subproject commit 5dda25750dd119c2bff8e279dd1c0f13fbd422e5
diff --git a/third_party/neon_2_sse/README.chromium b/third_party/neon_2_sse/README.chromium index 883d0ed..6b372bb 100644 --- a/third_party/neon_2_sse/README.chromium +++ b/third_party/neon_2_sse/README.chromium
@@ -1,8 +1,8 @@ Name: ARM_NEON_2_x86_SSE Short Name: neon_2_sse URL: https://github.com/intel/ARM_NEON_2_x86_SSE -Version: a15b489e1222b2087007546b4912e21293ea86ff -Date: 2022-09-23 +Version: eb8b80b28f956275e291ea04a7beb5ed8289e872 +Date: 2024-12-09 License: BSD-Source-Code License File: LICENSE Security Critical: Yes
diff --git a/third_party/neon_2_sse/src b/third_party/neon_2_sse/src index a15b489..eb8b80b 160000 --- a/third_party/neon_2_sse/src +++ b/third_party/neon_2_sse/src
@@ -1 +1 @@ -Subproject commit a15b489e1222b2087007546b4912e21293ea86ff +Subproject commit eb8b80b28f956275e291ea04a7beb5ed8289e872
diff --git a/third_party/rust/chromium_crates_io/gnrt_config.toml b/third_party/rust/chromium_crates_io/gnrt_config.toml index 9f36dd0..2db6d28 100644 --- a/third_party/rust/chromium_crates_io/gnrt_config.toml +++ b/third_party/rust/chromium_crates_io/gnrt_config.toml
@@ -218,9 +218,6 @@ [crate.small_ctor] group = 'test' -[crate.unicode-ident] -license_files = ['LICENSE-APACHE', 'LICENSE-UNICODE'] - [crate.unicode-linebreak] allow_first_party_usage = false build_script_outputs = [ "tables.rs" ]
diff --git a/third_party/rust/miniz_oxide/v0_8/README.chromium b/third_party/rust/miniz_oxide/v0_8/README.chromium index 1127e124..e44bf99 100644 --- a/third_party/rust/miniz_oxide/v0_8/README.chromium +++ b/third_party/rust/miniz_oxide/v0_8/README.chromium
@@ -3,7 +3,7 @@ Version: 0.8.0 Revision: 58cf901875b2a5b3c9eeb844bd534f6cee54f847 License: Apache-2.0 -License File: //third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE,//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-APACHE.md +License File: //third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-APACHE.md Shipped: yes Security Critical: yes
diff --git a/third_party/ruy/src b/third_party/ruy/src index 9889171..95484c3 160000 --- a/third_party/ruy/src +++ b/third_party/ruy/src
@@ -1 +1 @@ -Subproject commit 9889171210b81138fd15fb57dd06e98fe6d37b3c +Subproject commit 95484c3e02206f73309c08ee5ee23d2304ca092b
diff --git a/third_party/skia b/third_party/skia index 16e728a..9e2547e 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 16e728a177b3902b1e9e311bf4af3acd769730e7 +Subproject commit 9e2547efbe95f4a535bb7871256a7286e67a5a0e
diff --git a/third_party/swiftshader b/third_party/swiftshader index 7e54d43..c0fe4d4 160000 --- a/third_party/swiftshader +++ b/third_party/swiftshader
@@ -1 +1 @@ -Subproject commit 7e54d43d6905f978ccf90680dd22a48b0ede8d8b +Subproject commit c0fe4d40475b709a42d78315d3929d41d44838c8
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium index 35bf2a8e..29fd8db 100644 --- a/third_party/tflite/README.chromium +++ b/third_party/tflite/README.chromium
@@ -1,8 +1,8 @@ Name: TensorFlow Lite Short Name: tflite URL: https://github.com/tensorflow/tensorflow -Version: 54d2d15dabe13df91cd97d5290f31b776660ca79 -Date: 2024-11-25 +Version: 73e1e9f4d021a1819a3e2a28889b75de1174bdbe +Date: 2024-12-09 License: Apache-2.0 License File: LICENSE Security Critical: Yes
diff --git a/third_party/tflite/src b/third_party/tflite/src index 54d2d15..73e1e9f 160000 --- a/third_party/tflite/src +++ b/third_party/tflite/src
@@ -1 +1 @@ -Subproject commit 54d2d15dabe13df91cd97d5290f31b776660ca79 +Subproject commit 73e1e9f4d021a1819a3e2a28889b75de1174bdbe
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src index 64eb522..726f4dd 160000 --- a/third_party/webgpu-cts/src +++ b/third_party/webgpu-cts/src
@@ -1 +1 @@ -Subproject commit 64eb522c87efb458b46d84048c3bb4c3c063a21c +Subproject commit 726f4dd24eac0296f4ae39f11ad28d42635b5e55
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt index aadc83a..90853ca1 100644 --- a/third_party/webgpu-cts/ts_sources.txt +++ b/third_party/webgpu-cts/ts_sources.txt
@@ -620,6 +620,8 @@ src/webgpu/shader/execution/expression/call/builtin/subgroupBallot.spec.ts src/webgpu/shader/execution/expression/call/builtin/subgroupBitwise.spec.ts src/webgpu/shader/execution/expression/call/builtin/subgroupBroadcast.spec.ts +src/webgpu/shader/execution/expression/call/builtin/subgroupElect.spec.ts +src/webgpu/shader/execution/expression/call/builtin/subgroupMinMax.spec.ts src/webgpu/shader/execution/expression/call/builtin/subgroupMul.spec.ts src/webgpu/shader/execution/expression/call/builtin/subgroupShuffle.spec.ts src/webgpu/shader/execution/expression/call/builtin/tan.cache.ts
diff --git a/third_party/webrtc b/third_party/webrtc index 3a1f2e6..e754fcf 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 3a1f2e6a694464636d5e779157fc80d691981463 +Subproject commit e754fcfee51354cf4e0f54cbe7051eb235264514
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium index 1072b1f..96b7b02 100644 --- a/third_party/wpt_tools/README.chromium +++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@ Name: web-platform-tests - Test Suites for Web Platform specifications Short Name: wpt URL: https://github.com/web-platform-tests/wpt/ -Version: 6a035397d6fc64d82db054c21cb531592748362e +Version: 39138b0492366aa07ef3e0cce12f67ff2de966a3 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) Security Critical: no Shipped: no
diff --git a/third_party/wpt_tools/WPTIncludeList b/third_party/wpt_tools/WPTIncludeList index 871e6e0a..80c074926 100644 --- a/third_party/wpt_tools/WPTIncludeList +++ b/third_party/wpt_tools/WPTIncludeList
@@ -405,6 +405,7 @@ ./tools/wptrunner/wptrunner/executors/executorservodriver.py ./tools/wptrunner/wptrunner/executors/executorwebdriver.py ./tools/wptrunner/wptrunner/executors/executorwebkit.py +./tools/wptrunner/wptrunner/executors/message-queue.js ./tools/wptrunner/wptrunner/executors/process.py ./tools/wptrunner/wptrunner/executors/protocol.py ./tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py
diff --git a/third_party/wpt_tools/wpt/tools/lint/lint.py b/third_party/wpt_tools/wpt/tools/lint/lint.py index 32bc7ec..c1c3b25 100644 --- a/third_party/wpt_tools/wpt/tools/lint/lint.py +++ b/third_party/wpt_tools/wpt/tools/lint/lint.py
@@ -475,7 +475,7 @@ testdriver_vendor_nodes: List[ElementTree.Element] = [] if source_file.testdriver_nodes: - if test_type != "testharness": + if test_type not in {"testharness", "reftest", "print-reftest", "crashtest", "support"}: errors.append(rules.TestdriverInUnsupportedType.error(path, (test_type,))) if len(source_file.testdriver_nodes) > 1:
diff --git a/third_party/wpt_tools/wpt/tools/manifest/item.py b/third_party/wpt_tools/wpt/tools/manifest/item.py index e25f7ca..e1f509b 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/item.py +++ b/third_party/wpt_tools/wpt/tools/manifest/item.py
@@ -166,7 +166,7 @@ return self._extras.get("pac") @property - def testdriver(self) -> Optional[Text]: + def testdriver(self) -> Optional[bool]: return self._extras.get("testdriver") @property @@ -240,6 +240,10 @@ rv[key] = v return rv + @property + def testdriver(self) -> Optional[bool]: + return self._extras.get("testdriver") + def to_json(self) -> Tuple[Optional[Text], List[Tuple[Text, Text]], Dict[Text, Any]]: # type: ignore rel_url = None if self._url == self.path else self._url rv: Tuple[Optional[Text], List[Tuple[Text, Text]], Dict[Text, Any]] = (rel_url, self.references, {}) @@ -252,6 +256,8 @@ extras["dpi"] = self.dpi if self.fuzzy: extras["fuzzy"] = list(self.fuzzy.items()) + if self.testdriver: + extras["testdriver"] = self.testdriver return rv @classmethod @@ -315,6 +321,16 @@ def timeout(self) -> Optional[Text]: return None + @property + def testdriver(self) -> Optional[bool]: + return self._extras.get("testdriver") + + def to_json(self): # type: ignore + rel_url, extras = super().to_json() + if self.testdriver: + extras["testdriver"] = self.testdriver + return rel_url, extras + class WebDriverSpecTest(URLManifestItem): __slots__ = ()
diff --git a/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py b/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py index 02ab1ad4..e5fd0294 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py +++ b/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py
@@ -946,7 +946,8 @@ self.tests_root, self.rel_path, self.url_base, - self.rel_url + self.rel_url, + testdriver=self.has_testdriver, )] elif self.name_is_print_reftest: @@ -965,6 +966,7 @@ viewport_size=self.viewport_size, fuzzy=self.fuzzy, page_ranges=self.page_ranges, + testdriver=self.has_testdriver, )] elif self.name_is_multi_global: @@ -1065,7 +1067,8 @@ timeout=self.timeout, viewport_size=self.viewport_size, dpi=self.dpi, - fuzzy=self.fuzzy + fuzzy=self.fuzzy, + testdriver=self.has_testdriver, )) elif self.content_is_css_visual and not self.name_is_reference:
diff --git a/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py b/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py index f1fad73..4640731 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py +++ b/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py
@@ -6,7 +6,6 @@ import site import sys import sysconfig -from pathlib import Path from shutil import which # The `pkg_resources` module is provided by `setuptools`, which is itself a @@ -50,11 +49,40 @@ self._working_set = None call(*self.virtualenv, self.path) + def get_paths(self): + """Wrapper around sysconfig.get_paths(), returning the appropriate paths for the env.""" + if "venv" in sysconfig.get_scheme_names(): + # This should always be used on Python 3.11 and above. + scheme = "venv" + elif os.name == "nt": + # This matches nt_venv, unless sysconfig has been modified. + scheme = "nt" + elif os.name == "posix": + # This matches posix_venv, unless sysconfig has been modified. + scheme = "posix_prefix" + elif sys.version_info >= (3, 10): + # Using the default scheme is somewhat fragile, as various Python + # distributors (e.g., what Debian and Fedora package, and what Xcode + # includes) change the default scheme away from the upstream + # defaults, but it's about as good as we can do. + scheme = sysconfig.get_default_scheme() + else: + # This is explicitly documented as having previously existed in the 3.10 + # docs, and has existed since CPython 2.7 and 3.1 (but not 3.0). + scheme = sysconfig._get_default_scheme() + + vars = { + "base": self.path, + "platbase": self.path, + "installed_base": self.path, + "installed_platbase": self.path, + } + + return sysconfig.get_paths(scheme, vars) + @property def bin_path(self): - if sys.platform in ("win32", "cygwin"): - return os.path.join(self.path, "Scripts") - return os.path.join(self.path, "bin") + return self.get_paths()["scripts"] @property def pip_path(self): @@ -67,24 +95,10 @@ @property def lib_path(self): - base = self.path - - # this block is literally taken from virtualenv 16.4.3 - IS_PYPY = hasattr(sys, "pypy_version_info") - IS_JYTHON = sys.platform.startswith("java") - if IS_JYTHON: - site_packages = os.path.join(base, "Lib", "site-packages") - elif IS_PYPY: - site_packages = os.path.join(base, "site-packages") - else: - IS_WIN = sys.platform == "win32" - if IS_WIN: - site_packages = os.path.join(base, "Lib", "site-packages") - else: - version = f"{sys.version_info.major}.{sys.version_info.minor}" - site_packages = os.path.join(base, "lib", f"python{version}", "site-packages") - - return site_packages + # We always return platlib here, even if it differs to purelib, because we can + # always install pure-Python code into the platlib safely too. It's also very + # unlikely to differ for a venv. + return self.get_paths()["platlib"] @property def working_set(self): @@ -97,43 +111,35 @@ return self._working_set def activate(self): - if sys.platform == 'darwin': + if sys.platform == "darwin": # The default Python on macOS sets a __PYVENV_LAUNCHER__ environment # variable which affects invocation of python (e.g. via pip) in a # virtualenv. Unset it if present to avoid this. More background: # https://github.com/web-platform-tests/wpt/issues/27377 # https://github.com/python/cpython/pull/9516 - os.environ.pop('__PYVENV_LAUNCHER__', None) + os.environ.pop("__PYVENV_LAUNCHER__", None) + + paths = self.get_paths() # Setup the path and site packages as if we'd launched with the virtualenv active - bin_dir = os.path.join(self.path, "bin") + bin_dir = paths["scripts"] os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep)) + + # While not required (`./venv/bin/python3` won't set it, but + # `source ./venv/bin/activate && python3` will), we have historically set this. os.environ["VIRTUAL_ENV"] = self.path prev_length = len(sys.path) - schemes = sysconfig.get_scheme_names() - if "venv" in schemes: - scheme = "venv" - else: - scheme = "nt" if os.name == "nt" else "posix_user" - sys_paths = sysconfig.get_paths(scheme) - data_path = sys_paths["data"] - added = set() # Add the venv library paths as sitedirs. - # This converts system paths like /usr/local/lib/python3.10/site-packages - # to venv-relative paths like {self.path}/lib/python3.10/site-packages and adds - # those paths as site dirs to be used for module import. for key in ["purelib", "platlib"]: - host_path = Path(sys_paths[key]) - relative_path = host_path.relative_to(data_path) - site_dir = os.path.normpath(os.path.normcase(Path(self.path) / relative_path)) - if site_dir not in added: - site.addsitedir(site_dir) - added.add(site_dir) + site.addsitedir(paths[key]) + + # Rearrange the path sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length] - sys.real_prefix = sys.prefix + # Change prefixes, similar to what initconfig/site does for venvs. + sys.exec_prefix = self.path sys.prefix = self.path def start(self):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py index 2cb638b..1e9a2f30 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py
@@ -1,19 +1,13 @@ # mypy: allow-untyped-defs import os -import subprocess import tempfile -from mozprocess import ProcessHandler - from tools.serve.serve import make_hosts_file -from .base import (Browser, - ExecutorBrowser, - OutputHandler, +from .base import (WebDriverBrowser, require_arg, - get_free_port, - browser_command) + get_free_port) from .base import get_timeout_multiplier # noqa: F401 from ..executors import executor_kwargs as base_executor_kwargs from ..executors.executorservodriver import (ServoWebDriverTestharnessExecutor, # noqa: F401 @@ -64,8 +58,7 @@ def env_options(): return {"server_host": "127.0.0.1", - "testharnessreport": "testharnessreport-servodriver.js", - "supports_debugger": True} + "supports_debugger": False} def update_properties(): @@ -79,107 +72,40 @@ return hosts_path -class ServoWebDriverBrowser(Browser): +class ServoWebDriverBrowser(WebDriverBrowser): init_timeout = 300 # Large timeout for cases where we're booting an Android emulator def __init__(self, logger, binary, debug_info=None, webdriver_host="127.0.0.1", server_config=None, binary_args=None, user_stylesheets=None, headless=None, **kwargs): - Browser.__init__(self, logger) - self.binary = binary - self.binary_args = binary_args or [] - self.webdriver_host = webdriver_host - self.webdriver_port = None - self.proc = None - self.debug_info = debug_info - self.hosts_path = write_hosts_file(server_config) - self.server_ports = server_config.ports if server_config else {} - self.command = None - self.user_stylesheets = user_stylesheets if user_stylesheets else [] - self.headless = headless if headless else False - self.ca_certificate_path = server_config.ssl_config["ca_cert_path"] - self.output_handler = None - - def start(self, **kwargs): - self.webdriver_port = get_free_port() - + hosts_path = write_hosts_file(server_config) + port = get_free_port() env = os.environ.copy() - env["HOST_FILE"] = self.hosts_path + env["HOST_FILE"] = hosts_path env["RUST_BACKTRACE"] = "1" - env["EMULATOR_REVERSE_FORWARD_PORTS"] = ",".join( - str(port) - for _protocol, ports in self.server_ports.items() - for port in ports - if port - ) - debug_args, command = browser_command( - self.binary, - self.binary_args + [ - "--hard-fail", - "--webdriver=%s" % self.webdriver_port, - "about:blank", - ], - self.debug_info - ) + args = [ + "--hard-fail", + "--webdriver=%s" % port, + "about:blank", + ] - if self.headless: - command += ["--headless"] + ca_cert_path = server_config.ssl_config["ca_cert_path"] + if ca_cert_path: + args += ["--certificate-path", ca_cert_path] + if binary_args: + args += binary_args + if user_stylesheets: + for stylesheet in user_stylesheets: + args += ["--user-stylesheet", stylesheet] + if headless: + args += ["--headless"] - if self.ca_certificate_path: - command += ["--certificate-path", self.ca_certificate_path] - - for stylesheet in self.user_stylesheets: - command += ["--user-stylesheet", stylesheet] - - self.command = command - - self.command = debug_args + self.command - - if not self.debug_info or not self.debug_info.interactive: - self.output_handler = OutputHandler(self.logger, self.command) - self.proc = ProcessHandler(self.command, - processOutputLine=[self.on_output], - env=env, - storeOutput=False) - self.proc.run() - self.output_handler.after_process_start(self.proc.pid) - self.output_handler.start() - else: - self.proc = subprocess.Popen(self.command, env=env) - - self.logger.debug("Servo Started") - - def stop(self, force=False): - self.logger.debug("Stopping browser") - if self.proc is not None: - try: - self.proc.kill() - except OSError: - # This can happen on Windows if the process is already dead - pass - if self.output_handler is not None: - self.output_handler.after_process_stop() - - @property - def pid(self): - if self.proc is None: - return None - - try: - return self.proc.pid - except AttributeError: - return None - - def is_alive(self): - return self.proc.poll() is None + WebDriverBrowser.__init__(self, env=env, logger=logger, host=webdriver_host, port=port, + supports_pac=False, webdriver_binary=binary, webdriver_args=args, + binary=binary) + self.hosts_path = hosts_path def cleanup(self): - self.stop() + WebDriverBrowser.cleanup(self) os.remove(self.hosts_path) - - def executor_browser(self): - assert self.webdriver_port is not None - return ExecutorBrowser, {"webdriver_host": self.webdriver_host, - "webdriver_port": self.webdriver_port, - "init_timeout": self.init_timeout}
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py index 071ff6d..9a6d3c8f 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py
@@ -23,8 +23,6 @@ sys.path.insert(0, repo_root) from tools import localpaths # noqa: F401 -from wptserve.handlers import StringHandler - serve = None @@ -226,29 +224,47 @@ self.config.aliases, self.config) + testharnessreport_format_args = { + "output": self.pause_after_test, + "timeout_multiplier": self.testharness_timeout_multipler, + "explicit_timeout": "true" if self.debug_info is not None else "false", + "debug": "true" if self.debug_test else "false", + } for path, format_args, content_type, route in [ ("testharness_runner.html", {}, "text/html", "/testharness_runner.html"), ("print_pdf_runner.html", {}, "text/html", "/print_pdf_runner.html"), - (os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.js"), None, + (os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.js"), {}, "text/javascript", "/_pdf_js/pdf.js"), - (os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.worker.js"), None, + (os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.worker.js"), {}, "text/javascript", "/_pdf_js/pdf.worker.js"), - (self.options.get("testharnessreport", "testharnessreport.js"), - {"output": self.pause_after_test, - "timeout_multiplier": self.testharness_timeout_multipler, - "explicit_timeout": "true" if self.debug_info is not None else "false", - "debug": "true" if self.debug_test else "false"}, - "text/javascript;charset=utf8", - "/resources/testharnessreport.js")]: - path = os.path.normpath(os.path.join(here, path)) + ( + self.options.get("testharnessreport", [ + # All testharness tests, even those that don't use testdriver, require + # `message-queue.js` to signal completion. + os.path.join("executors", "message-queue.js"), + "testharnessreport.js"]), + testharnessreport_format_args, + "text/javascript;charset=utf8", + "/resources/testharnessreport.js", + ), + ( + [os.path.join(repo_root, "resources", "testdriver.js"), + # Include `message-queue.js` to support testdriver in non-testharness tests. + os.path.join("executors", "message-queue.js"), + "testdriver-extra.js"], + {}, + "text/javascript", + "/resources/testdriver.js", + ), + ]: + paths = [path] if isinstance(path, str) else path + abs_paths = [os.path.normpath(os.path.join(here, path)) for path in paths] # Note that .headers. files don't apply to static routes, so we need to # readd any static headers here. headers = {"Cache-Control": "max-age=3600"} - route_builder.add_static(path, format_args, content_type, route, + route_builder.add_static(abs_paths, format_args, content_type, route, headers=headers) - route_builder.add_handler("GET", "/resources/testdriver.js", TestdriverLoader()) - for url_base, test_root in self.test_paths.items(): if url_base == "/": continue @@ -316,27 +332,6 @@ return failed, pending -class TestdriverLoader: - """A special static handler for serving `/resources/testdriver.js`. - - This handler lazily reads `testdriver{,-extra}.js` so that wptrunner doesn't - need to pass the entire file contents to child `wptserve` processes, which - can slow `wptserve` startup by several seconds (crbug.com/1479850). - """ - def __init__(self): - self._handler = None - - def __call__(self, request, response): - if not self._handler: - data = b"" - with open(os.path.join(repo_root, "resources", "testdriver.js"), "rb") as fp: - data += fp.read() - with open(os.path.join(here, "testdriver-extra.js"), "rb") as fp: - data += fp.read() - self._handler = StringHandler(data, "text/javascript") - return self._handler(request, response) - - def wait_for_service(logger: StructuredLogger, host: str, port: int,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py index 9534eaea..8f9d45d6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py
@@ -111,10 +111,10 @@ else: self.webdriver.execute_script(message_script) - def _get_next_message_classic(self, url): + def _get_next_message_classic(self, url, script_resume): try: message_script, self._pending_message = self._pending_message, "" - return self.parent.base.execute_script(message_script + self.script_resume, + return self.parent.base.execute_script(message_script + script_resume, asynchronous=True, args=[strip_server(url)]) except error.JavascriptErrorException as js_error:
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py index 5d7d55f..41b8ed9 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py
@@ -1,18 +1,8 @@ # mypy: allow-untyped-defs -import json import os -import socket -import traceback -from .base import (Protocol, - RefTestExecutor, - RefTestImplementation, - TestharnessExecutor, - TimedRunner, - strip_server) -from .protocol import BaseProtocolPart -from ..environment import wait_for_service +from .executorwebdriver import WebDriverProtocol, WebDriverTestharnessExecutor, WebDriverRefTestExecutor webdriver = None ServoCommandExtensions = None @@ -64,240 +54,57 @@ return value -class ServoBaseProtocolPart(BaseProtocolPart): - def execute_script(self, script, asynchronous=False): - pass - - def set_timeout(self, timeout): - pass - - def wait(self): - return False - - def set_window(self, handle): - pass - - def window_handles(self): - return [] - - def load(self, url): - pass - - -class ServoWebDriverProtocol(Protocol): - implements = [ServoBaseProtocolPart] - +class ServoWebDriverProtocol(WebDriverProtocol): def __init__(self, executor, browser, capabilities, **kwargs): do_delayed_imports() - Protocol.__init__(self, executor, browser) - self.capabilities = capabilities - self.host = browser.webdriver_host - self.port = browser.webdriver_port - self.init_timeout = browser.init_timeout - self.session = None + WebDriverProtocol.__init__(self, executor, browser, capabilities, **kwargs) def connect(self): - """Connect to browser via WebDriver.""" - wait_for_service(self.logger, self.host, self.port, timeout=self.init_timeout) + """Connect to browser via WebDriver and crete a WebDriver session.""" + self.logger.debug("Connecting to WebDriver on URL: %s" % self.url) - self.session = webdriver.Session(self.host, self.port, extension=ServoCommandExtensions) - self.session.start() + host, port = self.url.split(":")[1].strip("/"), self.url.split(':')[-1].strip("/") - def after_connect(self): - pass - - def teardown(self): - self.logger.debug("Hanging up on WebDriver session") - try: - self.session.end() - except Exception: - pass - - def is_alive(self): - try: - # Get a simple property over the connection - self.session.window_handle - # TODO what exception? - except Exception: - return False - return True - - def wait(self): - while True: - try: - return self.session.execute_async_script("""let callback = arguments[arguments.length - 1]; -addEventListener("__test_restart", e => {e.preventDefault(); callback(true)})""") - except webdriver.TimeoutException: - pass - except (socket.timeout, OSError): - break - except Exception: - self.logger.error(traceback.format_exc()) - break - return False + capabilities = {"alwaysMatch": self.capabilities} + self.webdriver = webdriver.Session(host, port, + capabilities=capabilities, + enable_bidi=self.enable_bidi, + extension=ServoCommandExtensions) + self.webdriver.start() -class ServoWebDriverRun(TimedRunner): - def set_timeout(self): - pass - - def run_func(self): - try: - self.result = True, self.func(self.protocol.session, self.url, self.timeout) - except webdriver.TimeoutException: - self.result = False, ("EXTERNAL-TIMEOUT", None) - except (socket.timeout, OSError): - self.result = False, ("CRASH", None) - except Exception as e: - message = getattr(e, "message", "") - if message: - message += "\n" - message += traceback.format_exc() - self.result = False, ("INTERNAL-ERROR", e) - finally: - self.result_flag.set() - - -class ServoWebDriverTestharnessExecutor(TestharnessExecutor): +class ServoWebDriverTestharnessExecutor(WebDriverTestharnessExecutor): supports_testdriver = True + protocol_cls = ServoWebDriverProtocol def __init__(self, logger, browser, server_config, timeout_multiplier=1, - close_after_done=True, capabilities=None, debug_info=None, + close_after_done=True, capabilities={}, debug_info=None, **kwargs): - TestharnessExecutor.__init__(self, logger, browser, server_config, timeout_multiplier=1, - debug_info=None) - self.protocol = ServoWebDriverProtocol(self, browser, capabilities=capabilities) - with open(os.path.join(here, "testharness_servodriver.js")) as f: - self.script = f.read() - self.timeout = None - - def on_protocol_change(self, new_protocol): - pass - - def is_alive(self): - return self.protocol.is_alive() - - def do_test(self, test): - url = self.test_url(test) - - timeout = test.timeout * self.timeout_multiplier + self.extra_timeout - - if timeout != self.timeout: - try: - self.protocol.session.timeouts.script = timeout - self.timeout = timeout - except OSError: - msg = "Lost WebDriver connection" - self.logger.error(msg) - return ("INTERNAL-ERROR", msg) - - success, data = ServoWebDriverRun(self.logger, - self.do_testharness, - self.protocol, - url, - timeout, - self.extra_timeout).run() - - if success: - return self.convert_result(test, data) - - return (test.make_result(*data), []) - - def do_testharness(self, session, url, timeout): - session.url = url - result = json.loads( - session.execute_async_script( - self.script % {"abs_url": url, - "url": strip_server(url), - "timeout_multiplier": self.timeout_multiplier, - "timeout": timeout * 1000})) - # Prevent leaking every page in history until Servo develops a more sane - # page cache - session.back() - return result + WebDriverTestharnessExecutor.__init__(self, logger, browser, server_config, + timeout_multiplier, capabilities=capabilities, + debug_info=debug_info, close_after_done=close_after_done, + cleanup_after_test=False) def on_environment_change(self, new_environment): - self.protocol.session.extension.change_prefs( + self.protocol.webdriver.extension.change_prefs( self.last_environment.get("prefs", {}), new_environment.get("prefs", {}) ) -class TimeoutError(Exception): - pass +class ServoWebDriverRefTestExecutor(WebDriverRefTestExecutor): + protocol_cls = ServoWebDriverProtocol - -class ServoWebDriverRefTestExecutor(RefTestExecutor): def __init__(self, logger, browser, server_config, timeout_multiplier=1, - screenshot_cache=None, capabilities=None, debug_info=None, + screenshot_cache=None, capabilities={}, debug_info=None, **kwargs): - """Selenium WebDriver-based executor for reftests""" - RefTestExecutor.__init__(self, - logger, - browser, - server_config, - screenshot_cache=screenshot_cache, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info) - self.protocol = ServoWebDriverProtocol(self, browser, - capabilities=capabilities) - self.implementation = RefTestImplementation(self) - self.timeout = None - with open(os.path.join(here, "test-wait.js")) as f: - self.wait_script = f.read() % {"classname": "reftest-wait"} - - def reset(self): - self.implementation.reset() - - def is_alive(self): - return self.protocol.is_alive() - - def do_test(self, test): - try: - result = self.implementation.run_test(test) - return self.convert_result(test, result) - except OSError: - return test.make_result("CRASH", None), [] - except TimeoutError: - return test.make_result("TIMEOUT", None), [] - except Exception as e: - message = getattr(e, "message", "") - if message: - message += "\n" - message += traceback.format_exc() - return test.make_result("INTERNAL-ERROR", message), [] - - def screenshot(self, test, viewport_size, dpi, page_ranges): - # https://github.com/web-platform-tests/wpt/issues/7135 - assert viewport_size is None - assert dpi is None - - timeout = (test.timeout * self.timeout_multiplier + self.extra_timeout - if self.debug_info is None else None) - - if self.timeout != timeout: - try: - self.protocol.session.timeouts.script = timeout - self.timeout = timeout - except OSError: - msg = "Lost webdriver connection" - self.logger.error(msg) - return ("INTERNAL-ERROR", msg) - - return ServoWebDriverRun(self.logger, - self._screenshot, - self.protocol, - self.test_url(test), - timeout, - self.extra_timeout).run() - - def _screenshot(self, session, url, timeout): - session.url = url - session.execute_async_script(self.wait_script) - return session.screenshot() + WebDriverRefTestExecutor.__init__(self, logger, browser, server_config, + timeout_multiplier, screenshot_cache, + capabilities=capabilities, + debug_info=debug_info) def on_environment_change(self, new_environment): - self.protocol.session.extension.change_prefs( + self.protocol.webdriver.extension.change_prefs( self.last_environment.get("prefs", {}), new_environment.get("prefs", {}) )
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py index 26b73b7..7513887 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -437,24 +437,22 @@ class WebDriverTestDriverProtocolPart(TestDriverProtocolPart): def setup(self): self.webdriver = self.parent.webdriver - with open(os.path.join(here, "testharness_webdriver_resume.js")) as f: - self.script_resume = f.read() - def get_next_message(self, url, test_window): + def get_next_message(self, url, script_resume, test_window): if hasattr(self.parent, "bidi_script"): # If `bidi_script` is available, the messages can be handled via BiDi. - return self._get_next_message_bidi(url, test_window) + return self._get_next_message_bidi(url, script_resume, test_window) else: - return self._get_next_message_classic(url) + return self._get_next_message_classic(url, script_resume) - def _get_next_message_classic(self, url): + def _get_next_message_classic(self, url, script_resume): """ Get the next message from the test_driver using the classic WebDriver async script execution. This will block the event loop until the test_driver send a message. """ - return self.parent.base.execute_script(self.script_resume, asynchronous=True, args=[strip_server(url)]) + return self.parent.base.execute_script(script_resume, asynchronous=True, args=[strip_server(url)]) - def _get_next_message_bidi(self, url, test_window): + def _get_next_message_bidi(self, url, script_resume, test_window): """ Get the next message from the test_driver using async call. This will not block the event loop, which allows for processing the events from the test_runner to test_driver while waiting for the next test_driver commands. @@ -470,7 +468,7 @@ %s }).apply(null, args); }) - }""" % self.script_resume + }""" % script_resume bidi_url_argument = { "type": "string", @@ -837,64 +835,19 @@ self.result_flag.set() -class WebDriverTestharnessExecutor(TestharnessExecutor): - supports_testdriver = True - protocol_cls = WebDriverProtocol +# TODO(web-platform-tests/wpt#13183): Add testdriver support to the other +# executors. +class TestDriverExecutorMixin: + def __init__(self, script_resume: str): + self.script_resume = script_resume - def __init__(self, logger, browser, server_config, timeout_multiplier=1, - close_after_done=True, capabilities=None, debug_info=None, - cleanup_after_test=True, **kwargs): - """WebDriver-based executor for testharness.js tests""" - TestharnessExecutor.__init__(self, logger, browser, server_config, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info) - self.protocol = self.protocol_cls(self, browser, capabilities) - with open(os.path.join(here, "window-loaded.js")) as f: - self.window_loaded_script = f.read() - - - self.close_after_done = close_after_done - self.cleanup_after_test = cleanup_after_test - - def is_alive(self): - return self.protocol.is_alive() - - def on_environment_change(self, new_environment): - if new_environment["protocol"] != self.last_environment["protocol"]: - self.protocol.testharness.load_runner(new_environment["protocol"]) - - def do_test(self, test): - url = self.test_url(test) - - success, data = WebDriverRun(self.logger, - self.do_testharness, - self.protocol, - url, - test.timeout * self.timeout_multiplier, - self.extra_timeout).run() - - if success: - data, extra = data - return self.convert_result(test, data, extra=extra) - - return (test.make_result(*data), []) - - def do_testharness(self, protocol, url, timeout): - # The previous test may not have closed its old windows (if something - # went wrong or if cleanup_after_test was False), so clean up here. - protocol.testharness.close_old_windows() - + def run_testdriver(self, protocol, url, timeout): # If protocol implements `bidi_events`, remove all the existing subscriptions. if hasattr(protocol, 'bidi_events'): # Use protocol loop to run the async cleanup. protocol.loop.run_until_complete(protocol.bidi_events.unsubscribe_all()) - # Now start the test harness test_window = self.get_or_create_test_window(protocol) - self.protocol.base.set_window(test_window) - # Wait until about:blank has been loaded - protocol.base.execute_script(self.window_loaded_script, asynchronous=True) - # Exceptions occurred outside the main loop. unexpected_exceptions = [] @@ -948,7 +901,8 @@ # TODO: what to do if there are more then 1 unexpected exceptions? raise unexpected_exceptions[0] - test_driver_message = protocol.testdriver.get_next_message(url, test_window) + test_driver_message = protocol.testdriver.get_next_message(url, self.script_resume, + test_window) self.logger.debug("Receive message from testdriver: %s" % test_driver_message) # As of 2019-03-29, WebDriver does not define expected behavior for @@ -981,42 +935,107 @@ # Use protocol loop to run the async cleanup. protocol.loop.run_until_complete(protocol.bidi_events.unsubscribe_all()) - extra = {} - if leak_part := getattr(protocol, "leak", None): - testharness_window = protocol.base.current_window - extra_windows = set(protocol.base.window_handles()) - extra_windows -= {protocol.testharness.runner_handle, testharness_window} - protocol.testharness.close_windows(extra_windows) - try: - protocol.base.set_window(testharness_window) - if counters := leak_part.check(): - extra["leak_counters"] = counters - except webdriver_error.NoSuchWindowException: - pass - finally: - protocol.base.set_window(protocol.testharness.runner_handle) - - # Attempt to clean up any leftover windows, if allowed. This is - # preferable as it will blame the correct test if something goes wrong - # closing windows, but if the user wants to see the test results we - # have to leave the window(s) open. - if self.cleanup_after_test: - protocol.testharness.close_old_windows() - if len(unexpected_exceptions) > 0: # TODO: what to do if there are more then 1 unexpected exceptions? raise unexpected_exceptions[0] - return rv, extra + return rv def get_or_create_test_window(self, protocol): - return protocol.base.create_window() + return protocol.base.current_window -class WebDriverRefTestExecutor(RefTestExecutor): +class WebDriverTestharnessExecutor(TestharnessExecutor, TestDriverExecutorMixin): + supports_testdriver = True protocol_cls = WebDriverProtocol def __init__(self, logger, browser, server_config, timeout_multiplier=1, + close_after_done=True, capabilities=None, debug_info=None, + cleanup_after_test=True, **kwargs): + """WebDriver-based executor for testharness.js tests""" + TestharnessExecutor.__init__(self, logger, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info) + self.protocol = self.protocol_cls(self, browser, capabilities) + with open(os.path.join(here, "testharness_webdriver_resume.js")) as f: + script_resume = f.read() + TestDriverExecutorMixin.__init__(self, script_resume) + with open(os.path.join(here, "window-loaded.js")) as f: + self.window_loaded_script = f.read() + + self.close_after_done = close_after_done + self.cleanup_after_test = cleanup_after_test + + def is_alive(self): + return self.protocol.is_alive() + + def on_environment_change(self, new_environment): + if new_environment["protocol"] != self.last_environment["protocol"]: + self.protocol.testharness.load_runner(new_environment["protocol"]) + + def do_test(self, test): + url = self.test_url(test) + + success, data = WebDriverRun(self.logger, + self.do_testharness, + self.protocol, + url, + test.timeout * self.timeout_multiplier, + self.extra_timeout).run() + + if success: + data, extra = data + return self.convert_result(test, data, extra=extra) + + return (test.make_result(*data), []) + + def do_testharness(self, protocol, url, timeout): + try: + # The previous test may not have closed its old windows (if something + # went wrong or if cleanup_after_test was False), so clean up here. + protocol.testharness.close_old_windows() + raw_results = self.run_testdriver(protocol, url, timeout) + extra = {} + if counters := self._check_for_leaks(protocol): + extra["leak_counters"] = counters + return raw_results, extra + finally: + # Attempt to clean up any leftover windows, if allowed. This is + # preferable as it will blame the correct test if something goes + # wrong closing windows, but if the user wants to see the test + # results we have to leave the window(s) open. + if self.cleanup_after_test: + protocol.testharness.close_old_windows() + + def _check_for_leaks(self, protocol): + leak_part = getattr(protocol, "leak", None) + if not leak_part: + return None + testharness_window = protocol.base.current_window + extra_windows = set(protocol.base.window_handles()) + extra_windows -= {protocol.testharness.runner_handle, testharness_window} + protocol.testharness.close_windows(extra_windows) + try: + protocol.base.set_window(testharness_window) + return leak_part.check() + except webdriver_error.NoSuchWindowException: + return None + finally: + protocol.base.set_window(protocol.testharness.runner_handle) + + def get_or_create_test_window(self, protocol): + test_window = protocol.base.create_window() + protocol.base.set_window(test_window) + # Wait until about:blank has been loaded + protocol.base.execute_script(self.window_loaded_script, asynchronous=True) + return test_window + + +class WebDriverRefTestExecutor(RefTestExecutor, TestDriverExecutorMixin): + protocol_cls = WebDriverProtocol + supports_testdriver = True + + def __init__(self, logger, browser, server_config, timeout_multiplier=1, screenshot_cache=None, close_after_done=True, debug_info=None, capabilities=None, debug_test=False, reftest_screenshot="unexpected", **kwargs): @@ -1038,7 +1057,8 @@ self.debug_test = debug_test with open(os.path.join(here, "test-wait.js")) as f: - self.wait_script = f.read() % {"classname": "reftest-wait"} + wait_script = f.read() % {"classname": "reftest-wait"} + TestDriverExecutorMixin.__init__(self, wait_script) def reset(self): self.implementation.reset() @@ -1084,8 +1104,9 @@ self.extra_timeout).run() def _screenshot(self, protocol, url, timeout): - self.protocol.base.load(url) - self.protocol.base.execute_script(self.wait_script, True) + # There's nothing we want from the "complete" message, so discard the + # return value. + self.run_testdriver(protocol, url, timeout) screenshot = self.protocol.webdriver.screenshot() if screenshot is None: @@ -1130,8 +1151,9 @@ self.extra_timeout).run() def _render(self, protocol, url, timeout): - protocol.webdriver.url = url - protocol.base.execute_script(self.wait_script, asynchronous=True) + # There's nothing we want from the "complete" message, so discard the + # return value. + self.run_testdriver(protocol, url, timeout) pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size) screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges) @@ -1143,8 +1165,9 @@ return screenshots -class WebDriverCrashtestExecutor(CrashtestExecutor): +class WebDriverCrashtestExecutor(CrashtestExecutor, TestDriverExecutorMixin): protocol_cls = WebDriverProtocol + supports_testdriver = True def __init__(self, logger, browser, server_config, timeout_multiplier=1, screenshot_cache=None, close_after_done=True, @@ -1162,7 +1185,8 @@ capabilities=capabilities) with open(os.path.join(here, "test-wait.js")) as f: - self.wait_script = f.read() % {"classname": "test-wait"} + wait_script = f.read() % {"classname": "test-wait"} + TestDriverExecutorMixin.__init__(self, wait_script) def do_test(self, test): timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None @@ -1181,8 +1205,9 @@ return (test.make_result(*data), []) def do_crashtest(self, protocol, url, timeout): - protocol.base.load(url) - protocol.base.execute_script(self.wait_script, asynchronous=True) + # There's nothing we want from the "complete" message, so discard the + # return value. + self.run_testdriver(protocol, url, timeout) result = {"status": "PASS", "message": None} if (leak_part := getattr(protocol, "leak", None)) and (counters := leak_part.check()): result["extra"] = {"leak_counters": counters}
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/message-queue.js b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/message-queue.js new file mode 100644 index 0000000..c79b96a --- /dev/null +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/message-queue.js
@@ -0,0 +1,81 @@ +(function() { + if (window.__wptrunner_message_queue && window.__wptrunner_process_next_event) { + // Another script already set up the testdriver infrastructure. + return; + } + + class MessageQueue { + constructor() { + this.item_id = 0; + this._queue = []; + } + + push(item) { + let cmd_id = this.item_id++; + item.id = cmd_id; + this._queue.push(item); + __wptrunner_process_next_event(); + return cmd_id; + } + + shift() { + return this._queue.shift(); + } + } + + window.__wptrunner_testdriver_callback = null; + window.__wptrunner_message_queue = new MessageQueue(); + window.__wptrunner_url = null; + + window.__wptrunner_process_next_event = function() { + /* This function handles the next testdriver event. The presence of + window.testdriver_callback is used as a switch; when that function + is present we are able to handle the next event and when is is not + present we must wait. Therefore to drive the event processing, this + function must be called in two circumstances: + * Every time there is a new event that we may be able to handle + * Every time we set the callback function + This function unsets the callback, so no further testdriver actions + will be run until it is reset, which wptrunner does after it has + completed handling the current action. + */ + + if (!window.__wptrunner_testdriver_callback) { + return; + } + var data = window.__wptrunner_message_queue.shift(); + if (!data) { + return; + } + + var payload = undefined; + + switch(data.type) { + case "complete": + var tests = data.tests; + var status = data.status; + if (tests && status) { + var subtest_results = tests.map(function(x) { + return [x.name, x.status, x.message, x.stack]; + }); + payload = [status.status, + status.message, + status.stack, + subtest_results]; + clearTimeout(window.__wptrunner_timer); + } else { + // Non-testharness test. + payload = []; + } + break; + case "action": + payload = data; + break; + default: + return; + } + var callback = window.__wptrunner_testdriver_callback; + window.__wptrunner_testdriver_callback = null; + callback([__wptrunner_url, data.type, payload]); + }; +})();
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/test-wait.js b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/test-wait.js index ad08ad7..fca6f8df 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/test-wait.js +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/test-wait.js
@@ -1,4 +1,6 @@ -var callback = arguments[arguments.length - 1]; +const initialized = !!window.__wptrunner_url; +window.__wptrunner_testdriver_callback = arguments[arguments.length - 1]; +window.__wptrunner_url = arguments.length > 1 ? arguments[0] : location.href; var observer = null; var root = document.documentElement; @@ -13,7 +15,6 @@ } } - function wait_paints() { // As of 2017-04-05, the Chromium web browser exhibits a rendering bug // (https://bugs.chromium.org/p/chromium/issues/detail?id=708757) that @@ -32,24 +33,36 @@ } function screenshot_if_ready() { - if (root && - root.classList.contains("%(classname)s") && - observer === null) { - observer = new MutationObserver(wait_paints); - observer.observe(root, {attributes: true}); - var event = new Event("TestRendered", {bubbles: true}); - root.dispatchEvent(event); + if (root && root.classList.contains("%(classname)s")) { + if (observer === null) { + observer = new MutationObserver(wait_paints); + observer.observe(root, {attributes: true}); + var event = new Event("TestRendered", {bubbles: true}); + root.dispatchEvent(event); + } return; } if (observer !== null) { observer.disconnect(); } - callback(); + if (window.__wptrunner_message_queue) { + __wptrunner_message_queue.push({type: "complete"}); + } else { + // Not using `testdriver.js`, so manually post a raw completion message + // that the executor understands. + __wptrunner_testdriver_callback([__wptrunner_url, "complete", []]); + } } - -if (document.readyState != "complete") { - addEventListener('load', wait_load); -} else { - wait_load(); +// The `initialized` flag ensures only up to one `load` handler or +// `MutationObserver` is ever registered. +if (!initialized) { + if (document.readyState != "complete") { + addEventListener('load', wait_load, { once: true }); + } else { + wait_load(); + } +} +if (window.__wptrunner_process_next_event) { + window.__wptrunner_process_next_event(); }
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testdriver-extra.js b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testdriver-extra.js index c4a02ef..2dd9a70 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testdriver-extra.js +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testdriver-extra.js
@@ -58,8 +58,17 @@ event.stopImmediatePropagation(); }); + const root_classes = document.documentElement.classList; + // For non-testharness tests, the presence of `(ref)test-wait` indicates + // it's the "main" browsing context through which testdriver actions are + // routed. Evaluate this eagerly before the test starts and removes these + // classes. + if (root_classes.contains("reftest-wait") || root_classes.contains("test-wait")) { + window.__wptrunner_is_test_context = true; + } + function is_test_context() { - return window.__wptrunner_message_queue !== undefined; + return !!window.__wptrunner_is_test_context; } // Code copied from /common/utils.js @@ -242,7 +251,7 @@ }; window.test_driver_internal.set_test_context = function(context) { - if (window.__wptrunner_message_queue) { + if (is_test_context()) { throw new Error("Tried to set testharness context in a window containing testharness.js"); } testharness_context = context;
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport-servodriver.js b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport-servodriver.js deleted file mode 100644 index 7819538..0000000 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport-servodriver.js +++ /dev/null
@@ -1,23 +0,0 @@ -setup({output:%(output)d, debug: %(debug)s}); - -add_completion_callback(function() { - add_completion_callback(function (tests, status) { - var subtest_results = tests.map(function(x) { - return [x.name, x.status, x.message, x.stack] - }); - var id = location.pathname + location.search + location.hash; - var results = JSON.stringify([id, - status.status, - status.message, - status.stack, - subtest_results]); - (function done() { - if (window.__wd_results_callback__) { - clearTimeout(__wd_results_timer__); - __wd_results_callback__(results) - } else { - setTimeout(done, 20); - } - })() - }) -});
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport.js b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport.js index d3856924..fb9e8c6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport.js +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testharnessreport.js
@@ -1,75 +1,9 @@ -class MessageQueue { - constructor() { - this.item_id = 0; - this._queue = []; - } - - push(item) { - let cmd_id = this.item_id++; - item.id = cmd_id; - this._queue.push(item); - __wptrunner_process_next_event(); - return cmd_id; - } - - shift() { - return this._queue.shift(); - } -} - -window.__wptrunner_testdriver_callback = null; -window.__wptrunner_message_queue = new MessageQueue(); -window.__wptrunner_url = null; - -window.__wptrunner_process_next_event = function() { - /* This function handles the next testdriver event. The presence of - window.testdriver_callback is used as a switch; when that function - is present we are able to handle the next event and when is is not - present we must wait. Therefore to drive the event processing, this - function must be called in two circumstances: - * Every time there is a new event that we may be able to handle - * Every time we set the callback function - This function unsets the callback, so no further testdriver actions - will be run until it is reset, which wptrunner does after it has - completed handling the current action. - */ - - if (!window.__wptrunner_testdriver_callback) { - return; - } - var data = window.__wptrunner_message_queue.shift(); - if (!data) { - return; - } - - var payload = undefined; - - switch(data.type) { - case "complete": - var tests = data.tests; - var status = data.status; - - var subtest_results = tests.map(function(x) { - return [x.name, x.status, x.message, x.stack]; - }); - payload = [status.status, - status.message, - status.stack, - subtest_results]; - clearTimeout(window.__wptrunner_timer); - break; - case "action": - payload = data; - break; - default: - return; - } - var callback = window.__wptrunner_testdriver_callback; - window.__wptrunner_testdriver_callback = null; - callback([__wptrunner_url, data.type, payload]); -}; - (function() { + // Signal to `testdriver.js` that this is the "main" test browsing context, + // meaning testdriver actions should be queued for retrieval instead of + // `postMessage()`d elsewhere. + window.__wptrunner_is_test_context = true; + var props = {output: %(output)d, timeout_multiplier: %(timeout_multiplier)s, explicit_timeout: %(explicit_timeout)s, @@ -85,4 +19,3 @@ }); setup(props); })(); -
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py index 7d26bb76..fbaed2e 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -258,24 +258,21 @@ logger.test_end(test.id, status="SKIP", subsuite=subsuite_name) test_status.skipped += 1 - if test_type == "testharness": - for test in test_loader.tests[subsuite_name][test_type]: - skip_reason = None - if test.testdriver and not executor_cls.supports_testdriver: - skip_reason = "Executor does not support testdriver.js" - elif test.jsshell and not executor_cls.supports_jsshell: - skip_reason = "Executor does not support jsshell" - if skip_reason: - logger.test_start(test.id, subsuite=subsuite_name) - logger.test_end(test.id, - status="SKIP", - subsuite=subsuite_name, - message=skip_reason) - test_status.skipped += 1 - else: - tests_to_run[(subsuite_name, test_type)].append(test) - else: - tests_to_run[(subsuite_name, test_type)] = test_loader.tests[subsuite_name][test_type] + for test in test_loader.tests[subsuite_name][test_type]: + skip_reason = None + if getattr(test, "testdriver", False) and not executor_cls.supports_testdriver: + skip_reason = "Executor does not support testdriver.js" + elif test_type == "testharness" and test.jsshell and not executor_cls.supports_jsshell: + skip_reason = "Executor does not support jsshell" + if skip_reason: + logger.test_start(test.id, subsuite=subsuite_name) + logger.test_end(test.id, + status="SKIP", + subsuite=subsuite_name, + message=skip_reason) + test_status.skipped += 1 + else: + tests_to_run[(subsuite_name, test_type)].append(test) unexpected_fail_tests = defaultdict(list) unexpected_pass_tests = defaultdict(list)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py index 2e3fd97..42214f07e 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py
@@ -535,7 +535,7 @@ def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, references, timeout=None, path=None, viewport_size=None, dpi=None, fuzzy=None, - protocol="http", subdomain=False): + protocol="http", subdomain=False, testdriver=False): Test.__init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, timeout, path, protocol, subdomain) @@ -546,6 +546,7 @@ self.references = references self.viewport_size = self.get_viewport_size(viewport_size) self.dpi = dpi + self.testdriver = testdriver self._fuzzy = fuzzy or {} @classmethod @@ -553,7 +554,8 @@ return {"viewport_size": manifest_test.viewport_size, "dpi": manifest_test.dpi, "protocol": server_protocol(manifest_test), - "fuzzy": manifest_test.fuzzy} + "fuzzy": manifest_test.fuzzy, + "testdriver": bool(getattr(manifest_test, "testdriver", False))} @classmethod def from_manifest(cls, @@ -692,10 +694,10 @@ def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, references, timeout=None, path=None, viewport_size=None, dpi=None, fuzzy=None, - page_ranges=None, protocol="http", subdomain=False): + page_ranges=None, protocol="http", subdomain=False, testdriver=False): super().__init__(url_base, tests_root, url, inherit_metadata, test_metadata, references, timeout, path, viewport_size, dpi, - fuzzy, protocol, subdomain=subdomain) + fuzzy, protocol, subdomain=subdomain, testdriver=testdriver) self._page_ranges = page_ranges @classmethod @@ -726,6 +728,26 @@ result_cls = CrashtestResult test_type = "crashtest" + def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, + timeout=None, path=None, protocol="http", subdomain=False, testdriver=False): + super().__init__(url_base, tests_root, url, inherit_metadata, test_metadata, + timeout, path, protocol, subdomain=subdomain) + self.testdriver = testdriver + + @classmethod + def from_manifest(cls, manifest_file, manifest_item, inherit_metadata, test_metadata): + timeout = cls.long_timeout if manifest_item.timeout == "long" else cls.default_timeout + return cls(manifest_file.url_base, + manifest_file.tests_root, + manifest_item.url, + inherit_metadata, + test_metadata, + timeout=timeout, + path=os.path.join(manifest_file.tests_root, manifest_item.path), + protocol=server_protocol(manifest_item), + subdomain=manifest_item.subdomain, + testdriver=bool(getattr(manifest_item, "testdriver", False))) + manifest_test_cls = {"reftest": ReftestTest, "print-reftest": PrintReftestTest,
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py index 62faf47..cde04b13 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py
@@ -513,11 +513,13 @@ Note that *.headers files have no effect in this handler. - :param path: Path to the template file to use + :param path: Path(s) to template files to use. If a sequence of paths is provided instead + of a single path, the contents of each file will be concatenated together before the + `format_args` are interpolated. :param format_args: Dictionary of values to substitute into the template file :param content_type: Content type header to server the response with :param headers: List of headers to send with responses""" - self._path = path + self._paths = [path] if isinstance(path, str) else path self._format_args = format_args self._content_type = content_type self._headers = headers @@ -525,7 +527,7 @@ def __getnewargs_ex__(self): # Do not pickle `self._handler`, which can be arbitrarily large. - args = self._path, self._format_args, self._content_type + args = self._paths, self._format_args, self._content_type return args, self._headers def __call__(self, request, response): @@ -534,8 +536,10 @@ # contents across processes can slow `wptserve` startup by several # seconds (crbug.com/1479850). if not self._handler: - with open(self._path) as f: - data = f.read() + data = "" + for path in self._paths: + with open(path) as f: + data += f.read() if self._format_args: data = data % self._format_args self._handler = StringHandler(data, self._content_type, **self._headers)
diff --git a/third_party/xnnpack/BUILD.gn b/third_party/xnnpack/BUILD.gn index c89d941c..86c7de3e 100644 --- a/third_party/xnnpack/BUILD.gn +++ b/third_party/xnnpack/BUILD.gn
@@ -83,6 +83,7 @@ ":f16-maxpool_f16c-no-avx2-no-fma", ":f16-pavgpool_f16c-fma-avx2", ":f16-qs8-vcvt_x64", + ":f16-qu8-vcvt_x64", ":f16-raddstoreexpminusmax_f16c-fma-avx2", ":f16-rminmax_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl", ":f16-rminmax_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni-gfni-avx512fp16", @@ -322,6 +323,8 @@ ":qs8-packw_avx2-avxvnni-f16c-fma", ":qs8-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni", ":qs8-packw_x64", + ":qs8-qc4w-packw_avx2-avxvnni-f16c-fma", + ":qs8-qc4w-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni", ":qs8-qc4w-packw_x64", ":qs8-qc8w-dwconv_avx-no-avx2-no-f16c-no-fma", ":qs8-qc8w-dwconv_f16c-fma-avx2", @@ -550,6 +553,7 @@ ":f16-maxpool_f16c-no-avx2-no-fma_standalone", ":f16-pavgpool_f16c-fma-avx2_standalone", ":f16-qs8-vcvt_x64_standalone", + ":f16-qu8-vcvt_x64_standalone", ":f16-raddstoreexpminusmax_f16c-fma-avx2_standalone", ":f16-rminmax_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni-gfni-avx512fp16_standalone", ":f16-rminmax_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl_standalone", @@ -789,6 +793,8 @@ ":qs8-packw_avx2-avxvnni-f16c-fma_standalone", ":qs8-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni_standalone", ":qs8-packw_x64_standalone", + ":qs8-qc4w-packw_avx2-avxvnni-f16c-fma_standalone", + ":qs8-qc4w-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni_standalone", ":qs8-qc4w-packw_x64_standalone", ":qs8-qc8w-dwconv_avx-no-avx2-no-f16c-no-fma_standalone", ":qs8-qc8w-dwconv_f16c-fma-avx2_standalone", @@ -1014,6 +1020,7 @@ ":f16-pavgpool_arch=armv8.2-a+fp16", ":f16-qs8-vcvt_arch=armv8.2-a+fp16", ":f16-qs8-vcvt_arm64", + ":f16-qu8-vcvt_arm64", ":f16-raddstoreexpminusmax_arch=armv8.2-a+fp16", ":f16-rminmax_arch=armv8.2-a+fp16", ":f16-rminmax_arm64", @@ -1107,6 +1114,8 @@ ":qp8-f32-qb4w-gemm_arch=armv8.2-a+i8mm+fp16", ":qp8-f32-qc4w-gemm_arch=armv8.2-a+dotprod", ":qp8-f32-qc4w-gemm_arch=armv8.2-a+i8mm+fp16", + ":qp8-f32-qc8w-gemm_arch=armv8.2-a+dotprod", + ":qp8-f32-qc8w-gemm_arch=armv8.2-a+i8mm+fp16", ":qs8-dwconv_arm64", ":qs8-f16-vcvt_arch=armv8.2-a+fp16", ":qs8-f32-vcvt_arm64", @@ -1197,6 +1206,7 @@ ":f16-pavgpool_arch=armv8.2-a+fp16_standalone", ":f16-qs8-vcvt_arch=armv8.2-a+fp16_standalone", ":f16-qs8-vcvt_arm64_standalone", + ":f16-qu8-vcvt_arm64_standalone", ":f16-raddstoreexpminusmax_arch=armv8.2-a+fp16_standalone", ":f16-rminmax_arch=armv8.2-a+fp16_standalone", ":f16-rminmax_arm64_standalone", @@ -1290,6 +1300,8 @@ ":qp8-f32-qb4w-gemm_arch=armv8.2-a+i8mm+fp16_standalone", ":qp8-f32-qc4w-gemm_arch=armv8.2-a+dotprod_standalone", ":qp8-f32-qc4w-gemm_arch=armv8.2-a+i8mm+fp16_standalone", + ":qp8-f32-qc8w-gemm_arch=armv8.2-a+dotprod_standalone", + ":qp8-f32-qc8w-gemm_arch=armv8.2-a+i8mm+fp16_standalone", ":qs8-dwconv_arm64_standalone", ":qs8-f16-vcvt_arch=armv8.2-a+fp16_standalone", ":qs8-f32-vcvt_arm64_standalone", @@ -2816,6 +2828,55 @@ } } + source_set("f16-qu8-vcvt_x64") { + cflags = [] + + sources = [ + "src/include/xnnpack.h", + "src/src/f16-qu8-vcvt/gen/f16-qu8-vcvt-scalar-imagic-u4.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool", + ] + + public_configs = [ ":xnnpack_config" ] + } + + # This is a target that cannot depend on //base. + source_set("f16-qu8-vcvt_x64_standalone") { + cflags = [] + + sources = [ + "src/include/xnnpack.h", + "src/src/f16-qu8-vcvt/gen/f16-qu8-vcvt-scalar-imagic-u4.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + } + source_set("f16-raddstoreexpminusmax_f16c-fma-avx2") { cflags = [ "-mavx2", @@ -3912,7 +3973,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f16-vtanh/gen/f16-vtanh-f16c-expm1minus-rr1-p3h2ts-rcp-u72.c", + "src/src/f16-vtanh/gen/f16-vtanh-f16c-expm1minus-rr1-p3h2ts-rcp-u24.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -3939,7 +4000,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f16-vtanh/gen/f16-vtanh-f16c-expm1minus-rr1-p3h2ts-rcp-u72.c", + "src/src/f16-vtanh/gen/f16-vtanh-f16c-expm1minus-rr1-p3h2ts-rcp-u24.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -9700,7 +9761,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-velu/gen/f32-velu-avx512f-rr1-p6-u128.c", + "src/src/f32-velu/gen/f32-velu-avx512f-rr1-p6-u64.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -9723,7 +9784,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-velu/gen/f32-velu-avx512f-rr1-p6-u128.c", + "src/src/f32-velu/gen/f32-velu-avx512f-rr1-p6-u64.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -9753,7 +9814,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-velu/gen/f32-velu-avx2-rr1-lut4-p4-perm-u56.c", + "src/src/f32-velu/gen/f32-velu-avx2-rr1-lut4-p4-perm-u32.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -9780,7 +9841,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-velu/gen/f32-velu-avx2-rr1-lut4-p4-perm-u56.c", + "src/src/f32-velu/gen/f32-velu-avx2-rr1-lut4-p4-perm-u32.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -11767,7 +11828,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx-rr2-p5-nr2-u40.c", + "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx-rr2-p5-nr2-u16.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -11795,7 +11856,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx-rr2-p5-nr2-u40.c", + "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx-rr2-p5-nr2-u16.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -11874,7 +11935,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx2-rr1-p5-div-u40.c", + "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx2-rr1-p5-div-u16.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -11901,7 +11962,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx2-rr1-p5-div-u40.c", + "src/src/f32-vsigmoid/gen/f32-vsigmoid-avx2-rr1-p5-div-u16.c", ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -16907,6 +16968,136 @@ } } + source_set("qs8-qc4w-packw_avx2-avxvnni-f16c-fma") { + cflags = [ + "-mavx2", + "-mavxvnni", + "-mf16c", + "-mfma", + ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-avxvnni-prfm.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool", + ] + + public_configs = [ ":xnnpack_config" ] + } + + # This is a target that cannot depend on //base. + source_set("qs8-qc4w-packw_avx2-avxvnni-f16c-fma_standalone") { + cflags = [ + "-mavx2", + "-mavxvnni", + "-mf16c", + "-mfma", + ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-avxvnni-prfm.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + } + + source_set( + "qs8-qc4w-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni") { + cflags = [ + "-mavx512bw", + "-mavx512cd", + "-mavx512dq", + "-mavx512f", + "-mavx512vl", + "-mavx512vnni", + "-mf16c", + "-mfma", + ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x16c8-gemm-goi-avx256vnni-prfm.c", + "src/src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-avx256vnni-prfm.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool", + ] + + public_configs = [ ":xnnpack_config" ] + } + + # This is a target that cannot depend on //base. + source_set( + "qs8-qc4w-packw_f16c-fma-avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vnni_standalone") { + cflags = [ + "-mavx512bw", + "-mavx512cd", + "-mavx512dq", + "-mavx512f", + "-mavx512vl", + "-mavx512vnni", + "-mf16c", + "-mfma", + ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x16c8-gemm-goi-avx256vnni-prfm.c", + "src/src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-avx256vnni-prfm.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + } + source_set("qs8-qc4w-packw_x64") { cflags = [] @@ -29532,6 +29723,55 @@ } } + source_set("f16-qu8-vcvt_arm64") { + cflags = [] + + sources = [ + "src/include/xnnpack.h", + "src/src/f16-qu8-vcvt/gen/f16-qu8-vcvt-scalar-imagic-u4.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool", + ] + + public_configs = [ ":xnnpack_config" ] + } + + # This is a target that cannot depend on //base. + source_set("f16-qu8-vcvt_arm64_standalone") { + cflags = [] + + sources = [ + "src/include/xnnpack.h", + "src/src/f16-qu8-vcvt/gen/f16-qu8-vcvt-scalar-imagic-u4.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + } + source_set("f16-raddstoreexpminusmax_arch=armv8.2-a+fp16") { cflags = [ "-march=armv8.2-a+fp16" ] @@ -30226,7 +30466,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f16-vsigmoid/gen/f16-vsigmoid-neonfp16arith-rr2-p2-nr1fma-u40.c", + "src/src/f16-vsigmoid/gen/f16-vsigmoid-neonfp16arith-rr2-p2-nr1fma-u32.c", "src/src/f16-vsigmoid/gen/f16-vsigmoid-neonfp16arith-rr2-p2-nr1recps-u16.c", ] @@ -30250,7 +30490,7 @@ sources = [ "src/include/xnnpack.h", - "src/src/f16-vsigmoid/gen/f16-vsigmoid-neonfp16arith-rr2-p2-nr1fma-u40.c", + "src/src/f16-vsigmoid/gen/f16-vsigmoid-neonfp16arith-rr2-p2-nr1fma-u32.c", "src/src/f16-vsigmoid/gen/f16-vsigmoid-neonfp16arith-rr2-p2-nr1recps-u16.c", ] @@ -34805,6 +35045,108 @@ } } + source_set("qp8-f32-qc8w-gemm_arch=armv8.2-a+dotprod") { + cflags = [ "-march=armv8.2-a+dotprod" ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-16x4c4-mstep4-aarch64-neondot.c", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x4c4-aarch64-neondot.c", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x4c8-aarch64-neondot.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool", + ] + + public_configs = [ ":xnnpack_config" ] + } + + # This is a target that cannot depend on //base. + source_set("qp8-f32-qc8w-gemm_arch=armv8.2-a+dotprod_standalone") { + cflags = [ "-march=armv8.2-a+dotprod" ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-16x4c4-mstep4-aarch64-neondot.c", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x4c4-aarch64-neondot.c", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x4c8-aarch64-neondot.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + } + + source_set("qp8-f32-qc8w-gemm_arch=armv8.2-a+i8mm+fp16") { + cflags = [ "-march=armv8.2-a+i8mm+fp16" ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-16x4c8-mstep4-neoni8mm.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool", + ] + + public_configs = [ ":xnnpack_config" ] + } + + # This is a target that cannot depend on //base. + source_set("qp8-f32-qc8w-gemm_arch=armv8.2-a+i8mm+fp16_standalone") { + cflags = [ "-march=armv8.2-a+i8mm+fp16" ] + + sources = [ + "src/include/xnnpack.h", + "src/src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-16x4c8-mstep4-neoni8mm.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + } + source_set("qs8-dwconv_arm64") { cflags = []
diff --git a/third_party/xnnpack/README.chromium b/third_party/xnnpack/README.chromium index b3c1ff2..fad85df 100644 --- a/third_party/xnnpack/README.chromium +++ b/third_party/xnnpack/README.chromium
@@ -1,8 +1,8 @@ Name: XNNPACK Short Name: xnnpack URL: https://github.com/google/xnnpack -Version: 98f1c8e5c5411bd435d994881440c3c6fc58d109 -Date: 2024-11-25 +Version: acb51c63d59d36b663e959b89a93f0e085e80ac0 +Date: 2024-12-09 License: BSD-3-Clause License File: src/LICENSE Security Critical: Yes
diff --git a/third_party/xnnpack/build_identifier.c b/third_party/xnnpack/build_identifier.c index f814992..97b79af6 100644 --- a/third_party/xnnpack/build_identifier.c +++ b/third_party/xnnpack/build_identifier.c
@@ -43,6 +43,7 @@ // - src/f16-pavgpool/f16-pavgpool-9p8x-minmax-avx2-c8.c // - src/f16-pavgpool/f16-pavgpool-9x-minmax-avx2-c8.c // - src/f16-qs8-vcvt/gen/f16-qs8-vcvt-scalar-imagic-u4.c +// - src/f16-qu8-vcvt/gen/f16-qu8-vcvt-scalar-imagic-u4.c // - src/f16-raddstoreexpminusmax/gen/f16-raddstoreexpminusmax-avx2-rr1-p2-u32.c // - src/f16-rminmax/f16-rmax-f16c-u32.c // - src/f16-rminmax/gen/f16-rmax-avx512fp16-u128-acc4.c @@ -101,7 +102,7 @@ // - src/f16-vrsqrt/gen/f16-vrsqrt-f16c-rsqrt-u32.c // - src/f16-vsigmoid/gen/f16-vsigmoid-avx2-rr1-p2-rcp-u32.c // - src/f16-vsqrt/gen/f16-vsqrt-f16c-rsqrt-u32.c -// - src/f16-vtanh/gen/f16-vtanh-f16c-expm1minus-rr1-p3h2ts-rcp-u72.c +// - src/f16-vtanh/gen/f16-vtanh-f16c-expm1minus-rr1-p3h2ts-rcp-u24.c // - src/f16-vtanh/gen/f16-vtanh-fma3-polynomial-p19h9t2-u32.c // - src/f16-vunary/gen/f16-vabs-sse2-u16.c // - src/f16-vunary/gen/f16-vneg-sse2-u16.c @@ -382,8 +383,8 @@ // - src/f32-vcopysign/gen/f32-vrcopysignc-scalar.c // - src/f32-vcopysign/gen/f32-vrcopysignc-sse2.c // - src/f32-velu/gen/f32-velu-avx-rr2-lut4-p4-perm-u32.c -// - src/f32-velu/gen/f32-velu-avx2-rr1-lut4-p4-perm-u56.c -// - src/f32-velu/gen/f32-velu-avx512f-rr1-p6-u128.c +// - src/f32-velu/gen/f32-velu-avx2-rr1-lut4-p4-perm-u32.c +// - src/f32-velu/gen/f32-velu-avx512f-rr1-p6-u64.c // - src/f32-velu/gen/f32-velu-scalar-rr2-lut16-p3-u2.c // - src/f32-velu/gen/f32-velu-scalar-rr2-lut16-p3-u4.c // - src/f32-velu/gen/f32-velu-sse2-rr2-lut16-p3-u12.c @@ -441,8 +442,8 @@ // - src/f32-vrsqrt/gen/f32-vrsqrt-scalar-rsqrt-u1.c // - src/f32-vrsqrt/gen/f32-vrsqrt-scalar-rsqrt-u4.c // - src/f32-vrsqrt/gen/f32-vrsqrt-sse-rsqrt-u8.c -// - src/f32-vsigmoid/gen/f32-vsigmoid-avx-rr2-p5-nr2-u40.c -// - src/f32-vsigmoid/gen/f32-vsigmoid-avx2-rr1-p5-div-u40.c +// - src/f32-vsigmoid/gen/f32-vsigmoid-avx-rr2-p5-nr2-u16.c +// - src/f32-vsigmoid/gen/f32-vsigmoid-avx2-rr1-p5-div-u16.c // - src/f32-vsigmoid/gen/f32-vsigmoid-avx512f-rr2-lut32-p2-perm2-scalef-div-u64.c // - src/f32-vsigmoid/gen/f32-vsigmoid-scalar-rr2-lut64-p2-div-u2.c // - src/f32-vsigmoid/gen/f32-vsigmoid-sse2-rr2-lut64-p2-div-u8.c @@ -607,7 +608,10 @@ // - src/qs8-packw/gen/qs8-packw-x8c8-gemm-goi-avx256vnni-prfm.c // - src/qs8-packw/gen/qs8-packw-x8c8-gemm-goi-avxvnni-prfm.c // - src/qs8-packw/gen/qs8-packw-x8c8-gemm-goi-avxvnni.c +// - src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x16c8-gemm-goi-avx256vnni-prfm.c // - src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x16c8-gemm-goi-scalar.c +// - src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-avx256vnni-prfm.c +// - src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-avxvnni-prfm.c // - src/qs8-qc4w-packw/gen/qs8-qc4w-packw-x8c8-gemm-goi-scalar.c // - src/qs8-qc8w-dwconv/gen/qs8-qc8w-dwconv-25p16c-minmax-fp32-avx-mul16-add16.c // - src/qs8-qc8w-dwconv/gen/qs8-qc8w-dwconv-25p16c-minmax-fp32-avx2-mul32.c @@ -929,10 +933,10 @@ #include <string.h> static const uint8_t xnn_build_identifier[] = { - 10, 243, 165, 162, 236, 132, 57, 241, - 181, 146, 33, 192, 235, 201, 173, 180, - 120, 25, 221, 70, 171, 12, 216, 183, - 247, 169, 250, 57, 205, 41, 120, 22 + 134, 14, 156, 130, 30, 132, 68, 25, + 79, 183, 144, 102, 1, 152, 248, 226, + 248, 39, 21, 0, 87, 30, 69, 153, + 81, 20, 12, 245, 44, 98, 182, 103 }; size_t xnn_experimental_get_build_identifier_size() {
diff --git a/third_party/xnnpack/src b/third_party/xnnpack/src index 98f1c8e..7440eee 160000 --- a/third_party/xnnpack/src +++ b/third_party/xnnpack/src
@@ -1 +1 @@ -Subproject commit 98f1c8e5c5411bd435d994881440c3c6fc58d109 +Subproject commit 7440eee88f66c4b81d4e7d31f6ae07af66e059ea
diff --git a/tools/android/build_speed/benchmark.py b/tools/android/build_speed/benchmark.py index 206c15c..8afee69 100755 --- a/tools/android/build_speed/benchmark.py +++ b/tools/android/build_speed/benchmark.py
@@ -90,6 +90,10 @@ 'use_siso=true', ] +_SERVER = [ + 'android_static_analysis="build_server"', +] + _INCREMENTAL_INSTALL = [ 'incremental_install=true', ] @@ -233,45 +237,6 @@ pathlib.Path(file_path).touch() -@contextlib.contextmanager -def _server(outdir: pathlib.Path): - cmd = [str(_SRC_ROOT / 'build/android/fast_local_dev_server.py')] - # Avoid the build server's output polluting benchmark results, but allow - # stderr to get through in case the build server fails with an error. - server_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True) - logging.debug('Started fast local dev server.') - # Give the server 1 second to fail fast. - try: - server_proc.wait(1) - except subprocess.TimeoutExpired: - pass - returncode = server_proc.poll() - if returncode is not None: - # The server failed to start. - stdout, _ = server_proc.communicate() - print(stdout) - logging.error(f'Failed to start fast local dev server: {returncode}, ' - 'perhaps the server is already running?') - raise Exception(f"Failed to start fast local dev server: {returncode}") - try: - yield - finally: - returncode = server_proc.poll() - if returncode is not None: - # The server failed to remain running. - stdout, _ = server_proc.communicate() - print(stdout) - raise Exception(f"The fast local dev server died: {returncode}") - logging.debug('Terminating fast local dev server.') - # Since Popen's default context manager just waits on exit, we need to - # use our custom context manager to actually terminate the build server - # when the current build is done to avoid skewing the next benchmark. - server_proc.terminate() - logging.debug('Waiting for fast local dev server termination...') - server_proc.wait() - logging.debug('Terminated fast local dev server.') - - def _detect_emulators() -> List[device_utils.DeviceUtils]: return [ device_utils.DeviceUtils(d) for d in adb_wrapper.AdbWrapper.Devices() @@ -352,10 +317,8 @@ return _run_and_time_cmd([str(_GN_PATH), 'gen', '-C', str(out_dir)]) -def _compile(out_dir: pathlib.Path, target: str, j: Optional[str]) -> float: +def _compile(out_dir: pathlib.Path, target: str) -> float: cmd = gn_helpers.CreateBuildCommand(str(out_dir)) - if j is not None: - cmd += ['-j', j] return _run_and_time_cmd(cmd + [target]) @@ -374,23 +337,22 @@ return _run_and_time_cmd(cmd) -def _run_and_maybe_install(out_dir: pathlib.Path, target: str, - emulator: Optional[device_utils.DeviceUtils], - j: Optional[str]) -> float: - total_time = _compile(out_dir, target, j) +def _run_and_maybe_install( + out_dir: pathlib.Path, target: str, + emulator: Optional[device_utils.DeviceUtils]) -> float: + total_time = _compile(out_dir, target) if emulator: total_time += _run_install(out_dir, target, emulator.serial) return total_time def _run_benchmark(benchmark: Benchmark, out_dir: pathlib.Path, target: str, - emulator: Optional[device_utils.DeviceUtils], - j: Optional[str]) -> float: + emulator: Optional[device_utils.DeviceUtils]) -> float: # This ensures that the only change is the one that this script makes. logging.info(f'Prepping benchmark...') if not benchmark.can_install: emulator = None - prep_time = _run_and_maybe_install(out_dir, target, emulator, j) + prep_time = _run_and_maybe_install(out_dir, target, emulator) logging.info(f'Took {prep_time:.1f}s to prep.') logging.info(f'Starting actual test...') change_file_path = _SRC_ROOT / benchmark.change_file @@ -404,7 +366,7 @@ f'Need to update {benchmark.from_string} in ' f'{benchmark.change_file}') f.write(new_content) - return _run_and_maybe_install(out_dir, target, emulator, j) + return _run_and_maybe_install(out_dir, target, emulator) def _format_result(time_taken: List[float]) -> str: @@ -428,14 +390,12 @@ def run_benchmarks(benchmarks: List[str], gn_args: List[str], output_directory: pathlib.Path, target: str, repeat: int, - no_server: bool, emulator_avd_name: Optional[str], - j: Optional[str]) -> Dict[str, List[float]]: + emulator_avd_name: Optional[str]) -> Dict[str, List[float]]: args_gn_path = output_directory / 'args.gn' if emulator_avd_name is None: emulator_ctx = contextlib.nullcontext else: emulator_ctx = functools.partial(_emulator, emulator_avd_name) - server_ctx = _server if not no_server else contextlib.nullcontext timings = collections.defaultdict(list) with _backup_file(args_gn_path): with open(args_gn_path, 'w') as f: @@ -447,16 +407,13 @@ timings['gn gen'].append(_run_gn_gen(output_directory)) for benchmark in _parse_benchmarks(benchmarks): logging.info(f'Starting {benchmark.name}...') - # Run the fast local dev server fresh for each benchmark run - # to avoid later benchmarks being slower due to the server - # accumulating queued tasks. Start a fresh emulator for each - # benchmark to produce more consistent results. - with emulator_ctx() as emulator, server_ctx(output_directory): + # Start a fresh emulator for each benchmark to produce more + # consistent results. + with emulator_ctx() as emulator: elapsed = _run_benchmark(benchmark=benchmark, out_dir=output_directory, target=target, - emulator=emulator, - j=j) + emulator=emulator) logging.info(f'Completed {benchmark.name}: {elapsed:.1f}s') timings[benchmark.name].append(elapsed) return timings @@ -515,8 +472,6 @@ help='Specify this to override the default emulator.') parser.add_argument('--target', help='Specify this to override the default target.') - parser.add_argument('-j', - help='Pass -j to use ninja instead of autoninja.') parser.add_argument('-v', '--verbose', action='count', @@ -540,6 +495,8 @@ level=level, format='%(levelname).1s %(relativeCreated)6d %(message)s') gn_args = _GN_ARGS + if not args.no_server: + gn_args += _SERVER if not args.no_incremental_install: gn_args += _INCREMENTAL_INSTALL if args.no_component_build: @@ -561,11 +518,9 @@ target = _TARGETS['bundle' if args.bundle else 'apk'] results = run_benchmarks(args.benchmark, gn_args, out_dir, target, - args.repeat, args.no_server, args.emulator, - args.j) + args.repeat, args.emulator) - server_str = f'{"not " if args.no_server else ""}using build server' - print(f'Summary ({server_str})') + print(f'Summary') print(f'emulator: {args.emulator}') print(f'gn args: {" ".join(gn_args)}') print(f'target: {target}')
diff --git a/tools/clang/spanify/extract_edits.py b/tools/clang/spanify/extract_edits.py index 9a7976b..5e7f5fe 100755 --- a/tools/clang/spanify/extract_edits.py +++ b/tools/clang/spanify/extract_edits.py
@@ -106,43 +106,18 @@ return hash((self.replacement, self.include_directive)) # Static method to get a node from a replacement key. - def from_key(replacement: str): - return Node.key_to_node.get(replacement) - - # This is not parsable by from_string but is for debugging. - def to_debug_string(self) -> str: - # include_directory already includes explanatory text. - result = "{" - result += ("is_buffer:{},replacement:{},{},size_info_available:{}" - "is_deref_node:{},is_data_change:{},neighbors:").format( - self.is_buffer, self.replacement, - self.include_directive, self.size_info_available, - self.is_deref_node, self.is_data_change) - neighbors = "{" - for node in self.neighbors: - if len(neighbors) > 1: - neighbors += ", " - neighbors += node.to_debug_string() - neighbors += "}" - # We started result with a '{' thus we end it to wrap everything up - # nicely. - return result + neighbors + "}" - + @classmethod + def from_key(cls: type, replacement: str): + return cls.key_to_node.get(replacement) # Static method to create a node from its string representation. This # deduplicate nodes by storing them in a dictionary. - def from_string(txt: str): + @classmethod + def from_string(cls: type, txt: str): # Skipping the first and last character that correspond to the curly # braces denoting the start and end of a serialized node. x = txt[1:-1].split('\\,') - # Value are escaped to avoid conflicts with the separator. Unescape - # them. - x = [urllib.parse.unquote(y) for y in x] - - # `./apply-edits.py` expects `\n` to be escaped. - x = [y.replace('\n', '\0') for y in x] - # Expect exactly 6 elements that correspond to the following node # attributes: # - is_buffer @@ -153,6 +128,13 @@ # - is_data_change assert len(x) == 6, txt + # Value are escaped to avoid conflicts with the separator. Unescape + # them. + x = [urllib.parse.unquote(y) for y in x] + + # `./apply-edits.py` expects `\n` to be escaped. + x = [y.replace('\n', '\0') for y in x] + node = Node(*x) # Deduplicate nodes, as they might appear multiple times in the input. @@ -182,8 +164,9 @@ return result + neighbors_directed # Static method to get all nodes. - def all(): - return Node.key_to_node.values() + @classmethod + def all(cls: type): + return cls.key_to_node.values() def DFS(node: Node):
diff --git a/tools/crates/gnrt/lib/readme.rs b/tools/crates/gnrt/lib/readme.rs index 7f4851b..799db591 100644 --- a/tools/crates/gnrt/lib/readme.rs +++ b/tools/crates/gnrt/lib/readme.rs
@@ -7,11 +7,14 @@ use crate::group::Group; use crate::paths; use anyhow::{bail, format_err, Result}; +use itertools::Itertools; use semver::Version; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; +use std::fmt::Display; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; #[derive(Clone, Debug, Serialize)] pub struct ReadmeFile { @@ -89,20 +92,8 @@ if let Some(config_license) = crate_config.and_then(|config| config.license.clone()) { config_license } else if let Some(pkg_license) = &package.license { - // Map to something in ALLOWED_LICENSES. - if let Some(mapped_license) = ALLOWED_LICENSES - .iter() - .find(|(allowed_license, _)| pkg_license == *allowed_license) - .map(|(_, mapped_license)| *mapped_license) - { - mapped_license.to_owned() - } else { - return Err(format_err!( - "License '{}' in Cargo.toml for {} crate is not in ALLOWED_LICENSES", - pkg_license, - package.name, - )); - } + let license_kinds = parse_license_string(pkg_license)?; + license_kinds_to_string(&license_kinds) } else { return Err(format_err!( "No license field found in Cargo.toml for {} crate", @@ -111,40 +102,21 @@ } }; - let path_if_exists = |path: &'a Path| -> Result<Option<&'a Path>> { - if crate_dir.join(path).try_exists()? { - Ok(Some(path)) + let license_files = if let Some(config_license_files) = crate_config.and_then(|config| { + if config.license_files.is_empty() { + None } else { - Ok(None) + Some(config.license_files.iter().map(Path::new)) } - }; - let to_crate_dir_string = |path: &Path| -> String { - format!("//{}", paths::normalize_unix_path_separator(&crate_dir.join(path))) - }; - - let license_files: Vec<String> = { - if let Some(config_license_files) = crate_config.and_then(|config| { - if config.license_files.is_empty() { - None - } else { - Some(config.license_files.iter().map(Path::new)) - } - }) { - config_license_files.map(to_crate_dir_string).collect() - } else if let Some(file) = &package.license_file { - path_if_exists(file.as_std_path())?.into_iter().map(to_crate_dir_string).collect() - } else { - EXPECTED_LICENSE_FILE - .iter() - .filter_map(|(l, path)| { - if license == **l { - path_if_exists(Path::new(path)).unwrap_or(None).map(to_crate_dir_string) - } else { - None - } - }) - .collect() - } + }) { + config_license_files + .map(|p| format!("//{}", paths::normalize_unix_path_separator(&crate_dir.join(p)))) + .collect() + } else if let Some(pkg_license) = &package.license { + let license_kinds = parse_license_string(pkg_license)?; + find_license_files_for_kinds(&license_kinds, &crate_dir)? + } else { + Vec::new() }; if license_files.is_empty() { @@ -207,58 +179,140 @@ Ok((dir, readme)) } -// Allowed licenses, in the format they are specified in Cargo.toml files from -// crates.io, and the format to write to README.chromium. -static ALLOWED_LICENSES: [(&str, &str); 22] = [ - // ("Cargo.toml string", "License for README.chromium") - ("Apache-2.0", "Apache-2.0"), - ("MIT OR Apache-2.0", "Apache-2.0"), - ("MIT/Apache-2.0", "Apache-2.0"), - ("MIT / Apache-2.0", "Apache-2.0"), - ("Apache-2.0 / MIT", "Apache-2.0"), - ("Apache-2.0 OR MIT", "Apache-2.0"), - ("Apache-2.0/MIT", "Apache-2.0"), - ("(Apache-2.0 OR MIT) AND BSD-3-Clause", "Apache-2.0, BSD-3-Clause"), - ("MIT OR Apache-2.0 OR Zlib", "Apache-2.0"), - ("MIT", "MIT"), - ("Unlicense OR MIT", "MIT"), - ("Unlicense/MIT", "MIT"), - ("Apache-2.0 OR BSL-1.0", "Apache-2.0"), - ("BSD-3-Clause", "BSD-3-Clause"), - ("ISC", "ISC"), - ("MIT OR Zlib OR Apache-2.0", "Apache-2.0"), - ("Zlib OR Apache-2.0 OR MIT", "Apache-2.0"), - ("0BSD OR MIT OR Apache-2.0", "Apache-2.0"), - ( - "(MIT OR Apache-2.0) AND Unicode-DFS-2016", - "Apache-2.0, Unicode-DFS-2016", - ), - ("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", "Apache-2.0"), - ("BSD-2-Clause OR Apache-2.0 OR MIT", "Apache-2.0"), - ("Zlib", "Zlib"), -]; +#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy)] +enum LicenseKind { + Apache2, + BSD3, + MIT, + ISC, + Zlib, + UnicodeDfs2016, +} -static EXPECTED_LICENSE_FILE: [(&str, &str); 22] = [ - ("Apache-2.0", "LICENSE"), - ("Apache-2.0", "LICENSE-APACHE"), - ("Apache-2.0", "LICENSE-APACHE.md"), - ("Apache-2.0", "LICENSE-APACHE.txt"), - ("Apache-2.0", "LICENSE.md"), - ("Apache-2.0", "license-apache-2.0"), - ("MIT", "LICENSE"), - ("MIT", "LICENSE.md"), - ("MIT", "LICENSE-MIT"), - ("MIT", "LICENSE-MIT.txt"), - ("MIT", "LICENSE-MIT.md"), - ("BSD-3-Clause", "LICENSE"), - ("BSD-3-Clause", "LICENSE.md"), - ("BSD-3-Clause", "LICENSE-BSD"), - ("BSD-3-Clause", "LICENSE-BSD.txt"), - ("BSD-3-Clause", "LICENSE-BSD.md"), - ("ISC", "LICENSE"), - ("ISC", "LICENSE.md"), - ("ISC", "LICENSE-ISC"), - ("Apache-2.0, BSD-3-Clause", "LICENSE"), - ("Apache-2.0, BSD-3-Clause", "LICENSE.md"), - ("Zlib", "LICENSE"), -]; +impl Display for LicenseKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LicenseKind::Apache2 => write!(f, "Apache-2.0"), + LicenseKind::BSD3 => write!(f, "BSD-3-Clause"), + LicenseKind::MIT => write!(f, "MIT"), + LicenseKind::ISC => write!(f, "ISC"), + LicenseKind::Zlib => write!(f, "Zlib"), + LicenseKind::UnicodeDfs2016 => write!(f, "Unicode-DFS-2016"), + } + } +} + +/// LICENSE_STRING_TO_LICENSE_KIND, converts licenses from the format they are +/// specified in Cargo.toml files from crates.io, to the LicenseKind that will +/// be written to README.chromium. +/// Each entry looks like the following: +/// h.insert( +/// "Cargo.toml string", +/// vec![LicenseKind::<License for README.chromium>] +/// ); +static LICENSE_STRING_TO_LICENSE_KIND: LazyLock<HashMap<&'static str, Vec<LicenseKind>>> = + LazyLock::new(|| { + let mut h = HashMap::new(); + h.insert("Apache-2.0", vec![LicenseKind::Apache2]); + h.insert("MIT OR Apache-2.0", vec![LicenseKind::Apache2]); + h.insert("MIT/Apache-2.0", vec![LicenseKind::Apache2]); + h.insert("MIT / Apache-2.0", vec![LicenseKind::Apache2]); + h.insert("Apache-2.0 / MIT", vec![LicenseKind::Apache2]); + h.insert("Apache-2.0 OR MIT", vec![LicenseKind::Apache2]); + h.insert("Apache-2.0/MIT", vec![LicenseKind::Apache2]); + h.insert( + "(Apache-2.0 OR MIT) AND BSD-3-Clause", + vec![LicenseKind::Apache2, LicenseKind::BSD3], + ); + h.insert("MIT OR Apache-2.0 OR Zlib", vec![LicenseKind::Apache2]); + h.insert("MIT", vec![LicenseKind::MIT]); + h.insert("Unlicense OR MIT", vec![LicenseKind::MIT]); + h.insert("Unlicense/MIT", vec![LicenseKind::MIT]); + h.insert("Apache-2.0 OR BSL-1.0", vec![LicenseKind::Apache2]); + h.insert("BSD-3-Clause", vec![LicenseKind::BSD3]); + h.insert("ISC", vec![LicenseKind::ISC]); + h.insert("MIT OR Zlib OR Apache-2.0", vec![LicenseKind::Apache2]); + h.insert("Zlib OR Apache-2.0 OR MIT", vec![LicenseKind::Apache2]); + h.insert("0BSD OR MIT OR Apache-2.0", vec![LicenseKind::Apache2]); + h.insert( + "(MIT OR Apache-2.0) AND Unicode-DFS-2016", + vec![LicenseKind::Apache2, LicenseKind::UnicodeDfs2016], + ); + h.insert("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", vec![LicenseKind::Apache2]); + h.insert("BSD-2-Clause OR Apache-2.0 OR MIT", vec![LicenseKind::Apache2]); + h.insert("Zlib", vec![LicenseKind::Zlib]); + h + }); + +static LICENSE_KIND_TO_LICENSE_FILES: LazyLock<HashMap<LicenseKind, Vec<&'static str>>> = + LazyLock::new(|| { + let mut h = HashMap::new(); + h.insert( + LicenseKind::Apache2, + vec![ + "LICENSE-APACHE", + "LICENSE-APACHE.md", + "LICENSE-APACHE.txt", + "license-apache-2.0", + "LICENSE.md", + "LICENSE", + ], + ); + h.insert( + LicenseKind::MIT, + vec!["LICENSE-MIT", "LICENSE-MIT.txt", "LICENSE-MIT.md", "LICENSE.md", "LICENSE"], + ); + h.insert( + LicenseKind::BSD3, + vec!["LICENSE-BSD", "LICENSE-BSD.txt", "LICENSE-BSD.md", "LICENSE.md", "LICENSE"], + ); + h.insert(LicenseKind::ISC, vec!["LICENSE-ISC", "LICENSE.md", "LICENSE"]); + h.insert(LicenseKind::Zlib, vec!["LICENSE-ZLIB", "LICENSE.md", "LICENSE"]); + h.insert(LicenseKind::UnicodeDfs2016, vec!["LICENSE-UNICODE", "LICENSE.md", "LICENSE"]); + h + }); + +/// Converts a license string from Cargo.toml into a Vec of LicenseKinds. +fn parse_license_string(pkg_license: &str) -> Result<Vec<LicenseKind>> { + LICENSE_STRING_TO_LICENSE_KIND.get(pkg_license).cloned().ok_or_else(|| { + format_err!("License '{}' not in LICENSE_STRING_TO_LICENSE_KIND", pkg_license) + }) +} + +/// Converts a slice of LicenseKinds into a comma-separated string. +fn license_kinds_to_string(license_kinds: &[LicenseKind]) -> String { + license_kinds.iter().join(", ") +} + +/// Finds license files for the given license kinds in the crate directory. +fn find_license_files_for_kinds( + license_kinds: &[LicenseKind], + crate_dir: &Path, +) -> Result<Vec<String>> { + let mut found_files = Vec::new(); + + for kind in license_kinds { + // Safe to unwrap because if a LicenseKind isn't in + // LICENSE_KIND_TO_LICENSE_FILES, it's a bug in gnrt's implementation. + let possible_files = LICENSE_KIND_TO_LICENSE_FILES.get(kind).unwrap_or_else(|| { + panic!("Bug in gnrt: License kind {:?} not in LICENSE_KIND_TO_LICENSE_FILES", kind) + }); + + // Try each possible file in priority order. + for file in possible_files { + let path = crate_dir.join(file); + if path.try_exists()? { + let normalized_path = format!("//{}", paths::normalize_unix_path_separator(&path)); + found_files.push(normalized_path); + break; // Found highest priority file for this license kind. + } + } + } + + // Check for duplicates using itertools. + if found_files.iter().duplicates().count() > 0 { + bail!("Duplicate license files found: {:?}", found_files); + } + + Ok(found_files) +}
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index f52225fd..edb3e24 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -432,10 +432,6 @@ "META": {"sizes": {"includes": [10],}}, "includes": [4100], }, - "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/internals/resources.grd": { - "META": {"sizes": {"includes": [20]}}, - "includes": [4120], - }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/intro/resources.grd": { "META": {"sizes": {"includes": [20],}}, "includes": [4140], @@ -628,6 +624,10 @@ "META": {"sizes": {"includes": [20]}}, "includes": [5080], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/user_education_internals/resources.grd": { + "META": {"sizes": {"includes": [20]}}, + "includes": [5090], + }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/web_app_internals/resources.grd": { "META": {"sizes": {"includes": [10]}}, "includes": [5100], @@ -866,6 +866,10 @@ "META": {"join": 2}, "includes": [6460], }, + "<(SHARED_INTERMEDIATE_DIR)/ash/webui/scanner_feedback_ui/resources/resources.grd": { + "META": {"sizes": {"includes": [20],}}, + "includes": [6470], + }, "<(SHARED_INTERMEDIATE_DIR)/ash/webui/personalization_app/resources/resources.grd": { "META": {"sizes": {"includes": [200],}}, "includes": [6480],
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 1a551198..f0b51e9 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -43198,12 +43198,22 @@ <description>Please enter the description of this user action.</description> </action> +<action name="Tabs.ArchivedDuplicateTab"> + <owner>bjfong@google.com</owner> + <owner>wylieb@chromium.org</owner> + <owner>clank-tab-dev@google.com</owner> + <description> + Recorded when a duplicate tab that is not the most recently used copy is + archived. This is happens when tabs share the same URL. + </description> +</action> + <action name="Tabs.ArchivedTabAutoDeleted"> <owner>wylieb@chromium.org</owner> <owner>clank-tab-dev@google.com</owner> <description> Recorded when an archived tab is deleted. This happens when the tab's last - archived tab exceeds the limit for auto-deletion. + archived time exceeds the limit for auto-deletion. </description> </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 651abdf..c08ca7e 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2464,6 +2464,8 @@ <int value="14" label="Viber"/> <int value="15" label="YouTube"/> <int value="16" label="Camera"/> + <int value="17" label="Pixel Launcher"/> + <int value="18" label="Third-party Launcher"/> </enum> <enum name="ClientSummarizedResultType"> @@ -15296,6 +15298,7 @@ <int value="-2036127998" label="LocalWebApprovals:disabled"/> <int value="-2035845836" label="ArcExtendServiceAnrTimeout:enabled"/> <int value="-2035126988" label="enabled-new-style-notification"/> + <int value="-2034315473" label="OnDeviceModelPerformanceParams:disabled"/> <int value="-2034064186" label="EnableKeyboardBacklightToggle:disabled"/> <int value="-2033950090" label="AutofillNoLocalSaveOnUploadSuccess:disabled"/> <int value="-2033908928" label="NightLight:enabled"/> @@ -18406,6 +18409,7 @@ <int value="-787885873" label="BorealisForceBetaClient:disabled"/> <int value="-787876637" label="HomeLauncherGestures:enabled"/> <int value="-787426248" label="ChromeHomeSurvey:disabled"/> + <int value="-787418584" label="EnableDozeModePowerScheduler:disabled"/> <int value="-787238455" label="OmniboxZeroSuggestionsOnSERP:disabled"/> <int value="-787176861" label="CaptureModeEducationBypassLimits:enabled"/> <int value="-785528415" label="FedCm:disabled"/> @@ -22128,6 +22132,7 @@ <int value="705946076" label="ContextMenuPerformanceInfoAndRemoteHintFetching:disabled"/> <int value="706280254" label="StoragePressureEvent:enabled"/> + <int value="707243920" label="OnDeviceModelPerformanceParams:enabled"/> <int value="707463326" label="DynamicSafeAreaInsets:enabled"/> <int value="708015891" label="AutofillUpdateChromeSettingsLinkToGPayWeb:enabled"/> @@ -22372,6 +22377,7 @@ label="GetDisplayMediaSetAutoSelectAllScreens:disabled"/> <int value="792307132" label="KeyboardBasedDisplayArrangementInSettings:enabled"/> + <int value="792700375" label="EnableDozeModePowerScheduler:enabled"/> <int value="792840942" label="BorealisDGPU:enabled"/> <int value="792884862" label="EnableSharedImageForWebview:enabled"/> <int value="793145445" label="ConchLargeModel:disabled"/> @@ -34196,6 +34202,9 @@ <int value="262" label="WritingSuggestions"/> <int value="263" label="Ink"/> <int value="264" label="VirtualKeyboard"/> + <int value="265" label="NonCookieStorageAccess"/> + <int value="266" label="IntlDurationFormat"/> + <int value="267" label="WindowControlsOverlay"/> </enum> <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom:WebDXFeature) --> @@ -34474,6 +34483,7 @@ </enum> <enum name="WebUIUrlHashes"> + <int value="-2137891043" label="chrome-untrusted://scanner-feedback/"/> <int value="-2103246641" label="chrome://signin-internals/"/> <int value="-2086395469" label="chrome://dlp-internals/"/> <int value="-2069349961" label="chrome://history-clusters-internals/"/> @@ -34550,6 +34560,7 @@ <int value="-1224398205" label="chrome://prefs-internals/"/> <int value="-1203248739" label="chrome://scanning/"/> <int value="-1198437953" label="chrome://download-shelf.top-chrome/"/> + <int value="-1179878260" label="chrome://user-education-internals/"/> <int value="-1177126000" label="chrome://profile-internals/"/> <int value="-1176451566" label="chrome://access-code-cast/"/> <int value="-1169621742" label="chrome://linux-proxy-config/"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index e31f11b..00a55fe 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -404,6 +404,21 @@ </summary> </histogram> +<histogram + name="Accessibility.Android.Performance.TimeUntilFirstAccessibilityFocus" + units="ms" expires_after="2025-05-04"> + <owner>mschillaci@google.com</owner> + <owner>lucasradaelli@google.com</owner> + <owner>chrome-a11y-core@google.com</owner> + <summary> + Tracks the time it takes for the WebContentsAccessibilityImpl to start + native initialization, until a node on the page is given accessibility focus + for the first time. We restrict this to TalkBack, which we know always + focuses the first item on a page. The metric is recorded when the + AccessibilityEvent is dispatched to the view. + </summary> +</histogram> + <histogram name="Accessibility.Android.UpdateAccessibilityServices.DidPoll" enum="BooleanHit" expires_after="2025-05-04"> <owner>mschillaci@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ash_user_education/enums.xml b/tools/metrics/histograms/metadata/ash_user_education/enums.xml index 45f8268..f6cc3b4b 100644 --- a/tools/metrics/histograms/metadata/ash_user_education/enums.xml +++ b/tools/metrics/histograms/metadata/ash_user_education/enums.xml
@@ -54,6 +54,7 @@ <int value="0" label="kHoldback"/> <int value="1" label="kV1"/> <int value="2" label="kV2"/> + <int value="3" label="kV3"/> </enum> <enum name="WelcomeTourInteraction"> @@ -75,6 +76,7 @@ <int value="6" label="kUserNotNewCrossDevice"/> <int value="7" label="kUserTypeNotRegular"/> <int value="8" label="kUserNotNewLocally"/> + <int value="9" label="kHoldbackExperimentArm"/> </enum> <enum name="WelcomeTourResult">
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index ad62929..ea09a96 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -2418,8 +2418,8 @@ </summary> </histogram> -<histogram name="Autofill.ExtractForm{OwnershipType}.FieldCount" units="fields" - expires_after="2025-06-08"> +<histogram name="Autofill.ExtractForm{OwnershipType}.FieldCount2" + units="fields" expires_after="2025-12-12"> <owner>jkeitel@google.com</owner> <owner>chrome-autofill-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/facilitated_payments/histograms.xml b/tools/metrics/histograms/metadata/facilitated_payments/histograms.xml index 2437f71..f8ccba4e 100644 --- a/tools/metrics/histograms/metadata/facilitated_payments/histograms.xml +++ b/tools/metrics/histograms/metadata/facilitated_payments/histograms.xml
@@ -31,6 +31,20 @@ summary="Facilitate a Pix based payment using Google Pay."/> </variants> +<histogram name="FacilitatedPayments.Pix.FopSelector.UserAction" + enum="FacilitatedPayments.FopSelectorAction" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + On a webpage that is eligible for Pix transactions on Chrome, this histogram + logs user actions on the Pix FOP selector. [Frequency] Logged once per Pix + payflow. Pix payflow is triggered at most once per page load. [Trigger] User + interacts with the Pix FOP selector. + </summary> +</histogram> + <histogram name="FacilitatedPayments.Pix.FopSelectorShown.LatencyAfterCopy" units="ms" expires_after="2025-07-01"> <owner>siashah@google.com</owner> @@ -46,6 +60,132 @@ </summary> </histogram> +<histogram name="FacilitatedPayments.Pix.GetClientToken.{Result}.Latency" + units="ms" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Latency for the call to fetch the client token. The client token is fetched + from the platform specific payment library in preparation for facilitating + the payment using Google Pay. {Result} is the token fetch result. + [Frequency] Logged at most once per Pix payflow. [Trigger] Page is loaded + and the main frame contains a valid payment code for Pix. + </summary> + <token key="Result" variants="BooleanResult"/> +</histogram> + +<histogram name="FacilitatedPayments.Pix.InitiatePayment.Attempt" + enum="BooleanAttempted" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Logs true when a request is sent to the Initiate Payment backend endpoint. + It should never log a false case. [Frequency] Logged at most once per Pix + flow. [Trigger] User selects a payment instrument from the list of options + shown in the Pix UI. + </summary> +</histogram> + +<histogram name="FacilitatedPayments.Pix.InitiatePayment.{Result}.Latency" + units="ms" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Logs the latency for the InitiatePayment backend endpoint and breaks it down + by the result. The result is {Result}. [Frequency] Logged at most once per + Pix payflow. [Trigger] User selects a payment instrument from the list of + options shown in the Pix UI. + </summary> + <token key="Result" variants="BooleanResult"/> +</histogram> + +<histogram name="FacilitatedPayments.Pix.InitiatePurchaseAction.Attempt" + enum="BooleanAttempted" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Logs true when a request is sent to to payments platform (client) which + faciliates the payment. It should never log a false case. [Frequency] Logged + at most once per Pix flow. [Trigger] User selects a payment instrument from + the list of options shown in the Pix UI and the backend returns the + instruction to trigger the purchase action flow in GMSCore. + </summary> +</histogram> + +<histogram + name="FacilitatedPayments.Pix.InitiatePurchaseAction.{Result}.Latency" + units="ms" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Logs the latency for the call made to payments platform (client) which + faciliates the payment and breaks it down by the result of the call. The + result is {Result}. [Frequency] Logged at most once per Pix payflow. + [Trigger] User selects a payment instrument from the list of options shown + in the Pix UI and the backend returns the instruction to trigger the + purchase action flow in GMSCore. + </summary> + <token key="Result"> + <variant name="Abandoned" summary="Abandoned InitiatePurchaseAction call"/> + <variant name="Failed" summary="Failed InitiatePurchaseAction call"/> + <variant name="Succeeded" summary="Successful InitiatePurchaseAction call"/> + </token> +</histogram> + +<histogram name="FacilitatedPayments.Pix.IsApiAvailable.{Result}.Latency" + units="ms" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Latency for the call to check whether the FacilitatedPayments API client is + available or not. The result is {Result}. The API client's availability is + checked to determine whether Chrome can offer to facilitate the payment + using Google Pay. [Frequency] Logged at most once per Pix payflow. [Trigger] + Page is loaded and the main frame contains a valid payment code for Pix. + </summary> + <token key="Result" variants="BooleanResult"/> +</histogram> + +<histogram name="FacilitatedPayments.Pix.LoadRiskData.{Result}.Latency" + units="ms" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Latency for the call to fetch risk data which was a {Result}. The risk data + gives device's risk fingerprint which is used to decide whether or not to + process the transaction. [Frequency] Logged at most once per page load. + [Trigger] The browser gets signal that a Pix code exists on the page. + </summary> + <token key="Result" variants="BooleanResult"/> +</histogram> + +<histogram name="FacilitatedPayments.Pix.PayflowExitedReason" + enum="FacilitatedPayments.PayFlowExitedReason" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + On a webpage that is eligible for facilitated payments, this histogram logs + the reasons why the payflow was exited. [Trigger] Payflow was exited early. + [Frequency] Logged at most once per payflow. + </summary> +</histogram> + <histogram name="FacilitatedPayments.Pix.PaymentCodeValidation.{PaymentCodeValidationResult}.Latency" units="ms" expires_after="2025-07-01"> @@ -88,201 +228,7 @@ </summary> </histogram> -<histogram name="FacilitatedPayments.SettingsPage.Shown" enum="BooleanShown" - expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Emits true when the FacilitatedPayments settings page is shown. Does not - emit any other value.[Trigger] User selects the Pay with a facilitated - payment type preference from the Payment Methods settings page. [Frequency] - Logged once for every time the page is shown. - </summary> -</histogram> - -<histogram - name="FacilitatedPayments.SettingsPage.{FacilitatedPaymentsType}.ToggleUpdated" - enum="Boolean" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Logs true when the toggle for {FacilitatedPaymentsType} is enabled and false - otherwise. Does not log if the toggle is not updated. [Trigger] User updates - the toggle for {FacilitatedPaymentsType} from the facilitated payments - settings page. [Frequency] Logged once per toggle update. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.FopSelector.UserAction" - enum="FacilitatedPayments.FopSelectorAction" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - On a webpage that is eligible for {FacilitatedPaymentsType} transactions on - Chrome, this histogram logs user actions on the {FacilitatedPaymentsType} - FOP selector. [Frequency] Logged once per {FacilitatedPaymentsType} payflow. - {FacilitatedPaymentsType} payflow is triggered at most once per page load. - [Trigger] User interacts with the {FacilitatedPaymentsType} FOP selector. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.GetClientToken.{Result}.Latency" - units="ms" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Latency for the call to fetch the client token. The client token is fetched - from the platform specific payment library in preparation for facilitating - the payment using Google Pay. {Result} is the token fetch result. - [Frequency] Logged at most once per {FacilitatedPaymentsType} payflow. - [Trigger] Page is loaded and the main frame contains a valid payment code - for {FacilitatedPaymentsType}. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> - <token key="Result" variants="BooleanResult"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.InitiatePayment.Attempt" - enum="BooleanAttempted" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Logs true when a request is sent to the Initiate Payment backend endpoint. - It should never log a false case. [Frequency] Logged at most once per - {FacilitatedPaymentsType} flow. [Trigger] User selects a payment instrument - from the list of options shown in the {FacilitatedPaymentsType} UI. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.InitiatePayment.{Result}.Latency" - units="ms" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Logs the latency for the InitiatePayment backend endpoint and breaks it down - by the result. The result is {Result}. [Frequency] Logged at most once per - {FacilitatedPaymentsType} payflow. [Trigger] User selects a payment - instrument from the list of options shown in the {FacilitatedPaymentsType} - UI. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> - <token key="Result" variants="BooleanResult"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.InitiatePurchaseAction.Attempt" - enum="BooleanAttempted" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Logs true when a request is sent to to payments platform (client) which - faciliates the payment. It should never log a false case. [Frequency] Logged - at most once per {FacilitatedPaymentsType} flow. [Trigger] User selects a - payment instrument from the list of options shown in the - {FacilitatedPaymentsType} UI and the backend returns the instruction to - trigger the purchase action flow in GMSCore. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.InitiatePurchaseAction.{Result}.Latency" - units="ms" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Logs the latency for the call made to payments platform (client) which - faciliates the payment and breaks it down by the result of the call. The - result is {Result}. [Frequency] Logged at most once per - {FacilitatedPaymentsType} payflow. [Trigger] User selects a payment - instrument from the list of options shown in the {FacilitatedPaymentsType} - UI and the backend returns the instruction to trigger the purchase action - flow in GMSCore. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> - <token key="Result"> - <variant name="Abandoned" summary="Abandoned InitiatePurchaseAction call"/> - <variant name="Failed" summary="Failed InitiatePurchaseAction call"/> - <variant name="Succeeded" summary="Successful InitiatePurchaseAction call"/> - </token> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.IsApiAvailable.{Result}.Latency" - units="ms" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Latency for the call to check whether the FacilitatedPayments API client is - available or not. The result is {Result}. The API client's availability is - checked to determine whether Chrome can offer to facilitate the payment - using Google Pay. [Frequency] Logged at most once per - {FacilitatedPaymentsType} payflow. [Trigger] Page is loaded and the main - frame contains a valid payment code for {FacilitatedPaymentsType}. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> - <token key="Result" variants="BooleanResult"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.LoadRiskData.{Result}.Latency" - units="ms" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - Latency for the call to fetch risk data which was a {Result}. The risk data - gives device's risk fingerprint which is used to decide whether or not to - process the transaction. [Frequency] Logged at most once per page load. - [Trigger] The browser gets signal that a {FacilitatedPaymentsType} code - exists on the page. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> - <token key="Result" variants="BooleanResult"/> -</histogram> - -<histogram - name="FacilitatedPayments.{FacilitatedPaymentsType}.PayflowExitedReason" - enum="FacilitatedPayments.PayFlowExitedReason" expires_after="2025-07-01"> - <owner>siashah@google.com</owner> - <owner>vishwasuppoor@google.com</owner> - <owner>rouslan@google.com</owner> - <owner>payments-autofill-team@google.com</owner> - <summary> - On a webpage that is eligible for facilitated payments, this histogram logs - the reasons why the payflow was exited. [Trigger] Payflow was exited early. - [Frequency] Logged at most once per payflow. - </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> -</histogram> - -<histogram name="FacilitatedPayments.{FacilitatedPaymentsType}.UiShown" +<histogram name="FacilitatedPayments.Pix.UiShown" enum="FacilitatedPayments.UiScreen" expires_after="2025-07-01"> <owner>siashah@google.com</owner> <owner>vishwasuppoor@google.com</owner> @@ -291,14 +237,39 @@ <summary> On a webpage that is eligible for facilitated payments, this histogram logs the UI screens being shown to the user. [Frequency] Each enum value is - logged at most once per {FacilitatedPaymentsType} payflow. - {FacilitatedPaymentsType} payflow is triggered at most once per page load. - [Trigger] The {FacilitatedPaymentsType} payflow could be triggered on pages - that have loaded, and the main frame contains a valid payment code for - {FacilitatedPaymentsType}. The screens are shown during the payflow based on - internal logic. + logged at most once per Pix payflow. Pix payflow is triggered at most once + per page load. [Trigger] The Pix payflow could be triggered on pages that + have loaded, and the main frame contains a valid payment code for Pix. The + screens are shown during the payflow based on internal logic. </summary> - <token key="FacilitatedPaymentsType" variants="FacilitatedPaymentsTypes"/> +</histogram> + +<histogram name="FacilitatedPayments.SettingsPage.Pix.ToggleUpdated" + enum="Boolean" expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Logs true when the toggle for Pix is enabled and false otherwise. Does not + log if the toggle is not updated. [Trigger] User updates the toggle for Pix + from the facilitated payments settings page. [Frequency] Logged once per + toggle update. + </summary> +</histogram> + +<histogram name="FacilitatedPayments.SettingsPage.Shown" enum="BooleanShown" + expires_after="2025-07-01"> + <owner>siashah@google.com</owner> + <owner>vishwasuppoor@google.com</owner> + <owner>rouslan@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Emits true when the FacilitatedPayments settings page is shown. Does not + emit any other value. [Trigger] User selects the Pay with a facilitated + payment type preference from the Payment Methods settings page. [Frequency] + Logged once for every time the page is shown. + </summary> </histogram> </histograms>
diff --git a/tools/metrics/histograms/metadata/file/enums.xml b/tools/metrics/histograms/metadata/file/enums.xml index ae165e6..e9bc02da 100644 --- a/tools/metrics/histograms/metadata/file/enums.xml +++ b/tools/metrics/histograms/metadata/file/enums.xml
@@ -904,6 +904,14 @@ <int value="2" label="Picker"/> </enum> +<enum name="TrashAutoCleanupError"> + <int value="0" label="Trash file successfully deleted"/> + <int value="1" label="Invalid trash info file"/> + <int value="2" label="Failed to get trash info file last modified time"/> + <int value="3" label="Failed to parse trash info file"/> + <int value="4" label="Failed to delete Trash file"/> +</enum> + <enum name="WebUrlFormat"> <int value="0" label="Missing"/> <int value="1" label="Empty"/>
diff --git a/tools/metrics/histograms/metadata/file/histograms.xml b/tools/metrics/histograms/metadata/file/histograms.xml index 556b148..0860aad 100644 --- a/tools/metrics/histograms/metadata/file/histograms.xml +++ b/tools/metrics/histograms/metadata/file/histograms.xml
@@ -1719,6 +1719,35 @@ </summary> </histogram> +<histogram name="FileBrowser.TrashAutoCleanup.Errors" + enum="TrashAutoCleanupError" expires_after="2025-07-01"> + <owner>simmonsjosh@google.com</owner> + <owner>src/ui/file_manager/OWNERS</owner> + <summary> + Records individual errors encountered during a Trash auto cleanup iteration. + </summary> +</histogram> + +<histogram name="FileBrowser.TrashAutoCleanup.FileCount" units="Files" + expires_after="2025-07-01"> + <owner>simmonsjosh@google.com</owner> + <owner>src/ui/file_manager/OWNERS</owner> + <summary> + Records the number of files involved in an iteration of the Trash auto + cleanup. + </summary> +</histogram> + +<histogram name="FileBrowser.TrashAutoCleanup.Time" units="ms" + expires_after="2025-07-01"> + <owner>simmonsjosh@google.com</owner> + <owner>src/ui/file_manager/OWNERS</owner> + <summary> + Records the time taken by a successful, non-empty iteration of the Trash + auto cleanup. + </summary> +</histogram> + <histogram name="FileBrowser.TrashFiles.{RootType}" units="units" expires_after="2025-07-01"> <owner>simmonsjosh@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ios/enums.xml b/tools/metrics/histograms/metadata/ios/enums.xml index 67ae2ad..aeda8c2 100644 --- a/tools/metrics/histograms/metadata/ios/enums.xml +++ b/tools/metrics/histograms/metadata/ios/enums.xml
@@ -823,6 +823,21 @@ <int value="1" label="No issues"/> </enum> +<!-- LINT.IfChange(IOSSafetyCheckNotificationsOptInSource) --> + +<enum name="IOSSafetyCheckNotificationsOptInSource"> + <int value="0" label="SafetyCheckPageOptIn"/> + <int value="1" label="SafetyCheckPageOptOut"/> + <int value="2" label="PasswordCheckupPageOptIn"/> + <int value="3" label="PasswordCheckupPageOptOut"/> + <int value="4" label="MagicStackLongPressMenuOptIn"/> + <int value="5" label="MagicStackLongPressMenuOptOut"/> + <int value="6" label="MagicStackTopRightActionButtonOptIn"/> + <int value="7" label="MagicStackTopRightActionButtonOptOut"/> +</enum> + +<!-- LINT.ThenChange(/ios/chrome/browser/safety_check_notifications/utils/constants.h:SafetyCheckNotificationsOptInSource) --> + <!-- LINT.IfChange(IOSSafetyCheckNotificationType) --> <enum name="IOSSafetyCheckNotificationType">
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml index 33e9a34..fbca96f 100644 --- a/tools/metrics/histograms/metadata/ios/histograms.xml +++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -2762,6 +2762,17 @@ </summary> </histogram> +<histogram name="IOS.Notifications.SafetyCheck.NotificationsOptInSource" + enum="IOSSafetyCheckNotificationsOptInSource" expires_after="2025-09-17"> + <owner>bwwilliams@google.com</owner> + <owner>scottyoder@google.com</owner> + <owner>bling-get-set-up@google.com</owner> + <summary> + Logs the source where the user opted in or opted out of receiving Safety + Check notifications. + </summary> +</histogram> + <histogram name="IOS.Notifications.SafetyCheck.Requested" enum="IOSSafetyCheckNotificationType" expires_after="2025-09-17"> <owner>bwwilliams@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index c90dd20..af629de 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -5157,6 +5157,16 @@ </summary> </histogram> +<histogram name="Net.RegistryControlledDomains.GetDomainAndRegistry.CacheHit" + enum="BooleanCacheHit" expires_after="2025-11-11"> + <owner>jkarlin@chromium.org</owner> + <owner>src/net/base/registry_controlled_domains/OWNERS</owner> + <summary> + Whether a call to GetDomainAndRegistry was served from the cache or not. + Recorded on all calls to GetDomainAndRegistry. + </summary> +</histogram> + <histogram name="Net.Reporting.HeaderType" enum="NetReportingHeaderType" expires_after="2025-04-23"> <owner>rodneyding@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml index b9b1ca0..a7d5fd9 100644 --- a/tools/metrics/histograms/metadata/optimization/histograms.xml +++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -56,6 +56,8 @@ <variant name="Compose" summary="Weights for On-Device Compose"/> <variant name="ContextualPageActionPriceTracking" summary="Contextual Page Action: Show price tracking"/> + <variant name="ExperimentalEmbedder" + summary="Embedder for performance experiments"/> <variant name="GeolocationPermissions" summary="Geolocation permissions"/> <variant name="LanguageDetection" summary="Language detection"/> <variant name="ModelExecutionFeatureHistoryQueryIntent"
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 54c4320..cf86726 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -1962,24 +1962,6 @@ </summary> </histogram> -<histogram name="Ads.InterestGroup.ServerAuction.KeyFetch.TotalTime2" - units="ms" expires_after="2024-12-08"> - <owner>behamilton@google.com</owner> - <owner>pauljensen@chromium.org</owner> - <owner>privacy-sandbox-dev@chromium.org</owner> - <summary> - The length of time it took to fetch and parse the key requested for a - Bidding and Auction Services auction. This metric is only recorded on a - per-fetch level so it will not be recorded if the key is requested while - waiting for an existing fetch for the key to complete. - - See - https://github.com/WICG/turtledove/blob/main/FLEDGE_browser_bidding_and_auction_API.md - for the latest version of the Protected Audience Bidding & Auction - Services explainer. - </summary> -</histogram> - <histogram name="Ads.InterestGroup.ServerAuction.PrevWinsArraySize" units="bytes" expires_after="2025-05-11"> <owner>caraitto@chromium.org</owner> @@ -6829,6 +6811,30 @@ </summary> </histogram> +<histogram name="OSCrypt.AppBound.ReEncrypt.ResultCode" enum="Hresult" + expires_after="2025-05-11"> + <owner>wfh@chromium.org</owner> + <owner>nparker@chromium.org</owner> + <summary> + The result code of the application-bound re-encrypt operation. This is + logged after a re-encryption attempt is made for decrypted data if + application-bound encryption signals that a re-encryption is required, for + supported Windows installs. + </summary> +</histogram> + +<histogram name="OSCrypt.AppBound.ReEncrypt.ResultLastError" + enum="WinGetLastError" expires_after="2025-05-11"> + <owner>wfh@chromium.org</owner> + <owner>nparker@chromium.org</owner> + <summary> + The GetLastError code for a failed application-bound re-encrypt operation. + This is logged after a re-encryption attempt is made for decrypted data if + application-bound encryption signals that a re-encryption is required, only + if the call to re-encrypt fails, for supported Windows installs. + </summary> +</histogram> + <histogram name="OSCrypt.AppBoundEncryption.SupportLevel" enum="AppBoundEncryptionSupportLevel" expires_after="2025-04-13"> <owner>wfh@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index 4d5d97a3..bd438d5b 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1817,6 +1817,20 @@ </summary> </histogram> +<histogram name="Tabs.ArchiveSettings.ArchiveDuplicateTabsEnabled" + enum="Boolean" expires_after="2025-03-02"> + <owner>bjfong@google.com</owner> + <owner>wylieb@chromium.org</owner> + <owner>clank-tab-dev@google.com</owner> + <summary> + Records when a user toggles the settings entry for automatically archiving + duplicate tabs on Android. The default state is enabled and is not recorded. + This histogram tracks the new state of the toggle and is emitted each time + it is changed. True corresponds to enabled and false corresponds to + disabled. + </summary> +</histogram> + <histogram name="Tabs.ArchiveSettings.AutoDeleteEnabled" enum="Boolean" expires_after="2025-03-02"> <owner>wylieb@chromium.org</owner>
diff --git a/ui/accessibility/android/java/src/org/chromium/ui/accessibility/AccessibilityState.java b/ui/accessibility/android/java/src/org/chromium/ui/accessibility/AccessibilityState.java index 6ec2aac..83646dd 100644 --- a/ui/accessibility/android/java/src/org/chromium/ui/accessibility/AccessibilityState.java +++ b/ui/accessibility/android/java/src/org/chromium/ui/accessibility/AccessibilityState.java
@@ -63,6 +63,9 @@ public static final String AUTOFILL_COMPAT_ACCESSIBILITY_SERVICE_ID = "android/com.android.server.autofill.AutofillCompatAccessibilityService"; + public static final String TALKBACK_SERVICE_ID = + "com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService"; + // Constant value to multiply animation timeouts by for pre-Q Android versions. private static final int ANIMATION_TIMEOUT_MULTIPLIER = 2; @@ -790,6 +793,18 @@ } /** + * Returns true when one of the running services is TalkBack based on list of service ids. This + * should not be used commonly, and is meant for identifying state while tracking metrics for + * performance improvements. + */ + public static boolean isTalkBackEnabled() { + if (!sInitialized) updateAccessibilityServices(); + return sServiceIds != null + && !sServiceIds.isEmpty() + && sServiceIds.contains(TALKBACK_SERVICE_ID); + } + + /** * Return a bitmask containing the union of all event types that running accessibility services * listen to. */ @@ -1182,6 +1197,13 @@ sEnabledServiceStringForTesting = enabledServiceString; } + public static void setServiceIdsForTesting(String newServiceId) { + if (!sInitialized) initializeForTesting(); + + sServiceIds = new ArrayList<String>(); + sServiceIds.add(newServiceId); + } + private static void initializeForTesting() { sState = new State(false, false, false, false, false, false, false, false); fetchAccessibilityManager();
diff --git a/ui/base/ime/ash/fake_ime_keyboard.cc b/ui/base/ime/ash/fake_ime_keyboard.cc index 477a801..060509b 100644 --- a/ui/base/ime/ash/fake_ime_keyboard.cc +++ b/ui/base/ime/ash/fake_ime_keyboard.cc
@@ -36,5 +36,17 @@ return auto_repeat_is_enabled_; } +void FakeImeKeyboard::SetSlowKeysEnabled(bool enabled) { + slow_keys_enabled_ = enabled; +} + +bool FakeImeKeyboard::IsSlowKeysEnabled() const { + return slow_keys_enabled_; +} + +void FakeImeKeyboard::SetSlowKeysDelay(base::TimeDelta delay) { + slow_keys_delay_ = delay; +} + } // namespace input_method } // namespace ash
diff --git a/ui/base/ime/ash/fake_ime_keyboard.h b/ui/base/ime/ash/fake_ime_keyboard.h index ad4c67a9b..53459a7 100644 --- a/ui/base/ime/ash/fake_ime_keyboard.h +++ b/ui/base/ime/ash/fake_ime_keyboard.h
@@ -8,6 +8,7 @@ #include <string> #include "base/component_export.h" +#include "base/time/time.h" #include "ui/base/ime/ash/ime_keyboard.h" namespace ash { @@ -28,11 +29,16 @@ bool SetAutoRepeatRate(const AutoRepeatRate& rate) override; void SetAutoRepeatEnabled(bool enabled) override; bool GetAutoRepeatEnabled() override; + void SetSlowKeysEnabled(bool enabled) override; + bool IsSlowKeysEnabled() const override; + void SetSlowKeysDelay(base::TimeDelta delay) override; int set_current_keyboard_layout_by_name_count_; AutoRepeatRate last_auto_repeat_rate_; // TODO(yusukes): Add more variables for counting the numbers of the API calls bool auto_repeat_is_enabled_; + bool slow_keys_enabled_ = false; + base::TimeDelta slow_keys_delay_; }; } // namespace input_method
diff --git a/ui/base/ime/ash/ime_keyboard.h b/ui/base/ime/ash/ime_keyboard.h index 5fa359e5..21b158d 100644 --- a/ui/base/ime/ash/ime_keyboard.h +++ b/ui/base/ime/ash/ime_keyboard.h
@@ -81,6 +81,17 @@ // non-UI threads. virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) = 0; + // Enables or disables the Slow Keys a11y functionality on the keyboard. + // Do not call the function from non-UI threads. + virtual void SetSlowKeysEnabled(bool enabled) = 0; + + // Returns whether Slow Keys is enabled. + virtual bool IsSlowKeysEnabled() const = 0; + + // Sets the amount of delay for Slow Keys. + // Do not call the function from non-UI threads. + virtual void SetSlowKeysDelay(base::TimeDelta delay) = 0; + protected: bool SetCurrentKeyboardLayoutByNameImpl(const std::string& layout_name);
diff --git a/ui/base/ime/ash/ime_keyboard_impl.cc b/ui/base/ime/ash/ime_keyboard_impl.cc index 5e06d8fd..7037cec 100644 --- a/ui/base/ime/ash/ime_keyboard_impl.cc +++ b/ui/base/ime/ash/ime_keyboard_impl.cc
@@ -44,6 +44,18 @@ return input_controller_->IsAutoRepeatEnabled(); } +void ImeKeyboardImpl::SetSlowKeysEnabled(bool enabled) { + input_controller_->SetSlowKeysEnabled(enabled); +} + +bool ImeKeyboardImpl::IsSlowKeysEnabled() const { + return input_controller_->IsSlowKeysEnabled(); +} + +void ImeKeyboardImpl::SetSlowKeysDelay(base::TimeDelta delay) { + input_controller_->SetSlowKeysDelay(delay); +} + void ImeKeyboardImpl::SetCapsLockEnabled(bool enable_caps_lock) { // Inform ImeKeyboard of caps lock state. ImeKeyboard::SetCapsLockEnabled(enable_caps_lock);
diff --git a/ui/base/ime/ash/ime_keyboard_impl.h b/ui/base/ime/ash/ime_keyboard_impl.h index f6a52a6b..5283b3e 100644 --- a/ui/base/ime/ash/ime_keyboard_impl.h +++ b/ui/base/ime/ash/ime_keyboard_impl.h
@@ -33,6 +33,9 @@ bool SetAutoRepeatRate(const AutoRepeatRate& rate) override; void SetAutoRepeatEnabled(bool enabled) override; bool GetAutoRepeatEnabled() override; + void SetSlowKeysEnabled(bool enabled) override; + bool IsSlowKeysEnabled() const override; + void SetSlowKeysDelay(base::TimeDelta delay) override; void SetCapsLockEnabled(bool enable_caps_lock) override; bool IsCapsLockEnabled() override;
diff --git a/ui/base/interaction/element_identifier.h b/ui/base/interaction/element_identifier.h index 21ce700..9bc5943c 100644 --- a/ui/base/interaction/element_identifier.h +++ b/ui/base/interaction/element_identifier.h
@@ -175,7 +175,8 @@ // The value of the identifier. Because all non-null values point to static // ElementIdentifierImpl objects this can be treated as a value from a set of // unique, opaque handles. - // RAW_PTR_EXCLUSION: #union, #global-scope + // RAW_PTR_EXCLUSION: Since all ElementIdentifierImpl instances are + // statically-allocated, this pointer can never dangle. RAW_PTR_EXCLUSION const internal::ElementIdentifierImpl* handle_ = nullptr; };
diff --git a/ui/events/ozone/BUILD.gn b/ui/events/ozone/BUILD.gn index 80de3121..f57ca4e 100644 --- a/ui/events/ozone/BUILD.gn +++ b/ui/events/ozone/BUILD.gn
@@ -27,6 +27,8 @@ "gamepad/gamepad_provider_ozone.h", "keyboard/event_auto_repeat_handler.cc", "keyboard/event_auto_repeat_handler.h", + "keyboard/slow_keys_handler.cc", + "keyboard/slow_keys_handler.h", ] deps = [ @@ -63,6 +65,7 @@ deps = [ ":ozone", "//base", + "//base/test:test_support", "//testing/gtest", "//ui/events", "//ui/events/ozone/layout:unittests", @@ -71,7 +74,10 @@ ] if (is_chromeos) { - sources += [ "chromeos/cursor_controller_unittest.cc" ] + sources += [ + "chromeos/cursor_controller_unittest.cc", + "keyboard/slow_keys_handler_unittest.cc", + ] } if (is_linux || is_chromeos) {
diff --git a/ui/events/ozone/evdev/BUILD.gn b/ui/events/ozone/evdev/BUILD.gn index 881605e..e97143a 100644 --- a/ui/events/ozone/evdev/BUILD.gn +++ b/ui/events/ozone/evdev/BUILD.gn
@@ -302,6 +302,7 @@ "gamepad_event_converter_evdev_unittest.cc", "input_controller_evdev_unittest.cc", "input_injector_evdev_unittest.cc", + "keyboard_evdev_unittest.cc", "libgestures_glue/haptic_touchpad_handler.cc", "libgestures_glue/haptic_touchpad_handler.h", "libgestures_glue/haptic_touchpad_handler_unittest.cc",
diff --git a/ui/events/ozone/evdev/input_controller_evdev.cc b/ui/events/ozone/evdev/input_controller_evdev.cc index bb3767d1..0d10b731 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.cc +++ b/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -188,6 +188,18 @@ keyboard_->GetAutoRepeatRate(delay, interval); } +void InputControllerEvdev::SetSlowKeysEnabled(bool enabled) { + keyboard_->SetSlowKeysEnabled(enabled); +} + +bool InputControllerEvdev::IsSlowKeysEnabled() const { + return keyboard_->IsSlowKeysEnabled(); +} + +void InputControllerEvdev::SetSlowKeysDelay(base::TimeDelta delay) { + keyboard_->SetSlowKeysDelay(delay); +} + void InputControllerEvdev::SetKeyboardKeyBitsMapping( base::flat_map<int, std::vector<uint64_t>> key_bits_mapping) { keyboard_key_bits_mapping_ = std::move(key_bits_mapping);
diff --git a/ui/events/ozone/evdev/input_controller_evdev.h b/ui/events/ozone/evdev/input_controller_evdev.h index b9cf4f1..93fdff0 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.h +++ b/ui/events/ozone/evdev/input_controller_evdev.h
@@ -61,6 +61,9 @@ const base::TimeDelta& interval) override; void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) override; + void SetSlowKeysEnabled(bool enabled) override; + bool IsSlowKeysEnabled() const override; + void SetSlowKeysDelay(base::TimeDelta delay) override; void SetCurrentLayoutByName(const std::string& layout_name, base::OnceCallback<void(bool)> callback) override; void SetKeyboardKeyBitsMapping(
diff --git a/ui/events/ozone/evdev/keyboard_evdev.cc b/ui/events/ozone/evdev/keyboard_evdev.cc index e29c536..135d9e70 100644 --- a/ui/events/ozone/evdev/keyboard_evdev.cc +++ b/ui/events/ozone/evdev/keyboard_evdev.cc
@@ -4,8 +4,10 @@ #include "ui/events/ozone/evdev/keyboard_evdev.h" +#include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/logging.h" +#include "base/memory/weak_ptr.h" #include "base/task/single_thread_task_runner.h" #include "ui/events/event.h" #include "ui/events/event_constants.h" @@ -62,8 +64,7 @@ keyboard_layout_engine_(keyboard_layout_engine), auto_repeat_handler_(this) {} -KeyboardEvdev::~KeyboardEvdev() { -} +KeyboardEvdev::~KeyboardEvdev() = default; void KeyboardEvdev::OnKeyChange(unsigned int key, unsigned int scan_code, @@ -75,6 +76,16 @@ if (key > KEY_MAX) return; + if (slow_keys_handler_.IsEnabled() && !suppress_auto_repeat && + !slow_keys_handler_.UpdateKeyStateAndShouldDispatch( + key, down, timestamp, device_id, + base::BindOnce(&KeyboardEvdev::OnKeyChangeCallbackAdapter, + weak_ptr_factory_.GetWeakPtr(), key, scan_code, down, + suppress_auto_repeat, device_id, flags))) { + // The SlowKeysHandler keeps track of recursion to prevent infinite loop. + return; + } + bool was_down = key_state_.test(key); bool is_repeat = down && was_down; if (!down && !was_down) @@ -122,6 +133,18 @@ auto_repeat_handler_.GetAutoRepeatRate(delay, interval); } +void KeyboardEvdev::SetSlowKeysEnabled(bool enabled) { + slow_keys_handler_.SetEnabled(enabled); +} + +bool KeyboardEvdev::IsSlowKeysEnabled() const { + return slow_keys_handler_.IsEnabled(); +} + +void KeyboardEvdev::SetSlowKeysDelay(base::TimeDelta delay) { + slow_keys_handler_.SetDelay(delay); +} + void KeyboardEvdev::SetCurrentLayoutByName( const std::string& layout_name, base::OnceCallback<void(bool)> callback) { @@ -219,4 +242,15 @@ callback_.Run(&event); } +void KeyboardEvdev::OnKeyChangeCallbackAdapter(unsigned int key, + unsigned int scan_code, + bool down, + bool suppress_auto_repeat, + int device_id, + int flags, + base::TimeTicks timestamp) { + OnKeyChange(key, scan_code, down, suppress_auto_repeat, timestamp, device_id, + flags); +} + } // namespace ui
diff --git a/ui/events/ozone/evdev/keyboard_evdev.h b/ui/events/ozone/evdev/keyboard_evdev.h index d890c73..ce5f450 100644 --- a/ui/events/ozone/evdev/keyboard_evdev.h +++ b/ui/events/ozone/evdev/keyboard_evdev.h
@@ -17,6 +17,7 @@ #include "ui/events/ozone/evdev/event_device_util.h" #include "ui/events/ozone/evdev/event_dispatch_callback.h" #include "ui/events/ozone/keyboard/event_auto_repeat_handler.h" +#include "ui/events/ozone/keyboard/slow_keys_handler.h" #include "ui/events/ozone/layout/keyboard_layout_engine.h" namespace ui { @@ -42,7 +43,7 @@ KeyboardEvdev(const KeyboardEvdev&) = delete; KeyboardEvdev& operator=(const KeyboardEvdev&) = delete; - ~KeyboardEvdev(); + virtual ~KeyboardEvdev(); // Handlers for raw key presses & releases. // @@ -71,6 +72,11 @@ const base::TimeDelta& interval); void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval); + // Configuration for slow keys. + void SetSlowKeysEnabled(bool enabled); + bool IsSlowKeysEnabled() const; + void SetSlowKeysDelay(base::TimeDelta delay); + // Handle keyboard layout changes. void SetCurrentLayoutByName(const std::string& layout_name, base::OnceCallback<void(bool)> callback); @@ -90,6 +96,16 @@ int device_id, int flags) override; + // Adapter function that simply reorders the arguments of OnKeyChange() for + // easier partial binding. + void OnKeyChangeCallbackAdapter(unsigned int key, + unsigned int scan_code, + bool down, + bool suppress_auto_repeat, + int device_id, + int flags, + base::TimeTicks timestamp); + // Aggregated key state. There is only one bit of state per key; we do not // attempt to count presses of the same key on multiple keyboards. // @@ -113,6 +129,9 @@ // Key repeat handler. EventAutoRepeatHandler auto_repeat_handler_; + // Slow keys handler. + SlowKeysHandler slow_keys_handler_; + base::WeakPtrFactory<KeyboardEvdev> weak_ptr_factory_{this}; };
diff --git a/ui/events/ozone/evdev/keyboard_evdev_unittest.cc b/ui/events/ozone/evdev/keyboard_evdev_unittest.cc new file mode 100644 index 0000000..fab2a8df --- /dev/null +++ b/ui/events/ozone/evdev/keyboard_evdev_unittest.cc
@@ -0,0 +1,263 @@ +// Copyright 2024 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/events/ozone/evdev/keyboard_evdev.h" + +#include <linux/input-event-codes.h> + +#include "base/functional/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_modifiers.h" +#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h" + +namespace ui { + +class KeyboardEvdevTest : public testing::Test { + public: + KeyboardEvdevTest() = default; + KeyboardEvdevTest(const KeyboardEvdevTest&) = delete; + KeyboardEvdevTest& operator=(const KeyboardEvdevTest&) = delete; + ~KeyboardEvdevTest() override = default; + + protected: + static constexpr base::TimeDelta kTestAutoRepeatDelay = + base::Milliseconds(300); + static constexpr base::TimeDelta kTestAutoRepeatInterval = + base::Milliseconds(100); + static constexpr int kTestDeviceId = 0; + + // testing::Test: + void SetUp() override { + testing::Test::SetUp(); + + kb_evdev_ = std::make_unique<KeyboardEvdev>( + &modifiers_, &stub_kb_layout_engine_, + base::BindRepeating(&KeyboardEvdevTest::OnEventDispatch, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&KeyboardEvdevTest::OnAnyKeysPressed, + weak_ptr_factory_.GetWeakPtr())); + } + + void OnEventDispatch(Event* event) { + dispatched_events_.push_back(event->Clone()); + } + + void OnAnyKeysPressed(bool any) { any_keys_pressed_.push_back(any); } + + unsigned int MakeFakeScanCode(unsigned int key) { return key + 1000u; } + + void PressKey(unsigned int key, base::TimeTicks timestamp) { + kb_evdev_->OnKeyChange(key, MakeFakeScanCode(key), /*down=*/true, + /*suppress_auto_repeat=*/false, timestamp, + kTestDeviceId, EF_NONE); + } + + void ReleaseKey(unsigned int key, base::TimeTicks timestamp) { + kb_evdev_->OnKeyChange(key, MakeFakeScanCode(key), /*down=*/false, + /*suppress_auto_repeat=*/false, timestamp, + kTestDeviceId, EF_NONE); + } + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + ui::EventModifiers modifiers_; + ui::StubKeyboardLayoutEngine stub_kb_layout_engine_; + std::unique_ptr<KeyboardEvdev> kb_evdev_; + + std::vector<std::unique_ptr<Event>> dispatched_events_; + std::vector<bool> any_keys_pressed_; + + base::WeakPtrFactory<KeyboardEvdevTest> weak_ptr_factory_{this}; +}; + +TEST_F(KeyboardEvdevTest, HeldKeyAutoRepeats) { + kb_evdev_->SetAutoRepeatRate(kTestAutoRepeatDelay, kTestAutoRepeatInterval); + const auto timestamp = EventTimeForNow(); + + PressKey(KEY_A, timestamp); + ASSERT_EQ(dispatched_events_.size(), 1u); + KeyEvent* key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp); + + task_environment_.FastForwardBy(kTestAutoRepeatDelay + + (kTestAutoRepeatInterval * 2.5)); + ASSERT_EQ(dispatched_events_.size(), 4u); + + key_event = dispatched_events_.at(1)->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp + kTestAutoRepeatDelay); + + key_event = dispatched_events_.at(2)->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), + timestamp + kTestAutoRepeatDelay + kTestAutoRepeatInterval); + + key_event = dispatched_events_.at(3)->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), + timestamp + kTestAutoRepeatDelay + (kTestAutoRepeatInterval * 2)); + + ReleaseKey(KEY_A, EventTimeForNow()); + ASSERT_EQ(dispatched_events_.size(), 5u); + key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyReleased); + EXPECT_EQ(key_event->time_stamp(), EventTimeForNow()); + + task_environment_.FastForwardBy(kTestAutoRepeatDelay * 2); + ASSERT_EQ(dispatched_events_.size(), 5u); +} + +class KeyboardEvdevSlowKeysTest : public KeyboardEvdevTest { + public: + KeyboardEvdevSlowKeysTest() = default; + KeyboardEvdevSlowKeysTest(const KeyboardEvdevSlowKeysTest&) = delete; + KeyboardEvdevSlowKeysTest& operator=(const KeyboardEvdevSlowKeysTest&) = + delete; + ~KeyboardEvdevSlowKeysTest() override = default; + + protected: + static constexpr base::TimeDelta kTestSlowKeysDelay = + base::Milliseconds(1000); + + // KeyboardEvdevTest: + void SetUp() override { + KeyboardEvdevTest::SetUp(); + + ASSERT_FALSE(kb_evdev_->IsSlowKeysEnabled()); + kb_evdev_->SetSlowKeysEnabled(true); + kb_evdev_->SetSlowKeysDelay(kTestSlowKeysDelay); + ASSERT_TRUE(kb_evdev_->IsSlowKeysEnabled()); + + kb_evdev_->SetAutoRepeatEnabled(false); + } + + void FastForwardWithinSlowKeysDelay() { + task_environment_.FastForwardBy(kTestSlowKeysDelay * 0.2); + } + void FastForwardPastSlowKeysDelay() { + task_environment_.FastForwardBy(kTestSlowKeysDelay * 1.5); + } +}; + +TEST_F(KeyboardEvdevSlowKeysTest, SlowKeysDisabled) { + kb_evdev_->SetSlowKeysEnabled(false); + EXPECT_FALSE(kb_evdev_->IsSlowKeysEnabled()); + + const base::TimeTicks timestamp = EventTimeForNow(); + + PressKey(KEY_A, timestamp); + ASSERT_EQ(dispatched_events_.size(), 1u); + KeyEvent* key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp); +} + +TEST_F(KeyboardEvdevSlowKeysTest, SuppressAutoRepeatBypassesSlowKeys) { + const base::TimeTicks timestamp = EventTimeForNow(); + + kb_evdev_->OnKeyChange(KEY_A, KEY_A, /*down=*/true, + /*suppress_auto_repeat=*/true, timestamp, + kTestDeviceId, EF_NONE); + + ASSERT_EQ(dispatched_events_.size(), 1u); + KeyEvent* key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp); +} + +TEST_F(KeyboardEvdevSlowKeysTest, KeyPressIsDelayed) { + const base::TimeTicks timestamp = EventTimeForNow(); + + PressKey(KEY_A, timestamp); + ASSERT_EQ(dispatched_events_.size(), 0u); + + FastForwardPastSlowKeysDelay(); + ASSERT_EQ(dispatched_events_.size(), 1u); + KeyEvent* key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp + kTestSlowKeysDelay); + + ReleaseKey(KEY_A, EventTimeForNow()); + ASSERT_EQ(dispatched_events_.size(), 2u); + key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyReleased); + EXPECT_EQ(key_event->time_stamp(), EventTimeForNow()); +} + +TEST_F(KeyboardEvdevSlowKeysTest, KeyReleaseCancelsDelayedKeyPress) { + PressKey(KEY_A, EventTimeForNow()); + ASSERT_EQ(dispatched_events_.size(), 0u); + + FastForwardWithinSlowKeysDelay(); + ASSERT_EQ(dispatched_events_.size(), 0u); + + ReleaseKey(KEY_A, EventTimeForNow()); + ASSERT_EQ(dispatched_events_.size(), 0u); + + FastForwardPastSlowKeysDelay(); + ASSERT_EQ(dispatched_events_.size(), 0u); +} + +TEST_F(KeyboardEvdevSlowKeysTest, RepeatKeysStartAfterSlowKeys) { + kb_evdev_->SetAutoRepeatEnabled(true); + kb_evdev_->SetAutoRepeatRate(kTestAutoRepeatDelay, kTestAutoRepeatInterval); + + const base::TimeTicks timestamp = EventTimeForNow(); + + PressKey(KEY_A, timestamp); + ASSERT_EQ(dispatched_events_.size(), 0u); + + task_environment_.FastForwardBy(kTestSlowKeysDelay); + ASSERT_EQ(dispatched_events_.size(), 1u); + KeyEvent* key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp + kTestSlowKeysDelay); + + task_environment_.FastForwardBy(kTestAutoRepeatDelay); + ASSERT_EQ(dispatched_events_.size(), 2u); + key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), + timestamp + kTestSlowKeysDelay + kTestAutoRepeatDelay); + + task_environment_.FastForwardBy(kTestAutoRepeatInterval); + ASSERT_EQ(dispatched_events_.size(), 3u); + key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyPressed); + EXPECT_EQ(key_event->time_stamp(), timestamp + kTestSlowKeysDelay + + kTestAutoRepeatDelay + + kTestAutoRepeatInterval); + + ReleaseKey(KEY_A, EventTimeForNow()); + ASSERT_EQ(dispatched_events_.size(), 4u); + key_event = dispatched_events_.back()->AsKeyEvent(); + EXPECT_EQ(key_event->code(), DomCode::US_A); + EXPECT_EQ(key_event->type(), EventType::kKeyReleased); + EXPECT_EQ(key_event->time_stamp(), EventTimeForNow()); + + task_environment_.FastForwardBy(kTestSlowKeysDelay + kTestAutoRepeatDelay); + ASSERT_EQ(dispatched_events_.size(), 4u); +} + +} // namespace ui
diff --git a/ui/events/ozone/keyboard/slow_keys_handler.cc b/ui/events/ozone/keyboard/slow_keys_handler.cc new file mode 100644 index 0000000..2597420b --- /dev/null +++ b/ui/events/ozone/keyboard/slow_keys_handler.cc
@@ -0,0 +1,117 @@ +// Copyright 2024 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/events/ozone/keyboard/slow_keys_handler.h" + +#include "base/containers/map_util.h" +#include "base/location.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event_constants.h" + +namespace ui { + +namespace { + +// Default delay duration. +constexpr base::TimeDelta kDefaultDelay = base::Milliseconds(500); +// Max delay duration. +constexpr base::TimeDelta kMaxDelay = base::Seconds(10); + +} // namespace + +SlowKeysHandler::SlowKeysHandler() : delay_(kDefaultDelay) {} + +SlowKeysHandler::~SlowKeysHandler() = default; + +bool SlowKeysHandler::IsEnabled() const { + return enabled_; +} + +void SlowKeysHandler::SetEnabled(bool enabled) { + if (!enabled) { + Clear(); + } + enabled_ = enabled; +} + +base::TimeDelta SlowKeysHandler::GetDelay() const { + return delay_; +} + +void SlowKeysHandler::SetDelay(base::TimeDelta delay) { + if (delay != delay_) { + Clear(); + } + if (delay.is_positive() && delay < kMaxDelay) { + delay_ = delay; + } +} + +void SlowKeysHandler::Clear() { + delayed_keys_map_.clear(); +} + +bool SlowKeysHandler::UpdateKeyStateAndShouldDispatch( + unsigned int key, + bool down, + base::TimeTicks timestamp, + int device_id, + OnKeyChangeCallback callback) { + if (!enabled_) { + return true; + } + + DelayMapKey delay_key{ + .device_id = device_id, + .key = key, + }; + + auto* old_timer = base::FindPtrOrNull(delayed_keys_map_, delay_key); + bool had_timer = old_timer; + bool pending = old_timer && old_timer->IsRunning(); + + if (!down) { + delayed_keys_map_.erase(delay_key); + } + // Don't use `old_timer` after this, since it may have been invalidated. + + if (!had_timer && down) { + auto timer = std::make_unique<base::OneShotTimer>(); + timer->Start(FROM_HERE, delay_, + base::BindOnce(&SlowKeysHandler::OnDelayReached, + weak_ptr_factory_.GetWeakPtr(), + /*input_timestamp=*/timestamp, + /*system_timestamp=*/EventTimeForNow(), + std::move(callback))); + delayed_keys_map_[delay_key] = std::move(timer); + return false; + } else if (pending && !processing_delayed_key_) { + return false; + } + return true; +} + +void SlowKeysHandler::OnDelayReached(base::TimeTicks input_timestamp, + base::TimeTicks system_timestamp, + OnKeyChangeCallback callback) { + if (!callback) { + return; + } + + auto delta = EventTimeForNow() - system_timestamp; + auto new_timestamp = input_timestamp + delta; + + // The OnKeyChangeCallback could call `UpdateKeyStateAndShouldDispatch` again, + // so `processing_delayed_key_` signals the recursive call to prevent infinite + // loop. This relies on the fact that this handler is used in a + // single-threaded context that processes one key at a time. If that + // assumption is ever broken, this logic will need to be updated. + processing_delayed_key_ = true; + std::move(callback).Run(new_timestamp); + processing_delayed_key_ = false; +} + +} // namespace ui
diff --git a/ui/events/ozone/keyboard/slow_keys_handler.h b/ui/events/ozone/keyboard/slow_keys_handler.h new file mode 100644 index 0000000..162cdfdb --- /dev/null +++ b/ui/events/ozone/keyboard/slow_keys_handler.h
@@ -0,0 +1,77 @@ +// Copyright 2024 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_EVENTS_OZONE_KEYBOARD_SLOW_KEYS_HANDLER_H_ +#define UI_EVENTS_OZONE_KEYBOARD_SLOW_KEYS_HANDLER_H_ + +#include "base/component_export.h" +#include "base/containers/flat_map.h" +#include "base/functional/callback_forward.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "base/timer/timer.h" + +namespace ui { + +// Class that handles the Slow Keys accessibility functionality. +class COMPONENT_EXPORT(EVENTS_OZONE) SlowKeysHandler { + public: + // This callback is called after a key is held down past the delay threshold. + // The TimeTicks param is the new timestamp with the delay. + using OnKeyChangeCallback = base::OnceCallback<void(base::TimeTicks)>; + + SlowKeysHandler(); + SlowKeysHandler(const SlowKeysHandler&) = delete; + SlowKeysHandler& operator=(const SlowKeysHandler&) = delete; + ~SlowKeysHandler(); + + // Called on every key state change to update the handler's internal key + // state. Returns true if the key event should be dispatched by the caller + // immediately without delay. Returns false if the key event should be + // discarded. The `callback` is called by the handler when the slow keys delay + // is reached and the key is still held down. + bool UpdateKeyStateAndShouldDispatch(unsigned int key, + bool down, + base::TimeTicks timestamp, + int device_id, + OnKeyChangeCallback callback); + + // Getters and setters. + bool IsEnabled() const; + void SetEnabled(bool enabled); + base::TimeDelta GetDelay() const; + void SetDelay(base::TimeDelta delay); + + private: + struct DelayMapKey { + int device_id; + unsigned int key; + + auto operator<=>(const DelayMapKey& rhs) const = default; + }; + + // Clears any pending delayed keys. + void Clear(); + + // Callback when a slow key delay is reached. + // `input_timestamp` is the timestamp from the input event. + // `system_timestamp` is the current system timestamp. + // `callback` is the OnKeyChangeCallback to call. + void OnDelayReached(base::TimeTicks input_timestamp, + base::TimeTicks system_timestamp, + OnKeyChangeCallback callback); + + bool enabled_ = false; + base::TimeDelta delay_; + + base::flat_map<DelayMapKey, std::unique_ptr<base::OneShotTimer>> + delayed_keys_map_; + bool processing_delayed_key_ = false; + + base::WeakPtrFactory<SlowKeysHandler> weak_ptr_factory_{this}; +}; + +} // namespace ui + +#endif // UI_EVENTS_OZONE_KEYBOARD_SLOW_KEYS_HANDLER_H_
diff --git a/ui/events/ozone/keyboard/slow_keys_handler_unittest.cc b/ui/events/ozone/keyboard/slow_keys_handler_unittest.cc new file mode 100644 index 0000000..10cc74b1 --- /dev/null +++ b/ui/events/ozone/keyboard/slow_keys_handler_unittest.cc
@@ -0,0 +1,308 @@ +// Copyright 2024 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/events/ozone/keyboard/slow_keys_handler.h" + +#include <linux/input-event-codes.h> + +#include <vector> + +#include "base/functional/callback_forward.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event_constants.h" + +namespace ui { + +using testing::ElementsAre; + +namespace { + +class SlowKeysHandlerTest : public testing::Test { + protected: + static constexpr base::TimeDelta kTestSlowKeysDelay = + base::Milliseconds(1000); + static constexpr int kTestDeviceId = 0; + + // testing::Test: + void SetUp() override { + testing::Test::SetUp(); + + handler_.SetEnabled(true); + handler_.SetDelay(kTestSlowKeysDelay); + } + + bool UpdateKeyStateAndShouldDispatch(unsigned int key, + bool down, + int device_id, + base::TimeTicks timestamp) { + return handler_.UpdateKeyStateAndShouldDispatch( + key, down, timestamp, device_id, + MakeOnKeyChangeCallback(key, down, device_id)); + } + + base::OnceCallback<void(base::TimeTicks)> + MakeOnKeyChangeCallback(unsigned int key, bool down, int device_id) { + return base::BindLambdaForTesting([=, this](base::TimeTicks timestamp) { + this->on_key_change_callback_call_args_.push_back(timestamp); + this->should_dispatch_return_values_.push_back( + UpdateKeyStateAndShouldDispatch(key, down, device_id, timestamp)); + }); + } + + void FastForwardByDelayMultiplier(float multiplier) { + task_environment_.FastForwardBy(kTestSlowKeysDelay * multiplier); + } + void FastForwardWithinDelay() { FastForwardByDelayMultiplier(0.1); } + void FastForwardPastDelay() { FastForwardByDelayMultiplier(1.5); } + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + SlowKeysHandler handler_; + std::vector<base::TimeTicks> on_key_change_callback_call_args_; + std::vector<bool> should_dispatch_return_values_; +}; + +} // namespace + +TEST_F(SlowKeysHandlerTest, SetEnabled) { + handler_.SetEnabled(true); + EXPECT_TRUE(handler_.IsEnabled()); + + handler_.SetEnabled(false); + EXPECT_FALSE(handler_.IsEnabled()); +} + +TEST_F(SlowKeysHandlerTest, SetDelay) { + const base::TimeDelta delay = base::Milliseconds(456); + handler_.SetDelay(delay); + EXPECT_EQ(handler_.GetDelay(), delay); +} + +TEST_F(SlowKeysHandlerTest, SetNegativeDelay) { + ASSERT_EQ(handler_.GetDelay(), kTestSlowKeysDelay); + handler_.SetDelay(base::Milliseconds(-345)); + EXPECT_EQ(handler_.GetDelay(), kTestSlowKeysDelay); +} + +TEST_F(SlowKeysHandlerTest, SetLargeDelay) { + ASSERT_EQ(handler_.GetDelay(), kTestSlowKeysDelay); + handler_.SetDelay(base::Minutes(10)); + EXPECT_EQ(handler_.GetDelay(), kTestSlowKeysDelay); +} + +TEST_F(SlowKeysHandlerTest, AlwaysDispatchWhenDisabled) { + handler_.SetEnabled(false); + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); +} + +TEST_F(SlowKeysHandlerTest, KeyReleasedBeforeDelayDiscarded) { + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardWithinDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/false, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); +} + +TEST_F(SlowKeysHandlerTest, KeyHeldPastDelayAccepted) { + const auto original_timestamp = EventTimeForNow(); + + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, original_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardPastDelay(); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(original_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true)); + + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/false, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 1u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 1u); +} + +TEST_F(SlowKeysHandlerTest, ModifierKey) { + const auto original_timestamp = EventTimeForNow(); + + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_LEFTCTRL, /*down=*/true, kTestDeviceId, original_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardPastDelay(); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(original_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true)); + + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch( + KEY_LEFTCTRL, /*down=*/false, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 1u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 1u); +} + +TEST_F(SlowKeysHandlerTest, DifferentKeysHaveIndependentDelays) { + // t = 0.0, KEY_A delay ends at 1.0 + const auto key_a_down_timestamp = EventTimeForNow(); + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, key_a_down_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + // t = 0.7, KEY_B delay ends at 1.7 + FastForwardByDelayMultiplier(0.7); + const auto key_b_down_timestamp = EventTimeForNow(); + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_B, /*down=*/true, kTestDeviceId, key_b_down_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + // t = 1.3 + FastForwardByDelayMultiplier(0.6); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(key_a_down_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true)); + + // t = 1.8 + FastForwardByDelayMultiplier(0.5); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(key_a_down_timestamp + kTestSlowKeysDelay, + key_b_down_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true, true)); + + // Verify key ups get dispatched without any additional key change calls. + FastForwardPastDelay(); + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/false, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 2u); + + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch( + KEY_B, /*down=*/false, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 2u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 2u); +} + +TEST_F(SlowKeysHandlerTest, DifferentDevicesHaveIndependentDelays) { + const int device_id_1 = 1; + const int device_id_2 = 2; + + // t = 0.0, device 1 delay ends at 1.0 + const auto device_1_down_timestamp = EventTimeForNow(); + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, device_id_1, device_1_down_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + // t = 0.7, device 2 delay ends at 1.7 + FastForwardByDelayMultiplier(0.7); + const auto device_2_down_timestamp = EventTimeForNow(); + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, device_id_2, device_2_down_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + // t = 1.3 + FastForwardByDelayMultiplier(0.6); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(device_1_down_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true)); + + // t = 1.8 + FastForwardByDelayMultiplier(0.5); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(device_1_down_timestamp + kTestSlowKeysDelay, + device_2_down_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true, true)); + + // Verify key ups get dispatched without any additional key change calls. + FastForwardPastDelay(); + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch(KEY_A, /*down=*/false, + device_id_1, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 2u); + + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch(KEY_A, /*down=*/false, + device_id_2, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 2u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 2u); +} + +TEST_F(SlowKeysHandlerTest, ExtraKeyPressesBeforeDelayDiscarded) { + const auto original_timestamp = EventTimeForNow(); + + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, original_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + // Extra key press. + FastForwardWithinDelay(); + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardPastDelay(); + EXPECT_THAT(on_key_change_callback_call_args_, + ElementsAre(original_timestamp + kTestSlowKeysDelay)); + EXPECT_THAT(should_dispatch_return_values_, ElementsAre(true)); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 1u); +} + +// This can happen when slow keys is enabled while a key is held down then +// released afterward. +TEST_F(SlowKeysHandlerTest, KeyUpWithoutKeyDown) { + const auto original_timestamp = EventTimeForNow(); + + EXPECT_TRUE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/false, kTestDeviceId, original_timestamp)); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); +} + +TEST_F(SlowKeysHandlerTest, DelayedKeysClearedWhenDisabling) { + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + handler_.SetEnabled(false); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); +} + +TEST_F(SlowKeysHandlerTest, DelayedKeysClearedWhenChangingDelay) { + EXPECT_FALSE(UpdateKeyStateAndShouldDispatch( + KEY_A, /*down=*/true, kTestDeviceId, EventTimeForNow())); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); + + handler_.SetDelay(handler_.GetDelay() + base::Milliseconds(10)); + + FastForwardPastDelay(); + ASSERT_EQ(on_key_change_callback_call_args_.size(), 0u); +} + +} // namespace ui
diff --git a/ui/file_manager/integration_tests/BUILD.gn b/ui/file_manager/integration_tests/BUILD.gn index dfd4f64..7562ec30 100644 --- a/ui/file_manager/integration_tests/BUILD.gn +++ b/ui/file_manager/integration_tests/BUILD.gn
@@ -89,7 +89,6 @@ # All non JS/TS files. copy("copy_app") { sources = [ - "file_manager/background.html", "file_manager/choose_entry.html", "file_manager_test_manifest.json", ]
diff --git a/ui/file_manager/integration_tests/definitions.d.ts b/ui/file_manager/integration_tests/definitions.d.ts index 64646cc..1cba40e 100644 --- a/ui/file_manager/integration_tests/definitions.d.ts +++ b/ui/file_manager/integration_tests/definitions.d.ts
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -interface Window { - chooseEntryResult?: string|null; - step: (() => void)|null; - autoStep(): void; - autostep: boolean; - currentStep: Promise<void>|null; +declare module globalThis { + /* eslint-disable no-var */ + var chooseEntryResult: string|undefined; + var step: (() => void)|null; + var autoStep: () => void; + var autostep: boolean; + var currentStep: Promise<void>|null; + /* eslint-enable no-var */ } // TODO(b/319189127): Remove these when the integration tests extension is
diff --git a/ui/file_manager/integration_tests/file_manager/background.html b/ui/file_manager/integration_tests/file_manager/background.html deleted file mode 100644 index dfb4d4e..0000000 --- a/ui/file_manager/integration_tests/file_manager/background.html +++ /dev/null
@@ -1,4 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> - -<script type="module" src="background.js"></script>
diff --git a/ui/file_manager/integration_tests/file_manager/background.ts b/ui/file_manager/integration_tests/file_manager/background.ts index 058b4db1..e64d816e 100644 --- a/ui/file_manager/integration_tests/file_manager/background.ts +++ b/ui/file_manager/integration_tests/file_manager/background.ts
@@ -52,7 +52,7 @@ * name to run. Use the configuration/details to setup the test environment, * then run the test case using chrome.test.RunTests. */ -window.addEventListener('load', async () => { +(async () => { // Request the guest mode state. remoteCall = new RemoteCallFilesApp(FILE_MANAGER_SWA_ID); const mode = await sendBrowserTestCommand({name: 'isInGuestMode'}); @@ -85,4 +85,4 @@ // Run the test. chrome.test.runTests([testCase[testCaseName]!]); -}); +})();
diff --git a/ui/file_manager/integration_tests/file_manager/choose_entry.ts b/ui/file_manager/integration_tests/file_manager/choose_entry.ts index b132ece..ae143f45 100644 --- a/ui/file_manager/integration_tests/file_manager/choose_entry.ts +++ b/ui/file_manager/integration_tests/file_manager/choose_entry.ts
@@ -7,7 +7,7 @@ * @suppress {checkTypes} */ -import {CHOOSE_ENTRY_PROPERTY} from './choose_entry_const.js'; +import {CHOOSE_ENTRY_PROPERTY, NO_ENTRIES_CHOSEN} from './choose_entry_const.js'; /** * Extracts parameters used by chooseEntry function. @@ -41,7 +41,7 @@ // See also crbug.com/1313625 // // In practice, it's (Entry | Entry[] | undefined). - let entryNames: (string|null) = null; + let entryNames: string = NO_ENTRIES_CHOSEN; if (!entry) { // No-op. } else if (params.acceptsMultiple) {
diff --git a/ui/file_manager/integration_tests/file_manager/choose_entry_const.ts b/ui/file_manager/integration_tests/file_manager/choose_entry_const.ts index 0b3b47fc..cb7187d 100644 --- a/ui/file_manager/integration_tests/file_manager/choose_entry_const.ts +++ b/ui/file_manager/integration_tests/file_manager/choose_entry_const.ts
@@ -4,3 +4,6 @@ // The name of the property under which we store the selected file entry. export const CHOOSE_ENTRY_PROPERTY = 'chooseEntryResult'; + +// The placeholder 'filename' when no file entries were selected. +export const NO_ENTRIES_CHOSEN = 'noEntriesChosen';
diff --git a/ui/file_manager/integration_tests/file_manager/dlp.ts b/ui/file_manager/integration_tests/file_manager/dlp.ts index fb74ca06..73028af 100644 --- a/ui/file_manager/integration_tests/file_manager/dlp.ts +++ b/ui/file_manager/integration_tests/file_manager/dlp.ts
@@ -6,6 +6,7 @@ import {addEntries, ENTRIES, EntryType, RootPath, sendBrowserTestCommand, sendTestMessage, TestEntryInfo} from '../test_util.js'; import {remoteCall} from './background.js'; +import {NO_ENTRIES_CHOSEN} from './choose_entry_const.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; import {BASIC_ANDROID_ENTRY_SET, BASIC_LOCAL_ENTRY_SET, FakeTask} from './test_data.js'; @@ -333,7 +334,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'downloads', [], closer)); } @@ -409,7 +410,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'downloads', [], closer)); } @@ -470,7 +471,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'downloads', [ENTRIES.hello], closer)); } @@ -509,7 +510,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'downloads', [], closer)); } @@ -535,7 +536,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'downloads', [], closer)); } @@ -561,7 +562,7 @@ // Open a save dialog in Play Files. chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'android_files', BASIC_ANDROID_ENTRY_SET, allowedCloser)); @@ -592,7 +593,7 @@ // Try to open a save dialog in Play Files. Since ARC is blocked by DLP, the // dialog should open in the default root instead. chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'saveFile'}, 'android_files', [ENTRIES.hello], blockedCloser)); } @@ -648,7 +649,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'openFile'}, 'downloads', BASIC_LOCAL_ENTRY_SET, closer)); } @@ -717,7 +718,7 @@ }; chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'openFile'}, 'downloads', [ENTRIES.directoryA], closer));
diff --git a/ui/file_manager/integration_tests/file_manager/file_dialog.ts b/ui/file_manager/integration_tests/file_manager/file_dialog.ts index 020810d3..3bc7a94 100644 --- a/ui/file_manager/integration_tests/file_manager/file_dialog.ts +++ b/ui/file_manager/integration_tests/file_manager/file_dialog.ts
@@ -6,6 +6,7 @@ import {addEntries, ENTRIES, getCaller, openEntryChoosingWindow, pending, pollForChosenEntry, repeatUntil, sendBrowserTestCommand, sendTestMessage} from '../test_util.js'; import {remoteCall} from './background.js'; +import {NO_ENTRIES_CHOSEN} from './choose_entry_const.js'; import {DirectoryTreePageObject} from './page_objects/directory_tree.js'; import {BASIC_LOCAL_ENTRY_SET} from './test_data.js'; @@ -201,7 +202,7 @@ const entrySet = await setUpFileEntrySet(volume); chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type}, volume, entrySet, closer)); } @@ -239,7 +240,7 @@ const entrySet = await setUpFileEntrySet(volume); chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type}, volume, entrySet, closer)); } @@ -259,7 +260,7 @@ const entrySet = await setUpFileEntrySet(volume); chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'openFile'}, volume, entrySet, closer)); } @@ -279,7 +280,7 @@ const entrySet = await setUpFileEntrySet(volume); chrome.test.assertEq( - undefined, + NO_ENTRIES_CHOSEN, await remoteCall.openAndWaitForClosingDialog( {type: 'openFile'}, volume, entrySet, closer)); } @@ -837,7 +838,7 @@ */ async function showSaveAndConfirmExpecting( extraParams: chrome.fileSystem.ChooseEntryOptions, - expectName: string): Promise<string|null> { + expectName: string): Promise<string> { const caller = getCaller(); const params = {
diff --git a/ui/file_manager/integration_tests/file_manager/holding_space.ts b/ui/file_manager/integration_tests/file_manager/holding_space.ts index 382b601..f3137506 100644 --- a/ui/file_manager/integration_tests/file_manager/holding_space.ts +++ b/ui/file_manager/integration_tests/file_manager/holding_space.ts
@@ -69,10 +69,6 @@ // Open Files app on Downloads. const appId = await remoteCall.setupAndWaitUntilReady(RootPath.DOWNLOADS); - // Check: `document.body` should indicate that tablet mode is disabled. - chrome.test.assertFalse( - document.body.classList.contains('tablet-mode-enabled')); - // Async function which repeats until the element matching the specified // `query` has a calculated display matching the specified `displayValue`. async function waitForElementWithDisplay(
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.ts b/ui/file_manager/integration_tests/file_manager/quick_view.ts index e5ea627..4f85d81 100644 --- a/ui/file_manager/integration_tests/file_manager/quick_view.ts +++ b/ui/file_manager/integration_tests/file_manager/quick_view.ts
@@ -1661,27 +1661,21 @@ const mimeType = await getQuickViewMetadataBoxField(appId, 'Type'); chrome.test.assertEq('image/tiff', mimeType); - // Get the fileSafeMedia element preview thumbnail image size. + // Get the fileSafeMedia element preview thumbnail image, as a data URL. const element = await remoteCall.waitForElement(appId, filesSafeMedia); - const image = new Image(); - let imageSize = ''; - image.onload = () => { - imageSize = `${image.naturalWidth} x ${image.naturalHeight}`; - }; + const dataURL = JSON.parse(element.attributes['src']!).data as string; - const sourceContent = JSON.parse(element.attributes['src']!); - - chrome.test.assertTrue(!!sourceContent.data); - image.src = sourceContent.data as string; - - // Check: the preview thumbnail should have an orientated size. - await repeatUntil(async () => { - if (!image.complete || imageSize !== '120 x 160') { - return pending(caller, 'Waiting for preview thumbnail size.'); - } - - return; - }); + // Check that the thumbnail image size is 120 x 160. In hexadecimal, this is + // 0x78 x 0xa0. We cannot say "new Image()" in a service worker, to decode + // the PNG-formatted image, so we look at the byte level for (0x78, 0xa0) as + // two big-endian uint32 values in the IHDR chunk of the PNG-formatted bytes. + // The "IHDR 120 x 160" bytes should be at byte offset 12: 8 bytes for the + // PNG magic header plus 4 bytes for the IHDR chunk length. + const prefix = 'data:image/png;base64,'; + chrome.test.assertTrue(dataURL.startsWith(prefix)); + const pngBytes = atob(dataURL.substring(prefix.length)); + const ihdr120x160 = 'IHDR\x00\x00\x00\x78\x00\x00\x00\xa0'; + chrome.test.assertEq(12, pngBytes.indexOf(ihdr120x160)); } /**
diff --git a/ui/file_manager/integration_tests/file_manager_test_manifest.json b/ui/file_manager/integration_tests/file_manager_test_manifest.json index 4c62d34..af49c0a 100644 --- a/ui/file_manager/integration_tests/file_manager_test_manifest.json +++ b/ui/file_manager/integration_tests/file_manager_test_manifest.json
@@ -2,12 +2,13 @@ // chrome-extension://oobinhbdbiehknkpbpejbbpdbkdjmoco/ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBjsTE4ocXJWzgcCDCUcsPASoRCGaTHrHn6b4zDTCayTuJtyGKzw4xZPMiG4dbEbmSAwEU7UCoyJAM1XfLS7UQ/Zz7ft8wpZkSS8/PJW+E4Qu++tMS0csj2Wdrrd2c5yyWxlJ+H9o2ivwtwuxs7pd+LXt+gsBA0epnT04T9EvOTQIDAQAB", "name": "Files test extension", - "version": "0.1", + "version": "0.2", "incognito": "split", // Run a separate instance for the incognito mode. - "manifest_version": 2, + "manifest_version": 3, "description": "Files test extension", "background": { - "page": "file_manager/background.html" + "service_worker": "file_manager/background.js", + "type": "module" }, "permissions": [ {"fileSystem": ["write"]}, @@ -16,5 +17,7 @@ "commandLinePrivate", "chrome-extension://oobinhbdbiehknkpbpejbbpdbkdjmoco/*" ], - "content_security_policy": "script-src 'self' chrome://resources ;" + "content_security_policy": { + "extension_page": "script-src 'self' chrome://resources ;" + } }
diff --git a/ui/file_manager/integration_tests/remote_call.ts b/ui/file_manager/integration_tests/remote_call.ts index 43799358..c78cf04 100644 --- a/ui/file_manager/integration_tests/remote_call.ts +++ b/ui/file_manager/integration_tests/remote_call.ts
@@ -15,13 +15,13 @@ * that if step() is defined at the time of this call, invoke it to start the * test auto-stepping ball rolling. */ -window.autoStep = () => { - window.autostep = window.autostep || false; - if (!window.autostep) { - window.autostep = true; +globalThis.autoStep = () => { + globalThis.autostep = globalThis.autostep || false; + if (!globalThis.autostep) { + globalThis.autostep = true; } - if (window.autostep && typeof window.step === 'function') { - window.step(); + if (globalThis.autostep && typeof globalThis.step === 'function') { + globalThis.step(); } }; @@ -1252,9 +1252,9 @@ dialogParams: chrome.fileSystem.ChooseEntryOptions, volumeType: string, expectedSet: TestEntryInfo[], closeDialog: (a: string) => Promise<void>, useBrowserOpen: boolean = false, - debug: boolean = false): Promise<string|null> { + debug: boolean = false): Promise<string> { const caller = getCaller(); - let resultPromise: () => Promise<string|null>; + let resultPromise: () => Promise<string>; if (useBrowserOpen) { await sendTestMessage({name: 'runSelectFileDialog'}); resultPromise = async(): Promise<string> => { @@ -1263,7 +1263,7 @@ }; } else { await openEntryChoosingWindow(dialogParams); - resultPromise = (): Promise<string|null> => { + resultPromise = (): Promise<string> => { return pollForChosenEntry(caller); }; }
diff --git a/ui/file_manager/integration_tests/test_util.ts b/ui/file_manager/integration_tests/test_util.ts index 756c8b2..8428bfd 100644 --- a/ui/file_manager/integration_tests/test_util.ts +++ b/ui/file_manager/integration_tests/test_util.ts
@@ -1811,10 +1811,10 @@ if (sender.id !== EXTENSION_ID) { return false; } else if (msg.msgType === CHOOSE_ENTRY_PROPERTY) { - if (msg.entryNames || (msg.entryNames === null)) { - window[CHOOSE_ENTRY_PROPERTY] = msg.entryNames as (string | null); + if (msg.entryNames) { + globalThis[CHOOSE_ENTRY_PROPERTY] = msg.entryNames as string; } else { - delete window[CHOOSE_ENTRY_PROPERTY]; + delete globalThis[CHOOSE_ENTRY_PROPERTY]; } return true; } @@ -1826,17 +1826,14 @@ * until entry selected in a dialog shown by chooseEntry() is set. * @return the entry set by the dialog shown via chooseEntry(). */ -export async function pollForChosenEntry(caller: string): Promise<string|null> { +export async function pollForChosenEntry(caller: string): Promise<string> { await repeatUntil(() => { - if (window[CHOOSE_ENTRY_PROPERTY] !== undefined) { + if (globalThis[CHOOSE_ENTRY_PROPERTY] !== undefined) { return; } return pending(caller, 'Waiting for chooseEntry() result'); }); - // The "?? null" is to placate the TS type checker, which doesn't know that a - // post-condition of the "await repeatUntil" above finishing is that - // window[CHOOSE_ENTRY_PROPERTY] cannot be undefined (but it can be null). - return window[CHOOSE_ENTRY_PROPERTY] ?? null; + return globalThis[CHOOSE_ENTRY_PROPERTY]!; } /** Waits until the MediaApp/Backlight shows up. */
diff --git a/ui/gfx/codec/png_codec.cc b/ui/gfx/codec/png_codec.cc index b289771..35c3bdc 100644 --- a/ui/gfx/codec/png_codec.cc +++ b/ui/gfx/codec/png_codec.cc
@@ -25,7 +25,6 @@ #if BUILDFLAG(SKIA_BUILD_RUST_PNG) #include "third_party/skia/experimental/rust_png/decoder/SkPngRustDecoder.h" -#include "third_party/skia/experimental/rust_png/encoder/SkPngRustEncoder.h" #endif namespace gfx { @@ -196,37 +195,6 @@ static_cast<int>(comment_pointers.size())); } -// A helper that will encode a PNG image using either the `libpng`-based -// `SkPngEncoder::Encode` API, or (if `kRustyPngFeature` is built and enabled) -// the Rust-based `SkPngRustEncoder::Encode` API. -bool EncodePng(SkWStream* dst, - const SkPixmap& src, - const SkPngEncoder::Options& options) { - if (skia::IsRustyPngEnabled()) { -#if BUILDFLAG(SKIA_BUILD_RUST_PNG) - SkPngRustEncoder::Options rust_options; - if (options.fZLibLevel < 4) { - rust_options.fCompressionLevel = SkPngRustEncoder::CompressionLevel::kLow; - } else if (options.fZLibLevel < 7) { - rust_options.fCompressionLevel = - SkPngRustEncoder::CompressionLevel::kMedium; - } else { - rust_options.fCompressionLevel = - SkPngRustEncoder::CompressionLevel::kHigh; - } - rust_options.fComments = options.fComments; - // TODO(https://crbug.com/381139785): Translate the ICC profile as well. - - return SkPngRustEncoder::Encode(dst, src, rust_options); -#else - // The `if` condition guarantees `SKIA_BUILD_RUST_PNG`. - NOTREACHED(); -#endif - } - - return SkPngEncoder::Encode(dst, src, options); -} - std::optional<std::vector<uint8_t>> EncodeSkPixmap( const SkPixmap& src, const std::vector<PNGCodec::Comment>& comments, @@ -242,7 +210,7 @@ options.fFilterFlags = SkPngEncoder::FilterFlag::kNone; } - if (!EncodePng(&dst, src, options)) { + if (!skia::EncodePng(&dst, src, options)) { return std::nullopt; }
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index f3e7c9c..2a0b5af 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -145,6 +145,8 @@ "shader_tracking.h", "shared_gl_fence_egl.cc", "shared_gl_fence_egl.h", + "startup_trace.cc", + "startup_trace.h", "sync_control_vsync_provider.cc", "sync_control_vsync_provider.h", "trace_util.cc",
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index fa950e1..2c0d861 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -215,7 +215,7 @@ // that DWM power optimization can be turned on. BASE_FEATURE(kDirectCompositionLetterboxVideoOptimization, "DirectCompositionLetterboxVideoOptimization", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Do not consider hardware YUV overlay count when promoting quads to DComp // visuals. If there are more videos than hardware overlay planes, there may be
diff --git a/ui/gl/startup_trace.cc b/ui/gl/startup_trace.cc new file mode 100644 index 0000000..d6176961 --- /dev/null +++ b/ui/gl/startup_trace.cc
@@ -0,0 +1,73 @@ +// Copyright 2024 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/gl/startup_trace.h" + +#include "base/no_destructor.h" +#include "base/task/sequenced_task_runner.h" +#include "base/trace_event/trace_event.h" + +namespace gl { +namespace { +constexpr char kTraceCategory[] = "gpu,startup"; +} // namespace + +std::atomic<bool> StartupTrace::startup_in_progress_ = false; + +// static +StartupTrace* StartupTrace::GetInstance() { + static StartupTrace g_instance; + return &g_instance; +} + +// static +void StartupTrace::Startup() { + startup_in_progress_.store(true); +} + +// static +void StartupTrace::StarupDone() { + startup_in_progress_.store(false); + gl::StartupTrace::GetInstance()->RecordAndClearStages(); +} + +StartupTrace::StartupTrace() { + BindToCurrentThread(); +} + +StartupTrace::~StartupTrace() = default; + +void StartupTrace::BindToCurrentThread() { + if (!task_runner_ && base::SequencedTaskRunner::HasCurrentDefault()) { + task_runner_ = base::SequencedTaskRunner::GetCurrentDefault(); + } +} + +StartupTrace::ScopedStage::ScopedStage(size_t size) : size(size) {} +StartupTrace::ScopedStage::~ScopedStage() { + if (size) { + StartupTrace::GetInstance()->stages_[size - 1].end = base::TimeTicks::Now(); + } +} + +StartupTrace::ScopedStage StartupTrace::AddStage(const char* name) { + DCHECK(!base::SequencedTaskRunner::HasCurrentDefault() || + task_runner_->RunsTasksInCurrentSequence()); + stages_.emplace_back(name, base::TimeTicks::Now(), base::TimeTicks()); + return StartupTrace::ScopedStage{stages_.size()}; +} + +void StartupTrace::RecordAndClearStages() { + auto t = perfetto::ThreadTrack::Current(); + + for (auto& stage : stages_) { + TRACE_EVENT_BEGIN(kTraceCategory, perfetto::StaticString{stage.name}, t, + stage.start); + TRACE_EVENT_END(kTraceCategory, t, stage.end); + } + + stages_.clear(); +} + +} // namespace gl
diff --git a/ui/gl/startup_trace.h b/ui/gl/startup_trace.h new file mode 100644 index 0000000..64f12ff --- /dev/null +++ b/ui/gl/startup_trace.h
@@ -0,0 +1,92 @@ +// Copyright 2024 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_GL_STARTUP_TRACE_H_ +#define UI_GL_STARTUP_TRACE_H_ + +#include <vector> + +#include "base/memory/scoped_refptr.h" +#include "base/time/time.h" +#include "ui/gl/gl_export.h" + +namespace base { +class SequencedTaskRunner; +} + +namespace gl { + +// This class provides a method to trace the initialization of GPU process. When +// tracing instance is not initialized it will accumulate stages with start and +// end time stamp so they can emit traces once tracing inits. Calling this after +// `StartupDone()` will not add a stage. The caveat is that it cannot know +// before-hand whether the tracing category is on or not so the stage is +// recorded nonetheless. +// +// Example: +// GPU_STARTUP_TRACE_EVENT(__func__); +// +// Note: Currently it's only safe to invoke `GPU_STARTUP_TRACE_EVENT` from the +// gpu main thread between `Startup()` and `StartupDone()`. +class GL_EXPORT StartupTrace { + public: + struct Stage { + const char* name = nullptr; + const base::TimeTicks start; + base::TimeTicks end; + }; + + class GL_EXPORT ScopedStage { + public: + explicit ScopedStage(size_t size); + ~ScopedStage(); + + private: + size_t size = 0; + }; + + StartupTrace(); + StartupTrace(const StartupTrace&) = delete; + StartupTrace(StartupTrace&&) = delete; + StartupTrace& operator=(const StartupTrace&) = delete; + StartupTrace& operator=(StartupTrace&&) = delete; + ~StartupTrace(); + + static StartupTrace* GetInstance(); + ALWAYS_INLINE static bool IsEnabled() { + return startup_in_progress_.load(std::memory_order_acquire); + } + + void BindToCurrentThread(); + ScopedStage AddStage(const char* name); + + // Called by the main thread before/after the tracing. + static void Startup(); + static void StarupDone(); + + private: + void RecordAndClearStages(); + + static std::atomic<bool> startup_in_progress_; + + scoped_refptr<base::SequencedTaskRunner> task_runner_; + std::vector<Stage> stages_; +}; + +} // namespace gl + +// Generate a unique variable name with a given prefix. +#define GPU_STARTUP_TRACE_INTERNAL_CONCAT2(a, b) a##b +#define GPU_STARTUP_TRACE_INTERNAL_CONCAT(a, b) \ + GPU_STARTUP_TRACE_INTERNAL_CONCAT2(a, b) +#define GPU_STARTUP_TRACE_UID(prefix) \ + GPU_STARTUP_TRACE_INTERNAL_CONCAT(prefix, __LINE__) + +#define GPU_STARTUP_TRACE_EVENT(name) \ + gl::StartupTrace::ScopedStage GPU_STARTUP_TRACE_UID(scoped_gpu_trace) = \ + gl::StartupTrace::IsEnabled() \ + ? gl::StartupTrace::GetInstance()->AddStage(name) \ + : gl::StartupTrace::ScopedStage(0); + +#endif // UI_GL_STARTUP_TRACE_H_
diff --git a/ui/latency/mojom/BUILD.gn b/ui/latency/mojom/BUILD.gn index a3901253..4d0f799 100644 --- a/ui/latency/mojom/BUILD.gn +++ b/ui/latency/mojom/BUILD.gn
@@ -52,7 +52,7 @@ mojom("test_interfaces") { testonly = true - sources = [ "traits_test_service.mojom" ] + sources = [ "traits_test_service.test-mojom" ] public_deps = [ ":mojom" ] }
diff --git a/ui/latency/mojom/mojom_traits_unittest.cc b/ui/latency/mojom/mojom_traits_unittest.cc index 37d5aad..4af1b08 100644 --- a/ui/latency/mojom/mojom_traits_unittest.cc +++ b/ui/latency/mojom/mojom_traits_unittest.cc
@@ -9,7 +9,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/latency/mojom/latency_info_mojom_traits.h" -#include "ui/latency/mojom/traits_test_service.mojom.h" +#include "ui/latency/mojom/traits_test_service.test-mojom.h" namespace ui {
diff --git a/ui/latency/mojom/traits_test_service.mojom b/ui/latency/mojom/traits_test_service.test-mojom similarity index 100% rename from ui/latency/mojom/traits_test_service.mojom rename to ui/latency/mojom/traits_test_service.test-mojom
diff --git a/ui/ozone/public/input_controller.h b/ui/ozone/public/input_controller.h index d4a6ba4..e04149a8 100644 --- a/ui/ozone/public/input_controller.h +++ b/ui/ozone/public/input_controller.h
@@ -80,6 +80,10 @@ const base::TimeDelta& interval) = 0; virtual void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) = 0; + virtual void SetSlowKeysEnabled(bool enabled) = 0; + virtual bool IsSlowKeysEnabled() const = 0; + virtual void SetSlowKeysDelay(base::TimeDelta delay) = 0; + // Callback is invoked when the keyboard layout is available and initialized. virtual void SetCurrentLayoutByName( const std::string& layout_name,
diff --git a/ui/ozone/public/stub_input_controller.cc b/ui/ozone/public/stub_input_controller.cc index 953cc68..00b62e4f6 100644 --- a/ui/ozone/public/stub_input_controller.cc +++ b/ui/ozone/public/stub_input_controller.cc
@@ -52,6 +52,11 @@ const base::TimeDelta& interval) {} void StubInputController::GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) {} +void StubInputController::SetSlowKeysEnabled(bool enabled) {} +bool StubInputController::IsSlowKeysEnabled() const { + return false; +} +void StubInputController::SetSlowKeysDelay(base::TimeDelta delay) {} void StubInputController::SetCurrentLayoutByName( const std::string& layout_name, base::OnceCallback<void(bool)> callback) {
diff --git a/ui/ozone/public/stub_input_controller.h b/ui/ozone/public/stub_input_controller.h index 86c6f45c..63fa5f9 100644 --- a/ui/ozone/public/stub_input_controller.h +++ b/ui/ozone/public/stub_input_controller.h
@@ -35,6 +35,9 @@ const base::TimeDelta& interval) override; void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) override; + void SetSlowKeysEnabled(bool enabled) override; + bool IsSlowKeysEnabled() const override; + void SetSlowKeysDelay(base::TimeDelta delay) override; void SetCurrentLayoutByName(const std::string& layout_name, base::OnceCallback<void(bool)> callback) override; void SetKeyboardKeyBitsMapping(
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc index 1c3cf9c..3ca1e78 100644 --- a/ui/views/accessibility/view_accessibility.cc +++ b/ui/views/accessibility/view_accessibility.cc
@@ -160,9 +160,6 @@ } void ViewAccessibility::GetAccessibleNodeData(ui::AXNodeData* data) const { - data->AddStringAttribute(ax::mojom::StringAttribute::kClassName, - view_->GetClassName()); - if (is_widget_closed_) { // Views may misbehave if their widget is closed; set "null-like" attributes // rather than possibly crashing. @@ -882,6 +879,14 @@ } } +void ViewAccessibility::OnViewAddedToWidget() { + // Ideally, we would like to set the class name when the object is created, + // this would be done in the ctor, but due to inheritance and the + // implementation of `GetClassName`, it would not work. As such, we set it + // here, since at this point the view object is fully initialized. + SetClassName(view_->GetClassName()); +} + void ViewAccessibility::SetPlaceholder(const std::string& placeholder) { data_.AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder, placeholder);
diff --git a/ui/views/accessibility/view_accessibility.h b/ui/views/accessibility/view_accessibility.h index c0a262d0..3e0be61 100644 --- a/ui/views/accessibility/view_accessibility.h +++ b/ui/views/accessibility/view_accessibility.h
@@ -371,6 +371,8 @@ void OnTooltipTextChanged( std::optional<std::u16string> old_tooltip_text = std::nullopt); + void OnViewAddedToWidget(); + void SetPlaceholder(const std::string& placeholder); void AddAction(ax::mojom::Action action);
diff --git a/ui/views/animation/ink_drop_host.h b/ui/views/animation/ink_drop_host.h index c579f65d..e5135719 100644 --- a/ui/views/animation/ink_drop_host.h +++ b/ui/views/animation/ink_drop_host.h
@@ -289,7 +289,7 @@ // Attention is a state we apply on Buttons' ink drop when we want to draw // users' attention to this button and prompt users' interaction. // It consists of two visual effects: a default light blue color and a pulsing - // effect. Current use case is IPH. Go to chrome://internals/user-education + // effect. Current use case is IPH. Go to chrome://user-education-internals // and press e.g. IPH_TabSearch to see the effects. bool in_attention_state_ = false; };
diff --git a/ui/views/view.cc b/ui/views/view.cc index 97bfb3d6..f4d9349 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -3149,6 +3149,7 @@ ViewHierarchyChangedImpl(details); if (is_added_to_widget) { AddedToWidget(); + GetViewAccessibility().OnViewAddedToWidget(); observers_.Notify(&ViewObserver::OnViewAddedToWidget, this); } }
diff --git a/ui/webui/resources/cr_elements/cr_ripple/cr_ripple.ts b/ui/webui/resources/cr_elements/cr_ripple/cr_ripple.ts index e6638a8..53788eb 100644 --- a/ui/webui/resources/cr_elements/cr_ripple/cr_ripple.ts +++ b/ui/webui/resources/cr_elements/cr_ripple/cr_ripple.ts
@@ -52,29 +52,16 @@ (this.parentNode as ShadowRoot).host : this.parentElement!; - this.eventTracker_.add(keyEventTarget, 'pointerdown', (e: Event) => { - const handled = this.uiDownAction(e as PointerEvent); + this.eventTracker_.add( + keyEventTarget, 'pointerdown', + (e: Event) => this.uiDownAction(e as PointerEvent)); + this.eventTracker_.add( + keyEventTarget, 'pointerup', () => this.uiUpAction()); - if (!handled) { - return; - } - - this.eventTracker_.add(keyEventTarget, 'pointermove', (e: Event) => { - // Only call setPointerCapture() if 'pointermove' happens and not - // in 'pointerdown', so that clicking any links or other elements - // within the parent works as expected. - this.setPointerCapture((e as PointerEvent).pointerId); - this.eventTracker_.remove(keyEventTarget, 'pointermove'); - }); - }); - - const cancelOrUp = (e: Event) => { - this.eventTracker_.remove(keyEventTarget, 'pointermove'); - this.uiUpAction(e as PointerEvent); - }; - - this.eventTracker_.add(keyEventTarget, 'pointercancel', cancelOrUp); - this.eventTracker_.add(keyEventTarget, 'pointerup', cancelOrUp); + // 'pointerup' does not fire if the pointer is moved outside the bounds of + // `keyEventTarget` before releasing, so also listen for `pointerout`. + this.eventTracker_.add( + keyEventTarget, 'pointerout', () => this.uiUpAction()); this.eventTracker_.add(keyEventTarget, 'keydown', (e: KeyboardEvent) => { if (e.defaultPrevented) { @@ -115,18 +102,15 @@ } } - uiDownAction(e?: PointerEvent): boolean { + uiDownAction(e?: PointerEvent) { if (e !== undefined && e.button !== 0) { // Ignore secondary mouse button clicks. - return false; + return; } - if (this.noink) { - return false; + if (!this.noink) { + this.downAction_(e); } - - this.downAction_(e); - return true; } private downAction_(e?: PointerEvent) { @@ -213,27 +197,19 @@ }); } - uiUpAction(e?: PointerEvent) { - if (this.noink) { - return; + uiUpAction() { + if (!this.noink) { + this.upAction_(); } - - this.upAction_(e); } - private upAction_(e?: PointerEvent) { - if (this.holdDown) { - return; + private upAction_() { + if (!this.holdDown) { + this.hideRipple_(); } - - this.hideRipple_(e); } - private hideRipple_(e?: PointerEvent) { - if (e !== undefined && this.hasPointerCapture(e.pointerId)) { - this.releasePointerCapture(e.pointerId); - } - + private hideRipple_() { if (this.ripples_.length === 0) { return; }
diff --git a/v8 b/v8 index bdff9e1..f99b675 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit bdff9e1d4b2c4b1a0c29c60f4c412f269750aff6 +Subproject commit f99b675360f4753b9474c0594114447e8ca2c2f0