diff --git a/DEPS b/DEPS index e1a38e4..fd570c6 100644 --- a/DEPS +++ b/DEPS
@@ -283,7 +283,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '593cd597a31e649f7219d3bdd021b76ec2f835c1', + 'angle_revision': 'a65af046953a0a16ceed4ad1dbb91fb377bf245b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -302,7 +302,7 @@ # 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. - 'fuchsia_version': 'version:8.20220608.1.1', + 'fuchsia_version': 'version:8.20220608.4.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -346,7 +346,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '45853b3700cddd1f4eefe531f18add46e6c90e76', + 'catapult_revision': '8a8c0b9c3967e17da1d9f64b3d57e4a969b465a7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -354,7 +354,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': '0cca99b9409a03b9523f1d5cd13675b5fc0aed62', + 'devtools_frontend_revision': 'ac6b02745945218c6e79b2adb8ef987f892fc141', # 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. @@ -771,7 +771,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '2eaeeed3b8899aa76e3f6defd20e7d7d89eeb360', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '8225446a8df15e53e96304852f134259e0e5e2df', 'condition': 'checkout_ios', }, @@ -1059,7 +1059,7 @@ }, 'src/third_party/breakpad/breakpad': - Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '8b68c72a3fff2bb687c7f411e5c1c09e356b8603', + Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'c4c43b80ea8854c57a4374ac32579b577172dc23', 'src/third_party/byte_buddy': { 'packages': [ @@ -1136,7 +1136,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8199bccb81a85678d731941c1ac5130a72014834', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b3579d428a79e0425f4d3d9be58d76470f96fb6b', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1425,7 +1425,7 @@ Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'd62ee21e6627888e84466b5a5ed15775582ac67b', + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'baef41447887e1a17897a4cb6ccc854ef3a9d652', 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -1533,7 +1533,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '31772328c517b725c81994e4b9b99aac18319e40', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'db7def5150207a574e8955afc591a5650b3ad290', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1669,7 +1669,7 @@ 'condition': 'checkout_android', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@23b710f1a0b3c44d51035c6400a554415f95d9c6', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@1190dc2b6863cf0137ac4c2d323c66c8887c8e4e', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1708,7 +1708,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'edd275f0ad33c708fba30643cf971adf0f6ba488', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ca6726d5c47156b6ed79a19d186b5bdb3384ff41', + Var('webrtc_git') + '/src.git' + '@' + 'da0ea972364f23d21893cf58701ce8ccd798c1c4', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1781,7 +1781,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e07d4ea1bf521f8fcfc328290cb212074b7e138b', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ea11a9525684a5ba7962ca95a9a42511bc0697a8', 'condition': 'checkout_src_internal', }, @@ -1811,7 +1811,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': '-r5clhZKMsKXeyTvDOdrDvtevLMbxBxCv4TpRaK5SK4C', + 'version': '7Wk1Iwgo26iCC0y5AnlUH7ejxibcMH_hpnDFC1GYhWMC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/gfx/BUILD.gn b/android_webview/browser/gfx/BUILD.gn index b313bc7..7062171 100644 --- a/android_webview/browser/gfx/BUILD.gn +++ b/android_webview/browser/gfx/BUILD.gn
@@ -83,7 +83,6 @@ "//content/public/browser", "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/service", - "//gpu/ipc:gl_in_process_context", "//gpu/ipc/common:android_image_reader_utils", "//gpu/ipc/common:common", "//gpu/skia_bindings",
diff --git a/android_webview/lib/BUILD.gn b/android_webview/lib/BUILD.gn index 408f059..66e2365 100644 --- a/android_webview/lib/BUILD.gn +++ b/android_webview/lib/BUILD.gn
@@ -44,7 +44,6 @@ "//gin", "//gpu/command_buffer/service", "//gpu/config", - "//gpu/ipc:gl_in_process_context", "//media", "//media:media_buildflags", "//third_party/blink/public/common:headers",
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc index c4520c5..aa6c6da 100644 --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc
@@ -59,7 +59,6 @@ #include "gin/v8_initializer.h" #include "gpu/command_buffer/service/gpu_switches.h" #include "gpu/config/gpu_finch_features.h" -#include "gpu/ipc/gl_in_process_context.h" #include "media/base/media_switches.h" #include "media/media_buildflags.h" #include "services/network/public/cpp/features.h"
diff --git a/android_webview/tools/automated_ui_tests/BUILD.gn b/android_webview/tools/automated_ui_tests/BUILD.gn index 6007e2f..5645be1 100644 --- a/android_webview/tools/automated_ui_tests/BUILD.gn +++ b/android_webview/tools/automated_ui_tests/BUILD.gn
@@ -63,9 +63,9 @@ "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:ui_java_test_support", ] data = [ "test/data/" ]
diff --git a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java index 517db69..9f3dab8 100644 --- a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java +++ b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
@@ -43,9 +43,6 @@ import android.content.Intent; import android.os.Build; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiSelector; import android.view.MenuItem; import androidx.test.espresso.NoMatchingViewException; @@ -58,6 +55,9 @@ import androidx.test.espresso.intent.Intents; import androidx.test.espresso.web.webdriver.Locator; import androidx.test.filters.SmallTest; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiSelector; import org.hamcrest.Description; import org.hamcrest.Matcher;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 54d0fc4..d0680b6 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -3170,6 +3170,7 @@ sources = [ "test/ash_pixel_diff_test_base.cc", "test/ash_pixel_diff_test_base.h", + "test/demo_ash_pixel_diff_test.cc", ] deps = [
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc index 747186a..a02ae49 100644 --- a/ash/ambient/ambient_controller.cc +++ b/ash/ambient/ambient_controller.cc
@@ -888,11 +888,7 @@ current_theme = animation_experiment_enabled.value() ? features::kAmbientModeAnimationThemeParam.Get() : kDefaultAmbientAnimationTheme; - } else if (features::IsPersonalizationHubEnabled()) { - // UX testers/dogfooders only have to enable the personalization hub to get - // the animation. They do not turn on the dedicated animation experiment - // flag as that is only intended for developers who want to bypass the hub. - // If the hub is disabled, fallback to the default theme. + } else if (features::IsAmbientModeAnimationEnabled()) { DCHECK(current_theme_from_pref_); current_theme = *current_theme_from_pref_; }
diff --git a/ash/ambient/ambient_controller_unittest.cc b/ash/ambient/ambient_controller_unittest.cc index a4e90de9..13eafdf 100644 --- a/ash/ambient/ambient_controller_unittest.cc +++ b/ash/ambient/ambient_controller_unittest.cc
@@ -1190,43 +1190,57 @@ } TEST_P(AmbientControllerTestForAnyTheme, MetricsEngagementTime) { + // TODO(esum): Find a better way of fast forwarding time for lottie animations + // in unit tests. Currently, the whole compositor stack is being used in this + // test harness and there is no good way to control the frame rate, so + // FastForwardBy() blocks for long periods of time. Do not make this value + // too high, or the test is at risk of timing out. + constexpr base::TimeDelta kExpectedEngagementTime = base::Milliseconds(100); + base::HistogramTester histogram_tester; Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false); LockScreen(); - FastForwardToLockScreenTimeout(); - FastForwardTiny(); + // Unlike other tests, the exact amount of time we spend in ambient mode + // matters to write the correct test expectation. So fast forward by the + // exact amount needed to trigger ambient mode. + // (FastForwardToLockScreenTimeout() adds on a little buffer to the timeout) + task_environment()->FastForwardBy(ambient_controller() + ->ambient_ui_model() + ->lock_screen_inactivity_timeout()); ASSERT_TRUE(ambient_controller()->IsShown()); - task_environment()->FastForwardBy(base::Minutes(1)); + task_environment()->FastForwardBy(kExpectedEngagementTime); UnlockScreen(); ASSERT_FALSE(ambient_controller()->IsShown()); histogram_tester.ExpectTimeBucketCount( - "Ash.AmbientMode.EngagementTime.ClamshellMode", base::Minutes(1), 1); + "Ash.AmbientMode.EngagementTime.ClamshellMode", kExpectedEngagementTime, + 1); histogram_tester.ExpectTimeBucketCount( base::StrCat({"Ash.AmbientMode.EngagementTime.", ToString(GetParam())}), - base::Minutes(1), 1); + kExpectedEngagementTime, 1); // Now do the same sequence in tablet mode. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true); LockScreen(); - FastForwardToLockScreenTimeout(); - FastForwardTiny(); + task_environment()->FastForwardBy(ambient_controller() + ->ambient_ui_model() + ->lock_screen_inactivity_timeout()); ASSERT_TRUE(ambient_controller()->IsShown()); - task_environment()->FastForwardBy(base::Minutes(1)); + task_environment()->FastForwardBy(kExpectedEngagementTime); UnlockScreen(); ASSERT_FALSE(ambient_controller()->IsShown()); histogram_tester.ExpectTimeBucketCount( - "Ash.AmbientMode.EngagementTime.TabletMode", base::Minutes(1), 1); + "Ash.AmbientMode.EngagementTime.TabletMode", kExpectedEngagementTime, 1); histogram_tester.ExpectTimeBucketCount( base::StrCat({"Ash.AmbientMode.EngagementTime.", ToString(GetParam())}), - base::Minutes(1), 2); + kExpectedEngagementTime, 2); } TEST_P(AmbientControllerTestForAnyTheme, MetricsStartupTime) {
diff --git a/ash/components/arc/compat_mode/resize_util_unittest.cc b/ash/components/arc/compat_mode/resize_util_unittest.cc index 7304be8..3cf11c0 100644 --- a/ash/components/arc/compat_mode/resize_util_unittest.cc +++ b/ash/components/arc/compat_mode/resize_util_unittest.cc
@@ -24,6 +24,15 @@ // ToastManager overrides: void Show(const ash::ToastData& data) override { called_show_ = true; } void Cancel(const std::string& id) override { called_cancel_ = true; } + bool MaybeToggleA11yHighlightOnActiveToastDismissButton( + const std::string& id) override { + return false; + } + bool MaybeActivateHighlightedDismissButtonOnActiveToast( + const std::string& id) override { + return false; + } + bool IsRunning(const std::string& id) const override { return false; } void ResetState() { called_show_ = false;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 008e44c..39442923 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -115,7 +115,7 @@ // Controls whether to launch the animated screensaver (as opposed to the // existing photo slideshow) when entering ambient mode. const base::Feature kAmbientModeAnimationFeature{ - "ChromeOSAmbientModeAnimation", base::FEATURE_DISABLED_BY_DEFAULT}; + "ChromeOSAmbientModeAnimation", base::FEATURE_ENABLED_BY_DEFAULT}; // Controls whether to allow Dev channel to use Prod server feature. const base::Feature kAmbientModeDevUseProdFeature{ @@ -1079,7 +1079,7 @@ // Enables new notifications UI and grouped notifications. const base::Feature kNotificationsRefresh{"NotificationsRefresh", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Controls whether to enable on-device grammar check service. const base::Feature kOnDeviceGrammarCheck{"OnDeviceGrammarCheck", @@ -1647,7 +1647,8 @@ } bool IsAmbientModeAnimationEnabled() { - return base::FeatureList::IsEnabled(kAmbientModeAnimationFeature); + return base::FeatureList::IsEnabled(kAmbientModeAnimationFeature) && + IsPersonalizationHubEnabled(); } bool IsAmbientModeDevUseProdEnabled() { @@ -1762,8 +1763,7 @@ } bool IsDarkLightModeEnabled() { - return base::FeatureList::IsEnabled(kNotificationsRefresh) || - chromeos::features::IsDarkLightModeEnabled(); + return chromeos::features::IsDarkLightModeEnabled(); } bool IsDemoModeSWAEnabled() {
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc index 3f79d74..def3c9a 100644 --- a/ash/constants/ash_switches.cc +++ b/ash/constants/ash_switches.cc
@@ -673,6 +673,10 @@ // Specifies the user that the browser data migration should happen for. const char kBrowserDataMigrationForUser[] = "browser-data-migration-for-user"; +// Run move migration instead of copy. Passed with +// `kBrowserDataMigrationForUser`. +const char kBrowserDataMigrationMoveMode[] = "browser-data-migration-move-mode"; + // Force skip or force migration. Should only be used for testing. const char kForceBrowserDataMigrationForTesting[] = "force-browser-data-migration-for-testing";
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h index 854ed04..ab02961 100644 --- a/ash/constants/ash_switches.h +++ b/ash/constants/ash_switches.h
@@ -217,6 +217,8 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kBrowserDataMigrationForUser[]; COMPONENT_EXPORT(ASH_CONSTANTS) +extern const char kBrowserDataMigrationMoveMode[]; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kForceBrowserDataMigrationForTesting[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kMarketingOptInUrl[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kNaturalScrollDefault[];
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc index 0ed62d2..711b0a823 100644 --- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc +++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -105,6 +105,14 @@ generator->ClickLeftButton(); base::RunLoop().RunUntilIdle(); } + + void ClickFloatButton(FrameCaptionButtonContainerView::TestApi* testApi) { + ui::test::EventGenerator* generator = GetEventGenerator(); + auto* float_button = testApi->float_button(); + generator->MoveMouseTo(float_button->GetBoundsInScreen().CenterPoint()); + generator->ClickLeftButton(); + base::RunLoop().RunUntilIdle(); + } }; // Test float button requires kFloatWindow feature to be enabled during setup. @@ -335,24 +343,18 @@ container.Layout(); FrameCaptionButtonContainerView::TestApi testApi(&container); FloatController* controller = Shell::Get()->float_controller(); - - ui::test::EventGenerator* generator = GetEventGenerator(); - generator->MoveMouseTo( - testApi.float_button()->GetBoundsInScreen().CenterPoint()); - generator->ClickLeftButton(); - + ClickFloatButton(&testApi); + auto* window_state = WindowState::Get(widget->GetNativeWindow()); // Check if window is floated. auto* window = widget->GetNativeWindow(); - EXPECT_TRUE(window->GetProperty(chromeos::kWindowFloatTypeKey)); + EXPECT_TRUE(window_state->IsFloated()); + EXPECT_TRUE(window->GetProperty(chromeos::kWindowToggleFloatKey)); EXPECT_TRUE(controller->IsFloated(window)); - - generator->MoveMouseTo( - testApi.float_button()->GetBoundsInScreen().CenterPoint()); - generator->ClickLeftButton(); - + ClickFloatButton(&testApi); // Check if window is unfloated. - EXPECT_FALSE(window->GetProperty(chromeos::kWindowFloatTypeKey)); + EXPECT_TRUE(window_state->IsNormalStateType()); EXPECT_FALSE(controller->IsFloated(window)); + EXPECT_FALSE(window->GetProperty(chromeos::kWindowToggleFloatKey)); } } // namespace ash
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index 91cae0d..3fa40787 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc
@@ -44,6 +44,7 @@ ACTIVE_WINDOW_STATE_TYPE_PINNED, ACTIVE_WINDOW_STATE_TYPE_TRUSTED_PINNED, ACTIVE_WINDOW_STATE_TYPE_PIP, + ACTIVE_WINDOW_STATE_TYPE_FLOATED, ACTIVE_WINDOW_STATE_TYPE_COUNT, }; @@ -72,6 +73,9 @@ case WindowStateType::kPip: active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_PIP; break; + case WindowStateType::kFloated: + active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_FLOATED; + break; case WindowStateType::kDefault: case WindowStateType::kNormal: case WindowStateType::kMinimized:
diff --git a/ash/public/cpp/system/toast_manager.h b/ash/public/cpp/system/toast_manager.h index 9227f56d..0bf06eb8 100644 --- a/ash/public/cpp/system/toast_manager.h +++ b/ash/public/cpp/system/toast_manager.h
@@ -25,6 +25,21 @@ // Cancels a toast with the provided ID. virtual void Cancel(const std::string& id) = 0; + // Toggles highlight on the dismiss button for an active toast. Returns false + // if this is not possible or if the highlight has been removed from the + // button. + virtual bool MaybeToggleA11yHighlightOnActiveToastDismissButton( + const std::string& id) = 0; + + // Activates the dismiss button on the active toast if there is a button and + // that button is highlighted. Returns false if either case is not true, or if + // there is no active toast. + virtual bool MaybeActivateHighlightedDismissButtonOnActiveToast( + const std::string& id) = 0; + + // Tells if the toast with the provided ID is running. + virtual bool IsRunning(const std::string& id) const = 0; + protected: ToastManager(); virtual ~ToastManager();
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc index cee433e..3e9e2c1 100644 --- a/ash/shelf/home_button.cc +++ b/ash/shelf/home_button.cc
@@ -195,7 +195,8 @@ } bool HomeButton::IsShowingAppList() const { - return controller_.is_showing_app_list(); + return Shell::Get()->app_list_controller()->GetTargetVisibility( + GetDisplayId()); } void HomeButton::HandleLocaleChange() {
diff --git a/ash/shelf/home_button_controller.cc b/ash/shelf/home_button_controller.cc index d6c4602..17294c2 100644 --- a/ash/shelf/home_button_controller.cc +++ b/ash/shelf/home_button_controller.cc
@@ -183,7 +183,6 @@ views::InkDrop::Get(button_)->AnimateToState(views::InkDropState::ACTIVATED, nullptr); } - is_showing_app_list_ = true; } void HomeButtonController::OnAppListDismissed() { @@ -195,8 +194,6 @@ ink_drop->SnapToActivated(); views::InkDrop::Get(button_)->AnimateToState(views::InkDropState::DEACTIVATED, nullptr); - - is_showing_app_list_ = false; } void HomeButtonController::InitializeAssistantOverlay() {
diff --git a/ash/shelf/home_button_controller.h b/ash/shelf/home_button_controller.h index 5e9e1b6f..6db20207 100644 --- a/ash/shelf/home_button_controller.h +++ b/ash/shelf/home_button_controller.h
@@ -47,8 +47,6 @@ // Whether the Assistant UI currently showing. bool IsAssistantVisible(); - bool is_showing_app_list() const { return is_showing_app_list_; } - private: // AppListControllerObserver: void OnAppListVisibilityWillChange(bool shown, int64_t display_id) override; @@ -76,10 +74,6 @@ // Initialize the Assistant overlay. void InitializeAssistantOverlay(); - // True if the app list is currently showing for the button's display. - // This is useful because other app_list_visible functions aren't per-display. - bool is_showing_app_list_ = false; - // The button that owns this controller. HomeButton* const button_;
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc index d787721..8302678 100644 --- a/ash/shelf/shelf_widget.cc +++ b/ash/shelf/shelf_widget.cc
@@ -863,11 +863,6 @@ ShowIfHidden(); } -bool ShelfWidget::IsShowingAppList() const { - return navigation_widget()->GetHomeButton() && - navigation_widget()->GetHomeButton()->IsShowingAppList(); -} - bool ShelfWidget::IsShowingMenu() const { return hotseat_widget()->GetShelfView()->IsShowingMenu(); }
diff --git a/ash/shelf/shelf_widget.h b/ash/shelf/shelf_widget.h index 229f7251f..523ad5dc 100644 --- a/ash/shelf/shelf_widget.h +++ b/ash/shelf/shelf_widget.h
@@ -83,7 +83,6 @@ } void PostCreateShelf(); - bool IsShowingAppList() const; bool IsShowingMenu() const; // Sets the focus cycler. Also adds the shelf to the cycle.
diff --git a/ash/style/system_toast_style.cc b/ash/style/system_toast_style.cc index 9df39e1..15530d1 100644 --- a/ash/style/system_toast_style.cc +++ b/ash/style/system_toast_style.cc
@@ -6,6 +6,8 @@ #include <string> +#include "ash/accessibility/accessibility_controller_impl.h" +#include "ash/accessibility/scoped_a11y_override_window_setter.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" @@ -14,6 +16,7 @@ #include "ash/system/toast/toast_overlay.h" #include "ash/wm/work_area_insets.h" #include "base/strings/strcat.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/compositor/layer.h" @@ -22,6 +25,7 @@ #include "ui/gfx/text_elider.h" #include "ui/gfx/text_utils.h" #include "ui/views/background.h" +#include "ui/views/controls/focus_ring.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/highlight_border.h" @@ -108,7 +112,9 @@ SystemToastStyle::SystemToastStyle(base::RepeatingClosure dismiss_callback, const std::u16string& text, const std::u16string& dismiss_text, - const bool is_managed) { + const bool is_managed) + : scoped_a11y_overrider_( + std::make_unique<ScopedA11yOverrideWindowSetter>()) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma); @@ -171,6 +177,30 @@ SystemToastStyle::~SystemToastStyle() = default; +bool SystemToastStyle::ToggleA11yFocus() { + if (!button_ || + !Shell::Get()->accessibility_controller()->spoken_feedback().enabled()) { + return false; + } + + auto* focus_ring = views::FocusRing::Get(button_); + focus_ring->SetHasFocusPredicate([&](views::View* view) -> bool { + return is_dismiss_button_highlighted_; + }); + + is_dismiss_button_highlighted_ = !is_dismiss_button_highlighted_; + scoped_a11y_overrider_->MaybeUpdateA11yOverrideWindow( + is_dismiss_button_highlighted_ ? button_->GetWidget()->GetNativeWindow() + : nullptr); + + if (is_dismiss_button_highlighted_) + button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); + + focus_ring->SetVisible(is_dismiss_button_highlighted_); + focus_ring->SchedulePaint(); + return is_dismiss_button_highlighted_; +} + void SystemToastStyle::SetText(const std::u16string& text) { label_->SetText(text); }
diff --git a/ash/style/system_toast_style.h b/ash/style/system_toast_style.h index 95cb89a..f8e1c9b 100644 --- a/ash/style/system_toast_style.h +++ b/ash/style/system_toast_style.h
@@ -18,6 +18,8 @@ namespace ash { +class ScopedA11yOverrideWindowSetter; + // A view that has rounded corner with label and button inside. The label shows // the information. The button inside is optional and has certain functionality // e.g. dismiss the view or retry. A managed icon will be put ahead of the label @@ -36,6 +38,14 @@ SystemToastStyle& operator=(const SystemToastStyle&) = delete; ~SystemToastStyle() override; + bool is_dismiss_button_highlighted() const { + return is_dismiss_button_highlighted_; + } + + // Returns true if the toast has a dismiss button and was highlighted for + // accessibility, false otherwise. + bool ToggleA11yFocus(); + // Updates the toast label text. void SetText(const std::u16string& text); @@ -48,6 +58,13 @@ views::Label* label_ = nullptr; views::LabelButton* button_ = nullptr; views::ImageView* managed_icon_ = nullptr; + + // Tells the toast if the dismiss button is already highlighted if one exists. + bool is_dismiss_button_highlighted_ = false; + + // Updates the current a11y override window when the dismiss button is being + // highlighted. + std::unique_ptr<ScopedA11yOverrideWindowSetter> scoped_a11y_overrider_; }; } // namespace ash
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc index 40e8d30..6c8ce9f 100644 --- a/ash/system/message_center/ash_notification_view.cc +++ b/ash/system/message_center/ash_notification_view.cc
@@ -1184,8 +1184,13 @@ NotificationViewBase::ToggleInlineSettings(event); if (is_grouped_parent_view_) { - grouped_notifications_scroll_view_->SetVisible( - !should_show_inline_settings); + if (shown_in_popup_) { + grouped_notifications_scroll_view_->SetVisible( + !should_show_inline_settings); + } else { + grouped_notifications_container_->SetVisible( + !should_show_inline_settings); + } } else { // In settings UI, we only show the app icon and header row along with the // inline settings UI. @@ -1457,9 +1462,10 @@ grouped_notifications_container_->GetIndexOf(to_be_removed); grouped_notifications_container_->RemoveChildViewT(to_be_removed).reset(); - message_center_utils::GetActiveNotificationViewControllerForNotificationView( - this) - ->AnimateResize(); + auto* notification_view_controller = message_center_utils:: + GetActiveNotificationViewControllerForNotificationView(this); + if (notification_view_controller) + notification_view_controller->AnimateResize(); if (shown_in_popup_) { grouped_notifications_scroll_view_->Layout();
diff --git a/ash/system/message_center/message_center_utils.cc b/ash/system/message_center/message_center_utils.cc index 5bac163..72b211f 100644 --- a/ash/system/message_center/message_center_utils.cc +++ b/ash/system/message_center/message_center_utils.cc
@@ -83,8 +83,9 @@ GetActiveNotificationViewControllerForDisplay(int64_t display_id) { RootWindowController* root_window_controller = Shell::GetRootWindowControllerWithDisplayId(display_id); - if (!root_window_controller) + if (!root_window_controller || !root_window_controller->GetStatusAreaWidget()) return nullptr; + return root_window_controller->GetStatusAreaWidget() ->unified_system_tray() ->GetNotificationGroupingController()
diff --git a/ash/system/message_center/notification_grouping_controller.cc b/ash/system/message_center/notification_grouping_controller.cc index 8429025..b9133fd 100644 --- a/ash/system/message_center/notification_grouping_controller.cc +++ b/ash/system/message_center/notification_grouping_controller.cc
@@ -145,8 +145,10 @@ ->FindNotificationById(notification_id) ->group_parent()); MessageView* parent_view = - GetActiveNotificationViewController()->GetMessageViewForNotificationId( - notification_id); + GetActiveNotificationViewController() + ? GetActiveNotificationViewController() + ->GetMessageViewForNotificationId(notification_id) + : nullptr; // TODO(crbug/1277765) Need this check to fix crbug/1275765. However, this // should not be necessary if the message center bubble is initialized @@ -193,8 +195,10 @@ Notification* notification = message_center->FindNotificationById(notification_id); MessageView* parent_view = - GetActiveNotificationViewController()->GetMessageViewForNotificationId( - parent_id); + GetActiveNotificationViewController() + ? GetActiveNotificationViewController() + ->GetMessageViewForNotificationId(parent_id) + : nullptr; if (parent_view) parent_view->AddGroupNotification(*notification); else @@ -258,9 +262,10 @@ metrics_utils::LogGroupNotificationAddedType( metrics_utils::GroupNotificationType::GROUP_CHILD); - auto* parent_view = - GetActiveNotificationViewController()->GetMessageViewForNotificationId( - new_parent_id); + auto* parent_view = GetActiveNotificationViewController() + ? GetActiveNotificationViewController() + ->GetMessageViewForNotificationId(new_parent_id) + : nullptr; if (parent_view) { parent_view->UpdateWithNotification(*new_parent_notification); // Grouped notifications should start off in the collapsed state. @@ -311,7 +316,8 @@ // in a grouped notification. auto grouped_notifications = grouped_notification_list_->GetGroupedNotificationsForParent(parent_id); - if (GetActiveNotificationViewController()->GetMessageViewForNotificationId( + if (GetActiveNotificationViewController() && + GetActiveNotificationViewController()->GetMessageViewForNotificationId( parent_id) && grouped_notifications.size() == 1) { MessageCenter::Get()->RemoveNotification(parent_id, true); @@ -355,9 +361,12 @@ message_center->FindParentNotification(notification); std::string parent_id = parent_notification->id(); - auto* parent_view = static_cast<AshNotificationView*>( - GetActiveNotificationViewController()->GetMessageViewForNotificationId( - parent_id)); + auto* parent_view = + GetActiveNotificationViewController() + ? static_cast<AshNotificationView*>( + GetActiveNotificationViewController() + ->GetMessageViewForNotificationId(parent_id)) + : nullptr; // If we are creating a new notification group for this `notifier_id`, // we must create a copy of the designated parent notification and
diff --git a/ash/system/network/network_list_view_controller_impl.cc b/ash/system/network/network_list_view_controller_impl.cc index 80468a2..b5d113b4 100644 --- a/ash/system/network/network_list_view_controller_impl.cc +++ b/ash/system/network/network_list_view_controller_impl.cc
@@ -237,6 +237,9 @@ network_detailed_network_view()->network_list()->ReorderChildView( wifi_header_view_, index++); + index = CreateItemViewsIfMissingAndReorder(NetworkType::kWiFi, index, + networks, &previous_network_views); + // Remaining views in |previous_network_views| are no longer needed // and should be deleted. for (const auto& id_and_view : previous_network_views) {
diff --git a/ash/system/network/network_list_view_controller_impl.h b/ash/system/network/network_list_view_controller_impl.h index afd4e8e..9dcc79e 100644 --- a/ash/system/network/network_list_view_controller_impl.h +++ b/ash/system/network/network_list_view_controller_impl.h
@@ -99,7 +99,7 @@ bool ShouldMobileDataSectionBeShown(); // Creates if missing and adds a Mobile or Wifi separator to the view. - // Also reorders seperator view in network list. A reference to the + // Also reorders separator view in network list. A reference to the // separator is captured in |*separator_view|. int CreateSeparatorIfMissingAndReorder(int index, views::Separator** separator_view);
diff --git a/ash/system/network/network_list_view_controller_unittest.cc b/ash/system/network/network_list_view_controller_unittest.cc index 9ffd02d..7f1a7d4 100644 --- a/ash/system/network/network_list_view_controller_unittest.cc +++ b/ash/system/network/network_list_view_controller_unittest.cc
@@ -74,6 +74,7 @@ const char kVpnDevicePath[] = "device/vpn"; const char kWifiName[] = "wifi"; +const char kWifiName2[] = "wifi_2"; const char kWifiDevicePath[] = "device/wifi"; const char kTestEuiccBasePath[] = "/org/chromium/Hermes/Euicc/"; @@ -241,44 +242,48 @@ mojo::Clone(networks)); } - // Checks that network list items are in the right order. This function - // assumes that Mobile and Wifi devices are present and enabled. - void CheckNetworkListOrdering(size_t ethernet_network_count, - size_t mobile_network_count) { - // TODO(tjohnsonkanu): add WiFi networks. - EXPECT_NE(nullptr, GetMobileSubHeader()); + // Checks that network list items are in the right order. Wifi section + // is always shown. + void CheckNetworkListOrdering(int ethernet_network_count, + int mobile_network_count, + int wifi_network_count) { EXPECT_NE(nullptr, GetWifiSubHeader()); size_t index = 0; // Expect that the view at |index| is a network item, and that it is an // ethernet network. - for (int i = 0; i < static_cast<int>(ethernet_network_count); i++) { + for (int i = 0; i < ethernet_network_count; i++) { CheckNetworkListItem(NetworkType::kEthernet, index++, /*guid=*/absl::nullopt); } - // Mobile data section. - if (index > 0) { - // Expect that the mobile network separator exists. - EXPECT_NE(nullptr, GetMobileSeparator()); - EXPECT_EQ(network_list()->children().at(index++), GetMobileSeparator()); - EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader()); - } else { - EXPECT_EQ(nullptr, GetMobileSeparator()); - EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader()); - } + // Mobile data section. If |mobile_network_count| is equal to -1 + // Mobile device is not available. + if (mobile_network_count != -1) { + EXPECT_NE(nullptr, GetMobileSubHeader()); + if (index > 0) { + // Expect that the mobile network separator exists. + EXPECT_NE(nullptr, GetMobileSeparator()); + EXPECT_EQ(network_list()->children().at(index++), GetMobileSeparator()); + EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader()); + } else { + EXPECT_EQ(nullptr, GetMobileSeparator()); + EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader()); + } - for (int i = 0; i < static_cast<int>(mobile_network_count); i++) { - CheckNetworkListItem(NetworkType::kMobile, index, /*guid=*/absl::nullopt); - EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(), - kNetworkListNetworkItemView); - } + for (int i = 0; i < mobile_network_count; i++) { + CheckNetworkListItem(NetworkType::kMobile, index, + /*guid=*/absl::nullopt); + EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(), + kNetworkListNetworkItemView); + } - if (!mobile_network_count) { - // No mobile networks message is shown. - EXPECT_NE(nullptr, GetMobileStatusMessage()); - index++; + if (!mobile_network_count) { + // No mobile networks message is shown. + EXPECT_NE(nullptr, GetMobileStatusMessage()); + index++; + } } // Wifi section. @@ -291,6 +296,12 @@ EXPECT_EQ(nullptr, GetWifiSeparator()); EXPECT_EQ(network_list()->children().at(index++), GetWifiSubHeader()); } + + for (int i = 0; i < wifi_network_count; i++) { + CheckNetworkListItem(NetworkType::kWiFi, index, /*guid=*/absl::nullopt); + EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(), + kNetworkListNetworkItemView); + } } void CheckNetworkListItem(NetworkType type, @@ -582,8 +593,9 @@ SetupCellular(); AddWifiDevice(); - CheckNetworkListOrdering(/*ethernet_network_count=*/0u, - /*mobile_network_count=*/0u); + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/0, + /*wifi_network_count=*/0); std::vector<NetworkStatePropertiesPtr> networks; @@ -593,8 +605,9 @@ networks.push_back(std::move(cellular_network)); UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/0u, - /*mobile_network_count=*/1u); + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/1, + /*wifi_network_count=*/0); CheckNetworkListItem(NetworkType::kCellular, /*index=*/1u, /*guid=*/kCellularName); @@ -603,8 +616,9 @@ networks.push_back(std::move(cellular_network)); UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/0u, - /*mobile_network_count=*/2u); + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/2, + /*wifi_network_count=*/0); CheckNetworkListItem(NetworkType::kCellular, /*index=*/2u, /*guid=*/kCellularName2); @@ -612,8 +626,9 @@ networks.front()->connection_state = ConnectionStateType::kNotConnected; UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/0u, - /*mobile_network_count=*/2u); + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/2, + /*wifi_network_count=*/0); CheckNetworkListItem(NetworkType::kCellular, /*index=*/1u, /*guid=*/kCellularName); CheckNetworkListItem(NetworkType::kCellular, /*index=*/2u, @@ -627,15 +642,14 @@ networks.push_back(std::move(tether_network)); UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/0u, - /*mobile_network_count=*/1u); + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/1, + /*wifi_network_count=*/0); CheckNetworkListItem(NetworkType::kTether, /*index=*/1u, /*guid=*/kTetherName); } TEST_F(NetworkListViewControllerTest, HasCorrectEthernetNetworkList) { - AddEuicc(); - SetupCellular(); std::vector<NetworkStatePropertiesPtr> networks; NetworkStatePropertiesPtr ethernet_network = @@ -644,19 +658,23 @@ networks.push_back(std::move(ethernet_network)); UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/1u, - /*mobile_network_count=*/0u); + CheckNetworkListOrdering(/*ethernet_network_count=*/1, + /*mobile_network_count=*/-1, + /*wifi_network_count=*/0); CheckNetworkListItem(NetworkType::kEthernet, /*index=*/0u, /*guid=*/kEthernet); // Add mobile network. + AddEuicc(); + SetupCellular(); NetworkStatePropertiesPtr cellular_network = CreateStandaloneNetworkProperties(kCellularName, NetworkType::kCellular, ConnectionStateType::kConnected); networks.push_back(std::move(cellular_network)); UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/1u, - /*mobile_network_count=*/1u); + CheckNetworkListOrdering(/*ethernet_network_count=*/1, + /*mobile_network_count=*/1, + /*wifi_network_count=*/0); // Mobile list item will be at index 3 after ethernet, separator and header. CheckNetworkListItem(NetworkType::kCellular, /*index=*/3u, @@ -667,8 +685,9 @@ networks.push_back(std::move(ethernet_network)); UpdateNetworkList(networks); - CheckNetworkListOrdering(/*ethernet_network_count=*/2u, - /*mobile_network_count=*/1u); + CheckNetworkListOrdering(/*ethernet_network_count=*/2, + /*mobile_network_count=*/1, + /*wifi_network_count=*/0); CheckNetworkListItem(NetworkType::kEthernet, /*index=*/0u, /*guid=*/kEthernet); CheckNetworkListItem(NetworkType::kEthernet, /*index=*/1u, @@ -679,6 +698,52 @@ /*guid=*/kCellularName); } +TEST_F(NetworkListViewControllerTest, HasCorrectWifiNetworkList) { + std::vector<NetworkStatePropertiesPtr> networks; + + // Add Wifi network. + NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties( + kWifiName, NetworkType::kWiFi, ConnectionStateType::kNotConnected); + networks.push_back(std::move(wifi_network)); + UpdateNetworkList(networks); + + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/-1, + /*wifi_network_count=*/1); + + // Wifi list item will be at index 1 after Wifi header. + CheckNetworkListItem(NetworkType::kWiFi, /*index=*/1u, /*guid=*/kWifiName); + + // Add mobile network. + AddEuicc(); + SetupCellular(); + NetworkStatePropertiesPtr cellular_network = + CreateStandaloneNetworkProperties(kCellularName, NetworkType::kCellular, + ConnectionStateType::kConnected); + networks.push_back(std::move(cellular_network)); + UpdateNetworkList(networks); + + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/1, + /*wifi_network_count=*/1); + + // Wifi list item be at index 4 after Mobile header, Mobile network + // item, Wifi separator and header. + CheckNetworkListItem(NetworkType::kWiFi, /*index=*/4u, /*guid=*/kWifiName); + + // Add a second Wifi network. + wifi_network = CreateStandaloneNetworkProperties( + kWifiName2, NetworkType::kWiFi, ConnectionStateType::kNotConnected); + networks.push_back(std::move(wifi_network)); + UpdateNetworkList(networks); + + CheckNetworkListOrdering(/*ethernet_network_count=*/0, + /*mobile_network_count=*/1, + /*wifi_network_count=*/2); + CheckNetworkListItem(NetworkType::kWiFi, /*index=*/4u, /*guid=*/kWifiName); + CheckNetworkListItem(NetworkType::kWiFi, /*index=*/5u, /*guid=*/kWifiName2); +} + TEST_F(NetworkListViewControllerTest, CellularStatusMessageAndToggleButtonState) { EXPECT_EQ(nullptr, GetMobileStatusMessage());
diff --git a/ash/system/time/calendar_event_list_item_view.cc b/ash/system/time/calendar_event_list_item_view.cc index c1f5f44..c2d6bd7 100644 --- a/ash/system/time/calendar_event_list_item_view.cc +++ b/ash/system/time/calendar_event_list_item_view.cc
@@ -34,6 +34,9 @@ namespace ash { namespace { +// The paddings for `CalendarEventListViewItem`. +constexpr auto kEventListItemInsets = gfx::Insets::VH(0, 20); + // Paddings in this view. constexpr int kEntryHorizontalPadding = 20; @@ -146,6 +149,7 @@ end_time_string, calendar_utils::GetTimeZone(start_time), base::UTF8ToUTF16(event.summary()))); SetFocusBehavior(FocusBehavior::ALWAYS); + SetBorder(views::CreateEmptyBorder(kEventListItemInsets)); summary_->SetText(event.summary().empty() ? l10n_util::GetStringUTF16(IDS_ASH_CALENDAR_NO_TITLE) : base::UTF8ToUTF16(event.summary()));
diff --git a/ash/system/time/calendar_event_list_view.cc b/ash/system/time/calendar_event_list_view.cc index e271971f..decd0c4 100644 --- a/ash/system/time/calendar_event_list_view.cc +++ b/ash/system/time/calendar_event_list_view.cc
@@ -39,13 +39,13 @@ constexpr gfx::Insets kCloseButtonContainerInsets{15}; // The paddings in `CalendarEventListView`. -constexpr auto kContentInsets = gfx::Insets::TLBR(0, 20, 20, 20); +constexpr auto kContentInsets = gfx::Insets::TLBR(0, 0, 20, 0); // The insets for `CalendarEmptyEventListView` label. constexpr auto kOpenGoogleCalendarInsets = gfx::Insets::VH(6, 16); // The insets for `CalendarEmptyEventListView`. -constexpr auto kOpenGoogleCalendarContainerInsets = gfx::Insets::VH(20, 60); +constexpr auto kOpenGoogleCalendarContainerInsets = gfx::Insets::VH(20, 80); // Border thickness for `CalendarEmptyEventListView`. constexpr int kOpenGoogleCalendarBorderThickness = 1;
diff --git a/ash/system/toast/toast_manager_impl.cc b/ash/system/toast/toast_manager_impl.cc index 1b34568..9c4cffb1 100644 --- a/ash/system/toast/toast_manager_impl.cc +++ b/ash/system/toast/toast_manager_impl.cc
@@ -65,6 +65,22 @@ queue_.erase(cancelled_toast); } +bool ToastManagerImpl::MaybeToggleA11yHighlightOnActiveToastDismissButton( + const std::string& id) { + DCHECK(IsRunning(id)); + return overlay_ && overlay_->MaybeToggleA11yHighlightOnDismissButton(); +} + +bool ToastManagerImpl::MaybeActivateHighlightedDismissButtonOnActiveToast( + const std::string& id) { + DCHECK(IsRunning(id)); + return overlay_ && overlay_->MaybeActivateHighlightedDismissButton(); +} + +bool ToastManagerImpl::IsRunning(const std::string& id) const { + return overlay_ && current_toast_data_ && current_toast_data_->id == id; +} + void ToastManagerImpl::OnClosed() { overlay_.reset(); current_toast_data_.reset(); @@ -76,10 +92,6 @@ ShowLatest(); } -bool ToastManagerImpl::IsRunning(const std::string& id) const { - return overlay_ && current_toast_data_ && current_toast_data_->id == id; -} - void ToastManagerImpl::ShowLatest() { DCHECK(!overlay_); DCHECK(!current_toast_data_);
diff --git a/ash/system/toast/toast_manager_impl.h b/ash/system/toast/toast_manager_impl.h index a41dacc..cdebe23 100644 --- a/ash/system/toast/toast_manager_impl.h +++ b/ash/system/toast/toast_manager_impl.h
@@ -33,6 +33,11 @@ // ToastManager overrides: void Show(const ToastData& data) override; void Cancel(const std::string& id) override; + bool MaybeToggleA11yHighlightOnActiveToastDismissButton( + const std::string& id) override; + bool MaybeActivateHighlightedDismissButtonOnActiveToast( + const std::string& id) override; + bool IsRunning(const std::string& id) const override; // ToastOverlay::Delegate overrides: void OnClosed() override; @@ -46,9 +51,6 @@ friend class AutoConnectNotifierTest; friend class DesksTestApi; - // Tells if the toast with the provided ID is running. - bool IsRunning(const std::string& id) const; - void ShowLatest(); void OnDurationPassed(int toast_number);
diff --git a/ash/system/toast/toast_overlay.cc b/ash/system/toast/toast_overlay.cc index a9d02a2..f3c30735 100644 --- a/ash/system/toast/toast_overlay.cc +++ b/ash/system/toast/toast_overlay.cc
@@ -178,6 +178,18 @@ return text_; } +bool ToastOverlay::MaybeToggleA11yHighlightOnDismissButton() { + return overlay_view_->ToggleA11yFocus(); +} + +bool ToastOverlay::MaybeActivateHighlightedDismissButton() { + if (!overlay_view_->is_dismiss_button_highlighted()) + return false; + + OnButtonClicked(); + return true; +} + gfx::Rect ToastOverlay::CalculateOverlayBounds() { // If the native window has not been initialized, as in the first call, get // the default root window. Otherwise get the window for this overlay_widget
diff --git a/ash/system/toast/toast_overlay.h b/ash/system/toast/toast_overlay.h index fdfaebb0..e0b9166 100644 --- a/ash/system/toast/toast_overlay.h +++ b/ash/system/toast/toast_overlay.h
@@ -71,6 +71,14 @@ const std::u16string GetText(); + // Returns true if the toast has a button and it can be highlighted for + // accessibility, false otherwise. + bool MaybeToggleA11yHighlightOnDismissButton(); + + // Activates the dismiss button in `overlay_view_` if it is highlighted. + // Returns false if `is_dismiss_button_highlighted_` is false. + bool MaybeActivateHighlightedDismissButton(); + private: friend class ToastManagerImplTest; friend class DesksTestApi;
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index c729a75..16a29d2 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -103,7 +103,7 @@ private: std::unique_ptr<MessageCenterUiController> const ui_controller_; - std::unique_ptr<AshMessagePopupCollection> const message_popup_collection_; + std::unique_ptr<AshMessagePopupCollection> message_popup_collection_; UnifiedSystemTray* const owner_; @@ -131,7 +131,12 @@ owner->shelf()->GetStatusAreaWidget()->GetNativeWindow())); } -UnifiedSystemTray::UiDelegate::~UiDelegate() = default; +UnifiedSystemTray::UiDelegate::~UiDelegate() { + // We need to destruct `message_popup_collection_` before + // `grouping_controller_` to prevent a msan failure, so explicitly delete + // it here. + message_popup_collection_.reset(); +} void UnifiedSystemTray::UiDelegate::OnMessageCenterContentsChanged() { owner_->UpdateNotificationInternal(); @@ -247,6 +252,10 @@ Shell::Get()->RemoveShellObserver(this); DestroyBubbles(); + + // We need to destruct `ui_delegate_` before `timer_` to prevent a msan + // failure, so explicitly delete it here. + ui_delegate_.reset(); } void UnifiedSystemTray::AddObserver(Observer* observer) { @@ -669,11 +678,21 @@ } AshMessagePopupCollection* UnifiedSystemTray::GetMessagePopupCollection() { + // We need a check here since this function might be called when UiDelegate's + // dtor is triggered. In that case, the unique_ptr `ui_delegate_` is null even + // though the UiDelegate object is still in the middle of dtor process. + if (!ui_delegate_) + return nullptr; return ui_delegate_->message_popup_collection(); } NotificationGroupingController* UnifiedSystemTray::GetNotificationGroupingController() { + // We need a check here since this function might be called when UiDelegate's + // dtor is triggered. In that case, the unique_ptr `ui_delegate_` is null even + // though the UiDelegate object is still in the middle of dtor process. + if (!ui_delegate_) + return nullptr; return ui_delegate_->grouping_controller(); }
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h index 4935f6e..906aca1 100644 --- a/ash/system/unified/unified_system_tray.h +++ b/ash/system/unified/unified_system_tray.h
@@ -260,7 +260,7 @@ // removing bubble related observers. void DestroyBubbles(); - const std::unique_ptr<UiDelegate> ui_delegate_; + std::unique_ptr<UiDelegate> ui_delegate_; std::unique_ptr<UnifiedSystemTrayBubble> bubble_;
diff --git a/ash/test/ash_pixel_diff_test_base.cc b/ash/test/ash_pixel_diff_test_base.cc index 39e315f2..fa22e51 100644 --- a/ash/test/ash_pixel_diff_test_base.cc +++ b/ash/test/ash_pixel_diff_test_base.cc
@@ -4,7 +4,9 @@ #include "ash/test/ash_pixel_diff_test_base.h" +#include "ash/constants/ash_features.h" #include "ash/shell.h" +#include "ash/style/ash_color_provider.h" #include "ash/system/power/power_status.h" #include "ash/wallpaper/wallpaper_controller_impl.h" #include "base/command_line.h" @@ -90,6 +92,13 @@ SimulateUserLogin(kAccountId_); + // If the dark/light mode feature is enabled, ensure to use the dark mode. + if (features::IsDarkLightModeEnabled()) { + auto* color_provider = AshColorProvider::Get(); + if (!color_provider->IsDarkModeEnabled()) + color_provider->ToggleColorMode(); + } + // Set variable UI components in explicit ways to stabilize screenshots. SetWallPaper(); SetBatteryState();
diff --git a/ash/test/demo_ash_pixel_diff_test.cc b/ash/test/demo_ash_pixel_diff_test.cc new file mode 100644 index 0000000..3e9aae42 --- /dev/null +++ b/ash/test/demo_ash_pixel_diff_test.cc
@@ -0,0 +1,28 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/test/ash_pixel_diff_test_base.h" + +namespace ash { + +class DemoAshPixelDiffTest : public AshPixelDiffTestBase { + public: + DemoAshPixelDiffTest() = default; + DemoAshPixelDiffTest(const DemoAshPixelDiffTest&) = delete; + DemoAshPixelDiffTest& operator=(const DemoAshPixelDiffTest&) = delete; + ~DemoAshPixelDiffTest() override = default; + + // AshPixelDiffTestBase: + void SetUp() override { + AshPixelDiffTestBase::SetUp(); + pixel_diff()->Init(/*screenshot_prefix=*/"ash_demo_test"); + } +}; + +// Verifies the primary display UI right after the ash pixel test sets up. +TEST_F(DemoAshPixelDiffTest, VerifyDefaultPrimaryDisplay) { + EXPECT_TRUE(ComparePrimaryFullScreen("primary_display")); +} + +} // namespace ash
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn index 563da69..2d46bcd2 100644 --- a/ash/webui/common/resources/BUILD.gn +++ b/ash/webui/common/resources/BUILD.gn
@@ -34,7 +34,7 @@ "mojo_utils.js", ] input_files_base_dir = rebase_path(".", "//") - deps = [ ":preprocess_generated" ] + public_deps = [ ":preprocess_generated" ] manifest_files = [ "$target_gen_dir/$preprocessed_gen_manifest" ] grd_prefix = "ash_common" out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp"
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 76cd412..be6958e9 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -262,6 +262,9 @@ source->AddBoolean("isPersonalizationHubEnabled", features::IsPersonalizationHubEnabled()); + source->AddBoolean("isAmbientModeAnimationEnabled", + features::IsAmbientModeAnimationEnabled()); + source->AddBoolean("isDarkLightModeEnabled", features::IsDarkLightModeEnabled());
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html index 2fb3f4a0..a9aece8 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html
@@ -205,7 +205,7 @@ is-google-photos> </template> </div> - <h2 id="textContainer" class="preview-text-container album-info-mainpage album-info-subpage" + <h3 id="textContainer" class="preview-text-container album-info-mainpage album-info-subpage" aria-label$="[[getPreviewTextAriaLabel_(firstPreviewAlbum_, topicSource_, previewAlbums_)]]"> <span id="currentlySet" class="currently-set-text" aria-hidden="true"> $i18n{currentlySet} @@ -219,7 +219,7 @@ <span id="albumDescription" aria-hidden="true"> [[getAlbumDescription_(topicSource_, previewAlbums_)]] </span> - </h2> + </h3> <div id="collageContainer" class$="[[getCollageContainerClass_(collageImages_)]]" aria-hidden="true"> <template is="dom-repeat" items="[[collageImages_]]"> <img class="collage-item" is="cr-auto-img"
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html index 97252c0..c5566c1 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html
@@ -177,8 +177,11 @@ </div> </template> <template is="dom-if" if="[[!loadingSettings_]]"> - <animation-theme-list selected-animation-theme="[[animationTheme_]]"> - </animation-theme-list> + <template is="dom-if" if="[[isAmbientModeAnimationEnabled_]]"> + <animation-theme-list + selected-animation-theme="[[animationTheme_]]"> + </animation-theme-list> + </template> <topic-source-list selected-topic-source="[[topicSource_]]" has-google-photos-albums="[[hasGooglePhotosAlbums_(albums_)]]"> </topic-source-list>
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts index 9add348..fe176a5 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts
@@ -16,6 +16,7 @@ import './topic_source_list_element.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {AmbientModeAlbum, AnimationTheme, TemperatureUnit, TopicSource} from '../personalization_app.mojom-webui.js'; import {isAmbientModeAllowed, Paths} from '../personalization_router_element.js'; @@ -41,10 +42,20 @@ return { path: Paths, queryParams: Object, + isAmbientModeAnimationEnabled_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('isAmbientModeAnimationEnabled'); + } + }, albums_: { type: Array, value: null, }, + animationTheme_: { + type: Object, + value: null, + }, ambientModeEnabled_: Boolean, temperatureUnit_: Number, topicSource_: Number, @@ -58,6 +69,7 @@ path: Paths; queryParams: Record<string, string>; + private isAmbientModeAnimationEnabled_: boolean; private albums_: AmbientModeAlbum[]|null = null; private ambientModeEnabled_: boolean|null = null; private animationTheme_: AnimationTheme|null = null;
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html index b106001..4d4515712 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html
@@ -11,8 +11,7 @@ } </style> <div id="weatherDiv"> - <h3 id="weatherTitle" class="ambient-subpage-element-title" - aria-hidden="true"> + <h3 id="weatherTitle" class="ambient-subpage-element-title"> $i18n{ambientModeWeatherTitle} </h3> <div class="weather-unit-list">
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_main_element.html b/ash/webui/personalization_app/resources/trusted/personalization_main_element.html index 9313c15..84984ed 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_main_element.html +++ b/ash/webui/personalization_app/resources/trusted/personalization_main_element.html
@@ -35,7 +35,7 @@ margin-inline-end: -18px; } - #ambientLabel > p { + #ambientLabel > h2 { color: var(--cros-text-color-primary); font: var(--personalization-app-label-font); margin: 14px 0; @@ -53,7 +53,9 @@ <template is="dom-if" if="[[isAmbientModeAllowed_()]]"> <ambient-preview clickable="[[clickable_]]" main-page> <div id="ambientLabel"> - <p on-click="onClickAmbientSubpageLink_" class="clickable">$i18n{screensaverLabel}</p> + <h2 on-click="onClickAmbientSubpageLink_" class="clickable"> + $i18n{screensaverLabel} + </h2> <cr-icon-button id="ambientSubpageLink" iron-icon="cr:chevron-right" on-click="onClickAmbientSubpageLink_"
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html b/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html index a5ec3dd..fe5c3e0 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html +++ b/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html
@@ -1,5 +1,5 @@ <style include="cros-button-style"> - #themeLabel > p { + #themeLabel > h2 { color: var(--cros-text-color-primary); font: var(--personalization-app-label-font); } @@ -44,7 +44,7 @@ </style> <div id="container"> <div id="themeLabel"> - <p>$i18n{themeLabel}</p> + <h2>$i18n{themeLabel}</h2> </div> <iron-a11y-keys id="keys" keys="left right" on-keys-pressed="onKeysPress_"> </iron-a11y-keys>
diff --git a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html index 6bdfab2..5c4f2344 100644 --- a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html
@@ -43,7 +43,7 @@ margin: 0; } - #infoContainer > p { + #infoContainer > h2 { color: var(--cros-text-color-primary); font: 400 22px/28px var(--cros-font-family-google-sans); } @@ -54,6 +54,7 @@ display: flex; flex-flow: row nowrap; padding-top: 4px; + text-decoration: none; width: fit-content; } @@ -61,7 +62,7 @@ outline: 2px solid var(--cros-focus-ring-color); } - #emailContainer > p { + #emailContainer > span { color: var(--cros-link-color); font: var(--cros-body-2-font); margin: 0; @@ -168,13 +169,12 @@ </div> <div id="infoContainer"> <template is="dom-if" if="[[info_]]"> - <p id="name">[[info_.name]]</p> - <div id="emailContainer" tabindex="0" on-click="onClickUserEmail_" - on-keypress="onClickUserEmail_" role="link" + <h2 id="name">[[info_.name]]</h2> + <a id="emailContainer" href="chrome://os-settings/accountManager" target="_blank" aria-description="$i18n{ariaLabelGoToAccountSettings}"> - <p id="email">[[info_.email]]</p> + <span id="email">[[info_.email]]</span> <iron-icon icon="cr:open-in-new"></iron-icon> - </div> + </a> </template> </div> </div>
diff --git a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts index a23399b..f75c36c2 100644 --- a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts +++ b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts
@@ -88,10 +88,6 @@ initializeUserData(getUserProvider(), this.getStore()); } - private onClickUserEmail_() { - window.open('chrome://os-settings/accountManager'); - } - private onClickUserSubpageLink_() { PersonalizationRouter.instance().goToRoute(Paths.USER); }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html index 5825cc92..3754a36 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html
@@ -22,12 +22,17 @@ grid-template-rows: auto minmax(158px, 220px) 20px 1fr 24px; } - #wallpaperLabel > p { + #wallpaperLabel > h2 { color: var(--cros-text-color-primary); + display: inline-block; font: var(--personalization-app-label-font); margin: 14px 0; } + iron-icon[icon='personalization:managed'] { + --iron-icon-fill-color: var(--cros-icon-color-secondary); + } + #wallpaperButton { --cr-icon-button-size: 48px; /* Make the arrow align with the thumbnail image */ @@ -58,22 +63,47 @@ </style> <div class="preview-container" id="container"> <div id="wallpaperLabel"> - <p on-click="onClickWallpaper_" class="clickable">$i18n{wallpaperLabel}</p> + <template is="dom-if" if="[[showPlaceholders_(imageLoading_, image_)]]"> + <h2>$i18n{wallpaperLabel}</h2> + </template> + <template is="dom-if" if="[[!showPlaceholders_(imageLoading_, image_)]]"> + <template is="dom-if" if="[[!isPolicyControlled_(image_)]]"> + <h2 on-click="onClickWallpaper_" class="clickable"> + $i18n{wallpaperLabel} + </h2> <cr-icon-button id="wallpaperButton" iron-icon="cr:chevron-right" role="button" on-click="onClickWallpaper_" class="tast-open-subpage" aria-label="$i18n{ariaLabelChangeWallpaper}"> </cr-icon-button> + </template> + <template is="dom-if" if="[[isPolicyControlled_(image_)]]"> + <p>$i18n{wallpaperLabel}</p> + <iron-icon icon="personalization:managed" title="$i18n{managedSetting}"> + </iron-icon> + </template> + </template> </div> - <template is="dom-if" if="[[showPlaceholders_(isLoading_, showImage_)]]"> + <template is="dom-if" if="[[showPlaceholders_(imageLoading_, image_)]]"> <div id="imagePlaceholder" class="photo-images-container placeholder"></div> </template> - <template is="dom-if" if="[[showImage_]]"> + <template is="dom-if" if="[[!showPlaceholders_(imageLoading_, image_)]]"> + <template is="dom-if" if="[[!isPolicyControlled_(image_)]]"> <div id="imageContainer" class="photo-images-container clickable" on-click="onClickWallpaper_" on-keypress="onClickWallpaper_"> - <img src$="[[getImageSrc_(image_)]]" alt$="[[getImageAltDescription_(image_)]]"> + <img src$="[[getImageSrc_(image_)]]" + alt$="[[getImageAltDescription_(image_)]]"> <div id="shelf"></div> </div> + </template> + <template is="dom-if" if="[[isPolicyControlled_(image_)]]"> + <div id="imageContainer" class="photo-images-container"> + <img src$="[[getImageSrc_(image_)]]" + aria-description="$i18n{managedSetting}" + alt$="[[getImageAltDescription_(image_)]]"> + <div id="shelf"></div> + </div> + </template> </template> <slot></slot> </div>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts index 16d1ea3..716b8da 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts
@@ -14,6 +14,8 @@ import './trusted_style.css.js'; import '../cros_button_style.css.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; + import {getLocalStorageAttribution, isNonEmptyArray} from '../../common/utils.js'; import {CurrentWallpaper, WallpaperProviderInterface, WallpaperType} from '../personalization_app.mojom-webui.js'; import {Paths, PersonalizationRouter} from '../personalization_router_element.js'; @@ -36,20 +38,16 @@ return { image_: { type: Object, + value: null, }, imageLoading_: { type: Boolean, }, - showImage_: { - type: Boolean, - computed: 'computeShowImage_(image_, imageLoading_)', - } }; } private image_: CurrentWallpaper|null; private imageLoading_: boolean; - private showImage_: boolean; private wallpaperProvider_: WallpaperProviderInterface; constructor() { @@ -71,7 +69,8 @@ /** * Navigate to wallpaper collections page. */ - onClickWallpaper_() { + private onClickWallpaper_() { + assert(!!this.image_ && this.image_.type !== WallpaperType.kPolicy); PersonalizationRouter.instance().goToRoute(Paths.COLLECTIONS); } @@ -109,18 +108,17 @@ this.i18n('unknownImageAttribution')}`; } - private computeShowImage_(image: CurrentWallpaper|null, loading: boolean): - boolean { - // Specifically check === false to avoid undefined case while component is - // initializing. - return loading === false && !!image; + /** + * Returns visible state of loading placeholder. + */ + private showPlaceholders_( + imageLoading: boolean, image: CurrentWallpaper|null): boolean { + return imageLoading || !image; } - /** - * Returns hidden state of loading placeholder. - */ - private showPlaceholders_(loading: boolean, showImage: boolean): boolean { - return loading || !showImage; + private isPolicyControlled_(image: CurrentWallpaper|null): boolean { + return !!image && image.type === WallpaperType.kPolicy; } } + customElements.define(WallpaperPreview.is, WallpaperPreview);
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts index 8f9d30d..c74a58d 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts
@@ -7,14 +7,15 @@ * personalization SWA. */ -import {loadTimeData} from '//resources/js/load_time_data.m.js'; -import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {Paths} from '../personalization_router_element.js'; +import {CurrentWallpaper, WallpaperType} from '../personalization_app.mojom-webui.js'; +import {Paths, PersonalizationRouter} from '../personalization_router_element.js'; +import {WithPersonalizationStore} from '../personalization_store.js'; import {getTemplate} from './wallpaper_subpage_element.html.js'; -export class WallpaperSubpage extends PolymerElement { +export class WallpaperSubpage extends WithPersonalizationStore { static get is() { return 'wallpaper-subpage'; } @@ -24,11 +25,33 @@ } static get properties() { - return {path: String, queryParams: Object}; + return { + path: String, + queryParams: Object, + currentSelected_: { + type: Object, + value: null, + observer: 'onCurrentSelectedChanged_', + }, + }; } path: string; queryParams: Record<string, string>; + currentSelected_: CurrentWallpaper|null; + + override connectedCallback(): void { + super.connectedCallback(); + this.watch('currentSelected_', state => state.wallpaper.currentSelected); + this.updateFromStore(); + } + + private onCurrentSelectedChanged_(value: CurrentWallpaper|null) { + if (value && value.type === WallpaperType.kPolicy && + loadTimeData.getBoolean('isPersonalizationHubEnabled')) { + PersonalizationRouter.reloadAtRoot(); + } + } private shouldShowCollections_(path: string): boolean { return path === Paths.COLLECTIONS;
diff --git a/ash/webui/shimless_rma/resources/shimless_rma.js b/ash/webui/shimless_rma/resources/shimless_rma.js index 38a8ec4b..b84a5db 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma.js +++ b/ash/webui/shimless_rma/resources/shimless_rma.js
@@ -151,7 +151,7 @@ [State.kUpdateRoFirmware]: { componentIs: 'reimaging-firmware-update-page', requiresReloadWhenShown: false, - buttonNext: ButtonState.HIDDEN, + buttonNext: ButtonState.DISABLED, buttonExit: ButtonState.HIDDEN, buttonBack: ButtonState.HIDDEN, },
diff --git a/ash/wm/base_state.cc b/ash/wm/base_state.cc index acebe3c..a469df3 100644 --- a/ash/wm/base_state.cc +++ b/ash/wm/base_state.cc
@@ -85,6 +85,8 @@ return WindowStateType::kPinned; case WM_EVENT_PIP: return WindowStateType::kPip; + case WM_EVENT_FLOAT: + return WindowStateType::kFloated; case WM_EVENT_TRUSTED_PIN: return WindowStateType::kTrustedPinned; default:
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc index 158ce96..875405c 100644 --- a/ash/wm/default_state.cc +++ b/ash/wm/default_state.cc
@@ -11,6 +11,7 @@ #include "ash/screen_util.h" #include "ash/shell.h" #include "ash/wm/desks/desks_util.h" +#include "ash/wm/float/float_controller.h" #include "ash/wm/screen_pinning_controller.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_metrics_controller.h" @@ -21,6 +22,8 @@ #include "ash/wm/wm_event.h" #include "ash/wm/workspace_controller.h" #include "base/bind.h" +#include "base/check.h" +#include "base/check_op.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "chromeos/ui/base/window_state_type.h" @@ -434,6 +437,20 @@ window_state->UpdateWindowPropertiesFromStateType(); window_state->NotifyPreStateTypeChange(previous_state_type); + auto* const float_controller = Shell::Get()->float_controller(); + auto* window = window_state->window(); + if (state_type_ == WindowStateType::kFloated) { + DCHECK_EQ(next_state_type, WindowStateType::kFloated); + // Add window to float container. + float_controller->Float(window); + } + + // Unfloat floated window when exiting float state to another state. + if (previous_state_type == WindowStateType::kFloated) { + // Remove float window from float container. + float_controller->Unfloat(window); + } + // Don't update the window if the window is detached from parent. // This can happen during dragging. // TODO(oshima): This was added for DOCKED windows. Investigate if @@ -573,6 +590,11 @@ break; case WindowStateType::kInactive: case WindowStateType::kAutoPositioned: + case WindowStateType::kFloated: + // TODO(crbug.com/1331078): Handle Float Size and Position requirement. + // Temporarily set to current bounds. + bounds_in_parent = window->bounds(); + break; case WindowStateType::kPip: return; }
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc index 8b4300e4..b03e82d 100644 --- a/ash/wm/desks/desk_mini_view.cc +++ b/ash/wm/desks/desk_mini_view.cc
@@ -53,8 +53,11 @@ } // Tells whether `desk` contains an app window itself or if at least one visible -// on all desks window exists. +// on all desk window exists. Returns false if `desk` is nullptr. bool ContainsAppWindows(Desk* desk) { + if (!desk) + return false; + return desk->ContainsAppWindows() || !DesksController::Get()->visible_on_all_desks_windows().empty(); }
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index aac8803..d8d2f6d 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -224,11 +224,14 @@ void ShowDeskRemovalUndoToast(const std::string& toast_id, base::RepeatingClosure dismiss_callback, - base::RepeatingClosure expired_callback) { + base::RepeatingClosure expired_callback, + bool use_persistent_toast) { + // If ChromeVox is enabled, then we want the toast to be infinite duration. ToastData undo_toast_data( toast_id, ash::ToastCatalogName::kUndoCloseAll, l10n_util::GetStringUTF16(IDS_ASH_DESKS_CLOSE_ALL_TOAST_TEXT), - ToastData::kDefaultToastDuration, + use_persistent_toast ? ToastData::kInfiniteDuration + : ToastData::kDefaultToastDuration, /*visible_on_lock_screen=*/false, /*has_dismiss_button=*/true, l10n_util::GetStringUTF16(IDS_ASH_DESKS_CLOSE_ALL_UNDO_TEXT)); @@ -239,8 +242,8 @@ } // namespace -// Class that can hold the data for a removed desk while it waits for a user to -// confirm its deletion. +// Class that can hold the data for a removed desk while it waits for a user +// to confirm its deletion. class DesksController::RemovedDeskData { public: RemovedDeskData(std::unique_ptr<Desk> desk, int index) @@ -248,7 +251,11 @@ ++g_close_desk_toast_counter)), was_active_(desk->is_active()), desk_(std::move(desk)), - index_(index) { + index_(index), + is_toast_persistent_(Shell::Get() + ->accessibility_controller() + ->spoken_feedback() + .enabled()) { desk_->set_is_desk_being_removed(true); } @@ -266,6 +273,7 @@ bool was_active() const { return was_active_; } Desk* desk() { return desk_.get(); } int index() const { return index_; } + bool is_toast_persistent() const { return is_toast_persistent_; } std::unique_ptr<Desk> AcquireDesk() { return std::move(desk_); } private: @@ -273,6 +281,11 @@ const bool was_active_; std::unique_ptr<Desk> desk_; const int index_; + + // If this was created in overview with ChromeVox enabled and then ChromeVox + // is exited before this is destroyed, then we still need to know to destroy + // it when overview closes. + const bool is_toast_persistent_; }; // Helper class which wraps around a OneShotTimer and used for recording how @@ -1029,9 +1042,9 @@ } void DesksController::CreateNewDeskForTemplate( - const std::u16string& template_name, bool activate_desk, - base::OnceCallback<void(const Desk*)> callback) { + base::OnceCallback<void(const Desk*)> callback, + const std::u16string& customized_desk_name) { DCHECK(!callback.is_null()); if (!CanCreateDesks()) { @@ -1044,18 +1057,27 @@ if (animation_) animation_.reset(); - // Change the desk name if the current name already exists. - int count = 1; - std::u16string desk_name = template_name; - while (HasDeskWithName(desk_name)) { - desk_name = std::u16string(template_name) - .append(u" (" + base::FormatNumber(count) + u")"); - count++; + // Desk name was set to a default name upon creation. If + // `customized_desk_name` is provided, override desk name to be + // `customized_desk_name` or `customized_desk_name ({counter})` to resolve + // naming conflicts. + std::u16string desk_name; + if (!customized_desk_name.empty()) { + int count = 1; + desk_name = customized_desk_name; + while (HasDeskWithName(desk_name)) { + desk_name = std::u16string(customized_desk_name) + .append(u" (" + base::FormatNumber(count) + u")"); + count++; + } } NewDesk(DesksCreationRemovalSource::kLaunchTemplate); Desk* desk = desks().back().get(); - desk->SetName(desk_name, /*set_by_user=*/true); + + if (!desk_name.empty()) { + desk->SetName(desk_name, /*set_by_user=*/true); + } // Force update user prefs because `SetName()` does not trigger it. desks_restore_util::UpdatePrimaryUserDeskNamesPrefs(); @@ -1207,6 +1229,8 @@ case chromeos::WindowStateType::kPinned: case chromeos::WindowStateType::kTrustedPinned: case chromeos::WindowStateType::kPip: + // TODO(crbug.com/1331825): Float state support for desk template. + case chromeos::WindowStateType::kFloated: NOTREACHED(); break; } @@ -1259,6 +1283,35 @@ ToastManager::Get()->Cancel(toast_id); } +void DesksController::MaybeDismissPersistentDeskRemovalToast() { + if (temporary_removed_desk_ && + temporary_removed_desk_->is_toast_persistent()) { + ToastManager::Get()->Cancel(temporary_removed_desk_->toast_id()); + } +} + +bool DesksController::MaybeToggleA11yHighlightOnUndoDeskRemovalToast() { + if (!temporary_removed_desk_ || + !ToastManager::Get()->IsRunning(temporary_removed_desk_->toast_id())) { + return false; + } + + return ToastManager::Get() + ->MaybeToggleA11yHighlightOnActiveToastDismissButton( + temporary_removed_desk_->toast_id()); +} + +bool DesksController::MaybeActivateDeskRemovalUndoButtonOnHighlightedToast() { + if (!temporary_removed_desk_ || + !ToastManager::Get()->IsRunning(temporary_removed_desk_->toast_id())) { + return false; + } + + return ToastManager::Get() + ->MaybeActivateHighlightedDismissButtonOnActiveToast( + temporary_removed_desk_->toast_id()); +} + void DesksController::OnWindowActivating(ActivationReason reason, aura::Window* gaining_active, aura::Window* losing_active) { @@ -1591,7 +1644,8 @@ /*expired_callback=*/ base::BindRepeating(&DesksController::MaybeCommitPendingDeskRemoval, base::Unretained(this), - temporary_removed_desk_->toast_id())); + temporary_removed_desk_->toast_id()), + temporary_removed_desk_->is_toast_persistent()); } }
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h index 38ecb00d..c155f17 100644 --- a/ash/wm/desks/desks_controller.h +++ b/ash/wm/desks/desks_controller.h
@@ -307,13 +307,15 @@ DeskTemplateType template_type, aura::Window* root_window_to_show) const; - // Creates (and optionally activates) a new desk for a template with name - // `template_name` or `template_name ({counter})` to resolve naming - // conflicts. Runs `callback` with the newly created desk if creation was - // successful, nullptr otherwise. - void CreateNewDeskForTemplate(const std::u16string& template_name, - bool activate_desk, - base::OnceCallback<void(const Desk*)> callback); + // Creates (and optionally activates) a new desk. If `customized_desk_name` + // is provided, desk name will be `customized_desk_name` or + // `customized_desk_name ({counter})` to resolve naming conflicts. Runs + // `callback` with the newly created desk if creation was successful, nullptr + // otherwise. + void CreateNewDeskForTemplate( + bool activate_desk, + base::OnceCallback<void(const Desk*)> callback, + const std::u16string& customized_desk_name = std::u16string()); // Called when an app with `app_id` is a single instance app which is about to // get launched from a saved template. Moves the existing app instance to the @@ -334,6 +336,20 @@ // there is a desk removal in progress. void MaybeCancelDeskRemoval(); + // Cancels the desk removal toast if there is currently a + // `temporary_removed_desk_` and + // `temporary_removed_desk_->is_toast_persistent()` is true. + void MaybeDismissPersistentDeskRemovalToast(); + + // Adds focus highlight to an active toast to undo desk removal if one is + // active and the toast is not already highlighted. Otherwise, it removes the + // highlight from an active toast and returns false. + bool MaybeToggleA11yHighlightOnUndoDeskRemovalToast(); + + // Activates the undo button on a highlighted toast to undo desk removal if + // one is active. Returns true if the activation was successful. + bool MaybeActivateDeskRemovalUndoButtonOnHighlightedToast(); + // ::wm::ActivationChangeObserver: void OnWindowActivating(ActivationReason reason, aura::Window* gaining_active,
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index 3a726122..848bddf 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -7913,6 +7913,43 @@ EXPECT_TRUE(window.window()->transform().IsIdentity()); } +// Tests that we can undo close-all solely via keyboard navigation (tabbing to +// the undo toast and pressing enter). +TEST_F(DesksCloseAllTest, CanUndoDeskClosureThroughKeyboardNavigation) { + NewDesk(); + Shell::Get()->accessibility_controller()->spoken_feedback().SetEnabled(true); + EnterOverview(); + ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession()); + + // Tab to the first mini view and perform close-all on it. + SendKey(ui::VKEY_TAB); + ASSERT_EQ(GetPrimaryRootDesksBarView()->mini_views()[0], + Shell::Get() + ->overview_controller() + ->overview_session() + ->highlight_controller() + ->highlighted_view()); + SendKey(ui::VKEY_W, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN); + ASSERT_EQ(1u, DesksController::Get()->desks().size()); + + // Tab to the undo toast. + SendKey(ui::VKEY_TAB); + SendKey(ui::VKEY_TAB); + SendKey(ui::VKEY_TAB); + + // If the highlight controller returns a nullptr after tabbing, then the undo + // toast's button should be highlighted. + ASSERT_EQ(nullptr, Shell::Get() + ->overview_controller() + ->overview_session() + ->highlight_controller() + ->highlighted_view()); + + // Pressing enter should restore the desk. + SendKey(ui::VKEY_RETURN); + EXPECT_EQ(2u, DesksController::Get()->desks().size()); +} + // TODO(afakhry): Add more tests: // - Always on top windows are not tracked by any desk. // - Reusing containers when desks are removed and created.
diff --git a/ash/wm/desks/templates/saved_desk_presenter.cc b/ash/wm/desks/templates/saved_desk_presenter.cc index df1b5ea5..970f18bb 100644 --- a/ash/wm/desks/templates/saved_desk_presenter.cc +++ b/ash/wm/desks/templates/saved_desk_presenter.cc
@@ -308,10 +308,11 @@ const auto saved_desk_type = entry->type(); const bool activate_desk = saved_desk_type == DeskTemplateType::kTemplate; DesksController::Get()->CreateNewDeskForTemplate( - saved_desk_name, activate_desk, + activate_desk, base::BindOnce(&SavedDeskPresenter::OnNewDeskCreatedForTemplate, weak_ptr_factory_.GetWeakPtr(), std::move(entry), - time_launch_started, delay, root_window)); + time_launch_started, delay, root_window), + saved_desk_name); if (on_update_ui_closure_for_testing) std::move(on_update_ui_closure_for_testing).Run();
diff --git a/ash/wm/float/float_controller.cc b/ash/wm/float/float_controller.cc index d347eee..29cdf17a 100644 --- a/ash/wm/float/float_controller.cc +++ b/ash/wm/float/float_controller.cc
@@ -31,7 +31,7 @@ // Only one floating window is allowed, reset previously floated window. ResetFloatedWindow(); DCHECK(!float_window_); - DCHECK(window->GetProperty(chromeos::kWindowFloatTypeKey)); + DCHECK(window->GetProperty(chromeos::kWindowToggleFloatKey)); float_window_ = window; float_window_observation_.Observe(float_window_); aura::Window* float_container = @@ -41,8 +41,8 @@ } void FloatController::Unfloat(aura::Window* window) { - DCHECK(!window->GetProperty(chromeos::kWindowFloatTypeKey)); - // Re-parent window to active desk container. + DCHECK(!window->GetProperty(chromeos::kWindowToggleFloatKey)); + // Re-parent window to active desk container. desks_util::GetActiveDeskContainerForRoot(float_window_->GetRootWindow()) ->AddChild(float_window_); float_window_observation_.Reset(); @@ -51,7 +51,7 @@ void FloatController::ResetFloatedWindow() { if (float_window_) - float_window_->SetProperty(chromeos::kWindowFloatTypeKey, false); + float_window_->SetProperty(chromeos::kWindowToggleFloatKey, false); } } // namespace ash \ No newline at end of file
diff --git a/ash/wm/float/float_controller.h b/ash/wm/float/float_controller.h index 3466cc11..c02c19b 100644 --- a/ash/wm/float/float_controller.h +++ b/ash/wm/float/float_controller.h
@@ -32,8 +32,7 @@ void OnWindowDestroying(aura::Window* window) override; private: - friend class WindowState; - + friend class DefaultState; // Floats/Unfloats `window`. // Only one floating window is allowed, floating a new window will // unfloat the other floated window (if any).
diff --git a/ash/wm/lock_window_state.cc b/ash/wm/lock_window_state.cc index 5481d947..17a4abd 100644 --- a/ash/wm/lock_window_state.cc +++ b/ash/wm/lock_window_state.cc
@@ -43,9 +43,9 @@ UpdateWindow(window_state, WindowStateType::kFullscreen); break; case WM_EVENT_PIP: + case WM_EVENT_FLOAT: case WM_EVENT_PIN: case WM_EVENT_TRUSTED_PIN: - case WM_EVENT_TOGGLE_FLOATING: NOTREACHED(); break; case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
diff --git a/ash/wm/multitask_menu_nudge_controller.cc b/ash/wm/multitask_menu_nudge_controller.cc index 5fd5ef5..f4456f09 100644 --- a/ash/wm/multitask_menu_nudge_controller.cc +++ b/ash/wm/multitask_menu_nudge_controller.cc
@@ -149,7 +149,9 @@ // restore button (depending on the window state). auto* frame_header = chromeos::FrameHeader::Get( views::Widget::GetWidgetForNativeWindow(window_)); - DCHECK(frame_header); + // Frame might not be in tests. + if (!frame_header) + return; anchor_view_ = frame_header->caption_button_container()->size_button(); DCHECK(anchor_view_);
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc index 0527704..3543022 100644 --- a/ash/wm/overview/overview_controller.cc +++ b/ash/wm/overview/overview_controller.cc
@@ -142,6 +142,11 @@ ToggleOverview(type); RecordOverviewEndAction(action); + + // If there is an undo toast active and the toast was created when ChromeVox + // was enabled, then we need to close the toast when overview closes. + DesksController::Get()->MaybeDismissPersistentDeskRemovalToast(); + return true; }
diff --git a/ash/wm/overview/overview_highlight_controller.cc b/ash/wm/overview/overview_highlight_controller.cc index c6a9c7a..a328b7f 100644 --- a/ash/wm/overview/overview_highlight_controller.cc +++ b/ash/wm/overview/overview_highlight_controller.cc
@@ -51,9 +51,11 @@ return; int index = 0; + bool item_was_deleted = false; if (!highlighted_view_) { // Pick up where we left off if |deleted_index_| has a value. if (deleted_index_) { + item_was_deleted = true; index = *deleted_index_ >= count ? 0 : *deleted_index_; deleted_index_.reset(); } else if (reverse) { @@ -68,6 +70,19 @@ index = (((reverse ? -1 : 1) + current_index) + count) % count; } + // If we are moving over either end of the list of traversible views and there + // is an active toast with an undo button for desk removal that can be + // highlighted, then we unfocus any traversible views while the dismiss button + // is focused. + if (((index == 0 && !reverse) || (index == count - 1 && reverse)) && + !item_was_deleted && + DesksController::Get() + ->MaybeToggleA11yHighlightOnUndoDeskRemovalToast()) { + SetFocusHighlightVisibility(false); + highlighted_view_ = nullptr; + return; + } + UpdateHighlight(traversable_views[index]); } @@ -124,6 +139,11 @@ } bool OverviewHighlightController::MaybeActivateHighlightedView() { + if (DesksController::Get() + ->MaybeActivateDeskRemovalUndoButtonOnHighlightedToast()) { + return true; + } + if (!highlighted_view_) return false;
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc index 882e40b8..63cfc64 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_state.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -280,7 +280,6 @@ UpdateWindow(window_state, WindowStateType::kTrustedPinned, true /* animated */); break; - case WM_EVENT_TOGGLE_FLOATING: case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION: case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE: case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE: @@ -308,6 +307,9 @@ } break; } + // TODO(shidi): Float is currently disabled for tablet mode. + case WM_EVENT_FLOAT: + break; case WM_EVENT_SNAP_PRIMARY: case WM_EVENT_SNAP_SECONDARY: DoTabletSnap(window_state, event->type());
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index 769b5a3..9b53ee15 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc
@@ -100,6 +100,10 @@ {WindowStateType::kSecondarySnapped, 1}, {WindowStateType::kMaximized, 2}, {WindowStateType::kFullscreen, 3}, + // TODO(crbug.com/1330999): Special handling is needed for + // Fullscreen/Float restore behavior in + // WindowState::UpdateWindowStateRestoreHistoryStack. + {WindowStateType::kFloated, 3}, {WindowStateType::kPip, 4}, {WindowStateType::kMinimized, 4}, }); @@ -333,6 +337,10 @@ return GetStateType() == WindowStateType::kPip; } +bool WindowState::IsFloated() const { + return GetStateType() == WindowStateType::kFloated; +} + bool WindowState::IsNormalStateType() const { return IsNormalWindowStateType(GetStateType()); } @@ -1142,15 +1150,20 @@ } return; } - if (key == chromeos::kWindowFloatTypeKey) { + // `kWindowToggleFloatKey` is only used to toggle float event, not an + // indicator of window's float state. this is created to allow access from + // both chromeos/ash and avoid recursive call to `kWindowStateTypeKey`. + // TODO(shidi): Create API to allow outside access and remove this property. + if (key == chromeos::kWindowToggleFloatKey) { DCHECK(chromeos::wm::features::IsFloatWindowEnabled()); - auto* const float_controller = Shell::Get()->float_controller(); - if (window->GetProperty(chromeos::kWindowFloatTypeKey)) { - float_controller->Float(window); + if (IsFloated()) { + // If window is already floated, unfloat and restore. + Restore(); } else { - float_controller->Unfloat(window); + WMEvent event(WM_EVENT_FLOAT); + OnWMEvent(&event); + return; } - return; } if (key == chromeos::kWindowStateTypeKey) { if (!ignore_property_change_) {
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h index 5257182..567d0e6 100644 --- a/ash/wm/window_state.h +++ b/ash/wm/window_state.h
@@ -135,6 +135,7 @@ bool IsPinned() const; bool IsTrustedPinned() const; bool IsPip() const; + bool IsFloated() const; // True if the window's state type is chromeos::WindowStateType::kMaximized, // chromeos::WindowStateType::kFullscreen or
diff --git a/ash/wm/wm_event.cc b/ash/wm/wm_event.cc index ea6ec42..1fb408f7 100644 --- a/ash/wm/wm_event.cc +++ b/ash/wm/wm_event.cc
@@ -69,7 +69,6 @@ case WM_EVENT_NORMAL: case WM_EVENT_MAXIMIZE: case WM_EVENT_MINIMIZE: - case WM_EVENT_TOGGLE_FLOATING: case WM_EVENT_FULLSCREEN: case WM_EVENT_SNAP_PRIMARY: case WM_EVENT_SNAP_SECONDARY: @@ -78,6 +77,7 @@ case WM_EVENT_PIN: case WM_EVENT_TRUSTED_PIN: case WM_EVENT_PIP: + case WM_EVENT_FLOAT: return true; default: break;
diff --git a/ash/wm/wm_event.h b/ash/wm/wm_event.h index bff0f00..7f77c4f5 100644 --- a/ash/wm/wm_event.h +++ b/ash/wm/wm_event.h
@@ -47,9 +47,6 @@ // Following events are compond events which may lead to different // states depending on the current state. - // A user requested to make a window floating. - WM_EVENT_TOGGLE_FLOATING, - // A user requested to toggle maximized state by double clicking window // header. WM_EVENT_TOGGLE_MAXIMIZE_CAPTION, @@ -117,6 +114,9 @@ // TODO(oshima): Consider consolidating this into // WM_EVENT_WORKAREA_BOUNDS_CHANGED WM_EVENT_SYSTEM_UI_AREA_CHANGED, + + // A user requested to float a window. + WM_EVENT_FLOAT, }; class SetBoundsWMEvent;
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc index e9bddce1..7afcb1c16 100644 --- a/ash/wm/workspace/workspace_window_resizer.cc +++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -368,9 +368,9 @@ #if DCHECK_IS_ON() // Other state types either create a different window resizer, or none at all. std::vector<WindowStateType> draggable_states = { - WindowStateType::kDefault, WindowStateType::kNormal, + WindowStateType::kDefault, WindowStateType::kNormal, WindowStateType::kPrimarySnapped, WindowStateType::kSecondarySnapped, - WindowStateType::kMaximized}; + WindowStateType::kMaximized, WindowStateType::kFloated}; DCHECK(base::Contains(draggable_states, state)); #endif
diff --git a/base/BUILD.gn b/base/BUILD.gn index f990dad..ff7c1c9f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -78,7 +78,7 @@ # Chromecast builds have full control over the platform and ensure that # the kernel and glibc versions used have patched the vulnerabilities, # so it is safe to use mutex priority inheritance on Chromecast platform. -assert(!enable_mutex_priority_inheritance || is_chromecast, +assert(!enable_mutex_priority_inheritance || is_castos || is_cast_android, "Do not enable PI mutexes without consulting the security team") assert(!is_nacl || is_nacl_saigo, @@ -1494,8 +1494,7 @@ # Needed for <atomic> if using newer C++ library than sysroot, except if # building inside the cros_sdk environment - use host_toolchain as a # more robust check for this. - if (!use_sysroot && - (is_android || ((is_linux || is_chromeos) && !is_chromecast)) && + if (!use_sysroot && (is_android || is_chromeos || (is_linux && !is_castos)) && host_toolchain != "//build/toolchain/cros:host") { libs += [ "atomic" ] } @@ -1583,7 +1582,7 @@ # Allow more direct string conversions on platforms with native utf8 # strings - if (is_apple || is_chromeos || is_chromecast || is_fuchsia) { + if (is_apple || is_chromeos || is_castos || is_cast_android || is_fuchsia) { defines += [ "SYSTEM_NATIVE_UTF8" ] } @@ -2289,7 +2288,7 @@ # TODO(b/167763382) Find an alternate solution for Chromecast devices, since # adding the icui18n and icuuc deps significantly increases the binary size. - if (!is_chromecast) { + if (!is_castos && !is_cast_android) { sources += [ "time/time_exploded_icu.cc" ] # The ICU dependency is only needed on systems with a 32-bit time_t. @@ -3520,7 +3519,7 @@ # Allow more direct string conversions on platforms with native utf8 # strings - if (is_apple || is_chromeos || is_chromecast || is_fuchsia) { + if (is_apple || is_chromeos || is_castos || is_cast_android || is_fuchsia) { defines += [ "SYSTEM_NATIVE_UTF8" ] } @@ -4282,9 +4281,9 @@ "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_core_core_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", ] sources = [
diff --git a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc index a6feb12..814b786 100644 --- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc +++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -399,11 +399,11 @@ MaybeAdjustSize(size), ""); } -#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(IS_CHROMECAST) +#if BUILDFLAG(IS_CAST_ANDROID) extern "C" { void __real_free(void*); } // extern "C" -#endif +#endif // BUILDFLAG(IS_CAST_ANDROID) void PartitionFree(const AllocatorDispatch*, void* object, void* context) { ScopedDisallowAllocations guard{}; @@ -419,11 +419,11 @@ } #endif // BUILDFLAG(IS_APPLE) - // On Chromecast, there is at least one case where a system malloc() pointer - // can be passed to PartitionAlloc's free(). If we don't own the pointer, pass - // it along. This should not have a runtime cost vs regular Android, since on - // Android we have a PA_CHECK() rather than the branch here. -#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(IS_CHROMECAST) + // On Android Chromecast devices, there is at least one case where a system + // malloc() pointer can be passed to PartitionAlloc's free(). If we don't own + // the pointer, pass it along. This should not have a runtime cost vs regular + // Android, since on Android we have a PA_CHECK() rather than the branch here. +#if BUILDFLAG(IS_CAST_ANDROID) if (UNLIKELY(!partition_alloc::IsManagedByPartitionAlloc( reinterpret_cast<uintptr_t>(object)) && object)) { @@ -432,7 +432,7 @@ // here. return __real_free(object); } -#endif +#endif // BUILDFLAG(IS_CAST_ANDROID) partition_alloc::ThreadSafePartitionRoot::FreeNoHooks(object); }
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn index 34ede98..0aa0c78 100644 --- a/base/allocator/partition_allocator/BUILD.gn +++ b/base/allocator/partition_allocator/BUILD.gn
@@ -436,7 +436,10 @@ buildflag_header("chromecast_buildflags") { header = "chromecast_buildflags.h" - flags = [ "PA_IS_CASTOS=$is_castos" ] + flags = [ + "PA_IS_CAST_ANDROID=$is_cast_android", + "PA_IS_CASTOS=$is_castos", + ] } buildflag_header("chromeos_buildflags") {
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 46c9ad7..9d7ce56 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -4519,8 +4519,7 @@ #endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) -#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - BUILDFLAG(PA_IS_CASTOS) +#if BUILDFLAG(PA_IS_CAST_ANDROID) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) extern "C" { void* __real_malloc(size_t); } // extern "C"
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h index e9624ca6..571b1c8 100644 --- a/base/allocator/partition_allocator/partition_root.h +++ b/base/allocator/partition_allocator/partition_root.h
@@ -1128,9 +1128,10 @@ // forward allocations we don't own to the system malloc() implementation in // these rare cases, assuming that some remain. // - // On Chromecast, this is already checked in PartitionFree() in the shim. + // On Android Chromecast devices, this is already checked in PartitionFree() + // in the shim. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - ((BUILDFLAG(IS_ANDROID) && !BUILDFLAG(PA_IS_CASTOS))) + (BUILDFLAG(IS_ANDROID) && !BUILDFLAG(PA_IS_CAST_ANDROID)) PA_CHECK(IsManagedByPartitionAlloc(object_addr)); #endif
diff --git a/base/fuchsia/filtered_service_directory.h b/base/fuchsia/filtered_service_directory.h index 157ca7d..169959bd 100644 --- a/base/fuchsia/filtered_service_directory.h +++ b/base/fuchsia/filtered_service_directory.h
@@ -15,14 +15,6 @@ #include "base/base_export.h" #include "base/strings/string_piece.h" -// TODO(crbug.com/1196525): Remove once Chromecast calls are checking results. -#include "build/chromecast_buildflags.h" -#if BUILDFLAG(IS_CHROMECAST) -#define MAYBE_NODISCARD -#else -#define MAYBE_NODISCARD [[nodiscard]] -#endif - namespace base { // ServiceDirectory that uses the supplied sys::ServiceDirectory to satisfy @@ -40,12 +32,12 @@ ~FilteredServiceDirectory(); // Adds the specified service to the list of allowed services. - MAYBE_NODISCARD zx_status_t AddService(base::StringPiece service_name); + [[nodiscard]] zx_status_t AddService(base::StringPiece service_name); // Connects a directory client. The directory can be passed to a sandboxed // process to be used for /svc namespace. - MAYBE_NODISCARD zx_status_t - ConnectClient(fidl::InterfaceRequest<::fuchsia::io::Directory> dir_request); + [[nodiscard]] zx_status_t ConnectClient( + fidl::InterfaceRequest<::fuchsia::io::Directory> dir_request); // Accessor for the OutgoingDirectory, used to add handlers for services // in addition to those provided from |directory| via AddService().
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc index 83c641d..a671af1 100644 --- a/base/i18n/icu_util.cc +++ b/base/i18n/icu_util.cc
@@ -53,9 +53,8 @@ #include "third_party/icu/source/common/unicode/unistr.h" #endif -#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || \ - ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \ - !BUILDFLAG(IS_CHROMECAST)) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || \ + BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) #include "third_party/icu/source/i18n/unicode/timezone.h" #endif @@ -326,8 +325,7 @@ FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdForIcuInitialization(); icu::TimeZone::adoptDefault( icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(zone_id))); -#elif (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \ - !BUILDFLAG(IS_CHROMECAST) +#elif BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) // To respond to the time zone change properly, the default time zone // cache in ICU has to be populated on starting up. // See TimeZoneMonitorLinux::NotifyClientsFromImpl().
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc index 468ea2d..91824d9e 100644 --- a/base/json/json_parser.cc +++ b/base/json/json_parser.cc
@@ -423,7 +423,7 @@ return absl::nullopt; } - std::vector<Value::DictStorage::value_type> dict_storage; + std::vector<Value::DeprecatedDictStorage::value_type> dict_storage; Token token = GetNextToken(); while (token != T_OBJECT_END) { @@ -473,7 +473,7 @@ // Reverse |dict_storage| to keep the last of elements with the same key in // the input. ranges::reverse(dict_storage); - return Value(Value::DictStorage(std::move(dict_storage))); + return Value(Value::DeprecatedDictStorage(std::move(dict_storage))); } absl::optional<Value> JSONParser::ConsumeList() {
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc index 78090502..016f431 100644 --- a/base/process/process_metrics_win.cc +++ b/base/process/process_metrics_win.cc
@@ -167,6 +167,9 @@ // constant rate TSC. return GetCumulativeCPUUsage(); #else // !defined(ARCH_CPU_ARM64) + if (!time_internal::HasConstantRateTSC()) + return GetCumulativeCPUUsage(); + ULONG64 process_cycle_time = 0; if (!QueryProcessCycleTime(process_.get(), &process_cycle_time)) { NOTREACHED();
diff --git a/base/task/sequenced_task_runner.h b/base/task/sequenced_task_runner.h index f755bba..90452fc 100644 --- a/base/task/sequenced_task_runner.h +++ b/base/task/sequenced_task_runner.h
@@ -33,6 +33,7 @@ class DelayedTaskManager; } class DeadlineTimer; +class MetronomeTimer; class TimeDelta; class TimeTicks; @@ -48,6 +49,7 @@ friend class base::internal::DelayTimerBase; friend class base::internal::DelayedTaskManager; friend class base::DeadlineTimer; + friend class base::MetronomeTimer; friend class blink::MetronomeSource; friend class blink::TimerBase; friend class blink::WebRtcMetronomeTaskQueue;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java index 3ad851a..97e47eb6 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java +++ b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
@@ -9,7 +9,8 @@ import android.os.Build; import android.os.SystemClock; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; + +import androidx.test.uiautomator.UiDevice; import org.junit.runners.model.Statement;
diff --git a/base/time/time_exploded_posix.cc b/base/time/time_exploded_posix.cc index e769489..45327a8 100644 --- a/base/time/time_exploded_posix.cc +++ b/base/time/time_exploded_posix.cc
@@ -130,10 +130,10 @@ if (sizeof(SysTime) < 8) { // TODO(b/167763382) Find an alternate solution for Chromecast devices, since // adding the icui18n dep significantly increases the binary size. -#if !BUILDFLAG(IS_CHROMECAST) +#if !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID) ExplodeUsingIcu(millis_since_unix_epoch, is_local, exploded); return; -#endif // !BUILDFLAG(IS_CHROMECAST) +#endif // !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID) } // Split the |millis_since_unix_epoch| into separate seconds and millisecond
diff --git a/base/timer/timer.cc b/base/timer/timer.cc index 75274373..04d1183 100644 --- a/base/timer/timer.cc +++ b/base/timer/timer.cc
@@ -402,4 +402,71 @@ // No more member accesses here: |this| could be deleted at this point. } +MetronomeTimer::MetronomeTimer() = default; +MetronomeTimer::~MetronomeTimer() = default; + +MetronomeTimer::MetronomeTimer(const Location& posted_from, + TimeDelta interval, + RepeatingClosure user_task, + TimeTicks phase) + : TimerBase(posted_from), + interval_(interval), + user_task_(user_task), + phase_(phase) {} + +void MetronomeTimer::Start(const Location& posted_from, + TimeDelta interval, + RepeatingClosure user_task, + TimeTicks phase) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + user_task_ = std::move(user_task); + posted_from_ = posted_from; + interval_ = interval; + phase_ = phase; + + Reset(); +} + +void MetronomeTimer::OnStop() { + user_task_.Reset(); + // No more member accesses here: |this| could be deleted after freeing + // |user_task_|. +} + +void MetronomeTimer::Reset() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(user_task_); + // We can't reuse the |scheduled_task_|, so abandon it and post a new one. + AbandonScheduledTask(); + ScheduleNewTask(); +} + +void MetronomeTimer::ScheduleNewTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + is_running_ = true; + + // The next wake up is scheduled at the next aligned time which is at least + // `interval_ / 2` after now. `interval_ / 2` is added to avoid playing + // "catch-up" if wake ups are late. + TimeTicks deadline = + (TimeTicks::Now() + interval_ / 2).SnappedToNextTick(phase_, interval_); + + delayed_task_handle_ = GetTaskRunner()->PostCancelableDelayedTaskAt( + base::subtle::PostDelayedTaskPassKey(), posted_from_, + BindOnce(&MetronomeTimer::OnScheduledTaskInvoked, Unretained(this)), + deadline, subtle::DelayPolicy::kPrecise); +} + +void MetronomeTimer::OnScheduledTaskInvoked() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!delayed_task_handle_.IsValid()); + + // Make a local copy of the task to run in case the task destroy the timer + // instance. + RepeatingClosure task = user_task_; + ScheduleNewTask(); + std::move(task).Run(); + // No more member accesses here: |this| could be deleted at this point. +} + } // namespace base
diff --git a/base/timer/timer.h b/base/timer/timer.h index 9e52ef0..a20af99c 100644 --- a/base/timer/timer.h +++ b/base/timer/timer.h
@@ -11,6 +11,15 @@ // - DeadlineTimer: Once at the specified `TimeTicks` time. // - RepeatingTimer: Repeatedly, with a specified `TimeDelta` delay before the // first invocation and between invocations. +// - MetronomeTimer: Repeatedly, with a specified `TimeDelta` delay between the +// beginning of each invocations such that a constant phase is respected. +// (Retaining)OneShotTimer and RepeatingTimer automatically apply some leeway to +// the delay whereas DeadlineTimer and MetronomeTimer allow more control over +// the requested time. As a result, the former are generally more +// power-efficient. +// Prefer using (Retaining)OneShotTimer and RepeatingTimer because they +// automatically apply some leeway to the delay which enables power-efficient +// scheduling. // Scheduled invocations can be cancelled with Stop() or by deleting the // Timer. The latter makes it easy to ensure that an object is not accessed by a @@ -452,6 +461,63 @@ OnceClosure user_task_; }; +//----------------------------------------------------------------------------- +// Repeatedly invokes a callback, waiting for a precise delay between the +// beginning of each invocation. See usage notes at the top of the file. +class BASE_EXPORT MetronomeTimer : public internal::TimerBase { + public: + MetronomeTimer(); + ~MetronomeTimer() override; + + MetronomeTimer(const MetronomeTimer&) = delete; + MetronomeTimer& operator=(const MetronomeTimer&) = delete; + + MetronomeTimer(const Location& posted_from, + TimeDelta interval, + RepeatingClosure user_task, + TimeTicks phase = TimeTicks()); + + // Start the timer to repeatedly run |user_task| at the specified |interval|; + // If not specified, the phase is up to the scheduler, otherwise each + // invocation starts as close as possible to `phase + n * delay` for some + // integer n. If the timer is already running, it will be replaced to call the + // given |user_task|. + void Start(const Location& posted_from, + TimeDelta interval, + RepeatingClosure user_task, + TimeTicks phase = TimeTicks()); + + // Same as the previous overload, except that the user task is specified by + // `receiver` and `method`. + template <class Receiver> + void Start(const Location& posted_from, + TimeDelta interval, + Receiver* receiver, + void (Receiver::*method)(), + TimeTicks phase = TimeTicks()) { + Start(posted_from, interval, BindOnce(method, Unretained(receiver)), phase); + } + + // Call this method to reset the timer delay. The user task must be set. If + // the timer is not running, this will start it by posting a task. + void Reset(); + + protected: + void OnStop() override; + + // Schedules |OnScheduledTaskInvoked()| to run on the current sequence at + // the next tick. + void ScheduleNewTask(); + + private: + // Called when the scheduled task is invoked to run the |user_task|. + void OnScheduledTaskInvoked(); + + TimeDelta interval_; + RepeatingClosure user_task_; + TimeTicks phase_; +}; + } // namespace base #endif // BASE_TIMER_TIMER_H_
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc index 248ad7a..bd85512 100644 --- a/base/timer/timer_unittest.cc +++ b/base/timer/timer_unittest.cc
@@ -538,6 +538,107 @@ testing::Mock::VerifyAndClearExpectations(&destructed); } +TEST(TimerTest, MetronomeTimer) { + test::TaskEnvironment task_environment( + test::TaskEnvironment::TimeSource::MOCK_TIME); + MetronomeTimer timer; + TimeTicks start = TimeTicks::Now(); + + // Ensure the run_loop.Run() below doesn't straddle over multiple ticks. + task_environment.AdvanceClock( + start.SnappedToNextTick(TimeTicks(), Seconds(5)) - start); + start = TimeTicks::Now(); + + RunLoop run_loop; + timer.Start(FROM_HERE, Seconds(5), run_loop.QuitClosure()); + run_loop.Run(); + EXPECT_EQ(start + Seconds(5), TimeTicks::Now()); +} + +TEST(TimerTest, MetronomeTimerCustomPhase) { + test::TaskEnvironment task_environment( + test::TaskEnvironment::TimeSource::MOCK_TIME); + RunLoop run_loop; + MetronomeTimer timer; + TimeTicks start = TimeTicks::Now(); + + timer.Start(FROM_HERE, Seconds(5), run_loop.QuitClosure(), start); + run_loop.Run(); + EXPECT_EQ(start + Seconds(5), TimeTicks::Now()); +} + +TEST(TimerTest, MetronomeTimerReset) { + test::TaskEnvironment task_environment( + test::TaskEnvironment::TimeSource::MOCK_TIME); + RunLoop run_loop; + TimeTicks start = TimeTicks::Now(); + MetronomeTimer timer(FROM_HERE, Seconds(5), run_loop.QuitClosure(), start); + + timer.Reset(); + run_loop.Run(); + EXPECT_EQ(start + Seconds(5), TimeTicks::Now()); +} + +TEST(TimerTest, MetronomeTimerStartTwice) { + test::TaskEnvironment task_environment( + test::TaskEnvironment::TimeSource::MOCK_TIME); + MetronomeTimer timer; + TimeTicks start = TimeTicks::Now(); + + { + RunLoop run_loop; + timer.Start(FROM_HERE, Seconds(4), run_loop.QuitClosure(), start); + run_loop.Run(); + } + EXPECT_EQ(start + Seconds(4), TimeTicks::Now()); + + { + RunLoop run_loop; + timer.Start(FROM_HERE, Seconds(2), run_loop.QuitClosure(), start); + run_loop.Run(); + } + EXPECT_EQ(start + Seconds(6), TimeTicks::Now()); +} + +TEST(TimerTest, MetronomeTimerMultiple) { + test::TaskEnvironment task_environment( + test::TaskEnvironment::TimeSource::MOCK_TIME); + MetronomeTimer timer; + TimeTicks start = TimeTicks::Now(); + + // Ensure the subsequent FastForwardBy() don't straddle over multiple ticks. + task_environment.AdvanceClock( + start.SnappedToNextTick(TimeTicks(), Seconds(5)) - start); + + MockRepeatingCallback<void()> callback; + timer.Start(FROM_HERE, Seconds(5), callback.Get()); + + // The first tick is skipped because it is too close. Ticks at 5s and 10s. + EXPECT_CALL(callback, Run()).Times(2); + task_environment.FastForwardBy(Seconds(10)); + + EXPECT_CALL(callback, Run()).Times(2); + // Ticks at 15s and 25s, while 20s is missed. + task_environment.AdvanceClock(Seconds(12)); + task_environment.FastForwardBy(Seconds(3)); +} + +TEST(TimerTest, MetronomeTimerCancel) { + test::TaskEnvironment task_environment( + test::TaskEnvironment::TimeSource::MOCK_TIME); + RunLoop run_loop; + MetronomeTimer timer; + TimeTicks start = TimeTicks::Now(); + + MockRepeatingCallback<void()> callback; + timer.Start(FROM_HERE, Seconds(5), callback.Get()); + + EXPECT_CALL(callback, Run()).Times(0); + timer.Stop(); + task_environment.FastForwardBy(Seconds(5)); + EXPECT_EQ(start + Seconds(5), TimeTicks::Now()); +} + INSTANTIATE_TEST_SUITE_P(All, TimerTestWithThreadType, testing::ValuesIn(testing_main_threads));
diff --git a/base/values.cc b/base/values.cc index 3282df3..a63668de 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -231,7 +231,8 @@ Value::Value(List&& value) noexcept : data_(std::move(value)) {} -Value::Value(const DictStorage& value) : data_(absl::in_place_type_t<Dict>()) { +Value::Value(const DeprecatedDictStorage& value) + : data_(absl::in_place_type_t<Dict>()) { dict().reserve(value.size()); for (const auto& it : value) { dict().try_emplace(dict().end(), it.first, @@ -239,7 +240,8 @@ } } -Value::Value(DictStorage&& value) : data_(absl::in_place_type_t<Dict>()) { +Value::Value(DeprecatedDictStorage&& value) + : data_(absl::in_place_type_t<Dict>()) { dict().reserve(value.size()); for (auto& it : value) { dict().try_emplace(dict().end(), std::move(it.first), @@ -1380,8 +1382,8 @@ return const_dict_iterator_proxy(&dict()); } -Value::DictStorage Value::TakeDictDeprecated() && { - DictStorage storage; +Value::DeprecatedDictStorage Value::TakeDictDeprecated() && { + DeprecatedDictStorage storage; storage.reserve(dict().size()); for (auto& pair : dict()) { storage.try_emplace(storage.end(), std::move(pair.first),
diff --git a/base/values.h b/base/values.h index 8db7e6a..1b42ee1 100644 --- a/base/values.h +++ b/base/values.h
@@ -207,13 +207,13 @@ using DeprecatedListStorage = std::vector<Value>; using DeprecatedDictStorage = flat_map<std::string, Value>; - // TODO(https://crbug.com/1291666): Make these private. + // TODO(https://crbug.com/1291666): Make this private. using ListStorage = DeprecatedListStorage; - using DictStorage = DeprecatedDictStorage; // Like `DictStorage`, but with std::unique_ptr in the mapped type. This is - // due to legacy reasons, and should be removed once no caller relies on - // stability of pointers anymore. + // due to legacy reasons, and should be replaced with a private version of + // DeprecatedDictStorage once no caller relies on stability of pointers + // anymore. using LegacyDictStorage = flat_map<std::string, std::unique_ptr<Value>>; using DeprecatedListView = CheckedContiguousRange<ListStorage>; @@ -303,8 +303,8 @@ explicit Value(List&& value) noexcept; // DEPRECATED: prefer `Value(Dict&&)`. - explicit Value(const DictStorage& value); - explicit Value(DictStorage&& value); + explicit Value(const DeprecatedDictStorage& value); + explicit Value(DeprecatedDictStorage&& value); // DEPRECATED: prefer `Value(List&&)`. explicit Value(span<const Value> value);
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index b221d45..431bbf47 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -193,8 +193,29 @@ EXPECT_EQ(Value::Type::DICTIONARY, value.type()); } -TEST(ValuesTest, ConstructDictFromStorage) { - Value::DictStorage storage; +TEST(ValuesTest, ConstructDictFromValueDict) { + Value::Dict dict; + dict.Set("foo", "bar"); + { + Value value(dict.Clone()); + EXPECT_EQ(Value::Type::DICT, value.type()); + EXPECT_TRUE(value.GetIfDict()); + EXPECT_TRUE(value.GetDict().FindString("foo")); + EXPECT_EQ("bar", *value.GetDict().FindString("foo")); + } + + dict.Set("foo", "baz"); + { + Value value(std::move(dict)); + EXPECT_EQ(Value::Type::DICT, value.type()); + EXPECT_TRUE(value.GetIfDict()); + EXPECT_TRUE(value.GetDict().FindString("foo")); + EXPECT_EQ("baz", *value.GetDict().FindString("foo")); + } +} + +TEST(ValuesTest, ConstructDictFromDeprecatedDictStorage) { + Value::DeprecatedDictStorage storage; storage.emplace("foo", "bar"); { Value value(storage); @@ -328,9 +349,9 @@ } TEST(ValuesTest, CopyDictionary) { - Value::DictStorage storage; - storage.emplace("Int", 123); - Value value(std::move(storage)); + Value::Dict dict; + dict.Set("Int", 123); + Value value(std::move(dict)); Value copied_value(value.Clone()); EXPECT_EQ(value, copied_value); @@ -430,7 +451,27 @@ } TEST(ValuesTest, MoveConstructDictionary) { - Value::DictStorage storage; + Value::Dict dict; + dict.Set("Int", 123); + + Value value(std::move(dict)); + Value moved_value(std::move(value)); + EXPECT_EQ(Value::Type::DICTIONARY, moved_value.type()); + EXPECT_EQ(123, moved_value.FindKey("Int")->GetInt()); +} + +TEST(ValuesTest, MoveAssignDictionary) { + Value::Dict dict; + dict.Set("Int", 123); + + Value blank; + blank = Value(std::move(dict)); + EXPECT_EQ(Value::Type::DICTIONARY, blank.type()); + EXPECT_EQ(123, blank.FindKey("Int")->GetInt()); +} + +TEST(ValuesTest, MoveConstructDeprecatedDictStorage) { + Value::DeprecatedDictStorage storage; storage.emplace("Int", 123); Value value(std::move(storage)); @@ -439,8 +480,8 @@ EXPECT_EQ(123, moved_value.FindKey("Int")->GetInt()); } -TEST(ValuesTest, MoveAssignDictionary) { - Value::DictStorage storage; +TEST(ValuesTest, MoveAssignDeprecatedDictStorage) { + Value::DeprecatedDictStorage storage; storage.emplace("Int", 123); Value blank; @@ -449,9 +490,9 @@ EXPECT_EQ(123, blank.FindKey("Int")->GetInt()); } -TEST(ValuesTest, TakeDict) { +TEST(ValuesTest, TakeDictDeprecated) { // Prepare a dict with a value of each type. - Value::DictStorage storage; + Value::DeprecatedDictStorage storage; storage.emplace("null", Value::Type::NONE); storage.emplace("bool", Value::Type::BOOLEAN); storage.emplace("int", Value::Type::INTEGER); @@ -730,397 +771,397 @@ } TEST(ValuesTest, FindKey) { - Value::DictStorage storage; - storage.emplace("foo", "bar"); - Value dict(std::move(storage)); - EXPECT_NE(nullptr, dict.FindKey("foo")); - EXPECT_EQ(nullptr, dict.FindKey("baz")); + Value::Dict dict; + dict.Set("foo", "bar"); + Value value(std::move(dict)); + EXPECT_NE(nullptr, value.FindKey("foo")); + EXPECT_EQ(nullptr, value.FindKey("baz")); // Single not found key. - bool found = dict.FindKey("notfound"); + bool found = value.FindKey("notfound"); EXPECT_FALSE(found); } TEST(ValuesTest, FindKeyChangeValue) { - Value::DictStorage storage; - storage.emplace("foo", "bar"); - Value dict(std::move(storage)); - Value* found = dict.FindKey("foo"); + Value::Dict dict; + dict.Set("foo", "bar"); + Value value(std::move(dict)); + Value* found = value.FindKey("foo"); EXPECT_NE(nullptr, found); EXPECT_EQ("bar", found->GetString()); *found = Value(123); - EXPECT_EQ(123, dict.FindKey("foo")->GetInt()); + EXPECT_EQ(123, value.FindKey("foo")->GetInt()); } TEST(ValuesTest, FindKeyConst) { - Value::DictStorage storage; - storage.emplace("foo", "bar"); - const Value dict(std::move(storage)); - EXPECT_NE(nullptr, dict.FindKey("foo")); - EXPECT_EQ(nullptr, dict.FindKey("baz")); + Value::Dict dict; + dict.Set("foo", "bar"); + const Value value(std::move(dict)); + EXPECT_NE(nullptr, value.FindKey("foo")); + EXPECT_EQ(nullptr, value.FindKey("baz")); } TEST(ValuesTest, FindKeyOfType) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - Value dict(std::move(storage)); - EXPECT_NE(nullptr, dict.FindKeyOfType("null", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DICTIONARY)); + Value value(std::move(dict)); + EXPECT_NE(nullptr, value.FindKeyOfType("null", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::NONE)); - EXPECT_NE(nullptr, dict.FindKeyOfType("bool", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::NONE)); + EXPECT_NE(nullptr, value.FindKeyOfType("bool", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BOOLEAN)); - EXPECT_NE(nullptr, dict.FindKeyOfType("int", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BOOLEAN)); + EXPECT_NE(nullptr, value.FindKeyOfType("int", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::INTEGER)); - EXPECT_NE(nullptr, dict.FindKeyOfType("double", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::INTEGER)); + EXPECT_NE(nullptr, value.FindKeyOfType("double", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DOUBLE)); - EXPECT_NE(nullptr, dict.FindKeyOfType("string", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DOUBLE)); + EXPECT_NE(nullptr, value.FindKeyOfType("string", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::STRING)); - EXPECT_NE(nullptr, dict.FindKeyOfType("blob", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::STRING)); + EXPECT_NE(nullptr, value.FindKeyOfType("blob", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BINARY)); - EXPECT_NE(nullptr, dict.FindKeyOfType("list", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BINARY)); + EXPECT_NE(nullptr, value.FindKeyOfType("list", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::LIST)); - EXPECT_NE(nullptr, dict.FindKeyOfType("dict", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::LIST)); + EXPECT_NE(nullptr, value.FindKeyOfType("dict", Value::Type::DICTIONARY)); } TEST(ValuesTest, FindKeyOfTypeConst) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_NE(nullptr, dict.FindKeyOfType("null", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DICTIONARY)); + const Value value(std::move(dict)); + EXPECT_NE(nullptr, value.FindKeyOfType("null", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::NONE)); - EXPECT_NE(nullptr, dict.FindKeyOfType("bool", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::NONE)); + EXPECT_NE(nullptr, value.FindKeyOfType("bool", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BOOLEAN)); - EXPECT_NE(nullptr, dict.FindKeyOfType("int", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BOOLEAN)); + EXPECT_NE(nullptr, value.FindKeyOfType("int", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::INTEGER)); - EXPECT_NE(nullptr, dict.FindKeyOfType("double", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::INTEGER)); + EXPECT_NE(nullptr, value.FindKeyOfType("double", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DOUBLE)); - EXPECT_NE(nullptr, dict.FindKeyOfType("string", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DOUBLE)); + EXPECT_NE(nullptr, value.FindKeyOfType("string", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::STRING)); - EXPECT_NE(nullptr, dict.FindKeyOfType("blob", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::STRING)); + EXPECT_NE(nullptr, value.FindKeyOfType("blob", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BINARY)); - EXPECT_NE(nullptr, dict.FindKeyOfType("list", Value::Type::LIST)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BINARY)); + EXPECT_NE(nullptr, value.FindKeyOfType("list", Value::Type::LIST)); + EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DICTIONARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::NONE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BOOLEAN)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::INTEGER)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::DOUBLE)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::STRING)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BINARY)); - EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::LIST)); - EXPECT_NE(nullptr, dict.FindKeyOfType("dict", Value::Type::DICTIONARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::NONE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BOOLEAN)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::INTEGER)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::DOUBLE)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::STRING)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BINARY)); + EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::LIST)); + EXPECT_NE(nullptr, value.FindKeyOfType("dict", Value::Type::DICTIONARY)); } TEST(ValuesTest, FindBoolKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("null")); - EXPECT_NE(absl::nullopt, dict.FindBoolKey("bool")); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("int")); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("double")); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("string")); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("blob")); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("list")); - EXPECT_EQ(absl::nullopt, dict.FindBoolKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("null")); + EXPECT_NE(absl::nullopt, value.FindBoolKey("bool")); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("int")); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("double")); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("string")); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("blob")); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("list")); + EXPECT_EQ(absl::nullopt, value.FindBoolKey("dict")); } TEST(ValuesTest, FindIntKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("null")); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("bool")); - EXPECT_NE(absl::nullopt, dict.FindIntKey("int")); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("double")); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("string")); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("blob")); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("list")); - EXPECT_EQ(absl::nullopt, dict.FindIntKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(absl::nullopt, value.FindIntKey("null")); + EXPECT_EQ(absl::nullopt, value.FindIntKey("bool")); + EXPECT_NE(absl::nullopt, value.FindIntKey("int")); + EXPECT_EQ(absl::nullopt, value.FindIntKey("double")); + EXPECT_EQ(absl::nullopt, value.FindIntKey("string")); + EXPECT_EQ(absl::nullopt, value.FindIntKey("blob")); + EXPECT_EQ(absl::nullopt, value.FindIntKey("list")); + EXPECT_EQ(absl::nullopt, value.FindIntKey("dict")); } TEST(ValuesTest, FindDoubleKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("null")); - EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("bool")); - EXPECT_NE(absl::nullopt, dict.FindDoubleKey("int")); - EXPECT_NE(absl::nullopt, dict.FindDoubleKey("double")); - EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("string")); - EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("blob")); - EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("list")); - EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(absl::nullopt, value.FindDoubleKey("null")); + EXPECT_EQ(absl::nullopt, value.FindDoubleKey("bool")); + EXPECT_NE(absl::nullopt, value.FindDoubleKey("int")); + EXPECT_NE(absl::nullopt, value.FindDoubleKey("double")); + EXPECT_EQ(absl::nullopt, value.FindDoubleKey("string")); + EXPECT_EQ(absl::nullopt, value.FindDoubleKey("blob")); + EXPECT_EQ(absl::nullopt, value.FindDoubleKey("list")); + EXPECT_EQ(absl::nullopt, value.FindDoubleKey("dict")); } TEST(ValuesTest, FindStringKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(nullptr, dict.FindStringKey("null")); - EXPECT_EQ(nullptr, dict.FindStringKey("bool")); - EXPECT_EQ(nullptr, dict.FindStringKey("int")); - EXPECT_EQ(nullptr, dict.FindStringKey("double")); - EXPECT_NE(nullptr, dict.FindStringKey("string")); - EXPECT_EQ(nullptr, dict.FindStringKey("blob")); - EXPECT_EQ(nullptr, dict.FindStringKey("list")); - EXPECT_EQ(nullptr, dict.FindStringKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(nullptr, value.FindStringKey("null")); + EXPECT_EQ(nullptr, value.FindStringKey("bool")); + EXPECT_EQ(nullptr, value.FindStringKey("int")); + EXPECT_EQ(nullptr, value.FindStringKey("double")); + EXPECT_NE(nullptr, value.FindStringKey("string")); + EXPECT_EQ(nullptr, value.FindStringKey("blob")); + EXPECT_EQ(nullptr, value.FindStringKey("list")); + EXPECT_EQ(nullptr, value.FindStringKey("dict")); } TEST(ValuesTest, MutableFindStringKey) { - Value::DictStorage storage; - storage.emplace("string", "foo"); - Value dict(std::move(storage)); + Value::Dict dict; + dict.Set("string", "foo"); + Value value(std::move(dict)); - *(dict.FindStringKey("string")) = "bar"; + *(value.FindStringKey("string")) = "bar"; - Value::DictStorage expected_storage; - expected_storage.emplace("string", "bar"); - Value expected_dict(std::move(expected_storage)); + Value::Dict expected_dict; + expected_dict.Set("string", "bar"); + Value expected_value(std::move(expected_dict)); - EXPECT_EQ(expected_dict, dict); + EXPECT_EQ(expected_value, value); } TEST(ValuesTest, FindDictKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(nullptr, dict.FindDictKey("null")); - EXPECT_EQ(nullptr, dict.FindDictKey("bool")); - EXPECT_EQ(nullptr, dict.FindDictKey("int")); - EXPECT_EQ(nullptr, dict.FindDictKey("double")); - EXPECT_EQ(nullptr, dict.FindDictKey("string")); - EXPECT_EQ(nullptr, dict.FindDictKey("blob")); - EXPECT_EQ(nullptr, dict.FindDictKey("list")); - EXPECT_NE(nullptr, dict.FindDictKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(nullptr, value.FindDictKey("null")); + EXPECT_EQ(nullptr, value.FindDictKey("bool")); + EXPECT_EQ(nullptr, value.FindDictKey("int")); + EXPECT_EQ(nullptr, value.FindDictKey("double")); + EXPECT_EQ(nullptr, value.FindDictKey("string")); + EXPECT_EQ(nullptr, value.FindDictKey("blob")); + EXPECT_EQ(nullptr, value.FindDictKey("list")); + EXPECT_NE(nullptr, value.FindDictKey("dict")); } TEST(ValuesTest, FindListKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(nullptr, dict.FindListKey("null")); - EXPECT_EQ(nullptr, dict.FindListKey("bool")); - EXPECT_EQ(nullptr, dict.FindListKey("int")); - EXPECT_EQ(nullptr, dict.FindListKey("double")); - EXPECT_EQ(nullptr, dict.FindListKey("string")); - EXPECT_EQ(nullptr, dict.FindListKey("blob")); - EXPECT_NE(nullptr, dict.FindListKey("list")); - EXPECT_EQ(nullptr, dict.FindListKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(nullptr, value.FindListKey("null")); + EXPECT_EQ(nullptr, value.FindListKey("bool")); + EXPECT_EQ(nullptr, value.FindListKey("int")); + EXPECT_EQ(nullptr, value.FindListKey("double")); + EXPECT_EQ(nullptr, value.FindListKey("string")); + EXPECT_EQ(nullptr, value.FindListKey("blob")); + EXPECT_NE(nullptr, value.FindListKey("list")); + EXPECT_EQ(nullptr, value.FindListKey("dict")); } TEST(ValuesTest, FindBlobKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - const Value dict(std::move(storage)); - EXPECT_EQ(nullptr, dict.FindBlobKey("null")); - EXPECT_EQ(nullptr, dict.FindBlobKey("bool")); - EXPECT_EQ(nullptr, dict.FindBlobKey("int")); - EXPECT_EQ(nullptr, dict.FindBlobKey("double")); - EXPECT_EQ(nullptr, dict.FindBlobKey("string")); - EXPECT_NE(nullptr, dict.FindBlobKey("blob")); - EXPECT_EQ(nullptr, dict.FindBlobKey("list")); - EXPECT_EQ(nullptr, dict.FindBlobKey("dict")); + const Value value(std::move(dict)); + EXPECT_EQ(nullptr, value.FindBlobKey("null")); + EXPECT_EQ(nullptr, value.FindBlobKey("bool")); + EXPECT_EQ(nullptr, value.FindBlobKey("int")); + EXPECT_EQ(nullptr, value.FindBlobKey("double")); + EXPECT_EQ(nullptr, value.FindBlobKey("string")); + EXPECT_NE(nullptr, value.FindBlobKey("blob")); + EXPECT_EQ(nullptr, value.FindBlobKey("list")); + EXPECT_EQ(nullptr, value.FindBlobKey("dict")); } TEST(ValuesTest, SetKey) { - Value::DictStorage storage; - storage.emplace("null", Value::Type::NONE); - storage.emplace("bool", Value::Type::BOOLEAN); - storage.emplace("int", Value::Type::INTEGER); - storage.emplace("double", Value::Type::DOUBLE); - storage.emplace("string", Value::Type::STRING); - storage.emplace("blob", Value::Type::BINARY); - storage.emplace("list", Value::Type::LIST); - storage.emplace("dict", Value::Type::DICTIONARY); + Value::Dict dict; + dict.Set("null", Value()); + dict.Set("bool", false); + dict.Set("int", 0); + dict.Set("double", 0.0); + dict.Set("string", std::string()); + dict.Set("blob", Value(Value::BlobStorage())); + dict.Set("list", Value::List()); + dict.Set("dict", Value::Dict()); - Value dict(Value::Type::DICTIONARY); - dict.SetKey(StringPiece("null"), Value(Value::Type::NONE)); - dict.SetKey(StringPiece("bool"), Value(Value::Type::BOOLEAN)); - dict.SetKey(std::string("int"), Value(Value::Type::INTEGER)); - dict.SetKey(std::string("double"), Value(Value::Type::DOUBLE)); - dict.SetKey(std::string("string"), Value(Value::Type::STRING)); - dict.SetKey("blob", Value(Value::Type::BINARY)); - dict.SetKey("list", Value(Value::Type::LIST)); - dict.SetKey("dict", Value(Value::Type::DICTIONARY)); + Value value(Value::Type::DICTIONARY); + value.SetKey(StringPiece("null"), Value(Value::Type::NONE)); + value.SetKey(StringPiece("bool"), Value(Value::Type::BOOLEAN)); + value.SetKey(std::string("int"), Value(Value::Type::INTEGER)); + value.SetKey(std::string("double"), Value(Value::Type::DOUBLE)); + value.SetKey(std::string("string"), Value(Value::Type::STRING)); + value.SetKey("blob", Value(Value::Type::BINARY)); + value.SetKey("list", Value(Value::Type::LIST)); + value.SetKey("dict", Value(Value::Type::DICTIONARY)); - EXPECT_EQ(Value(std::move(storage)), dict); + EXPECT_EQ(Value(std::move(dict)), value); } TEST(ValuesTest, SetBoolKey) { @@ -2462,9 +2503,10 @@ EXPECT_EQ(perfetto::TracedValueToString(Value(list)), "[2,3]"); } { - Value::DictStorage dict; - dict["key"] = Value("value"); - EXPECT_EQ(perfetto::TracedValueToString(Value(dict)), "{key:value}"); + Value::Dict dict; + dict.Set("key", "value"); + EXPECT_EQ(perfetto::TracedValueToString(Value(std::move(dict))), + "{key:value}"); } } #endif // BUILDFLAG(ENABLE_BASE_TRACING)
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 8782816a..973bffa 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -564,6 +564,7 @@ "//components/security_interstitials/content/android:java", "//components/security_state/content/android:java", "//components/security_state/core:security_state_enums_java", + "//components/segmentation_platform/content:content_java", "//components/segmentation_platform/public:public_java", "//components/send_tab_to_self:send_tab_to_self_java", "//components/signin/core/browser:signin_enums_java", @@ -1682,6 +1683,7 @@ "//third_party/androidx:androidx_collection_collection_java", "//third_party/androidx:androidx_preference_preference_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/androidx:androidx_viewpager2_viewpager2_java", "//third_party/androidx:androidx_viewpager_viewpager_java", "//third_party/blink/public:blink_headers_java", @@ -1694,7 +1696,6 @@ "//third_party/junit", "//third_party/metrics_proto:metrics_proto_java", "//third_party/mockito:mockito_java", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:clipboard_java_test_support", "//ui/android:ui_java", "//ui/android:ui_java_test_support", @@ -1801,8 +1802,8 @@ "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_browser_browser_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:ui_java", ] @@ -3282,9 +3283,9 @@ "//content/public/test/android:content_java_test_support", "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/hamcrest:hamcrest_library_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", ] } @@ -3932,6 +3933,8 @@ "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java", "java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java", + "java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java", + "java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java", "java/src/org/chromium/chrome/browser/datareduction/DataSaverOSSetting.java", "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java", "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 8791057..920ff8b5 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -477,6 +477,7 @@ "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityModule.java", "java/src/org/chromium/chrome/browser/customtabs/features/CustomTabNavigationBarController.java", "java/src/org/chromium/chrome/browser/customtabs/features/ImmersiveModeController.java", + "java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java", "java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabBrowserControlsVisibilityDelegate.java", "java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java", "java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarAnimationDelegate.java", @@ -981,6 +982,7 @@ "java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java", "java/src/org/chromium/chrome/browser/searchwidget/SearchType.java", "java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java", + "java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java", "java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerServiceImpl.java", "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundServiceImpl.java", "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundTask.java",
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java index f93665a..c7386047 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
@@ -27,7 +27,6 @@ import android.content.Intent; import android.graphics.Bitmap; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import android.util.Base64; import android.view.View; import android.view.ViewGroup; @@ -37,6 +36,7 @@ import androidx.test.espresso.ViewAction; import androidx.test.espresso.contrib.RecyclerViewActions; import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.uiautomator.UiDevice; import org.hamcrest.Matcher; import org.junit.Assert;
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java index cb5ccaca..426b51d 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -54,7 +54,6 @@ import android.os.Build; import android.os.Build.VERSION_CODES; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import android.view.View; import android.widget.ImageView; @@ -68,6 +67,7 @@ import androidx.test.espresso.contrib.AccessibilityChecks; import androidx.test.espresso.contrib.RecyclerViewActions; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; import org.hamcrest.Matcher; import org.hamcrest.Matchers;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java index 36a8688..adb9627 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -11,6 +11,7 @@ import android.graphics.Rect; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.ImageView; @@ -84,6 +85,7 @@ private boolean mIsInitialized; private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener; + private OnLayoutChangeListener mListLayoutListener; /** * Construct a coordinator for UI that shows a list of tabs. @@ -259,7 +261,11 @@ } if (mMode == TabListMode.GRID && selectionDelegateProvider == null) { - mGlobalLayoutListener = this::updateThumbnailAndSpanCount; + mGlobalLayoutListener = this::updateThumbnailLocation; + if (TabUiFeatureUtilities.isTabletGridTabSwitcherEnabled(mContext)) { + mListLayoutListener = (view, left, top, right, bottom, oldLeft, oldTop, oldRight, + oldBottom) -> updateGridCardLayout(right - left); + } } } @@ -311,23 +317,19 @@ return true; } - private void updateThumbnailAndSpanCount() { - updateThumbnailLocation(); - if (mMode == TabListMode.GRID - && TabUiFeatureUtilities.isTabletGridTabSwitcherEnabled(mContext)) { - // Determine and set span count - final GridLayoutManager layoutManager = - (GridLayoutManager) mRecyclerView.getLayoutManager(); - mMediator.updateSpanCount(layoutManager, - mContext.getResources().getConfiguration().orientation, - mContext.getResources().getConfiguration().screenWidthDp); - // Determine grid card width and account for margins on left and right. - final int cardWidthPx = (layoutManager.getWidth() / layoutManager.getSpanCount()); - final int cardHeightPx = TabUtils.deriveGridCardHeight(cardWidthPx, mContext); - for (int i = 0; i < mModel.size(); i++) { - mModel.get(i).model.set(TabProperties.GRID_CARD_WIDTH, cardWidthPx); - mModel.get(i).model.set(TabProperties.GRID_CARD_HEIGHT, cardHeightPx); - } + private void updateGridCardLayout(int viewWidth) { + // Determine and set span count + final GridLayoutManager layoutManager = + (GridLayoutManager) mRecyclerView.getLayoutManager(); + mMediator.updateSpanCount(layoutManager, + mContext.getResources().getConfiguration().orientation, + mContext.getResources().getConfiguration().screenWidthDp); + // Determine grid card width and account for margins on left and right. + final int cardWidthPx = (viewWidth / layoutManager.getSpanCount()); + final int cardHeightPx = TabUtils.deriveGridCardHeight(cardWidthPx, mContext); + for (int i = 0; i < mModel.size(); i++) { + mModel.get(i).model.set(TabProperties.GRID_CARD_WIDTH, cardWidthPx); + mModel.get(i).model.set(TabProperties.GRID_CARD_HEIGHT, cardHeightPx); } } @@ -394,6 +396,9 @@ if (mGlobalLayoutListener != null) { mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener); } + if (mListLayoutListener != null) { + mRecyclerView.addOnLayoutChangeListener(mListLayoutListener); + } mRecyclerView.prepareTabSwitcherView(); mMediator.prepareTabSwitcherView(); } @@ -402,6 +407,9 @@ if (mGlobalLayoutListener != null) { mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener); } + if (mListLayoutListener != null) { + mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener); + } mRecyclerView.postHiding(); mMediator.postHiding(); } @@ -415,6 +423,9 @@ if (mGlobalLayoutListener != null) { mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener); } + if (mListLayoutListener != null) { + mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener); + } mRecyclerView.setRecyclerListener(null); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java index 6b0bca6a..f7deb3f2 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java
@@ -28,7 +28,6 @@ import android.os.Build; import android.provider.Settings; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -36,6 +35,7 @@ import androidx.test.espresso.NoMatchingRootException; import androidx.test.espresso.intent.Intents; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; import org.junit.After; import org.junit.Before;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java index 4d60f61..796b2d3 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
@@ -33,7 +33,6 @@ import android.content.res.Configuration; import android.graphics.drawable.Animatable; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -42,6 +41,7 @@ import androidx.test.espresso.NoMatchingRootException; import androidx.test.espresso.contrib.RecyclerViewActions; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; import org.junit.After; import org.junit.Before;
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS index e746f0c2..ac2385a 100644 --- a/chrome/android/java/DEPS +++ b/chrome/android/java/DEPS
@@ -56,6 +56,7 @@ "+components/permissions/android/java/src/org/chromium/components/permissions", "+components/search_engines/android/java/src/org/chromium/components/search_engines", "+components/security_state/content/android/java", + "+components/segmentation_platform/content/android/java", "+components/segmentation_platform/public/android/java", "+components/sync/android/java/src/org/chromium/components/sync", "+components/query_tiles/android/java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java index cda122dc..a2c28b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -433,6 +433,11 @@ mActivity.getApplicationContext().getPackageName(), targetActivityClassName); newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS); + + if ((mIntent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0) { + newIntent.setFlags(newIntent.getFlags() | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + } + Uri uri = newIntent.getData(); boolean isContentScheme = false; if (uri != null && UrlConstants.CONTENT_SCHEME.equals(uri.getScheme())) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 5b98383..b81362d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -90,8 +90,8 @@ protected BaseCustomTabActivityComponent createComponent( ChromeActivityCommonsModule commonsModule) { BaseCustomTabActivityComponent component = super.createComponent(commonsModule); - mOpenTimeRecorder = new CustomTabsOpenTimeRecorder( - getLifecycleDispatcher(), mNavigationController, this::isFinishing); + mOpenTimeRecorder = new CustomTabsOpenTimeRecorder(getLifecycleDispatcher(), + mNavigationController, this::isFinishing, mIntentDataProvider); return component; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java index 8a58f6a5..ab17b3d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
@@ -19,7 +19,9 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.customtabs.features.TabInteractionRecorder; import org.chromium.chrome.browser.dependency_injection.ActivityScope; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabHidingType; @@ -191,6 +193,23 @@ if (isFirstMainFrameCommit) mFirstCommitTimestamp = SystemClock.elapsedRealtime(); } + @Override + public void onClosingStateChanged(Tab tab, boolean closing) { + if (!closing) return; + + if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_RETAINING_STATE)) { + TabInteractionRecorder observer = TabInteractionRecorder.getFromTab(tab); + if (observer != null) observer.onTabClosing(); + } + } + + @Override + public void onShown(Tab tab, int type) { + if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_RETAINING_STATE)) { + TabInteractionRecorder.createForTab(tab); + } + } + public void onFirstMeaningfulPaint(Tab tab) { mNavigationInfoCaptureTrigger.onFirstMeaningfulPaint(tab); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java index d7a0a458..6bb9a92e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java
@@ -5,11 +5,14 @@ package org.chromium.chrome.browser.customtabs; import android.os.SystemClock; +import android.text.format.DateUtils; import androidx.annotation.IntDef; +import org.chromium.base.annotations.NativeMethods; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.BooleanSupplier; +import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -35,6 +38,7 @@ class CustomTabsOpenTimeRecorder implements StartStopWithNativeObserver { private final CustomTabActivityNavigationController mNavigationController; private final BooleanSupplier mIsCctFinishing; + private final BrowserServicesIntentDataProvider mIntent; private long mOnStartTimestampMs; @@ -53,10 +57,11 @@ public CustomTabsOpenTimeRecorder(ActivityLifecycleDispatcher lifecycleDispatcher, CustomTabActivityNavigationController navigationController, - BooleanSupplier isCctFinishing) { + BooleanSupplier isCctFinishing, BrowserServicesIntentDataProvider intent) { lifecycleDispatcher.register(this); mNavigationController = navigationController; mIsCctFinishing = isCctFinishing; + mIntent = intent; } @Override @@ -71,13 +76,30 @@ RecordHistogram.recordEnumeratedHistogram( "CustomTabs.CloseCause", mCloseCause, CloseCause.COUNT); + long duration = SystemClock.elapsedRealtime() - mOnStartTimestampMs; // Additional check with |mIsCctFinishing| can eliminate some false positives. // See Javadoc for more details. if (mCloseCause == CloseCause.AUTOCLOSE && mIsCctFinishing.getAsBoolean()) { - long duration = SystemClock.elapsedRealtime() - mOnStartTimestampMs; RecordHistogram.recordLongTimesHistogram( "CustomTabs.AutoclosedSessionDuration", duration); } + + if (mIsCctFinishing.getAsBoolean()) { + long time = System.currentTimeMillis() / DateUtils.SECOND_IN_MILLIS; + String packageName = mIntent.getClientPackageName(); + // TODO(crbug.com/1334500): add tracking didUserInteract. + boolean wasUserClose = mCloseCause != CloseCause.AUTOCLOSE; + boolean isPartial = mIntent.isPartialHeightCustomTab(); + + long recordDuration = Math.min(duration / DateUtils.SECOND_IN_MILLIS, 300); + // For the real implementation, there'll be a native method on this class or a new + // class entirely. Just for the proof-of-concept I tacked the native method onto another + // class that already have natives. + CustomTabsOpenTimeRecorderJni.get().recordCustomTabSession(time, + (packageName != null ? packageName : ""), recordDuration, wasUserClose, + isPartial); + } + mOnStartTimestampMs = 0; } @@ -90,4 +112,10 @@ void onUserLeaveHint() { mCloseCause = CloseCause.USER_ACTION_ANDROID; } + + @NativeMethods + interface Natives { + void recordCustomTabSession(long time, String packageName, long sessionDuration, + boolean wasAutomaticallyClosed, boolean isPartialCct); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java index 7b0a1d8..d274372 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
@@ -717,6 +717,12 @@ return getFullyExpandedYCoordinate() + mFullyExpandedAdjustmentHeight; } + @Override + public boolean changeBackgroundColorForResizing() { + // Need to return true to keep the transparent background we set in the init step. + return true; + } + @VisibleForTesting void setMockViewForTesting(LinearLayout navbar, ImageView spinnerView, CircularProgressDrawable spinner, View toolbar, View toolbarCoordinator,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java new file mode 100644 index 0000000..7f36027 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java
@@ -0,0 +1,94 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.customtabs.features; + +import android.os.SystemClock; + +import androidx.annotation.Nullable; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; +import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.chrome.browser.tab.Tab; + +import java.util.Locale; + +/** + * Class used to monitor interactions for the current custom tab. This class is created in native + * and owned by C++ object. This class has the ability to record whether the current web content has + * seen interaction when the tab is closing, as well as the timestamp when this happens. + * + * Note that this object's lifecycle is bounded to a {@link WebContents} but not a {@link Tab}. To + * observe the first frame of tab load, this recorder has to attach to the web content before the + * first navigation for the visible frame finishes, or a pre-rendered frame become active. + * */ +@JNINamespace("customtabs") +public class TabInteractionRecorder { + private static final String TAG = "CctInteraction"; + + private final long mNativeTabInteractionRecorder; + + // Do not instantiate in Java. + private TabInteractionRecorder(long nativePtr) { + mNativeTabInteractionRecorder = nativePtr; + } + + @CalledByNative + private static @Nullable TabInteractionRecorder create(long nativePtr) { + if (nativePtr == 0) return null; + return new TabInteractionRecorder(nativePtr); + } + + /** + * Get the TabInteractionRecorder that lives in the main web contents of the given tab. + * Note that the object might be come stale if the web contents of the given tab is swapped + * after this function is called. + * */ + public static @Nullable TabInteractionRecorder getFromTab(Tab tab) { + return TabInteractionRecorderJni.get().getFromTab(tab); + } + + /** + * Create a TabInteractionRecorder and start observing the web contents in the given tab. If an + * observer already exists for the tab, do nothing. + */ + public static void createForTab(Tab tab) { + TabInteractionRecorderJni.get().createForTab(tab); + } + + /** + * Notify this recorder tab is being closed. Record whether this instance has seen any + * interaction, and the timestamp when the tab is closed, into SharedPreferences. + * + * This class works correctly assuming there will be only one tab opened throughout the lifetime + * of a given CCT session. If CCT ever changed into serving multiple tabs, this recorder will + * only works for the last tab being closed. + */ + public void onTabClosing() { + long timestamp = SystemClock.uptimeMillis(); + boolean hadInteraction = + TabInteractionRecorderJni.get().hadInteraction(mNativeTabInteractionRecorder); + + Log.d(TAG, + String.format(Locale.US, + "timestamp=%d, TabInteractionRecorder.recordInteractions=%b", timestamp, + hadInteraction)); + + SharedPreferencesManager pref = SharedPreferencesManager.getInstance(); + pref.writeLong(ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP, timestamp); + pref.writeBoolean( + ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION, hadInteraction); + } + + @NativeMethods + interface Natives { + TabInteractionRecorder getFromTab(Tab tab); + TabInteractionRecorder createForTab(Tab tab); + boolean hadInteraction(long nativeTabInteractionRecorderAndroid); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java index c3404fde..5eb9a4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
@@ -244,7 +244,7 @@ /** * Creates and returns an {@link Intent} that instantiates a new Chrome instance. - * @param activity The activity firing the intent. + * @param context The application context of the activity firing the intent. * @param instanceId ID of the new Chrome instance to be created. * @param preferNew {@code true} if the new instance should be instanted as a fresh * new one not loading any tabs from a persistent disk file. @@ -253,9 +253,9 @@ * @return The created intent. */ public static Intent createNewWindowIntent( - Activity activity, int instanceId, boolean preferNew, boolean openAdjacently) { + Context context, int instanceId, boolean preferNew, boolean openAdjacently) { assert instanceSwitcherEnabled(); - Intent intent = new Intent(activity, ChromeTabbedActivity.class); + Intent intent = new Intent(context, ChromeTabbedActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); if (instanceId != INVALID_INSTANCE_ID) { @@ -263,7 +263,7 @@ } if (preferNew) intent.putExtra(IntentHandler.EXTRA_PREFER_NEW, true); if (openAdjacently) intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName()); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); IntentUtils.addTrustedIntentExtras(intent); return intent; @@ -587,6 +587,11 @@ String.valueOf(index)); } + /** + * Read the time when an instance was last accessed. + * @param index Instance ID + * @return The time when the instance was last accessed. + */ static long readLastAccessedTime(int index) { return SharedPreferencesManager.getInstance().readLong(lastAccessedTimeKey(index)); } @@ -754,4 +759,23 @@ isInMultiWindowMode(activity) ? MultiWindowState.MULTI_WINDOW : MultiWindowState.SINGLE_WINDOW); } + + /** + * @return The instance ID of the Chrome window that was accessed last if the maximum number of + * instances is open. If fewer than the maximum number is open, the default ID will be + * returned, indicative of an unused window ID that can be potentially allocated to + * launch a VIEW intent. + */ + public static int getInstanceIdForViewIntent() { + int windowId = MultiWindowUtils.INVALID_INSTANCE_ID; + int maxInstances = MultiWindowUtils.getMaxInstances(); + if (MultiWindowUtils.getInstanceCount() < maxInstances) return windowId; + for (int i = 0; i < maxInstances; i++) { + if (MultiWindowUtils.readLastAccessedTime(i) + > MultiWindowUtils.readLastAccessedTime(windowId)) { + windowId = i; + } + } + return windowId; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java new file mode 100644 index 0000000..b9dd3c6 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
@@ -0,0 +1,78 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.segmentation_platform; + +import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabUtils; +import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonController; +import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures; +import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor; +import org.chromium.components.segmentation_platform.OnDemandSegmentSelectionResult; +import org.chromium.components.segmentation_platform.PageLoadTriggerContext; +import org.chromium.components.segmentation_platform.SegmentationPlatformService; +import org.chromium.content_public.browser.WebContents; + +/** + * Central class for contextual page actions bridging between UI and backend. Registers itself with + * segmentation platform for on-demand model execution on page load triggers. Provides updated + * button data to the toolbar when asked for it. + */ +public class ContextualPageActionController { + private static final String CONTEXTUAL_PAGE_ACTION_SEGMENTATION_KEY = "contextual_page_action"; + + private SegmentationPlatformService mSegmentationPlatformService; + private final ObservableSupplier<Tab> mTabSupplier; + private final AdaptiveToolbarButtonController mAdaptiveToolbarButtonController; + private int mSegmentSelectionCallbackId; + + /** + * Constructor. + * @param profileSupplier The supplier for current profile. + * @param tabSupplier The supplier of the current tab. + * @param adaptiveToolbarButtonController The {@link AdaptiveToolbarButtonController} that + * handles the logic to decide between multiple buttons to show. + */ + public ContextualPageActionController(ObservableSupplier<Profile> profileSupplier, + ObservableSupplier<Tab> tabSupplier, + AdaptiveToolbarButtonController adaptiveToolbarButtonController) { + mTabSupplier = tabSupplier; + mAdaptiveToolbarButtonController = adaptiveToolbarButtonController; + profileSupplier.addObserver(profile -> { + if (profile.isOffTheRecord()) return; + if (!AdaptiveToolbarFeatures.isContextualPageActionUiEnabled()) return; + + mSegmentationPlatformService = + SegmentationPlatformServiceFactory.getForProfile(profile); + mSegmentSelectionCallbackId = + mSegmentationPlatformService.registerOnDemandSegmentSelectionCallback( + CONTEXTUAL_PAGE_ACTION_SEGMENTATION_KEY, + this::onSegmentSelectionResult); + }); + } + + /** Called on destroy. */ + public void destroy() { + if (mSegmentationPlatformService == null) return; + mSegmentationPlatformService.unregisterOnDemandSegmentSelectionCallback( + CONTEXTUAL_PAGE_ACTION_SEGMENTATION_KEY, mSegmentSelectionCallbackId); + } + + private void onSegmentSelectionResult(OnDemandSegmentSelectionResult result) { + if (result == null || !(result.triggerContext instanceof PageLoadTriggerContext)) return; + WebContents webContents = ((PageLoadTriggerContext) result.triggerContext).webContents; + Tab processedTab = webContents == null || webContents.isDestroyed() + ? null + : TabUtils.fromWebContents(webContents); + Tab currentTab = mTabSupplier.get(); + boolean isSameTab = currentTab != null && processedTab != null + && currentTab.getId() == processedTab.getId(); + if (!isSameTab) return; + mAdaptiveToolbarButtonController.showDynamicAction( + AdaptiveToolbarStatePredictor.getAdaptiveToolbarButtonVariantFromSegmentId( + result.segmentSelectionResult.selectedSegment)); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS index aa5139c..94c8cc9e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -22,6 +22,7 @@ "+chrome/browser/usb/android/java/src/org/chromium/chrome/browser/usb/UsbNotificationManager.java", "+chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureNotificationServiceImpl.java", "+chrome/android/java/src/org/chromium/chrome/browser/metrics/UkmRecorder.java", + "+chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java", "+chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java", "+chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java", "+chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageOrigin.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java index f0441e6..9934fc8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
@@ -5,6 +5,8 @@ package org.chromium.chrome.browser.tab; import android.app.Activity; +import android.content.Intent; +import android.net.Uri; import android.os.Build; import android.os.Build.VERSION; import android.view.DragAndDropPermissions; @@ -17,6 +19,8 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.components.embedder_support.view.ContentView; import org.chromium.content_public.browser.ContentFeatureList; import org.chromium.content_public.browser.RenderWidgetHostView; @@ -57,7 +61,7 @@ boolean supportDropInChrome = ContentFeatureList.getFieldTrialParamByFeatureAsBoolean( ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, PARAM_DROP_IN_CHROME, false); - if (VERSION.SDK_INT >= Build.VERSION_CODES.N && supportDropInChrome) { + if (VERSION.SDK_INT >= Build.VERSION_CODES.N) { DragAndDropBrowserDelegate browserDelegate = new DragAndDropBrowserDelegateImpl(mTab, supportDropInChrome); getDragAndDropDelegate().setDragAndDropBrowserDelegate(browserDelegate); @@ -194,5 +198,17 @@ } return activity.requestDragAndDropPermissions(dropEvent); } + + @Override + public Intent createLinkIntent(String urlString) { + Intent intent = null; + if (ChromeFeatureList.isEnabled(ChromeFeatureList.NEW_INSTANCE_FROM_DRAGGED_LINK)) { + intent = MultiWindowUtils.createNewWindowIntent( + mTab.getContext().getApplicationContext(), + MultiWindowUtils.getInstanceIdForViewIntent(), true, false); + intent.setData(Uri.parse(urlString)); + } + return intent; + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java index 61f49f8..9280b87d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -94,6 +94,7 @@ import org.chromium.chrome.browser.price_tracking.PriceTrackingButtonController; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; +import org.chromium.chrome.browser.segmentation_platform.ContextualPageActionController; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; import org.chromium.chrome.browser.share.ShareButtonController; import org.chromium.chrome.browser.share.ShareDelegate; @@ -236,6 +237,7 @@ private List<ButtonDataProvider> mButtonDataProviders; @Nullable private AdaptiveToolbarButtonController mAdaptiveToolbarButtonController; + private ContextualPageActionController mContextualPageActionController; private IdentityDiscController mIdentityDiscController; private ChromeActionModeHandler mChromeActionModeHandler; private final ToolbarActionModeCallback mActionModeControllerCallback; @@ -541,6 +543,11 @@ mToolbarManager = null; } + if (mContextualPageActionController != null) { + mContextualPageActionController.destroy(); + mContextualPageActionController = null; + } + if (mAdaptiveToolbarButtonController != null) { mAdaptiveToolbarButtonController.destroy(); mAdaptiveToolbarButtonController = null; @@ -1098,6 +1105,8 @@ AdaptiveToolbarButtonVariant.VOICE, voiceToolbarButtonController); adaptiveToolbarButtonController.addButtonVariant( AdaptiveToolbarButtonVariant.PRICE_TRACKING, priceTrackingButtonController); + mContextualPageActionController = new ContextualPageActionController( + mProfileSupplier, mActivityTabProvider, adaptiveToolbarButtonController); mButtonDataProviders = Arrays.asList(mIdentityDiscController, adaptiveToolbarButtonController);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 9ccb1ba..60dbd9e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -105,6 +105,8 @@ import org.chromium.chrome.browser.history.HistoryItem; import org.chromium.chrome.browser.history.TestBrowsingHistoryObserver; import org.chromium.chrome.browser.metrics.PageLoadMetrics; +import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -222,6 +224,11 @@ public void tearDown() { TestThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(false)); + SharedPreferencesManager.getInstance().removeKey( + ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION); + SharedPreferencesManager.getInstance().removeKey( + ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP); + stopAndShutdownEmbeddedTestServer(); // finish() is called on a non-UI thread by the testing harness. Must hide the menu @@ -1343,6 +1350,29 @@ "No new spare renderer", 2000, 200); } + @Test + @SmallTest + @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) + @Features.EnableFeatures(ChromeFeatureList.CCT_RETAINING_STATE) + public void testInteractionRecordedOnClose() throws Exception { + Context context = InstrumentationRegistry.getInstrumentation() + .getTargetContext() + .getApplicationContext(); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent( + CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage)); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + final CustomTabActivity activity = mCustomTabActivityTestRule.getActivity(); + activity.getComponent().resolveNavigationController().finish(FinishReason.OTHER); + }); + CriteriaHelper.pollUiThread( + () + -> SharedPreferencesManager.getInstance().contains( + ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION) + && SharedPreferencesManager.getInstance().contains( + ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP)); + } + /** * Tests that hidden tab accepts a referrer, and that this is not lost when launching the * Custom Tab.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java index 7f06505..2ee28ec 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java
@@ -5,9 +5,9 @@ package org.chromium.chrome.browser.metrics; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; import org.junit.Assert; import org.junit.Before;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java index d591d72..90dea8e2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java
@@ -5,9 +5,9 @@ package org.chromium.chrome.browser.paint_preview; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; import org.junit.Assert; import org.junit.Rule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java index e5a6e24..013c818 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java
@@ -14,10 +14,10 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import android.view.View; import androidx.test.filters.SmallTest; +import androidx.test.uiautomator.UiDevice; import org.junit.Assert; import org.junit.Before;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java index 3279a4c..d1224b0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
@@ -9,15 +9,15 @@ import android.os.Build; import android.service.notification.StatusBarNotification; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiSelector; import android.text.TextUtils; import android.view.View; import androidx.annotation.RequiresApi; import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiSelector; import org.hamcrest.Matchers; import org.junit.After;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java index a8aae44..83d098e3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
@@ -16,7 +16,8 @@ import android.graphics.Point; import android.os.Build; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; + +import androidx.test.uiautomator.UiDevice; import org.json.JSONArray; import org.json.JSONException;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java index 8ba4bb5..9b18d3e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -19,9 +19,9 @@ import android.graphics.Color; import android.os.Build; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiDevice; import org.junit.Assert; import org.junit.Before;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java index f59a8ed..23c6d7e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
@@ -7,7 +7,8 @@ import android.content.Intent; import android.os.SystemClock; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; + +import androidx.test.uiautomator.UiDevice; import org.junit.Assert; import org.junit.rules.RuleChain;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java index 2dcbfe2..7f08a64 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java
@@ -4,9 +4,13 @@ package org.chromium.chrome.browser.history_clusters; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; +import android.app.Activity; import android.content.Intent; import android.view.ViewGroup; @@ -27,6 +31,7 @@ import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.chromium.base.Promise; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.JniMocker; @@ -81,6 +86,8 @@ private ActivityScenario<ChromeTabbedActivity> mActivityScenario; private HistoryClustersCoordinator mHistoryClustersCoordinator; private Intent mIntent = new Intent(); + private Activity mActivity; + private Promise mPromise = new Promise(); @Before public void setUp() { @@ -88,6 +95,7 @@ jniMocker.mock(LargeIconBridgeJni.TEST_HOOKS, mMockLargeIconBridgeJni); doReturn(1L).when(mMockLargeIconBridgeJni).init(); ShadowHistoryClustersBridge.sBridge = mHistoryClustersBridge; + doReturn(mPromise).when(mHistoryClustersBridge).queryClusters(anyString()); mActivityScenario = ActivityScenario.launch(ChromeTabbedActivity.class); HistoryClustersDelegate historyClustersDelegate = new HistoryClustersDelegate() { @@ -117,9 +125,11 @@ } }; - mActivityScenario.onActivity(activity - -> mHistoryClustersCoordinator = new HistoryClustersCoordinator( - mProfile, activity, mTemplateUrlService, historyClustersDelegate)); + mActivityScenario.onActivity(activity -> { + mActivity = activity; + mHistoryClustersCoordinator = new HistoryClustersCoordinator( + mProfile, activity, mTemplateUrlService, historyClustersDelegate); + }); } @After @@ -140,6 +150,30 @@ assertNotNull(toolbar); } + @Test + public void testSearchMenuItem() { + HistoryClustersToolbar toolbar = mHistoryClustersCoordinator.getActivityContentView() + .findViewById(R.id.selectable_list) + .findViewById(R.id.action_bar); + assertNotNull(toolbar); + + mHistoryClustersCoordinator.onMenuItemClick( + toolbar.getMenu().findItem(R.id.search_menu_id)); + assertTrue(toolbar.isSearching()); + } + + @Test + public void testCloseMenuItem() { + HistoryClustersToolbar toolbar = mHistoryClustersCoordinator.getActivityContentView() + .findViewById(R.id.selectable_list) + .findViewById(R.id.action_bar); + assertNotNull(toolbar); + + assertFalse(mActivity.isFinishing()); + mHistoryClustersCoordinator.onMenuItemClick(toolbar.getMenu().findItem(R.id.close_menu_id)); + assertTrue(mActivity.isFinishing()); + } + private static void resetStaticState() { DisplayAndroidManager.resetInstanceForTesting(); TabWindowManagerSingleton.resetTabModelSelectorFactoryForTesting();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java index d9e9b26..4f725e6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java
@@ -139,6 +139,41 @@ assertEquals(2, MultiWindowUtils.getInstanceCount()); } + @Test + public void testGetInstanceIdForViewIntent_LesserThanMaxWindowsOpen() { + when(mTabModelSelector.getModel(false)).thenReturn(mNormalTabModel); + when(mTabModelSelector.getModel(true)).thenReturn(mIncognitoTabModel); + + int maxInstances = MultiWindowUtils.getMaxInstances(); + // Simulate opening of 1 less than the max number of instances. + for (int i = 0; i < maxInstances - 1; i++) { + writeInstanceInfo(i, URL_1, /*tabCount=*/3, /*incognitoTabCount=*/0, i + 5); + } + + int instanceId = MultiWindowUtils.getInstanceIdForViewIntent(); + assertEquals("The default instance ID should be returned.", + MultiWindowUtils.INVALID_INSTANCE_ID, instanceId); + } + + @Test + public void testGetInstanceIdForViewIntent_MaxWindowsOpen() { + when(mTabModelSelector.getModel(false)).thenReturn(mNormalTabModel); + when(mTabModelSelector.getModel(true)).thenReturn(mIncognitoTabModel); + + int maxInstances = MultiWindowUtils.getMaxInstances(); + // Simulate opening of max number of instances. + for (int i = 0; i < maxInstances; i++) { + writeInstanceInfo(i, URL_1, /*tabCount=*/3, /*incognitoTabCount=*/0, i + 5); + } + + // Simulate last access of instance ID 0. + writeInstanceInfo(INSTANCE_ID_0, URL_1, /*tabCount=*/3, /*incognitoTabCount=*/0, TASK_ID_5); + + int instanceId = MultiWindowUtils.getInstanceIdForViewIntent(); + assertEquals( + "The last accessed instance ID should be returned.", INSTANCE_ID_0, instanceId); + } + private void writeInstanceInfo( int instanceId, String url, int tabCount, int incognitoTabCount, int taskId) { MultiInstanceManagerApi31.writeUrl(instanceId, url);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java index 4e5d3ec..7c20894 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java
@@ -11,10 +11,14 @@ import static org.mockito.Mockito.when; import android.app.Activity; +import android.content.Intent; +import android.net.Uri; import android.os.Build; import android.view.DragAndDropPermissions; import android.view.DragEvent; +import androidx.test.core.app.ApplicationProvider; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,12 +26,16 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; import org.robolectric.annotation.LooperMode; import org.chromium.base.FeatureList; import org.chromium.base.FeatureList.TestValues; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.IntentHandler; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.TabViewAndroidDelegate.DragAndDropBrowserDelegateImpl; import org.chromium.components.embedder_support.view.ContentView; import org.chromium.content_public.browser.WebContents; @@ -35,6 +43,7 @@ import org.chromium.ui.base.ApplicationViewportInsetSupplier; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.dragdrop.DragAndDropBrowserDelegate; +import org.chromium.url.JUnitTestGURLs; /** Unit tests for the TabViewAndroidDelegate. */ @RunWith(BaseRobolectricTestRunner.class) @@ -82,11 +91,15 @@ when(mTab.getWindowAndroid()).thenReturn(mWindowAndroid); when(mTab.getWebContents()).thenReturn(mWebContents); when(mTab.getContext()).thenReturn(mActivity); + when(mActivity.getApplicationContext()) + .thenReturn(ApplicationProvider.getApplicationContext()); when(mActivity.requestDragAndDropPermissions(mDragEvent)) .thenReturn(mDragAndDropPermissions); FeatureList.TestValues testValues = new TestValues(); testValues.addFeatureFlagOverride(ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, false); + testValues.addFeatureFlagOverride(ChromeFeatureList.INSTANCE_SWITCHER, true); + testValues.addFeatureFlagOverride(ChromeFeatureList.NEW_INSTANCE_FROM_DRAGGED_LINK, true); FeatureList.setTestValues(testValues); mViewAndroidDelegate = new TabViewAndroidDelegate(mTab, mContentView); verify(mTab).addObserver(mTabObserverCaptor.capture()); @@ -129,7 +142,7 @@ } @Test - public void testDragAndDropBrowserDelegate() { + public void testDragAndDropBrowserDelegate_getDragAndDropPermissions() { DragAndDropBrowserDelegate delegate = new DragAndDropBrowserDelegateImpl(mTab, true); assertTrue("SupportDropInChrome should be true.", delegate.getSupportDropInChrome()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { @@ -137,4 +150,20 @@ assertNotNull("DragAndDropPermissions should not be null.", permissions); } } + + @Test + @Config(sdk = 30) + public void testDragAndDropBrowserDelegate_createLinkIntent() { + DragAndDropBrowserDelegate delegate = new DragAndDropBrowserDelegateImpl(mTab, true); + Intent intent = delegate.createLinkIntent(JUnitTestGURLs.EXAMPLE_URL); + assertEquals("The intent flags should match.", + Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK, + intent.getFlags()); + assertEquals("The intent class should be ChromeTabbedActivity.", + ChromeTabbedActivity.class.getName(), intent.getComponent().getClassName()); + assertTrue("preferNew extra should be true.", + intent.getBooleanExtra(IntentHandler.EXTRA_PREFER_NEW, false)); + assertEquals("The intent should contain Uri data.", Uri.parse(JUnitTestGURLs.EXAMPLE_URL), + intent.getData()); + } }
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index 47efe5f..d2928a0 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -123,6 +123,7 @@ #define IDC_VIRTUAL_CARD_ENROLL 35032 #define IDC_FOLLOW 35033 #define IDC_UNFOLLOW 35034 +#define IDC_BASIC_PRINT_DEPRECATED 35035 // Page-manipulation commands that target a specified tab, which may not be the // active one.
diff --git a/chrome/app/printing_strings.grdp b/chrome/app/printing_strings.grdp index b70cab2..ae15f300 100644 --- a/chrome/app/printing_strings.grdp +++ b/chrome/app/printing_strings.grdp
@@ -338,7 +338,7 @@ </if> <if expr="not chromeos_ash and not chromeos_lacros"> <message name="IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION" desc="Option allowing the user to access advanced printer settings using the native print system dialog instead of printing through the print preview mechanism. Shortcut key is not translated"> - Print using system dialog... <ph name="SHORTCUT_KEY">$1<ex>(Shift+Ctrl+P)</ex></ph> + Print using system dialog... <ph name="SHORTCUT_KEY">$1<ex>(Ctrl+Alt+P)</ex></ph> </message> </if> <if expr="is_macosx"> @@ -361,4 +361,7 @@ <message name="IDS_PRINT_SPOOL_FAILED_ERROR_TEXT" desc="Text in a messagebox when printing fails because of printer issues."> Something went wrong when trying to print. Please check your printer and try again. </message> + <message name="IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT" desc="Notification to tell users about the deprecation of the Ctrl+Shift+P for printing via the system dialog. Shortcut keys are not translated"> + This shortcut has changed. Please use <ph name="NEW_SHORTCUT_KEY">$1<ex>(Ctrl+Alt+P)</ex></ph> to print using system dialog. + </message> </grit-part>
diff --git a/chrome/app/printing_strings_grdp/IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT.png.sha1 b/chrome/app/printing_strings_grdp/IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT.png.sha1 new file mode 100644 index 0000000..e32a872 --- /dev/null +++ b/chrome/app/printing_strings_grdp/IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT.png.sha1
@@ -0,0 +1 @@ +23847c4846637584e6773babe07944bec69c6ac8 \ No newline at end of file
diff --git a/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION.png.sha1 b/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION.png.sha1 new file mode 100644 index 0000000..58a59de5 --- /dev/null +++ b/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION.png.sha1
@@ -0,0 +1 @@ +124cad2482f34af1a1492eb07be843a7bda61830 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index de3ce3f7..379d1a27 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2597,11 +2597,15 @@ "android/cookies/cookies_fetcher_util.cc", "android/customtabs/client_data_header_web_contents_observer.cc", "android/customtabs/client_data_header_web_contents_observer.h", + "android/customtabs/custom_tab_session_state_tracker.cc", + "android/customtabs/custom_tab_session_state_tracker.h", "android/customtabs/custom_tabs_connection.cc", "android/customtabs/detached_resource_request.cc", "android/customtabs/detached_resource_request.h", "android/customtabs/origin_verifier.cc", "android/customtabs/origin_verifier.h", + "android/customtabs/tab_interaction_recorder_android.cc", + "android/customtabs/tab_interaction_recorder_android.h", "android/devtools_manager_delegate_android.cc", "android/devtools_manager_delegate_android.h", "android/devtools_server.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 38c7bb3..1dcd8f8b 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -8448,6 +8448,11 @@ flag_descriptions::kTouchDragAndContextMenuName, flag_descriptions::kTouchDragAndContextMenuDescription, kOsAndroid, FEATURE_VALUE_TYPE(features::kTouchDragAndContextMenu)}, + + {"new-instance-from-dragged-link", + flag_descriptions::kNewInstanceFromDraggedLinkName, + flag_descriptions::kNewInstanceFromDraggedLinkDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kNewInstanceFromDraggedLink)}, #endif // BUILDFLAG(IS_ANDROID) {"autofill-enable-update-virtual-card-enrollment",
diff --git a/chrome/browser/android/customtabs/custom_tab_session_state_tracker.cc b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.cc new file mode 100644 index 0000000..82c57db --- /dev/null +++ b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.cc
@@ -0,0 +1,64 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/customtabs/custom_tab_session_state_tracker.h" + +#include "base/android/jni_string.h" +#include "chrome/android/chrome_jni_headers/CustomTabsOpenTimeRecorder_jni.h" + +namespace chrome { +namespace android { + +// static +CustomTabSessionStateTracker& CustomTabSessionStateTracker::GetInstance() { + static base::NoDestructor<CustomTabSessionStateTracker> instance; + return *instance; +} + +bool CustomTabSessionStateTracker::HasCustomTabSessionState() const { + return has_custom_tab_session_; +} + +void CustomTabSessionStateTracker::RecordCustomTabSession( + int64_t time_sec, + std::string package_name, + int32_t session_duration, + bool was_user_closed, + bool is_partial) { + has_custom_tab_session_ = true; + custom_tab_session_ = std::make_unique<metrics::CustomTabSessionProto>(); + custom_tab_session_->set_time_sec(time_sec); + custom_tab_session_->set_package_name(package_name); + custom_tab_session_->set_session_duration_sec(session_duration); + // TODO(crbug.com/1334500): add set_did_user_interact as well. + custom_tab_session_->set_was_user_closed(was_user_closed); + custom_tab_session_->set_is_partial(is_partial); +} + +std::unique_ptr<metrics::CustomTabSessionProto> +CustomTabSessionStateTracker::GetSession() { + // Clear the session because we only want the state recorded once. + has_custom_tab_session_ = false; + + return std::move(custom_tab_session_); +} + +CustomTabSessionStateTracker::CustomTabSessionStateTracker() = default; +CustomTabSessionStateTracker::~CustomTabSessionStateTracker() = default; + +} // namespace android +} // namespace chrome + +static void JNI_CustomTabsOpenTimeRecorder_RecordCustomTabSession( + JNIEnv* env, + jlong j_time, + const base::android::JavaParamRef<jstring>& j_package_name, + jlong j_session_duration, + jboolean j_was_user_closed, + jboolean j_is_partial_cct) { + std::string package_name = ConvertJavaStringToUTF8(env, j_package_name); + chrome::android::CustomTabSessionStateTracker::GetInstance() + .RecordCustomTabSession(j_time, package_name, j_session_duration, + j_was_user_closed, j_is_partial_cct); +}
diff --git a/chrome/browser/android/customtabs/custom_tab_session_state_tracker.h b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.h new file mode 100644 index 0000000..6a69571 --- /dev/null +++ b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.h
@@ -0,0 +1,47 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_CUSTOMTABS_CUSTOM_TAB_SESSION_STATE_TRACKER_H_ +#define CHROME_BROWSER_ANDROID_CUSTOMTABS_CUSTOM_TAB_SESSION_STATE_TRACKER_H_ + +#include "base/feature_list.h" +#include "base/no_destructor.h" +#include "third_party/metrics_proto/custom_tab_session.pb.h" + +namespace chrome { +namespace android { + +// This is a singleton. +class CustomTabSessionStateTracker { + public: + static CustomTabSessionStateTracker& GetInstance(); + + CustomTabSessionStateTracker(const CustomTabSessionStateTracker&) = delete; + CustomTabSessionStateTracker& operator=(const CustomTabSessionStateTracker&) = + delete; + + void RecordCustomTabSession(int64_t time_sec, + std::string package_name, + int32_t session_duration, + bool was_user_closed, + bool is_partial); + + bool HasCustomTabSessionState() const; + std::unique_ptr<metrics::CustomTabSessionProto> GetSession(); + + private: + friend class base::NoDestructor<CustomTabSessionStateTracker>; + + CustomTabSessionStateTracker(); + ~CustomTabSessionStateTracker(); + + bool has_custom_tab_session_; + + std::unique_ptr<metrics::CustomTabSessionProto> custom_tab_session_; +}; + +} // namespace android +} // namespace chrome + +#endif // CHROME_BROWSER_ANDROID_CUSTOMTABS_CUSTOM_TAB_SESSION_STATE_TRACKER_H_
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc b/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc new file mode 100644 index 0000000..861a07b --- /dev/null +++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc
@@ -0,0 +1,159 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/customtabs/tab_interaction_recorder_android.h" + +#include <memory> + +#include "base/android/jni_android.h" +#include "base/bind.h" +#include "base/memory/raw_ptr.h" +#include "chrome/android/chrome_jni_headers/TabInteractionRecorder_jni.h" +#include "chrome/browser/android/tab_android.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/core/browser/autofill_manager.h" +#include "content/public/browser/global_routing_id.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" + +namespace customtabs { + +using autofill::AutofillManager; +using base::android::JavaParamRef; +using base::android::ScopedJavaLocalRef; +using content::RenderFrameHost; + +namespace { + +// static +AutofillManager* GetAutofillManager(RenderFrameHost* render_frame_host) { + auto* autofill_driver = + autofill::ContentAutofillDriver::GetForRenderFrameHost(render_frame_host); + if (!autofill_driver) + return nullptr; + return autofill_driver->autofill_manager(); +} +} // namespace + +AutofillObserverImpl::AutofillObserverImpl( + autofill::AutofillManager* autofill_manager, + OnFormInteractionCallback form_interaction_callback) + : autofill_manager_(autofill_manager), + form_interaction_callback_(std::move(form_interaction_callback)) { + autofill_manager->AddObserver(this); +} + +AutofillObserverImpl::~AutofillObserverImpl() = default; + +void AutofillObserverImpl::OnFormSubmitted() { + OnFormInteraction(); +} + +void AutofillObserverImpl::OnSelectControlDidChange() { + OnFormInteraction(); +} + +void AutofillObserverImpl::OnTextFieldDidChange() { + OnFormInteraction(); +} + +void AutofillObserverImpl::OnTextFieldDidScroll() { + OnFormInteraction(); +} + +void AutofillObserverImpl::OnFormInteraction() { + DCHECK(autofill_manager_); + autofill_manager_->RemoveObserver(this); + autofill_manager_ = nullptr; + std::move(form_interaction_callback_).Run(); +} + +TabInteractionRecorderAndroid::~TabInteractionRecorderAndroid() = default; + +TabInteractionRecorderAndroid::TabInteractionRecorderAndroid( + content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + content::WebContentsUserData<TabInteractionRecorderAndroid>( + *web_contents) {} + +bool TabInteractionRecorderAndroid::HasNavigatedFromFirstPage() const { + return web_contents()->GetController().CanGoBack() || + web_contents()->GetController().CanGoForward(); +} + +// content::WebContentsObserver: +void TabInteractionRecorderAndroid::RenderFrameHostStateChanged( + RenderFrameHost* render_frame_host, + RenderFrameHost::LifecycleState old_state, + RenderFrameHost::LifecycleState new_state) { + if (old_state == RenderFrameHost::LifecycleState::kActive) { + rfh_observer_map_.erase(render_frame_host->GetGlobalId()); + } else if (new_state == RenderFrameHost::LifecycleState::kActive && + !has_form_interactions_) { + StartObservingFrame(render_frame_host); + } +} + +void TabInteractionRecorderAndroid::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (has_form_interactions_) + return; + if (!navigation_handle->IsSameDocument() && + navigation_handle->HasCommitted() && + navigation_handle->GetRenderFrameHost()->IsActive()) + StartObservingFrame(navigation_handle->GetRenderFrameHost()); +} + +void TabInteractionRecorderAndroid::SetHasFormInteractions() { + has_form_interactions_ = true; + rfh_observer_map_.clear(); +} + +void TabInteractionRecorderAndroid::StartObservingFrame( + RenderFrameHost* render_frame_host) { + AutofillManager* autofill_manager = + test_autofill_manager_ ? test_autofill_manager_.get() + : GetAutofillManager(render_frame_host); + if (!autofill_manager) + return; + + rfh_observer_map_[render_frame_host->GetGlobalId()] = + std::make_unique<AutofillObserverImpl>( + autofill_manager, + base::BindOnce(&TabInteractionRecorderAndroid::SetHasFormInteractions, + weak_factory_.GetWeakPtr())); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(TabInteractionRecorderAndroid); + +// JNI methods +jboolean TabInteractionRecorderAndroid::HadInteraction(JNIEnv* env) const { + bool has_interaction = has_form_interactions() || HasNavigatedFromFirstPage(); + return static_cast<jboolean>(has_interaction); +} + +ScopedJavaLocalRef<jobject> JNI_TabInteractionRecorder_GetFromTab( + JNIEnv* env, + const JavaParamRef<jobject>& jtab) { + TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab); + auto* recorder = + TabInteractionRecorderAndroid::FromWebContents(tab->web_contents()); + return Java_TabInteractionRecorder_create( + env, reinterpret_cast<int64_t>(recorder)); +} + +ScopedJavaLocalRef<jobject> JNI_TabInteractionRecorder_CreateForTab( + JNIEnv* env, + const JavaParamRef<jobject>& jtab) { + TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab); + TabInteractionRecorderAndroid::CreateForWebContents(tab->web_contents()); + + auto* recorder = + TabInteractionRecorderAndroid::FromWebContents(tab->web_contents()); + return Java_TabInteractionRecorder_create( + env, reinterpret_cast<int64_t>(recorder)); +} + +} // namespace customtabs
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.h b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h new file mode 100644 index 0000000..3acba528 --- /dev/null +++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
@@ -0,0 +1,107 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_ +#define CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_ + +#include "base/android/jni_android.h" +#include "base/bind.h" +#include "base/callback_forward.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/autofill/core/browser/autofill_manager.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" +#include "url/gurl.h" + +namespace customtabs { + +// Autofill observer impl for the TabInteractionRecorderAndroid to use. +class AutofillObserverImpl : public autofill::AutofillManager::Observer { + public: + using OnFormInteractionCallback = base::OnceCallback<void()>; + + explicit AutofillObserverImpl( + autofill::AutofillManager* autofill_manager, + OnFormInteractionCallback form_interaction_callback); + + AutofillObserverImpl(const AutofillObserverImpl&) = delete; + AutofillObserverImpl operator=(const AutofillObserverImpl&) = delete; + ~AutofillObserverImpl() override; + + // AutofillManager::Observer: + void OnFormSubmitted() override; + void OnSelectControlDidChange() override; + void OnTextFieldDidChange() override; + void OnTextFieldDidScroll() override; + + private: + void OnFormInteraction(); + + raw_ptr<autofill::AutofillManager> autofill_manager_; + OnFormInteractionCallback form_interaction_callback_; +}; + +// Class that record interaction from the web contents. The definition +// of an "interaction" includes user's engagement with text inputs or selection +// inputs, or changes in navigation stacks. +// +// To attach this class to the web contents correctly, it has to be setup +// before the first navigation finishes in order to attach observers to +// corresponding autofill managers; otherwise the interaction with first frame +// would be missing. +class TabInteractionRecorderAndroid + : public content::WebContentsObserver, + public content::WebContentsUserData<TabInteractionRecorderAndroid> { + public: + ~TabInteractionRecorderAndroid() override; + + // Return whether the |web_contents()| has navigated away from the first page. + bool HasNavigatedFromFirstPage() const; + + // Return whether the |web_contents()| has seen any form interactions. + bool has_form_interactions() const { return has_form_interactions_; } + + // content::WebContentsObserver: + void RenderFrameHostStateChanged( + content::RenderFrameHost* render_frame_host, + content::RenderFrameHost::LifecycleState old_state, + content::RenderFrameHost::LifecycleState new_state) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + + // JNI methods + jboolean HadInteraction(JNIEnv* env) const; + +#ifdef UNIT_TEST + void SetAutofillManagerForTest( + autofill::AutofillManager* test_autofill_manager) { + test_autofill_manager_ = test_autofill_manager; + } +#endif + + private: + explicit TabInteractionRecorderAndroid(content::WebContents* web_contents); + + friend class AutofillObserverImpl; + void StartObservingFrame(content::RenderFrameHost* render_frame_host); + void SetHasFormInteractions(); + + bool has_form_interactions_ = false; + std::unordered_map<content::GlobalRenderFrameHostId, + std::unique_ptr<AutofillObserverImpl>, + content::GlobalRenderFrameHostIdHasher> + rfh_observer_map_; + raw_ptr<autofill::AutofillManager> test_autofill_manager_ = nullptr; + + // content::WebContentsUserData<TabInteractionRecorderAndroid> + friend class content::WebContentsUserData<TabInteractionRecorderAndroid>; + WEB_CONTENTS_USER_DATA_KEY_DECL(); + + base::WeakPtrFactory<TabInteractionRecorderAndroid> weak_factory_{this}; +}; + +} // namespace customtabs + +#endif // CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc b/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc new file mode 100644 index 0000000..c62365d1 --- /dev/null +++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc
@@ -0,0 +1,183 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/customtabs/tab_interaction_recorder_android.h" + +#include <memory> +#include <utility> + +#include "base/test/mock_callback.h" +#include "chrome/browser/ui/tab_helpers.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/content_autofill_driver_factory_test_api.h" +#include "components/autofill/content/browser/content_autofill_driver_test_api.h" +#include "components/autofill/core/browser/autofill_manager.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/test_autofill_client.h" +#include "components/autofill/core/browser/test_autofill_driver.h" +#include "components/autofill/core/browser/test_browser_autofill_manager.h" +#include "components/autofill/core/common/autofill_tick_clock.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/web_contents_tester.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using autofill::AutofillManager; +using testing::_; +using testing::NiceMock; +using AutofillObsever = AutofillManager::Observer; + +namespace customtabs { + +namespace { +class MockAutofillClient : public autofill::TestAutofillClient { + public: + MockAutofillClient() = default; + MockAutofillClient(const MockAutofillClient&) = delete; + MockAutofillClient& operator=(const MockAutofillClient&) = delete; + ~MockAutofillClient() override = default; +}; + +class MockAutofillDriver : public autofill::TestAutofillDriver { + public: + MockAutofillDriver() = default; + MockAutofillDriver(const MockAutofillDriver&) = delete; + MockAutofillDriver& operator=(const MockAutofillDriver&) = delete; + ~MockAutofillDriver() override = default; +}; + +class MockAutofillManager : public autofill::TestBrowserAutofillManager { + public: + MockAutofillManager(autofill::TestAutofillDriver* driver, + autofill::TestAutofillClient* client) + : autofill::TestBrowserAutofillManager(driver, client) {} + MockAutofillManager(const MockAutofillManager&) = delete; + MockAutofillManager& operator=(const MockAutofillManager&) = delete; + ~MockAutofillManager() override = default; +}; + +void OnTextFieldDidChangeForAutofillManager(AutofillManager* autofill_manager) { + autofill::FormData form; + autofill::test::CreateTestAddressFormData(&form); + autofill::FormFieldData field = form.fields.front(); + + autofill_manager->OnTextFieldDidChange( + form, field, gfx::RectF(), autofill::AutofillTickClock::NowTicks()); +} +} // namespace + +class AutofillObserverImplTest : public testing::Test { + public: + AutofillObserverImplTest() = default; + + void SetUp() override { + client_.SetPrefs(autofill::test::PrefServiceForTesting()); + driver_ = std::make_unique<NiceMock<MockAutofillDriver>>(); + manager_ = std::make_unique<MockAutofillManager>(driver_.get(), &client_); + } + + void TearDown() override { + manager_.reset(); + driver_.reset(); + } + + MockAutofillManager* autofill_manager() { return manager_.get(); } + + protected: + base::test::TaskEnvironment task_environment_; + NiceMock<MockAutofillClient> client_; + std::unique_ptr<MockAutofillDriver> driver_; + std::unique_ptr<MockAutofillManager> manager_; +}; + +TEST_F(AutofillObserverImplTest, TestFormInteraction) { + base::MockOnceCallback<void()> callback; + AutofillObserverImpl obsever(autofill_manager(), callback.Get()); + + EXPECT_CALL(callback, Run()).Times(1); + OnTextFieldDidChangeForAutofillManager(autofill_manager()); + + // Observer should no longer get notified after the first interaction. + EXPECT_CALL(callback, Run()).Times(0); + OnTextFieldDidChangeForAutofillManager(autofill_manager()); +} + +TEST_F(AutofillObserverImplTest, TestNoFormInteraction) { + base::MockOnceCallback<void()> callback; + auto* observer = new AutofillObserverImpl(autofill_manager(), callback.Get()); + + EXPECT_CALL(callback, Run()).Times(0); + delete observer; +} + +// === TabInteractionRecorderAndroidTest === + +class TabInteractionRecorderAndroidTest + : public ChromeRenderViewHostTestHarness { + public: + TabInteractionRecorderAndroidTest() = default; + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + + client_.SetPrefs(autofill::test::PrefServiceForTesting()); + driver_ = std::make_unique<NiceMock<MockAutofillDriver>>(); + manager_ = std::make_unique<MockAutofillManager>(driver_.get(), &client_); + } + + void TearDown() override { + manager_.reset(); + driver_.reset(); + ChromeRenderViewHostTestHarness::TearDown(); + } + + std::unique_ptr<content::WebContents> CreateTestWebContents() { + std::unique_ptr<content::WebContents> contents = + ChromeRenderViewHostTestHarness::CreateTestWebContents(); + TabInteractionRecorderAndroid::CreateForWebContents(contents.get()); + auto* helper = + TabInteractionRecorderAndroid::FromWebContents(contents.get()); + helper->SetAutofillManagerForTest(autofill_manager()); + + // Simulate a navigation event to force the initialization of the main + // frame. + content::WebContentsTester::For(contents.get()) + ->NavigateAndCommit(GURL("https://foo.com")); + task_environment()->RunUntilIdle(); + return contents; + } + + MockAutofillManager* autofill_manager() { return manager_.get(); } + + protected: + NiceMock<MockAutofillClient> client_; + std::unique_ptr<MockAutofillDriver> driver_; + std::unique_ptr<MockAutofillManager> manager_; +}; + +TEST_F(TabInteractionRecorderAndroidTest, HadFormInteraction) { + std::unique_ptr<content::WebContents> contents = CreateTestWebContents(); + auto* helper = TabInteractionRecorderAndroid::FromWebContents(contents.get()); + + EXPECT_FALSE(helper->has_form_interactions()); + OnTextFieldDidChangeForAutofillManager(autofill_manager()); + EXPECT_TRUE(helper->has_form_interactions()); +} + +TEST_F(TabInteractionRecorderAndroidTest, HasNavigatedFromFirstPage) { + std::unique_ptr<content::WebContents> contents = CreateTestWebContents(); + auto* helper = TabInteractionRecorderAndroid::FromWebContents(contents.get()); + + EXPECT_FALSE(helper->HasNavigatedFromFirstPage()); + + content::WebContentsTester::For(contents.get()) + ->NavigateAndCommit(GURL("https://bar.com")); + task_environment()->RunUntilIdle(); + EXPECT_TRUE(helper->HasNavigatedFromFirstPage()); +} + +} // namespace customtabs
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h index 2e666b3..01cd02d 100644 --- a/chrome/browser/app_controller_mac.h +++ b/chrome/browser/app_controller_mac.h
@@ -20,6 +20,7 @@ #include "components/prefs/pref_change_registrar.h" class AppControllerProfileObserver; +class AppControllerNativeThemeObserver; @class AppShimMenuController; class BookmarkMenuBridge; class CommandUpdater; @@ -35,7 +36,7 @@ class TabMenuBridge; namespace ui { -class ThemeProvider; +class ColorProvider; } // namespace ui // The application controller object, created by loading the MainMenu nib. @@ -59,6 +60,10 @@ std::unique_ptr<AppControllerProfileObserver> _profileAttributesStorageObserver; + // The NativeThemeObserver observes system-wide theme related settings + // change. + std::unique_ptr<AppControllerNativeThemeObserver> _nativeThemeObserver; + // Management of the bookmark menu which spans across all windows // (and Browser*s). |profileBookmarkMenuBridgeMap_| is a cache that owns one // pointer to a BookmarkMenuBridge for each profile. |bookmarkMenuBridge_| is @@ -115,6 +120,8 @@ // Request to keep the browser alive during that object's lifetime. std::unique_ptr<ScopedKeepAlive> _keep_alive; + + const ui::ColorProvider* _lastActiveColorProvider; } @property(readonly, nonatomic) BOOL startupComplete; @@ -196,9 +203,11 @@ // the original or the incognito profile. - (void)setLastProfile:(Profile*)profile; -// Returns the last active ThemeProvider. It is only valid to call this with a -// last available profile. -- (const ui::ThemeProvider&)lastActiveThemeProvider; +// Returns the last active ColorProvider. +- (const ui::ColorProvider&)lastActiveColorProvider; + +// This is called when the system wide light or dark mode changes. +- (void)nativeThemeDidChange; // Certain NSMenuItems [Close Tab and Close Window] have different // keyEquivalents depending on context. This must be invoked in two locations:
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 9163dc8..78a2ae8 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -57,7 +57,6 @@ #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" -#include "chrome/browser/themes/theme_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_commands.h" @@ -112,6 +111,8 @@ #include "net/base/mac/url_conversions.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" +#include "ui/native_theme/native_theme_mac.h" +#include "ui/native_theme/native_theme_observer.h" #include "url/gurl.h" namespace { @@ -512,6 +513,25 @@ AppController* const app_controller_; // Weak; owns us. }; +class AppControllerNativeThemeObserver : public ui::NativeThemeObserver { + public: + AppControllerNativeThemeObserver(AppController* app_controller) + : app_controller_(app_controller) { + native_theme_observation_.Observe( + ui::NativeThemeMac::GetInstanceForNativeUi()); + } + + // NativeThemeObserver: + void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override { + [app_controller_ nativeThemeDidChange]; + } + + private: + base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver> + native_theme_observation_{this}; + AppController* const app_controller_; // Weak; owns us. +}; + @implementation AppController @synthesize startupComplete = _startupComplete; @@ -761,6 +781,7 @@ profile = profile->GetOriginalProfile(); } [self setLastProfile:profile]; + _lastActiveColorProvider = browser->window()->GetColorProvider(); } - (void)activeSpaceDidChange:(NSNotification*)notify { @@ -882,6 +903,10 @@ std::make_unique<AppControllerProfileObserver>( g_browser_process->profile_manager(), self); + // Observe native theme change (e.g. light and dark mode). + _nativeThemeObserver = + std::make_unique<AppControllerNativeThemeObserver>(self); + // Record the path to the (browser) app bundle; this is used by the app mode // shim. if (base::mac::AmIBundled()) { @@ -902,8 +927,11 @@ Browser* browser = chrome::FindLastActive(); content::WebContents* activeWebContents = nullptr; - if (browser) + _lastActiveColorProvider = nullptr; + if (browser) { activeWebContents = browser->tab_strip_model()->GetActiveWebContents(); + _lastActiveColorProvider = browser->window()->GetColorProvider(); + } [self updateHandoffManager:activeWebContents]; [self openStartupUrls]; @@ -1726,14 +1754,14 @@ _menuState.get(), _lastProfile)); } -- (const ui::ThemeProvider&)lastActiveThemeProvider { - // Themes are only available while a profile is available. - DCHECK(_lastProfile); +- (const ui::ColorProvider&)lastActiveColorProvider { + DCHECK(_lastActiveColorProvider); + return *_lastActiveColorProvider; +} - // AppController is conceptually a root for Chromium Mac. As a result, it is - // allowed to refer to the profile to get a theme provider. Non-root UI - // concepts should rely on well known roots to obtain a ThemeProvider. - return ThemeService::GetThemeProviderForProfile(_lastProfile); +- (void)nativeThemeDidChange { + Browser* browser = chrome::FindBrowserWithProfile(_lastProfile); + _lastActiveColorProvider = browser->window()->GetColorProvider(); } - (BOOL)windowHasBrowserTabs:(NSWindow*)window { @@ -1899,6 +1927,8 @@ - (void)setLastProfileForTesting:(Profile*)profile { _lastProfile = profile; + Browser* browser = chrome::FindLastActiveWithProfile(profile); + _lastActiveColorProvider = browser->window()->GetColorProvider(); } @end // @implementation AppController
diff --git a/chrome/browser/apps/app_service/web_contents_app_id_utils.cc b/chrome/browser/apps/app_service/web_contents_app_id_utils.cc index 4ecc726..596725e7 100644 --- a/chrome/browser/apps/app_service/web_contents_app_id_utils.cc +++ b/chrome/browser/apps/app_service/web_contents_app_id_utils.cc
@@ -163,7 +163,6 @@ extensions::ExtensionRegistry::Get(profile)->GetInstalledExtension( app_id); if (extension) { - DCHECK(extension->is_app()); return true; } return IsAppReady(profile, app_id);
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc index d3e1f143..8800c48 100644 --- a/chrome/browser/ash/accessibility/dictation_browsertest.cc +++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -1168,6 +1168,20 @@ /*script=*/script); } + void RunHiddenMacroWithStringArg(int macro, const std::string& arg) { + std::string script = base::StringPrintf(R"( + accessibilityCommon.dictation_. + runHiddenMacroWithStringArgForTesting(%d, "%s"); + window.domAutomationController.send("done"); + )", + macro, arg.c_str()); + + extensions::browsertest_util::ExecuteScriptInBackgroundPage( + /*context=*/browser()->profile(), + /*extension_id=*/extension_misc::kAccessibilityCommonExtensionId, + /*script=*/script); + } + void RunMacroAndWaitForCaretBoundsChanged(int macro) { content::AccessibilityNotificationWaiter selection_waiter( browser()->tab_strip_model()->GetActiveWebContents(), @@ -1305,6 +1319,60 @@ SendFinalResultAndWaitForTextAreaValue("folks!", "This is a pop quiz folks!"); } +IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, SmartDeletePhraseSimple) { + ToggleDictationWithKeystroke(); + WaitForRecognitionStarted(); + SendFinalResultAndWaitForTextAreaValue("This is a difficult test", + "This is a difficult test"); + RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "difficult"); + WaitForTextAreaValue("This is a test"); +} + +IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, + SmartDeletePhraseCaseInsensitive) { + ToggleDictationWithKeystroke(); + WaitForRecognitionStarted(); + SendFinalResultAndWaitForTextAreaValue("This is a DIFFICULT test", + "This is a DIFFICULT test"); + RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "difficult"); + WaitForTextAreaValue("This is a test"); +} + +IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, + SmartDeletePhraseDuplicateMatches) { + ToggleDictationWithKeystroke(); + WaitForRecognitionStarted(); + SendFinalResultAndWaitForTextAreaValue("The cow jumped over the moon.", + "The cow jumped over the moon."); + // Deletes the right-most occurrence of "the". + RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "the"); + WaitForTextAreaValue("The cow jumped over moon."); +} + +IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, + SmartDeletePhraseDeletesLeftOfCaret) { + ToggleDictationWithKeystroke(); + WaitForRecognitionStarted(); + SendFinalResultAndWaitForTextAreaValue("The cow jumped over the moon.", + "The cow jumped over the moon."); + RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_WORD*/ 20); + RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_WORD*/ 20); + RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_WORD*/ 20); + RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "the"); + WaitForTextAreaValue("cow jumped over the moon."); +} + +IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, + SmartDeletePhraseDeletesAtWordBoundaries) { + ToggleDictationWithKeystroke(); + WaitForRecognitionStarted(); + SendFinalResultAndWaitForTextAreaValue("A square is also a rectangle.", + "A square is also a rectangle."); + // Deletes the first word "a", not the first character "a". + RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "a"); + WaitForTextAreaValue("A square is also rectangle."); +} + // Tests behavior of Dictation and installation of Pumpkin. class DictationPumpkinInstallTest : public DictationTest { protected:
diff --git a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc index 5282a81..432eec7 100644 --- a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc +++ b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
@@ -25,6 +25,7 @@ constexpr int kSideInset = 24; constexpr int kTopMargin = 24; constexpr int kMinHeight = 72; +constexpr int kMaxTextWidth = 256; constexpr SkColor kTextColor = gfx::kGoogleGrey200; constexpr SkColor kBackgroundColor = gfx::kGoogleGrey900; constexpr SkColor kForegroundColor = SkColorSetA(SK_ColorWHITE, 0x0F); @@ -88,8 +89,10 @@ } auto preferred_size = CalculatePreferredSize(); - preferred_size.SetSize(preferred_size.width() + kIconSize + kImageLabelSpace, - kMinHeight); + preferred_size.SetSize( + std::min(preferred_size.width() + kIconSize + kImageLabelSpace, + kMaxTextWidth + kIconSize + kImageLabelSpace + 2 * kSideInset), + kMinHeight); preferred_size.SetToMin(parent_size); SetSize(preferred_size); SetPosition(gfx::Point(
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.cc b/chrome/browser/ash/crosapi/browser_data_migrator.cc index a81bf51..1bd8d5e 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator.cc
@@ -325,15 +325,21 @@ local_state->CommitPendingWrite(); + const bool is_move = base::FeatureList::IsEnabled( + ash::features::kLacrosMoveProfileMigration) || + MoveMigrator::ResumeRequired(local_state, user_id_hash); + // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, remove // this log message. LOG(WARNING) << "Making a dbus method call to session_manager"; bool success = SessionManagerClient::Get()->RequestBrowserDataMigration( - cryptohome::CreateAccountIdentifierFromAccountId(account_id)); + cryptohome::CreateAccountIdentifierFromAccountId(account_id), is_move); // TODO(crbug.com/1261730): Add an UMA. - if (!success) + if (!success) { + LOG(ERROR) << "SessionManagerClient::RequestBrowserDataMigration() failed."; return false; + } AttemptRestart(); return true; @@ -358,7 +364,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } -void BrowserDataMigratorImpl::Migrate(MigrateCallback callback) { +void BrowserDataMigratorImpl::Migrate(crosapi::browser_util::MigrationMode mode, + MigrateCallback callback) { DCHECK(local_state_); DCHECK(completion_callback_.is_null()); completion_callback_ = std::move(callback); @@ -370,24 +377,25 @@ DCHECK(GetMigrationStep(local_state_) == MigrationStep::kRestartCalled); SetMigrationStep(local_state_, MigrationStep::kStarted); - if (base::FeatureList::IsEnabled( - ash::features::kLacrosMoveProfileMigration) || - MoveMigrator::ResumeRequired(local_state_, user_id_hash_)) { - LOG(WARNING) << "Initializing MoveMigrator."; - migrator_delegate_ = std::make_unique<MoveMigrator>( - original_profile_dir_, user_id_hash_, std::move(progress_tracker_), - cancel_flag_, local_state_, - base::BindOnce( - &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread, - weak_factory_.GetWeakPtr())); - } else { - LOG(WARNING) << "Initializing CopyMigrator."; - migrator_delegate_ = std::make_unique<CopyMigrator>( - original_profile_dir_, user_id_hash_, std::move(progress_tracker_), - cancel_flag_, - base::BindOnce( - &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread, - weak_factory_.GetWeakPtr())); + switch (mode) { + case crosapi::browser_util::MigrationMode::kMove: + LOG(WARNING) << "Initializing MoveMigrator."; + migrator_delegate_ = std::make_unique<MoveMigrator>( + original_profile_dir_, user_id_hash_, std::move(progress_tracker_), + cancel_flag_, local_state_, + base::BindOnce( + &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread, + weak_factory_.GetWeakPtr())); + break; + case crosapi::browser_util::MigrationMode::kCopy: + LOG(WARNING) << "Initializing CopyMigrator."; + migrator_delegate_ = std::make_unique<CopyMigrator>( + original_profile_dir_, user_id_hash_, std::move(progress_tracker_), + cancel_flag_, + base::BindOnce( + &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread, + weak_factory_.GetWeakPtr())); + break; } migrator_delegate_->Migrate();
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.h b/chrome/browser/ash/crosapi/browser_data_migrator.h index 1d066666..5ed2619 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator.h +++ b/chrome/browser/ash/crosapi/browser_data_migrator.h
@@ -77,9 +77,11 @@ virtual ~BrowserDataMigrator() = default; - // Carries out the migration. It needs to be called on UI thread. - // |callback| will be called on the end of the migration procedure. - virtual void Migrate(MigrateCallback callback) = 0; + // Carries out the migration with the mode specified by `MigrationMode`. It + // needs to be called on UI thread. |callback| will be called on the end of + // the migration procedure. + virtual void Migrate(crosapi::browser_util::MigrationMode mode, + MigrateCallback callback) = 0; // Cancels the migration. This should be called on UI thread. // If this is called during the migration, it is expected that |callback| @@ -117,17 +119,6 @@ Result data_migration_result; }; - // Specifies the mode of migration. - enum class Mode { - kCopy = 0, // Copies browser related files to lacros. - kMove = 1, // Moves browser related files to lacros while copying files - // that are needed by both ash and lacros. - kDeleteAndCopy = 2, // Similar to kCopy but deletes - // TargetInfo::no_copy_items to make extra space. - kDeleteAndMove = 3 // Similar to kMove but deletes - // TargetInfo::no_copy_items to make extra space. - }; - // Delegate interface which is responsible for the actual task of setting up // the profile directories for ash and lacros. The class should call // `MigrateInternalFinishedUIThread()` once migration is completed. @@ -187,7 +178,8 @@ base::OnceCallback<void(bool, const absl::optional<uint64_t>&)> callback); // `BrowserDataMigrator` methods. - void Migrate(MigrateCallback callback) override; + void Migrate(crosapi::browser_util::MigrationMode mode, + MigrateCallback callback) override; void Cancel() override; // Registers boolean pref `kCheckForMigrationOnRestart` with default as false.
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc index 56a701d..ec816f0 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc
@@ -99,8 +99,10 @@ std::make_unique<BrowserDataMigratorImpl>( from_dir_, user_id_hash, base::DoNothing(), &pref_service_); absl::optional<BrowserDataMigrator::Result> result; - migrator->Migrate(base::BindLambdaForTesting( - [&out_result = result, &run_loop](BrowserDataMigrator::Result result) { + migrator->Migrate( + crosapi::browser_util::MigrationMode::kCopy, + base::BindLambdaForTesting([&out_result = result, &run_loop]( + BrowserDataMigrator::Result result) { run_loop.Quit(); out_result = result; })); @@ -144,8 +146,10 @@ std::make_unique<BrowserDataMigratorImpl>( from_dir_, user_id_hash, base::DoNothing(), &pref_service_); absl::optional<BrowserDataMigrator::Result> result; - migrator->Migrate(base::BindLambdaForTesting( - [&out_result = result, &run_loop](BrowserDataMigrator::Result result) { + migrator->Migrate( + crosapi::browser_util::MigrationMode::kCopy, + base::BindLambdaForTesting([&out_result = result, &run_loop]( + BrowserDataMigrator::Result result) { run_loop.Quit(); out_result = result; })); @@ -192,8 +196,10 @@ std::make_unique<BrowserDataMigratorImpl>( from_dir_, user_id_hash, base::DoNothing(), &pref_service_); absl::optional<BrowserDataMigrator::Result> result; - migrator->Migrate(base::BindLambdaForTesting( - [&out_result = result, &run_loop](BrowserDataMigrator::Result result) { + migrator->Migrate( + crosapi::browser_util::MigrationMode::kCopy, + base::BindLambdaForTesting([&out_result = result, &run_loop]( + BrowserDataMigrator::Result result) { run_loop.Quit(); out_result = result; })); @@ -226,8 +232,10 @@ std::make_unique<BrowserDataMigratorImpl>( from_dir_, user_id_hash, base::DoNothing(), &pref_service_); absl::optional<BrowserDataMigrator::Result> result; - migrator->Migrate(base::BindLambdaForTesting( - [&out_result = result, &run_loop](BrowserDataMigrator::Result result) { + migrator->Migrate( + crosapi::browser_util::MigrationMode::kMove, + base::BindLambdaForTesting([&out_result = result, &run_loop]( + BrowserDataMigrator::Result result) { run_loop.Quit(); out_result = result; }));
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h index 5245f80..e0cc02b 100644 --- a/chrome/browser/ash/crosapi/browser_util.h +++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -90,6 +90,13 @@ const char* const crx_id; }; +// Specifies the mode of migration. The values correspond to `MigratorDelegate` +// either being `CopyMigrator` or `MoveMigrator`. +enum class MigrationMode { + kCopy = 0, // Migrate using `CopyMigrator`. + kMove = 1, // Migrate using `MoveMigrator`. +}; + extern const ComponentInfo kLacrosDogfoodCanaryInfo; extern const ComponentInfo kLacrosDogfoodDevInfo; extern const ComponentInfo kLacrosDogfoodBetaInfo;
diff --git a/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc b/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc index a04212d9f..5e7aa815 100644 --- a/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc +++ b/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc
@@ -115,7 +115,13 @@ g_browser_process->local_state()); } - migrator_->Migrate(base::BindOnce(&LacrosDataMigrationScreen::OnMigrated, + auto mode = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kBrowserDataMigrationMoveMode) + ? crosapi::browser_util::MigrationMode::kMove + : crosapi::browser_util::MigrationMode::kCopy; + + migrator_->Migrate(mode, + base::BindOnce(&LacrosDataMigrationScreen::OnMigrated, weak_factory_.GetWeakPtr())); // Show the screen.
diff --git a/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc b/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc index 10a135216..d3e2ed85 100644 --- a/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc
@@ -43,7 +43,8 @@ class FakeMigrator : public BrowserDataMigrator { public: // BrowserDataMigrator overrides. - void Migrate(MigrateCallback callback) override { + void Migrate(crosapi::browser_util::MigrationMode mode, + MigrateCallback callback) override { callback_ = std::move(callback); } void Cancel() override { cancel_called_ = true; }
diff --git a/chrome/browser/banners/android/BUILD.gn b/chrome/browser/banners/android/BUILD.gn index d294746..6872a59 100644 --- a/chrome/browser/banners/android/BUILD.gn +++ b/chrome/browser/banners/android/BUILD.gn
@@ -79,10 +79,10 @@ "//third_party/android_deps:espresso_java", "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit:junit", "//third_party/mockito:mockito_java", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:ui_full_java", "//ui/android:ui_java_test_support", ]
diff --git a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index d4d6018..cd5a626 100644 --- a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -26,9 +26,6 @@ import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiSelector; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -37,6 +34,9 @@ import androidx.test.espresso.matcher.RootMatchers; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiSelector; import org.hamcrest.Matcher; import org.hamcrest.Matchers;
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc index 4c4769ba..d12b2b0 100644 --- a/chrome/browser/chromeos/extensions/default_app_order.cc +++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -8,6 +8,7 @@ #include "ash/constants/ash_paths.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" +#include "ash/webui/projector_app/public/cpp/projector_app_constants.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/files/file_path.h" @@ -15,12 +16,14 @@ #include "base/json/json_file_value_serializer.h" #include "base/path_service.h" #include "base/task/thread_pool.h" +#include "chrome/browser/ash/crostini/crostini_terminal.h" #include "chrome/browser/ash/file_manager/app_id.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/app_list/page_break_constants.h" #include "chrome/browser/web_applications/web_app_id_constants.h" #include "chrome/common/extensions/extension_constants.h" +#include "chromeos/constants/chromeos_features.h" #include "components/app_constants/constants.h" #include "extensions/common/constants.h" @@ -38,8 +41,62 @@ const char kNameAttr[] = "name"; const char kImportDefaultOrderAttr[] = "import_default_order"; -// Canonical ordering specified in: go/default-apps -const char* const kDefaultAppOrder[] = { +// Reads external ordinal json file and returned the parsed value. Returns NULL +// if the file does not exist or could not be parsed properly. Caller takes +// ownership of the returned value. +std::unique_ptr<base::ListValue> ReadExternalOrdinalFile( + const base::FilePath& path) { + if (!base::PathExists(path)) + return NULL; + + JSONFileValueDeserializer deserializer(path); + std::string error_msg; + std::unique_ptr<base::Value> value = + deserializer.Deserialize(NULL, &error_msg); + if (!value) { + LOG(WARNING) << "Unable to deserialize default app ordinals json data:" + << error_msg << ", file=" << path.value(); + return NULL; + } + + std::unique_ptr<base::ListValue> ordinal_list_value = + base::ListValue::From(std::move(value)); + if (!ordinal_list_value) + LOG(WARNING) << "Expect a JSON list in file " << path.value(); + + return ordinal_list_value; +} + +std::string GetLocaleSpecificStringImpl(const base::DictionaryValue* root, + const std::string& locale, + const std::string& dictionary_name, + const std::string& entry_name) { + const base::DictionaryValue* dictionary_content = NULL; + if (!root || !root->GetDictionary(dictionary_name, &dictionary_content)) + return std::string(); + + const base::DictionaryValue* locale_dictionary = NULL; + if (dictionary_content->GetDictionary(locale, &locale_dictionary)) { + std::string result; + if (locale_dictionary->GetString(entry_name, &result)) + return result; + } + + const base::DictionaryValue* default_dictionary = NULL; + if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) { + std::string result; + if (default_dictionary->GetString(entry_name, &result)) + return result; + } + + return std::string(); +} + +// Gets built-in default app order. +void GetDefault(std::vector<std::string>* app_ids) { + // Canonical ordering specified in: go/default-apps + // clang-format off + app_ids->insert(app_ids->end(), { app_constants::kChromeAppId, arc::kPlayStoreAppId, @@ -85,6 +142,7 @@ arc::kPlayMoviesAppId, extension_misc::kGooglePlayMoviesAppId, + arc::kGoogleTVAppId, arc::kPlayMusicAppId, extension_misc::kGooglePlayMusicAppId, @@ -98,14 +156,12 @@ arc::kGooglePhotosAppId, extension_misc::kGooglePhotosAppId, - arc::kGoogleDuoAppId, web_app::kStadiaAppId, // First default page break app_list::kDefaultPageBreak1, arc::kGoogleMapsAppId, - extension_misc::kGoogleMapsAppId, // TODO(crbug.com/976578): Remove. web_app::kGoogleMapsAppId, ash::kInternalAppIdSettings, @@ -123,73 +179,32 @@ web_app::kYoutubeTVAppId, web_app::kGoogleNewsAppId, extensions::kWebStoreAppId, + + crostini::kCrostiniTerminalSystemAppId, + web_app::kMediaAppId, + ash::kChromeUITrustedProjectorSwaAppId, + arc::kLightRoomAppId, arc::kInfinitePainterAppId, web_app::kShowtimeAppId, extension_misc::kGooglePlusAppId, -}; + }); + // clang-format on -// Reads external ordinal json file and returned the parsed value. Returns NULL -// if the file does not exist or could not be parsed properly. Caller takes -// ownership of the returned value. -std::unique_ptr<base::ListValue> ReadExternalOrdinalFile( - const base::FilePath& path) { - if (!base::PathExists(path)) - return NULL; - - JSONFileValueDeserializer deserializer(path); - std::string error_msg; - std::unique_ptr<base::Value> value = - deserializer.Deserialize(NULL, &error_msg); - if (!value) { - LOG(WARNING) << "Unable to deserialize default app ordinals json data:" - << error_msg << ", file=" << path.value(); - return NULL; + if (chromeos::features::IsCloudGamingDeviceEnabled()) { + app_ids->push_back(web_app::kCloudGamingPartnerPlatform); } - - std::unique_ptr<base::ListValue> ordinal_list_value = - base::ListValue::From(std::move(value)); - if (!ordinal_list_value) - LOG(WARNING) << "Expect a JSON list in file " << path.value(); - - return ordinal_list_value; -} - -std::string GetLocaleSpecificStringImpl( - const base::DictionaryValue* root, - const std::string& locale, - const std::string& dictionary_name, - const std::string& entry_name) { - const base::DictionaryValue* dictionary_content = NULL; - if (!root || !root->GetDictionary(dictionary_name, &dictionary_content)) - return std::string(); - - const base::DictionaryValue* locale_dictionary = NULL; - if (dictionary_content->GetDictionary(locale, &locale_dictionary)) { - std::string result; - if (locale_dictionary->GetString(entry_name, &result)) - return result; - } - - const base::DictionaryValue* default_dictionary = NULL; - if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) { - std::string result; - if (default_dictionary->GetString(entry_name, &result)) - return result; - } - - return std::string(); -} - -// Gets built-in default app order. -void GetDefault(std::vector<std::string>* app_ids) { - for (size_t i = 0; i < std::size(kDefaultAppOrder); ++i) - app_ids->push_back(std::string(kDefaultAppOrder[i])); } } // namespace -const size_t kDefaultAppOrderCount = std::size(kDefaultAppOrder); +size_t DefaultAppCount() { + std::vector<std::string> apps; + + GetDefault(&apps); + + return apps.size(); +} ExternalLoader::ExternalLoader(bool async) : loaded_(base::WaitableEvent::ResetPolicy::MANUAL,
diff --git a/chrome/browser/chromeos/extensions/default_app_order.h b/chrome/browser/chromeos/extensions/default_app_order.h index 495d11c..546a09b 100644 --- a/chrome/browser/chromeos/extensions/default_app_order.h +++ b/chrome/browser/chromeos/extensions/default_app_order.h
@@ -52,7 +52,7 @@ std::string GetOemAppsFolderName(); // Number of apps in hard-coded apps order. -extern const size_t kDefaultAppOrderCount; +size_t DefaultAppCount(); } // namespace default_app_order } // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/default_app_order_unittest.cc b/chrome/browser/chromeos/extensions/default_app_order_unittest.cc index 34fe98a..f8d2f1c0 100644 --- a/chrome/browser/chromeos/extensions/default_app_order_unittest.cc +++ b/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
@@ -139,11 +139,11 @@ std::vector<std::string> apps; default_app_order::Get(&apps); - EXPECT_EQ(default_app_order::kDefaultAppOrderCount + 2, apps.size()); + EXPECT_EQ(default_app_order::DefaultAppCount() + 2, apps.size()); EXPECT_EQ(std::string("app1"), apps[0]); EXPECT_EQ(app_constants::kChromeAppId, apps[1]); EXPECT_EQ(std::string("app2"), - apps[default_app_order::kDefaultAppOrderCount + 1]); + apps[default_app_order::DefaultAppCount() + 1]); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc index 29a9f9f5a..bd1fdff6 100644 --- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc +++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
@@ -191,26 +191,31 @@ Respond(NoArguments()); } -WmDesksPrivateLaunchDeskTemplateFunction:: - WmDesksPrivateLaunchDeskTemplateFunction() = default; -WmDesksPrivateLaunchDeskTemplateFunction:: - ~WmDesksPrivateLaunchDeskTemplateFunction() = default; +WmDesksPrivateLaunchDeskFunction::WmDesksPrivateLaunchDeskFunction() = default; +WmDesksPrivateLaunchDeskFunction::~WmDesksPrivateLaunchDeskFunction() = default; -ExtensionFunction::ResponseAction -WmDesksPrivateLaunchDeskTemplateFunction::Run() { - std::unique_ptr<api::wm_desks_private::LaunchDeskTemplate::Params> params( - api::wm_desks_private::LaunchDeskTemplate::Params::Create(args())); +ExtensionFunction::ResponseAction WmDesksPrivateLaunchDeskFunction::Run() { + std::unique_ptr<api::wm_desks_private::LaunchDesk::Params> params( + api::wm_desks_private::LaunchDesk::Params::Create(args())); EXTENSION_FUNCTION_VALIDATE(params); - - DesksClient::Get()->LaunchDeskTemplate( - params->template_uuid, - base::BindOnce( - &WmDesksPrivateLaunchDeskTemplateFunction::OnLaunchDeskTemplate, - this)); - return RespondLater(); + auto& launch_options = params->launch_options; + std::u16string desk_name = launch_options.desk_name + ? base::UTF8ToUTF16(*launch_options.desk_name) + : u""; + if (launch_options.template_uuid) { + DesksClient::Get()->LaunchDeskTemplate( + *params->launch_options.template_uuid, + base::BindOnce(&WmDesksPrivateLaunchDeskFunction::OnLaunchDesk, this), + desk_name); + } else { + DesksClient::Get()->LaunchEmptyDesk( + base::BindOnce(&WmDesksPrivateLaunchDeskFunction::OnLaunchDesk, this), + desk_name); + } + return did_respond() ? AlreadyResponded() : RespondLater(); } -void WmDesksPrivateLaunchDeskTemplateFunction::OnLaunchDeskTemplate( +void WmDesksPrivateLaunchDeskFunction::OnLaunchDesk( std::string error_string, const base::GUID& desk_uuid) { if (!error_string.empty()) { @@ -218,9 +223,8 @@ return; } - Respond( - ArgumentList(api::wm_desks_private::LaunchDeskTemplate::Results::Create( - desk_uuid.AsLowercaseString()))); + Respond(ArgumentList(api::wm_desks_private::LaunchDesk::Results::Create( + desk_uuid.AsLowercaseString()))); } WmDesksPrivateRemoveDeskFunction::WmDesksPrivateRemoveDeskFunction() = default;
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h index ff99e058..be00f4bccd 100644 --- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h +++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h
@@ -122,25 +122,24 @@ void OnDeleteDeskTemplateCompleted(std::string error_string); }; -class WmDesksPrivateLaunchDeskTemplateFunction : public ExtensionFunction { +class WmDesksPrivateLaunchDeskFunction : public ExtensionFunction { public: - WmDesksPrivateLaunchDeskTemplateFunction(); - WmDesksPrivateLaunchDeskTemplateFunction( - const WmDesksPrivateLaunchDeskTemplateFunction&) = delete; - WmDesksPrivateLaunchDeskTemplateFunction& operator=( - const WmDesksPrivateLaunchDeskTemplateFunction&) = delete; + WmDesksPrivateLaunchDeskFunction(); + WmDesksPrivateLaunchDeskFunction(const WmDesksPrivateLaunchDeskFunction&) = + delete; + WmDesksPrivateLaunchDeskFunction& operator=( + const WmDesksPrivateLaunchDeskFunction&) = delete; - DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.launchDeskTemplate", - WMDESKSPRIVATE_LAUNCHDESKTEMPLATE) + DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.launchDesk", + WMDESKSPRIVATE_LAUNCHDESK) protected: - ~WmDesksPrivateLaunchDeskTemplateFunction() override; + ~WmDesksPrivateLaunchDeskFunction() override; // ExtensionFunction: ResponseAction Run() override; - void OnLaunchDeskTemplate(std::string error_string, - const base::GUID& desk_Id); + void OnLaunchDesk(std::string error_string, const base::GUID& desk_Id); }; class WmDesksPrivateRemoveDeskFunction : public ExtensionFunction { @@ -151,8 +150,8 @@ WmDesksPrivateRemoveDeskFunction& operator=( const WmDesksPrivateRemoveDeskFunction&) = delete; - DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.removeDeskAndCloseWindows", - WMDESKSPRIVATE_REMOVEDESKANDCLOSEWINDOWS) + DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.removeDesk", + WMDESKSPRIVATE_REMOVEDESK) protected: ~WmDesksPrivateRemoveDeskFunction() override;
diff --git a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc index a9028740..4e1b9c6 100644 --- a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc +++ b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc
@@ -2,8 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Lacros specific FileBrowserHandlerInternalSelectFileFunctionLacros overrides +// OnFilePathSelected() to do the following: +// * Use storage::IsolatedContext to create extensions::GrantedFileEntry. +// * Grant permissions needed to read/write/create file under the select path. +// * Populate results for API response needed to create JS FileEntry. + #include "chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h" -#include "base/notreached.h" + +#include <memory> +#include <utility> + +#include "chrome/common/extensions/api/file_browser_handler_internal.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "extensions/browser/api/file_handlers/app_file_handler_util.h" +#include "extensions/browser/granted_file_entry.h" + +using content::BrowserThread; +using extensions::api::file_browser_handler_internal::FileEntryInfoForGetFile; +using extensions::app_file_handler_util::CreateFileEntryWithPermissions; + +namespace SelectFile = + extensions::api::file_browser_handler_internal::SelectFile; FileBrowserHandlerInternalSelectFileFunctionLacros:: FileBrowserHandlerInternalSelectFileFunctionLacros() = default; @@ -14,16 +36,35 @@ void FileBrowserHandlerInternalSelectFileFunctionLacros::OnFilePathSelected( bool success, const base::FilePath& full_path) { - // Called by FileBrowserHandlerInternalSelectFileFunction::Run(), which is - // stubbed out. - NOTREACHED(); -} + DCHECK_CURRENTLY_ON(BrowserThread::UI); -ExtensionFunction::ResponseAction -FileBrowserHandlerInternalSelectFileFunctionLacros::Run() { - NOTIMPLEMENTED(); - return RespondNow( - Error("fileBrowserHandlerInternal.selectFile not implemented")); + if (!success) { + RespondWithFailure(); + return; + } + + int renderer_pid = render_frame_host()->GetProcess()->GetID(); + if (renderer_pid <= 0) { + RespondWithFailure(); + return; + } + + extensions::GrantedFileEntry granted_file_entry = + CreateFileEntryWithPermissions( + renderer_pid, full_path, + /* can_write */ true, /* can_create */ true, /* can_delete */ false); + + SelectFile::Results::Result result; + result.success = true; + + // The value will be consumed by DirectoryEntry.getFile() (JS). + result.entry_for_get_file = std::make_unique<FileEntryInfoForGetFile>(); + result.entry_for_get_file->file_system_id = granted_file_entry.filesystem_id; + result.entry_for_get_file->base_name = granted_file_entry.registered_name; + result.entry_for_get_file->entry_id = granted_file_entry.id; + result.entry_for_get_file->is_directory = false; + + RespondWithResult(result); } template <>
diff --git a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h index 5a1ec2b..69a08902 100644 --- a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h +++ b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h
@@ -24,10 +24,6 @@ // The class is ref counted, so destructor should not be public. ~FileBrowserHandlerInternalSelectFileFunctionLacros() override; - // ExtensionFunction implementation. - // Runs the extension function implementation. - ResponseAction Run() override; - private: DECLARE_EXTENSION_FUNCTION("fileBrowserHandlerInternal.selectFile", FILEBROWSERHANDLERINTERNAL_SELECTFILE)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 6af50d14..28ca3371 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1982,6 +1982,11 @@ "expiry_milestone": 106 }, { + "name": "enable-discover-feed-ghost-cards", + "owners": [ "edchin", "adamta", "sczs", "tinazwang" ], + "expiry_milestone": 106 + }, + { "name": "enable-discover-feed-preview", "owners": [ "tinazwang", "sczs" ], "expiry_milestone": 101 @@ -4301,6 +4306,11 @@ "expiry_milestone": 93 }, { + "name": "new-instance-from-dragged-link", + "owners": [ "aishwaryarj", "clank-app-team@google.com" ], + "expiry_milestone": 106 + }, + { "name": "new-mobile-identity-consistency-fre", "owners": [ "jlebel", "chrome-signin-team" ], "expiry_milestone": 106
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d9e4c49..76f58d1 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3411,6 +3411,11 @@ "When enabled, the network service runs on the browser process. Otherwise, " "it runs on a dedicated process."; +const char kNewInstanceFromDraggedLinkName[] = + "New instance creation from a dragged link"; +const char kNewInstanceFromDraggedLinkDescription[] = + "Enables creation of a new instance when a link is dragged out of Chrome."; + const char kNewWindowAppMenuName[] = "Show a menu item 'New Window'"; const char kNewWindowAppMenuDescription[] = "Show a new menu item 'New Window' on tablet-sized screen when Chrome "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index e91a9f5..144f98e 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1941,6 +1941,9 @@ extern const char kNetworkServiceInProcessName[]; extern const char kNetworkServiceInProcessDescription[]; +extern const char kNewInstanceFromDraggedLinkName[]; +extern const char kNewInstanceFromDraggedLinkDescription[]; + extern const char kNewWindowAppMenuName[]; extern const char kNewWindowAppMenuDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 3703c78e..db566f0 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -190,6 +190,7 @@ &kCCTResizableAllowResizeByUserGesture, &kCCTResizableForFirstParties, &kCCTResizableForThirdParties, + &kCCTRetainingState, &kCCTResourcePrefetch, &kCCTToolbarCustomizations, &kDontAutoHideBrowserControls, @@ -244,6 +245,7 @@ &kLensOnQuickActionSearchWidget, &kLocationBarModelOptimizations, &kMostRecentTabOnBackgroundCloseTab, + &kNewInstanceFromDraggedLink, &kNewWindowAppMenu, &kNotificationPermissionVariant, &kPageAnnotationsService, @@ -364,6 +366,7 @@ &query_tiles::features::kQueryTilesSegmentation, &reading_list::switches::kReadLater, &safe_browsing::kCreateSafebrowsingOnStartup, + &segmentation_platform::features::kContextualPageActions, &segmentation_platform::features::kContextualPageActionPriceTracking, &send_tab_to_self::kSendTabToSelfSigninPromo, &send_tab_to_self::kSendTabToSelfV2, @@ -492,6 +495,9 @@ const base::Feature kCCTIncognitoAvailableToThirdParty{ "CCTIncognitoAvailableToThirdParty", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kCCTPackageNameRecording{"CCTPackageNameRecording", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kCCTPostMessageAPI{"CCTPostMessageAPI", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -519,6 +525,9 @@ const base::Feature kCCTResourcePrefetch{"CCTResourcePrefetch", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kCCTRetainingState{"CCTRetainingState", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kCCTToolbarCustomizations{"CCTToolbarCustomizations", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -687,6 +696,9 @@ const base::Feature kMostRecentTabOnBackgroundCloseTab{ "MostRecentTabOnBackgroundCloseTab", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNewInstanceFromDraggedLink{ + "NewInstanceFromDraggedLink", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kNewWindowAppMenu{"NewWindowAppMenu", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 7ad04adb..2fafc23 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -38,6 +38,7 @@ extern const base::Feature kCCTIncognito; extern const base::Feature kCCTIncognitoAvailableToThirdParty; extern const base::Feature kCCTNewDownloadTab; +extern const base::Feature kCCTPackageNameRecording; extern const base::Feature kCCTPostMessageAPI; extern const base::Feature kCCTRedirectPreconnect; extern const base::Feature kCCTRemoveRemoteViewIds; @@ -47,6 +48,7 @@ extern const base::Feature kCCTResizableForFirstParties; extern const base::Feature kCCTResizableForThirdParties; extern const base::Feature kCCTResourcePrefetch; +extern const base::Feature kCCTRetainingState; extern const base::Feature kCCTToolbarCustomizations; extern const base::Feature kDontAutoHideBrowserControls; extern const base::Feature kChromeNewDownloadTab; @@ -106,6 +108,7 @@ extern const base::Feature kLensOnQuickActionSearchWidget; extern const base::Feature kLocationBarModelOptimizations; extern const base::Feature kMostRecentTabOnBackgroundCloseTab; +extern const base::Feature kNewInstanceFromDraggedLink; extern const base::Feature kNewWindowAppMenu; extern const base::Feature kNotificationPermissionVariant; extern const base::Feature kPageAnnotationsService;
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 df02578..be7eb27d 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
@@ -256,6 +256,7 @@ public static final String CCT_RESIZABLE_FOR_FIRST_PARTIES = "CCTResizableForFirstParties"; public static final String CCT_RESIZABLE_FOR_THIRD_PARTIES = "CCTResizableForThirdParties"; public static final String CCT_RESOURCE_PREFETCH = "CCTResourcePrefetch"; + public static final String CCT_RETAINING_STATE = "CCTRetainingState"; public static final String CCT_REPORT_PARALLEL_REQUEST_STATUS = "CCTReportParallelRequestStatus"; public static final String CCT_TOOLBAR_CUSTOMIZATIONS = "CCTToolbarCustomizations"; @@ -414,6 +415,7 @@ public static final String METRICS_SETTINGS_ANDROID = "MetricsSettingsAndroid"; public static final String MOST_RECENT_TAB_ON_BACKGROUND_CLOSE_TAB = "MostRecentTabOnBackgroundCloseTab"; + public static final String NEW_INSTANCE_FROM_DRAGGED_LINK = "NewInstanceFromDraggedLink"; public static final String NEW_WINDOW_APP_MENU = "NewWindowAppMenu"; public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant"; public static final String OFFLINE_INDICATOR = "OfflineIndicator";
diff --git a/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml b/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml index 01375bb..a166077 100644 --- a/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml +++ b/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml
@@ -13,6 +13,12 @@ android:visible="false" app:showAsAction="ifRoom" app:iconTint="@color/default_icon_color_secondary_tint_list" /> + <item + android:id="@+id/close_menu_id" + android:icon="@drawable/btn_close" + android:title="@string/close" + app:showAsAction="ifRoom" + app:iconTint="@color/default_icon_color_secondary_tint_list" /> </group> <group android:id="@+id/selection_mode_menu_group"
diff --git a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java index 8a50ffa..12af94bd 100644 --- a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java +++ b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java
@@ -4,7 +4,7 @@ package org.chromium.chrome.browser.history_clusters; -import android.content.Context; +import android.app.Activity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -36,7 +36,7 @@ private final ModelList mModelList; private final HistoryClustersDelegate mDelegate; private SimpleRecyclerViewAdapter mAdapter; - private final Context mContext; + private final Activity mActivity; private boolean mActivityViewInflated; private final PropertyModel mToolbarModel; private ViewGroup mActivityContentView; @@ -47,15 +47,14 @@ /** * Construct a new HistoryClustersCoordinator. * @param profile The profile from which the coordinator should access history data. - * @param context Android context from which UI configuration (strings, colors etc.) should be - * derived. + * @param activity Activity in which this UI resides. * @param historyClustersDelegate Delegate that provides functionality that must be implemented * externally, e.g. populating intents targeting activities we can't reference directly. */ - public HistoryClustersCoordinator(@NonNull Profile profile, @NonNull Context context, + public HistoryClustersCoordinator(@NonNull Profile profile, @NonNull Activity activity, TemplateUrlService templateUrlService, HistoryClustersDelegate historyClustersDelegate) { - mContext = context; + mActivity = activity; mDelegate = historyClustersDelegate; mModelList = new ModelList(); mToolbarModel = new PropertyModel.Builder(HistoryClustersToolbarProperties.ALL_KEYS) @@ -63,7 +62,7 @@ QueryState.forQueryless()) .build(); mMediator = new HistoryClustersMediator(HistoryClustersBridge.getForProfile(profile), - new LargeIconBridge(profile), context, context.getResources(), mModelList, + new LargeIconBridge(profile), mActivity, mActivity.getResources(), mModelList, mToolbarModel, mDelegate, System::currentTimeMillis, templateUrlService); } @@ -107,7 +106,7 @@ mAdapter.registerType(ItemType.TOGGLE, mDelegate::getToggleView, HistoryClustersViewBinder::bindToggleView); - LayoutInflater layoutInflater = LayoutInflater.from(mContext); + LayoutInflater layoutInflater = LayoutInflater.from(mActivity); mActivityContentView = (ViewGroup) layoutInflater.inflate( R.layout.history_clusters_activity_content, null); @@ -129,6 +128,9 @@ mMediator, R.string.history_clusters_search_your_journeys, R.id.search_menu_id); mSelectableListLayout.configureWideDisplayStyle(); mToolbar.setSearchEnabled(true); + if (!mDelegate.isSeparateActivity()) { + mToolbar.getMenu().removeItem(R.id.close_menu_id); + } PropertyModelChangeProcessor.create( mToolbarModel, mToolbar, HistoryClustersViewBinder::bindToolbar); @@ -163,6 +165,10 @@ mMediator.setQueryState(QueryState.forQuery("")); return true; } + if (menuItem.getItemId() == R.id.close_menu_id && mDelegate.isSeparateActivity()) { + mActivity.finish(); + return true; + } return false; } } \ No newline at end of file
diff --git a/chrome/browser/metrics/chrome_android_metrics_provider.cc b/chrome/browser/metrics/chrome_android_metrics_provider.cc index af0c834f..1658ca67 100644 --- a/chrome/browser/metrics/chrome_android_metrics_provider.cc +++ b/chrome/browser/metrics/chrome_android_metrics_provider.cc
@@ -6,8 +6,10 @@ #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" +#include "chrome/browser/android/customtabs/custom_tab_session_state_tracker.h" #include "chrome/browser/android/locale/locale_manager.h" #include "chrome/browser/android/metrics/uma_session_stats.h" +#include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/flags/android/chrome_session_state.h" #include "chrome/browser/notifications/jni_headers/NotificationSystemStatusUtil_jni.h" #include "components/prefs/pref_registry_simple.h" @@ -93,6 +95,15 @@ os_proto->set_dark_mode_state( ToProtoDarkModeState(chrome::android::GetDarkModeState())); + if (base::FeatureList::IsEnabled(chrome::android::kCCTPackageNameRecording) && + chrome::android::CustomTabSessionStateTracker::GetInstance() + .HasCustomTabSessionState()) { + uma_proto->mutable_custom_tab_session()->Swap( + chrome::android::CustomTabSessionStateTracker::GetInstance() + .GetSession() + .get()); + } + UmaSessionStats::GetInstance()->ProvideCurrentSessionData(); EmitAppNotificationStatusHistogram(); LocaleManager::RecordUserTypeMetrics();
diff --git a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc index e08a1d1..6348af1 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc +++ b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
@@ -238,7 +238,7 @@ const char* kScenarioSuffix = ".VideoCapture"; const std::vector<const char*> suffixes({"", kScenarioSuffix}); ExpectHistogramSamples(&histogram_tester_, suffixes, - {{"PerformanceMonitor.AverageCPU4.Total", 500}}); + {{"PerformanceMonitor.AverageCPU5.Total", 500}}); } #if BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/metrics/power/power_metrics_unittest.cc b/chrome/browser/metrics/power/power_metrics_unittest.cc index d7aec2a..505cd02 100644 --- a/chrome/browser/metrics/power/power_metrics_unittest.cc +++ b/chrome/browser/metrics/power/power_metrics_unittest.cc
@@ -84,7 +84,7 @@ ReportAggregatedProcessMetricsHistograms(process_metrics, suffixes); ExpectHistogramSamples(&histogram_tester, suffixes, { - {"PerformanceMonitor.AverageCPU4.Total", 20}, + {"PerformanceMonitor.AverageCPU5.Total", 20}, #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ BUILDFLAG(IS_AIX)
diff --git a/chrome/browser/metrics/power/process_metrics_recorder_util.cc b/chrome/browser/metrics/power/process_metrics_recorder_util.cc index ca6df4d..56a4542a 100644 --- a/chrome/browser/metrics/power/process_metrics_recorder_util.cc +++ b/chrome/browser/metrics/power/process_metrics_recorder_util.cc
@@ -26,14 +26,38 @@ constexpr int kCPUUsageHistogramMax = 200 * kCPUUsageFactor; constexpr int kCPUUsageHistogramBucketCount = 50; +#if BUILDFLAG(IS_WIN) +bool HasConstantRateTSC() { +#if defined(ARCH_CPU_ARM64) + // Constant rate TSC is never support on Arm CPUs. + return false; +#else + // Probe the CPU to detect if constant-rate TSC is supported. + return base::time_internal::HasConstantRateTSC(); +#endif +} +#endif // BUILDFLAG(IS_WIN) + +void RecordAverageCPUUsage(const char* histogram_suffix, double cpu_usage) { +#if BUILDFLAG(IS_WIN) + // Skip recording the average CPU usage if the CPU doesn't support constant + // rate TSC, since Windows does not offer a way to get a precise measurement + // without it. + if (!HasConstantRateTSC()) + return; +#endif + + base::UmaHistogramCustomCounts( + base::StrCat({"PerformanceMonitor.AverageCPU5.", histogram_suffix}), + cpu_usage * kCPUUsageFactor, kCPUUsageHistogramMin, kCPUUsageHistogramMax, + kCPUUsageHistogramBucketCount); +} + } // namespace void RecordProcessHistograms(const char* histogram_suffix, const ProcessMonitor::Metrics& metrics) { - base::UmaHistogramCustomCounts( - base::StrCat({"PerformanceMonitor.AverageCPU4.", histogram_suffix}), - metrics.cpu_usage * kCPUUsageFactor, kCPUUsageHistogramMin, - kCPUUsageHistogramMax, kCPUUsageHistogramBucketCount); + RecordAverageCPUUsage(histogram_suffix, metrics.cpu_usage); #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ BUILDFLAG(IS_AIX) base::UmaHistogramCounts10000(
diff --git a/chrome/browser/metrics/power/process_monitor.cc b/chrome/browser/metrics/power/process_monitor.cc index 0a1ebbb0..1dfa63ac 100644 --- a/chrome/browser/metrics/power/process_monitor.cc +++ b/chrome/browser/metrics/power/process_monitor.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_functions.h" #include "base/observer_list.h" #include "base/process/process_handle.h" #include "base/process/process_metrics.h" @@ -151,6 +152,13 @@ // Do an initial call to SampleMetrics() so that the next one returns // meaningful data. SampleMetrics(*this->process_metrics); + +#if BUILDFLAG(IS_WIN) && !defined(ARCH_CPU_ARM64) + // Record the value of HasConstantRateTSC to get a feel of the proportion of + // users that don't record the average CPU usage histogram. + base::UmaHistogramBoolean("PerformanceMonitor.HasPreciseCPUUsage", + base::time_internal::HasConstantRateTSC()); +#endif } ProcessInfo::~ProcessInfo() = default;
diff --git a/chrome/browser/paint_preview/android/BUILD.gn b/chrome/browser/paint_preview/android/BUILD.gn index 1231141..7202ca8f 100644 --- a/chrome/browser/paint_preview/android/BUILD.gn +++ b/chrome/browser/paint_preview/android/BUILD.gn
@@ -85,9 +85,9 @@ "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/junit", "//third_party/mockito:mockito_java", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:ui_java_test_support", "//ui/android:ui_no_recycler_view_java", "//url:gurl_java",
diff --git a/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java b/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java index 84e1cc0..cdf85318 100644 --- a/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java +++ b/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java
@@ -7,9 +7,8 @@ import static org.chromium.base.test.util.Batch.PER_CLASS; import static org.chromium.chrome.browser.paint_preview.TabbedPaintPreviewTest.assertAttachedAndShown; -import android.support.test.uiautomator.UiObjectNotFoundException; - import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.UiObjectNotFoundException; import org.junit.AfterClass; import org.junit.Assert;
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java index f5a54bcd..4c8cf99e 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -209,6 +209,10 @@ public static final KeyPrefix CUSTOM_TABS_DEX_LAST_UPDATE_TIME_PREF_PREFIX = new KeyPrefix("pref_local_custom_tabs_module_dex_last_update_time_*"); public static final String CUSTOM_TABS_LAST_URL = "pref_last_custom_tab_url"; + public static final String CUSTOM_TABS_LAST_CLOSE_TIMESTAMP = + "Chrome.CustomTabs.LastCloseTimestamp"; + public static final String CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION = + "Chrome.CustomTabs.LastCloseTabInteraction"; /** * Keys used to save whether it is ready to promo. @@ -966,6 +970,8 @@ CONTEXT_MENU_SHOP_IMAGE_WITH_GOOGLE_LENS_CLICKED, CONTINUOUS_SEARCH_DISMISSAL_COUNT, CRYPTID_LAST_RENDER_TIMESTAMP, + CUSTOM_TABS_LAST_CLOSE_TIMESTAMP, + CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION, DEFAULT_BROWSER_PROMO_LAST_DEFAULT_STATE, DEFAULT_BROWSER_PROMO_LAST_PROMO_TIME, DEFAULT_BROWSER_PROMO_PROMOED_BY_SYSTEM_SETTINGS,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index ef28a9d..e4daa3d3 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -253,7 +253,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" #include "ash/public/cpp/clipboard_history_controller.h" -#include "ash/public/cpp/new_window_delegate.h" #include "chrome/browser/ash/arc/arc_util.h" #include "chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" @@ -2765,16 +2764,10 @@ case IDC_CONTENT_CONTEXT_SEARCHWEBFOR: case IDC_CONTENT_CONTEXT_GOTOURL: -#if BUILDFLAG(IS_CHROMEOS_ASH) - ash::NewWindowDelegate::GetPrimary()->OpenUrl( - selection_navigation_url_, - ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction); -#else OpenURL(selection_navigation_url_, GURL(), ui::DispositionFromEventFlags( event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB), ui::PAGE_TRANSITION_LINK); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) break; case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS:
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn index 6219eeb..b4ba693 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
@@ -51,6 +51,7 @@ "dictation/macros/macro.js", "dictation/macros/macro_names.js", "dictation/macros/repeatable_key_press_macro.js", + "dictation/macros/smart_delete_phrase_macro.js", "dictation/macros/stop_listening_macro.js", "dictation/metrics_utils.js", "dictation/parse/input_text_strategy.js", @@ -240,6 +241,7 @@ "dictation/macros/macro.js", "dictation/macros/macro_names.js", "dictation/macros/repeatable_key_press_macro.js", + "dictation/macros/smart_delete_phrase_macro.js", "dictation/macros/stop_listening_macro.js", ] deps = [
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js index ef92840..e5e511a 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js
@@ -477,6 +477,14 @@ runHiddenMacroForTesting(name) { this.hiddenMacroManager_.runMacroForTesting(name); } + + /** + * @param {!MacroName} Name The macro to run. + * @param {string} arg + */ + runHiddenMacroWithStringArgForTesting(name, arg) { + this.hiddenMacroManager_.runMacroWithStringArgForTesting(name, arg); + } } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js index 2e90a38..37de5bcf 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js
@@ -227,6 +227,45 @@ offset }); } + + /** + * Deletes a phrase to the left of the text caret. If multiple instances of + * `phrase` are present, it deletes the one closest to the text caret. + * @param {string} phrase The phrase to be deleted. + */ + smartDeletePhrase(phrase) { + const editableNode = this.focusHandler_.getEditableNode(); + if (!editableNode || !editableNode.value || + editableNode.textSelStart !== editableNode.textSelEnd) { + return; + } + + const value = editableNode.value; + const caretIndex = editableNode.textSelStart; + const leftOfCaret = value.substring(0, caretIndex); + const rightOfCaret = value.substring(caretIndex); + phrase = phrase.toLowerCase().trim(); + + // Require `phrase` to be separated by word boundaries and prefer the + // RegExps that include a leading/trailing space to preserve spacing. + const lastPhrase = new RegExp(`(\\b${phrase}\\b)(?!.*\\b\\1\\b)`, 'i'); + const lastPhraseLeadingSpace = + new RegExp(`(\\b ${phrase}\\b)(?!.*\\b\\1\\b)`, 'i'); + const lastPhraseTrailingSpace = + new RegExp(`(\\b${phrase} \\b)(?!.*\\b\\1\\b)`, 'i'); + + let newLeft; + if (lastPhraseLeadingSpace.test(leftOfCaret)) { + newLeft = leftOfCaret.replace(lastPhraseLeadingSpace, ''); + } else if (lastPhraseTrailingSpace.test(leftOfCaret)) { + newLeft = leftOfCaret.replace(lastPhraseTrailingSpace, ''); + } else { + newLeft = leftOfCaret.replace(lastPhrase, ''); + } + + const newValue = newLeft + rightOfCaret; + editableNode.setValue(newValue); + } } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js index c2ac19a..85c49be 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js
@@ -5,6 +5,7 @@ import {DeletePrevSentMacro} from '/accessibility_common/dictation/macros/delete_prev_sent_macro.js'; import {MacroName} from '/accessibility_common/dictation/macros/macro_names.js'; import {DeletePrevWordMacro, NavNextWordMacro, NavPrevWordMacro} from '/accessibility_common/dictation/macros/repeatable_key_press_macro.js'; +import {SmartDeletePhraseMacro} from '/accessibility_common/dictation/macros/smart_delete_phrase_macro.js'; import {StopListeningMacro} from '/accessibility_common/dictation/macros/stop_listening_macro.js'; /** @@ -40,7 +41,26 @@ new NavPrevWordMacro(/*isRtlLocale=*/ false).runMacro(); break; default: - throw new Error(`Unrecognized macro: ${name}`); + throw new Error(`Cannot run macro: ${name} for testing`); + } + } + + /** + * @param {!MacroName} name The macro to run. + * @param {string} arg + */ + runMacroWithStringArgForTesting(name, arg) { + if (!HiddenMacroManager.isHiddenMacro(name)) { + throw new Error('HiddenMacroManager can only invoke hidden macros.'); + } + + switch (name) { + case MacroName.SMART_DELETE_PHRASE: + new SmartDeletePhraseMacro(this.inputController_, arg).runMacro(); + break; + default: + throw new Error( + `Cannot run macro: ${name} with string arg: ${arg} for testing`); } } @@ -64,4 +84,5 @@ MacroName.DELETE_PREV_SENT, MacroName.NAV_NEXT_WORD, MacroName.NAV_PREV_WORD, + MacroName.SMART_DELETE_PHRASE, ];
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js index eb97588..f63a558 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js
@@ -82,5 +82,8 @@ // Move the cursor to the previous word. NAV_PREV_WORD: 20, + // Deletes a provided word or phrase. + SMART_DELETE_PHRASE: 21, + // Any new actions should match with Voice Access's semantic tags. };
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/smart_delete_phrase_macro.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/smart_delete_phrase_macro.js new file mode 100644 index 0000000..0f3fea966 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/smart_delete_phrase_macro.js
@@ -0,0 +1,37 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {Macro} from '/accessibility_common/dictation/macros/macro.js'; +import {MacroName} from '/accessibility_common/dictation/macros/macro_names.js'; + +/** Implements a macro that deletes a provided word or phrase. */ +export class SmartDeletePhraseMacro extends Macro { + /** + * @param {!InputController} inputController + * @param {string} phrase + */ + constructor(inputController, phrase) { + super(MacroName.SMART_DELETE_PHRASE); + /** @private {!InputController} */ + this.inputController_ = inputController; + /** @private {string} */ + this.phrase_ = phrase; + } + + /** @override */ + checkContext() { + return this.createSuccessCheckContextResult_( + /*willImmediatelyDisambiguate=*/ false); + } + + /** @override */ + runMacro() { + if (!this.inputController_.isActive()) { + return this.createRunMacroResult_( + /*isSuccess=*/ false, MacroError.FAILED_ACTUATION); + } + this.inputController_.smartDeletePhrase(this.phrase_); + return this.createRunMacroResult_(/*isSuccess=*/ true); + } +}
diff --git a/chrome/browser/resources/webui_gallery/BUILD.gn b/chrome/browser/resources/webui_gallery/BUILD.gn index e6e105d..076c0ba3 100644 --- a/chrome/browser/resources/webui_gallery/BUILD.gn +++ b/chrome/browser/resources/webui_gallery/BUILD.gn
@@ -32,6 +32,7 @@ "demos/demo.css", "demos/cr_button_demo.html", "demos/cr_checkbox_demo.html", + "demos/cr_dialog_demo.html", "webui_gallery.html", ] input_files_base_dir = rebase_path(".", "//") @@ -45,7 +46,7 @@ copy("copy_ts_files") { sources = ts_files - outputs = [ "$target_gen_dir/{{source_file_part}}" ] + outputs = [ "$target_gen_dir/{{source_target_relative}}" ] } ts_library("build_ts") {
diff --git a/chrome/browser/resources/webui_gallery/app.ts b/chrome/browser/resources/webui_gallery/app.ts index 8e8ad9f..a7999f4eb 100644 --- a/chrome/browser/resources/webui_gallery/app.ts +++ b/chrome/browser/resources/webui_gallery/app.ts
@@ -33,6 +33,10 @@ { name: 'cr-checkbox demo', url: 'cr_checkbox_demo.html', + }, + { + name: 'cr-dialog demo', + url: 'cr_dialog_demo.html', } ]; },
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo.html new file mode 100644 index 0000000..4ea532e7 --- /dev/null +++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>cr-dialog demo</title> + <link rel="stylesheet" href="demo.css"> + <body> + <cr-dialog-demo></cr-dialog-demo> + <script src="cr_dialog_demo_component.js" type="module"></script> + </body> +</html>
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.html b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.html new file mode 100644 index 0000000..600ef473 --- /dev/null +++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.html
@@ -0,0 +1,78 @@ +<link rel="stylesheet" href="demo.css"> + +<style> + cr-input:first-of-type { + margin-block-start: 16px; + } + + [slot='header'] { + padding: 0 20px 16px; + } + + cr-dialog::part(body-container) { + max-height: 300px; + } + + #tallBlock { + background: var(--google-grey-200); + height: 800px; + margin: 16px 0; + } +</style> + +<h1>cr-dialog</h1> +<div class="demos"> + <cr-checkbox checked="{{showHeader_}}">Show header</cr-checkbox> + <cr-checkbox checked="{{showFooter_}}">Show footer</cr-checkbox> + <cr-checkbox checked="{{showScrollingBody_}}"> + Show tall scrolling body + </cr-checkbox> + <cr-checkbox checked="{{showInputs_}}">Show inputs</cr-checkbox> + <cr-checkbox checked="{{autofocusInput_}}" disabled$="[[!showInputs_]]"> + Autofocus input when dialog opens + </cr-checkbox> + + <cr-button on-click="openDialog_">Open dialog</cr-button> + <div> + <template is="dom-repeat" items="[[statusTexts_]]"> + <div>[[item]]</div> + </template> + </div> +</div> + +<template is="dom-if" if="[[isDialogOpen_]]" restamp> + <cr-dialog + id="dialog" + on-cr-dialog-open="onOpenDialog_" + on-cancel="onCancelDialog_" + on-close="onCloseDialog_" + show-on-attach> + <div slot="title">Dialog title</div> + <div slot="header" hidden$="[[!showHeader_]]"> + Dialogs can also include a header between the title and the body. It is + commonly used to display status updates or tabs. + </div> + <div slot="body"> + <div>Here is where some description text would go.</div> + <div hidden$="[[!showInputs_]]"> + <cr-input label="Example input" autofocus$="[[autofocusInput_]]"> + </cr-input> + <cr-input label="Example input"></cr-input> + </div> + <div hidden$="[[!showScrollingBody_]]"> + <div id="tallBlock"></div> + </div> + </div> + <div slot="button-container"> + <cr-button class="cancel-button" on-click="onClickCancel_"> + Cancel + </cr-button> + <cr-button class="action-button" on-click="onClickConfirm_"> + Confirm + </cr-button> + </div> + <div slot="footer" hidden$="[[!showFooter_]]"> + Dialogs also have a slot for text or other elements in the footer. + </div> + </cr-dialog> +</template> \ No newline at end of file
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.ts b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.ts new file mode 100644 index 0000000..e4af0bda --- /dev/null +++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.ts
@@ -0,0 +1,89 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; +import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; + +import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; + +import {getTemplate} from './cr_dialog_demo_component.html.js'; + +interface CrDialogDemoComponent { + $: { + dialog: CrDialogElement, + }; +} + +class CrDialogDemoComponent extends PolymerElement { + static get is() { + return 'cr-dialog-demo'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + autofocusInputs_: Boolean, + isDialogOpen_: Boolean, + showHeader_: Boolean, + showFooter_: Boolean, + showInputs_: Boolean, + showScrollingBody_: Boolean, + statusTexts_: Array, + }; + } + + private autofocusInputs_: Boolean = false; + private isDialogOpen_: Boolean = false; + private showHeader_: Boolean = false; + private showFooter_: Boolean = false; + private showInputs_: Boolean = false; + private showScrollingBody_: Boolean = false; + private statusTexts_: string[] = []; + + private getDialog_(): CrDialogElement|null { + return this.shadowRoot!.querySelector('cr-dialog'); + } + + private openDialog_() { + this.isDialogOpen_ = true; + } + + private onClickCancel_() { + const dialog = this.getDialog_(); + if (dialog) { + dialog.cancel(); + } + } + + private onClickConfirm_() { + const dialog = this.getDialog_(); + if (dialog) { + dialog.close(); + } + } + + private onOpenDialog_() { + this.statusTexts_ = + ['Dialog was opened and fired a `cr-dialog-open` event.']; + } + + private onCancelDialog_() { + this.push( + 'statusTexts_', 'Dialog was canceled and fired a `cancel` event.'); + } + + private onCloseDialog_() { + this.isDialogOpen_ = false; + this.push('statusTexts_', 'Dialog was closed and fired a `close` event.'); + } +} + +customElements.define(CrDialogDemoComponent.is, CrDialogDemoComponent); \ No newline at end of file
diff --git a/chrome/browser/resources/webui_gallery/webui_gallery.gni b/chrome/browser/resources/webui_gallery/webui_gallery.gni index b11378e..4a3e313 100644 --- a/chrome/browser/resources/webui_gallery/webui_gallery.gni +++ b/chrome/browser/resources/webui_gallery/webui_gallery.gni
@@ -3,7 +3,10 @@ # found in the LICENSE file. # Files holding a Polymer element definition AND have an equivalent .html file. -web_component_files = [ "app.ts" ] +web_component_files = [ + "app.ts", + "demos/cr_dialog_demo_component.ts", +] # Files that are passed as input to html_to_wrapper(). html_files = []
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.cc b/chrome/browser/sessions/chrome_tab_restore_service_client.cc index 5a75d2a..f8d4881 100644 --- a/chrome/browser/sessions/chrome_tab_restore_service_client.cc +++ b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
@@ -36,6 +36,7 @@ sessions::LiveTabContext* ChromeTabRestoreServiceClient::CreateLiveTabContext( sessions::LiveTabContext* existing_context, + sessions::SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state, @@ -48,8 +49,9 @@ DCHECK(existing_context); return existing_context; #else - return BrowserLiveTabContext::Create(profile_, app_name, bounds, show_state, - workspace, user_title, extra_data); + return BrowserLiveTabContext::Create(profile_, type, app_name, bounds, + show_state, workspace, user_title, + extra_data); #endif }
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.h b/chrome/browser/sessions/chrome_tab_restore_service_client.h index 64f7fa8..764d202 100644 --- a/chrome/browser/sessions/chrome_tab_restore_service_client.h +++ b/chrome/browser/sessions/chrome_tab_restore_service_client.h
@@ -26,6 +26,7 @@ // TabRestoreServiceClient: sessions::LiveTabContext* CreateLiveTabContext( sessions::LiveTabContext* existing_context, + sessions::SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state,
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index b4f3be7..01392fd 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -3717,9 +3717,10 @@ web_app::AppId app_id2 = InstallPWA(profile, example_url2); web_app::AppId app_id3 = InstallPWA(profile, example_url3); - // Open all 3. + // Open all 3, browser 2 is app_popup. Browser* app_browser = web_app::LaunchWebAppBrowserAndWait(profile, app_id); - Browser* app_browser2 = web_app::LaunchWebAppBrowserAndWait(profile, app_id2); + Browser* app_browser2 = web_app::LaunchWebAppBrowserAndWait( + profile, app_id2, WindowOpenDisposition::NEW_POPUP); Browser* app_browser3 = web_app::LaunchWebAppBrowserAndWait(profile, app_id3); // 3 apps + basic browser. @@ -3744,17 +3745,18 @@ bool app3_seen = false; ASSERT_EQ(4u, BrowserList::GetInstance()->size()); for (Browser* browser : *(BrowserList::GetInstance())) { - if (browser->type() == Browser::Type::TYPE_APP) { - if (web_app::AppBrowserController::IsForWebApp(browser, app_id)) { - EXPECT_FALSE(app1_seen); - app1_seen = true; - } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id2)) { - EXPECT_FALSE(app2_seen); - app2_seen = true; - } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id3)) { - EXPECT_FALSE(app3_seen); - app3_seen = true; - } + if (web_app::AppBrowserController::IsForWebApp(browser, app_id)) { + EXPECT_FALSE(app1_seen); + EXPECT_TRUE(browser->is_type_app()); + app1_seen = true; + } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id2)) { + EXPECT_FALSE(app2_seen); + EXPECT_TRUE(browser->is_type_app_popup()); + app2_seen = true; + } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id3)) { + EXPECT_FALSE(app3_seen); + EXPECT_TRUE(browser->is_type_app()); + app3_seen = true; } } EXPECT_TRUE(app1_seen);
diff --git a/chrome/browser/sessions/tab_restore_service_unittest.cc b/chrome/browser/sessions/tab_restore_service_unittest.cc index 36e375f..ef78287 100644 --- a/chrome/browser/sessions/tab_restore_service_unittest.cc +++ b/chrome/browser/sessions/tab_restore_service_unittest.cc
@@ -70,6 +70,22 @@ using ::testing::_; using ::testing::Return; +class MockLiveTab : public sessions::LiveTab { + public: + MockLiveTab() = default; + ~MockLiveTab() override = default; + + MOCK_METHOD0(IsInitialBlankNavigation, bool()); + MOCK_METHOD0(GetCurrentEntryIndex, int()); + MOCK_METHOD0(GetPendingEntryIndex, int()); + MOCK_METHOD1(GetEntryAtIndex, sessions::SerializedNavigationEntry(int index)); + MOCK_METHOD0(GetPendingEntry, sessions::SerializedNavigationEntry()); + MOCK_METHOD0(GetEntryCount, int()); + MOCK_METHOD0(GetPlatformSpecificTabData, + std::unique_ptr<sessions::PlatformSpecificTabData>()); + MOCK_METHOD0(GetUserAgentOverride, sessions::SerializedUserAgentOverride()); +}; + class MockLiveTabContext : public sessions::LiveTabContext { public: MockLiveTabContext() = default; @@ -77,6 +93,7 @@ MOCK_METHOD0(ShowBrowserWindow, void()); MOCK_CONST_METHOD0(GetSessionID, SessionID()); + MOCK_CONST_METHOD0(GetWindowType, sessions::SessionWindow::WindowType()); MOCK_CONST_METHOD0(GetTabCount, int()); MOCK_CONST_METHOD0(GetSelectedIndex, int()); MOCK_CONST_METHOD0(GetAppName, std::string()); @@ -135,9 +152,10 @@ MockTabRestoreServiceClient() = default; ~MockTabRestoreServiceClient() override = default; - MOCK_METHOD7(CreateLiveTabContext, + MOCK_METHOD8(CreateLiveTabContext, sessions::LiveTabContext*( sessions::LiveTabContext* existing_context, + sessions::SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state, @@ -445,6 +463,60 @@ ASSERT_EQ(kSampleValue, tab->extra_data[kSampleKey]); } +// Ensure fields are written and read from saved state. +TEST_F(TabRestoreServiceImplWithMockClientTest, WindowRestore) { + ON_CALL(*mock_tab_restore_service_client_, ShouldTrackURLForRestore(_)) + .WillByDefault(Return(true)); + + SerializedNavigationEntry navigation_entry = + SerializedNavigationEntryTestHelper::CreateNavigationForTest(); + testing::NiceMock<MockLiveTab> mock_live_tab; + ON_CALL(mock_live_tab, GetEntryCount).WillByDefault(Return(1)); + ON_CALL(mock_live_tab, GetEntryAtIndex) + .WillByDefault(Return(navigation_entry)); + + testing::NiceMock<MockLiveTabContext> mock_live_tab_context; + SessionID session_id = SessionID::NewUnique(); + ON_CALL(mock_live_tab_context, GetSessionID) + .WillByDefault(Return(session_id)); + ON_CALL(mock_live_tab_context, GetWindowType) + .WillByDefault(Return(sessions::SessionWindow::TYPE_APP_POPUP)); + ON_CALL(mock_live_tab_context, GetAppName).WillByDefault(Return("app-name")); + ON_CALL(mock_live_tab_context, GetUserTitle) + .WillByDefault(Return("user-title")); + ON_CALL(mock_live_tab_context, GetRestoredBounds) + .WillByDefault(Return(gfx::Rect(10, 20, 30, 40))); + ON_CALL(mock_live_tab_context, GetRestoredState) + .WillByDefault(Return(ui::SHOW_STATE_MAXIMIZED)); + ON_CALL(mock_live_tab_context, GetWorkspace) + .WillByDefault(Return("workspace")); + ON_CALL(mock_live_tab_context, GetTabCount).WillByDefault(Return(1)); + ON_CALL(mock_live_tab_context, GetLiveTabAt) + .WillByDefault(Return(&mock_live_tab)); + + service_->BrowserClosing(&mock_live_tab_context); + + // Validate while entries are in memory. + auto validate = [&]() { + ASSERT_EQ(1u, service_->entries().size()); + Entry* entry = service_->entries().front().get(); + EXPECT_EQ(sessions::TabRestoreService::WINDOW, entry->type); + Window* window = static_cast<Window*>(entry); + EXPECT_EQ(sessions::SessionWindow::TYPE_APP_POPUP, window->type); + EXPECT_EQ(0, window->selected_tab_index); + EXPECT_EQ("app-name", window->app_name); + EXPECT_EQ("user-title", window->user_title); + EXPECT_EQ(gfx::Rect(10, 20, 30, 40), window->bounds); + EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, window->show_state); + EXPECT_EQ("workspace", window->workspace); + }; + validate(); + + // Validate after persisting and reading from storage. + RecreateService(); + validate(); +} + // Make sure TabRestoreService doesn't create an entry for a tab with no // navigations. TEST_F(TabRestoreServiceImplTest, DontCreateEmptyTab) { @@ -734,6 +806,7 @@ ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry2->type); sessions::TabRestoreService::Window* window = static_cast<sessions::TabRestoreService::Window*>(entry2); + EXPECT_EQ(sessions::SessionWindow::TYPE_NORMAL, window->type); ASSERT_EQ(1U, window->tabs.size()); EXPECT_EQ(0, window->timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds()); EXPECT_EQ(0, window->selected_tab_index);
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 446f40f1..fd3c36b 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -97,7 +97,7 @@ // changed default theme assets, if you need themes to recreate their generated // images (which are cached), if you changed how missing values are // generated, or if you changed any constants. -const int kThemePackVersion = 100; +const int kThemePackVersion = 101; // IDs that are in the DataPack won't clash with the positive integer // uint16_t. kHeaderID should always have the maximum value because we want the @@ -1129,8 +1129,7 @@ {TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE, kColorWindowControlButtonBackgroundActive}, {TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE, - kColorWindowControlButtonBackgroundInactive}, - }; + kColorWindowControlButtonBackgroundInactive}}; for (const auto& entry : kThemePropertiesMap) { SkColor color;
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc index 11a0b68..0ea1acb 100644 --- a/chrome/browser/themes/theme_helper.cc +++ b/chrome/browser/themes/theme_helper.cc
@@ -38,97 +38,6 @@ // unpacked on the filesystem.) constexpr char kDefaultThemeGalleryID[] = "hkacjpbfdknhflllbcmjibkdeoafencn"; -// Returns an array of light and dark mode versions of the given color id -// Ex: [light mode, dark mode] -const std::array<SkColor, 2> GetTabGroupColors(int color_id) { - // Depending on UI variation enabled, dark mode saved group chip colors are - // calculated by blending the default dark mode toolbar color with the tab - // strip group colors at 24% or 48% alpha. - const SkColor default_dark_toolbar_color = - TP::GetDefaultColor(TP::COLOR_TOOLBAR, false, true); - float tab_group_chip_alpha = 0.24f; - - // Flat version of dark mode colors used in bookmarks bar to fill - // the buttons. - const SkColor kFlatGrey = SkColorSetRGB(0x5D, 0x5E, 0x62); - const SkColor kFlatBlue = SkColorSetRGB(0x49, 0x54, 0x68); - const SkColor kFlatRed = SkColorSetRGB(0x62, 0x4A, 0x4B); - const SkColor kFlatGreen = SkColorSetRGB(0x47, 0x59, 0x50); - const SkColor kFlatYellow = SkColorSetRGB(0x65, 0x5C, 0x44); - const SkColor kFlatCyan = SkColorSetRGB(0x45, 0x5D, 0x65); - const SkColor kFlatPurple = SkColorSetRGB(0x58, 0x4A, 0x68); - const SkColor kFlatPink = SkColorSetRGB(0x65, 0x4A, 0x5D); - const SkColor kFlatOrange = color_utils::AlphaBlend( - gfx::kGoogleOrange300, default_dark_toolbar_color, tab_group_chip_alpha); - - switch (color_id) { - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE: - case TP::COLOR_TAB_GROUP_DIALOG_BLUE: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE: - return {gfx::kGoogleBlue600, gfx::kGoogleBlue300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE: - return {gfx::kGoogleBlue050, kFlatBlue}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED: - case TP::COLOR_TAB_GROUP_DIALOG_RED: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED: - return {gfx::kGoogleRed600, gfx::kGoogleRed300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED: - return {gfx::kGoogleRed050, kFlatRed}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW: - case TP::COLOR_TAB_GROUP_DIALOG_YELLOW: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW: - return {gfx::kGoogleYellow600, gfx::kGoogleYellow300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW: - return {gfx::kGoogleYellow050, kFlatYellow}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN: - case TP::COLOR_TAB_GROUP_DIALOG_GREEN: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN: - return {gfx::kGoogleGreen700, gfx::kGoogleGreen300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN: - return {gfx::kGoogleGreen050, kFlatGreen}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK: - case TP::COLOR_TAB_GROUP_DIALOG_PINK: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK: - return {gfx::kGooglePink700, gfx::kGooglePink300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK: - return {gfx::kGooglePink050, kFlatPink}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE: - case TP::COLOR_TAB_GROUP_DIALOG_PURPLE: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE: - return {gfx::kGooglePurple500, gfx::kGooglePurple300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE: - return {gfx::kGooglePurple050, kFlatPurple}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN: - case TP::COLOR_TAB_GROUP_DIALOG_CYAN: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN: - return {gfx::kGoogleCyan900, gfx::kGoogleCyan300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN: - return {gfx::kGoogleCyan050, kFlatCyan}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE: - case TP::COLOR_TAB_GROUP_DIALOG_ORANGE: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE: - return {gfx::kGoogleOrange400, gfx::kGoogleOrange300}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE: - return {gfx::kGoogleOrange050, kFlatOrange}; - case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY: - return {gfx::kGoogleGrey100, kFlatGrey}; - case TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY: - case TP::COLOR_TAB_GROUP_DIALOG_GREY: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY: - case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY: - default: - return {gfx::kGoogleGrey700, gfx::kGoogleGrey300}; - } -} - SkColor IncreaseLightness(SkColor color, double percent) { color_utils::HSL result; color_utils::SkColorToHSL(color, &result); @@ -314,10 +223,6 @@ int id, bool incognito, const CustomThemeSupplier* theme_supplier) const { - if (TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY <= id && - id <= TP::MAX_COLOR_BOOKMARK_BAR) - return GetTabGroupColor(id, incognito, theme_supplier); - const absl::optional<SkColor> omnibox_color = GetOmniboxColor(id, incognito, theme_supplier); if (omnibox_color.has_value()) @@ -697,32 +602,3 @@ return absl::nullopt; } } - -SkColor ThemeHelper::GetTabGroupColor( - int id, - bool incognito, - const CustomThemeSupplier* theme_supplier) const { - // Deal with tab group colors in the tabstrip. - if (id <= TP::MAX_COLOR_TABSTRIP_INACTIVE) { - int tab_color_id = id < TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY - ? TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_ACTIVE - : TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_INACTIVE; - - return GetTabGroupColors(id)[color_utils::IsDark( - GetColor(tab_color_id, incognito, theme_supplier))]; - } - - // Deal with the rest of the tab group colors. - bool use_dark_mode_colors; - if (id >= TP::COLOR_TAB_GROUP_DIALOG_GREY && - id <= TP::MAX_COLOR_BOOKMARK_BAR) { - // To support custom themes, assume that the dark mode palette is more - // appropriate for bookmark chips, tab group dialog bubble, and context sub - // menu when the bookmark bar appears to be light text on dark bookmark bar. - use_dark_mode_colors = !color_utils::IsDark( - GetColor(TP::COLOR_BOOKMARK_TEXT, incognito, theme_supplier)); - } else { - use_dark_mode_colors = UseDarkModeColors(theme_supplier); - } - return GetTabGroupColors(id)[incognito || use_dark_mode_colors]; -}
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h index 599ca7f..14a6806 100644 --- a/chrome/browser/themes/theme_properties.h +++ b/chrome/browser/themes/theme_properties.h
@@ -179,71 +179,6 @@ // kThemePackVersion in browser_theme_pack.cc, or else themes will display // incorrectly. - // Note: All tab group color ids must be grouped together consecutively and - // grouped together by use (eg grouped by dialog, context menu etc). - // This permits range checking and reduces redundant code. If you change or - // add to any of the below color ids, change the relevant code in - // ThemeHelper. - - // The colors used for tab groups in the tabstrip. - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN, - COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN, - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, - // The colors used for tab groups in the bubble dialog view. - COLOR_TAB_GROUP_DIALOG_GREY, - COLOR_TAB_GROUP_DIALOG_BLUE, - COLOR_TAB_GROUP_DIALOG_RED, - COLOR_TAB_GROUP_DIALOG_YELLOW, - COLOR_TAB_GROUP_DIALOG_GREEN, - COLOR_TAB_GROUP_DIALOG_PINK, - COLOR_TAB_GROUP_DIALOG_PURPLE, - COLOR_TAB_GROUP_DIALOG_CYAN, - COLOR_TAB_GROUP_DIALOG_ORANGE, - // The colors used for tab groups in the context submenu. - COLOR_TAB_GROUP_CONTEXT_MENU_GREY, - COLOR_TAB_GROUP_CONTEXT_MENU_BLUE, - COLOR_TAB_GROUP_CONTEXT_MENU_RED, - COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW, - COLOR_TAB_GROUP_CONTEXT_MENU_GREEN, - COLOR_TAB_GROUP_CONTEXT_MENU_PINK, - COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE, - COLOR_TAB_GROUP_CONTEXT_MENU_CYAN, - COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE, - // The colors used for saved tab group chips on the bookmark bar. - COLOR_TAB_GROUP_BOOKMARK_BAR_GREY, - COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE, - COLOR_TAB_GROUP_BOOKMARK_BAR_RED, - COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW, - COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN, - COLOR_TAB_GROUP_BOOKMARK_BAR_PINK, - COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE, - COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN, - COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, - // If additional colors are ever added, update these references to those - // colors - MAX_COLOR_TABSTRIP_INACTIVE = - COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, - MAX_COLOR_BOOKMARK_BAR = COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, - - // /!\ If you make any changes to this enum, you must also increment - // kThemePackVersion in browser_theme_pack.cc, or else themes will display - // incorrectly. - // Calculated representative colors for the background of window control // buttons. COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index 5d2c348a9..4c3ae66 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -212,79 +212,6 @@ kColorTabForegroundInactiveFrameActive}, {TP::COLOR_TAB_FOREGROUND_INACTIVE_FRAME_INACTIVE, kColorTabForegroundInactiveFrameInactive}, - // The colors used for tab groups in the tabstrip. - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE, - kColorTabGroupTabStripFrameActiveBlue}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN, - kColorTabGroupTabStripFrameActiveCyan}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN, - kColorTabGroupTabStripFrameActiveGreen}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY, - kColorTabGroupTabStripFrameActiveGrey}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE, - kColorTabGroupTabStripFrameActiveOrange}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK, - kColorTabGroupTabStripFrameActivePink}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE, - kColorTabGroupTabStripFrameActivePurple}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED, - kColorTabGroupTabStripFrameActiveRed}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW, - kColorTabGroupTabStripFrameActiveYellow}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE, - kColorTabGroupTabStripFrameInactiveBlue}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN, - kColorTabGroupTabStripFrameInactiveCyan}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN, - kColorTabGroupTabStripFrameInactiveGreen}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY, - kColorTabGroupTabStripFrameInactiveGrey}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, - kColorTabGroupTabStripFrameInactiveOrange}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK, - kColorTabGroupTabStripFrameInactivePink}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE, - kColorTabGroupTabStripFrameInactivePurple}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED, - kColorTabGroupTabStripFrameInactiveRed}, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW, - kColorTabGroupTabStripFrameInactiveYellow}, - // The colors used for tab groups in the bubble dialog view. - {TP::COLOR_TAB_GROUP_DIALOG_BLUE, kColorTabGroupDialogBlue}, - {TP::COLOR_TAB_GROUP_DIALOG_CYAN, kColorTabGroupDialogCyan}, - {TP::COLOR_TAB_GROUP_DIALOG_GREEN, kColorTabGroupDialogGreen}, - {TP::COLOR_TAB_GROUP_DIALOG_GREY, kColorTabGroupDialogGrey}, - {TP::COLOR_TAB_GROUP_DIALOG_ORANGE, kColorTabGroupDialogOrange}, - {TP::COLOR_TAB_GROUP_DIALOG_PINK, kColorTabGroupDialogPink}, - {TP::COLOR_TAB_GROUP_DIALOG_PURPLE, kColorTabGroupDialogPurple}, - {TP::COLOR_TAB_GROUP_DIALOG_RED, kColorTabGroupDialogRed}, - {TP::COLOR_TAB_GROUP_DIALOG_YELLOW, kColorTabGroupDialogYellow}, - // The colors used for tab groups in the context submenu. - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE, kColorTabGroupContextMenuBlue}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN, kColorTabGroupContextMenuCyan}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN, kColorTabGroupContextMenuGreen}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY, kColorTabGroupContextMenuGrey}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK, kColorTabGroupContextMenuPink}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE, - kColorTabGroupContextMenuPurple}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE, - kColorTabGroupContextMenuOrange}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED, kColorTabGroupContextMenuRed}, - {TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW, - kColorTabGroupContextMenuYellow}, - // The colors used for saved tab group chips on the bookmark bar. - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE, kColorTabGroupBookmarkBarBlue}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN, kColorTabGroupBookmarkBarCyan}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN, kColorTabGroupBookmarkBarGreen}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY, kColorTabGroupBookmarkBarGrey}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, - kColorTabGroupBookmarkBarOrange}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK, kColorTabGroupBookmarkBarPink}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE, - kColorTabGroupBookmarkBarPurple}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED, kColorTabGroupBookmarkBarRed}, - {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW, - kColorTabGroupBookmarkBarYellow}, {TP::COLOR_TAB_STROKE_FRAME_ACTIVE, kColorTabStrokeFrameActive}, {TP::COLOR_TAB_STROKE_FRAME_INACTIVE, kColorTabStrokeFrameInactive}, // Toolbar and associated colors.
diff --git a/chrome/browser/themes/theme_service_test_utils.h b/chrome/browser/themes/theme_service_test_utils.h index dc06778..e2f2bf7 100644 --- a/chrome/browser/themes/theme_service_test_utils.h +++ b/chrome/browser/themes/theme_service_test_utils.h
@@ -27,7 +27,6 @@ {ThemeProperties::COLOR_OMNIBOX_RESULTS_TEXT_SECONDARY_SELECTED, 1}, {ThemeProperties::COLOR_STATUS_BUBBLE_INACTIVE, 1}, {ThemeProperties::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_INACTIVE, 1}, - {ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, 1}, {ThemeProperties::COLOR_TAB_STROKE_FRAME_INACTIVE, 1}, {ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR_FRAME_INACTIVE, 1}, {ThemeProperties::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE, 1}});
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc index 8288dfe..6ef8b508 100644 --- a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc +++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/android/tab_model/tab_model_list.h" #include "components/sessions/content/content_live_tab.h" #include "components/sessions/content/content_serialized_navigation_builder.h" +#include "components/sessions/core/session_types.h" #include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" #include "content/public/browser/browser_context.h" @@ -29,6 +30,12 @@ return tab_model_->GetSessionId(); } +sessions::SessionWindow::WindowType AndroidLiveTabContext::GetWindowType() + const { + // Not applicable to android. + return sessions::SessionWindow::TYPE_NORMAL; +} + int AndroidLiveTabContext::GetTabCount() const { return tab_model_->GetTabCount(); }
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.h b/chrome/browser/ui/android/tab_model/android_live_tab_context.h index c14b1a4..bf27884 100644 --- a/chrome/browser/ui/android/tab_model/android_live_tab_context.h +++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.h
@@ -33,6 +33,7 @@ // Overridden from LiveTabContext: void ShowBrowserWindow() override; SessionID GetSessionID() const override; + sessions::SessionWindow::WindowType GetWindowType() const override; int GetTabCount() const override; int GetSelectedIndex() const override; std::string GetAppName() const override;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java index ca95779..29dd13e1 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java
@@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import androidx.annotation.StringRes; +import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant; import org.chromium.chrome.browser.user_education.IPHCommandBuilder; @@ -49,6 +50,7 @@ private final IPHCommandBuilder mIPHCommandBuilder; @AdaptiveToolbarButtonVariant private final int mButtonVariant; + private final boolean mIsDynamicAction; public ButtonSpec(@NonNull Drawable drawable, @NonNull View.OnClickListener onClickListener, @Nullable View.OnLongClickListener onLongClickListener, int contentDescriptionResId, @@ -61,6 +63,7 @@ mSupportsTinting = supportsTinting; mIPHCommandBuilder = iphCommandBuilder; mButtonVariant = buttonVariant; + mIsDynamicAction = AdaptiveToolbarFeatures.isDynamicAction(mButtonVariant); } /** Returns the {@link Drawable} for the button icon. */ @@ -107,5 +110,10 @@ public int getButtonVariant() { return mButtonVariant; } + + /** Returns {@code true} if the button is a contextual page action. False otherwise. */ + public boolean isDynamicAction() { + return mIsDynamicAction; + } } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java index 8251bd1..17a0a0b 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
@@ -167,7 +167,8 @@ if (receivedButtonData == null) return null; if (!mIsSessionVariantRecorded && receivedButtonData.canShow() - && receivedButtonData.isEnabled()) { + && receivedButtonData.isEnabled() + && !receivedButtonData.getButtonSpec().isDynamicAction()) { mIsSessionVariantRecorded = true; RecordHistogram.recordEnumeratedHistogram( "Android.AdaptiveToolbarButton.SessionVariant", @@ -270,4 +271,11 @@ }); } } + + /** Called to notify the controller that a dynamic action is available and should be shown. */ + public void showDynamicAction(@AdaptiveToolbarButtonVariant int action) { + // TODO(shaktisahu): Fix logic to show the next preferred button. + setSingleProvider(mButtonDataProviderMap.get(action)); + notifyObservers(action != AdaptiveToolbarButtonVariant.UNKNOWN); + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java index 685f027..c06bfdc 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
@@ -86,10 +86,25 @@ int VOICE = 4; int AUTO = 5; int PRICE_TRACKING = 6; - int NUM_ENTRIES = 7; } + /** @return Whether the button variant is a dynamic action. */ + public static boolean isDynamicAction(@AdaptiveToolbarButtonVariant int variant) { + switch (variant) { + case AdaptiveToolbarButtonVariant.UNKNOWN: + case AdaptiveToolbarButtonVariant.NONE: + case AdaptiveToolbarButtonVariant.NEW_TAB: + case AdaptiveToolbarButtonVariant.SHARE: + case AdaptiveToolbarButtonVariant.VOICE: + case AdaptiveToolbarButtonVariant.AUTO: + return false; + case AdaptiveToolbarButtonVariant.PRICE_TRACKING: + return true; + } + return false; + } + /** * Returns whether the adaptive toolbar is enabled in single variant mode. Returns true also to * provide legacy support for feature flags {@code ShareButtonInTopToolbar} and {@code @@ -128,6 +143,15 @@ } /** + * @return Whether contextual page actions are enabled. + */ + public static boolean isContextualPageActionUiEnabled() { + return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_PAGE_ACTIONS) + && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.CONTEXTUAL_PAGE_ACTIONS, "enable_ui", true); + } + + /** * When the adaptive toolbar is configured in a single button variant mode, returns the {@link * AdaptiveToolbarButtonVariant} being used. *
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java index afa4b617..206eeb9 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
@@ -220,8 +220,7 @@ * Conversion method between {@link SegmentId} and {@link * AdaptiveToolbarButtonVariant}. */ - @VisibleForTesting - static @AdaptiveToolbarButtonVariant int getAdaptiveToolbarButtonVariantFromSegmentId( + public static @AdaptiveToolbarButtonVariant int getAdaptiveToolbarButtonVariantFromSegmentId( SegmentId segmentId) { switch (segmentId) { case OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index 54fb554..9e3813b 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -223,11 +223,13 @@ const char kPlayStorePackage[] = "com.android.vending"; // App IDs, kept in sorted order. +const char kAndroidContactsAppId[] = "kipfkokfekalckplgaikemhghlbkgpfl"; const char kGmailAppId[] = "hhkfkjpmacfncmbapfohfocpjpdnobjg"; const char kGoogleCalendarAppId[] = "decaoeahkmjpajbmlbpogjjkjbjokeed"; const char kGoogleDuoAppId[] = "djkcbcmkefiiphjkonbeknmcgiheajce"; const char kGoogleMapsAppId[] = "gmhipfhgnoelkiiofcnimehjnpaejiel"; const char kGooglePhotosAppId[] = "fdbkkojdbojonckghlanfaopfakedeca"; +const char kGoogleTVAppId[] = "kadljooblnjdohjelobhphgeimdbcpbo"; const char kInfinitePainterAppId[] = "afihfgfghkmdmggakhkgnfhlikhdpima"; const char kLightRoomAppId[] = "fpegfnbgomakooccabncdaelhfppceni"; const char kPlayBooksAppId[] = "cafegjnmmjpfibnlddppihpnkbkgicbg"; @@ -239,7 +241,6 @@ const char kYoutubeAppId[] = "aniolghapcdkoolpkffememnhpphmjkl"; const char kYoutubeMusicAppId[] = "hpdkdmlckojaocbedhffglopeafcgggc"; const char kYoutubeMusicWebApkAppId[] = "jcmmigapnpnikbmnjknhcoageaeinihi"; -const char kAndroidContactsAppId[] = "kipfkokfekalckplgaikemhghlbkgpfl"; bool ShouldShowInLauncher(const std::string& app_id) { for (auto* const id : kAppIdsHiddenInLauncher) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h index 39f4c30..c8d93e6 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.h +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -28,12 +28,14 @@ extern const char kPlayStoreActivity[]; extern const char kPlayStorePackage[]; +extern const char kAndroidContactsAppId[]; extern const char kCameraMigrationAppId[]; extern const char kGmailAppId[]; extern const char kGoogleCalendarAppId[]; extern const char kGoogleDuoAppId[]; extern const char kGoogleMapsAppId[]; extern const char kGooglePhotosAppId[]; +extern const char kGoogleTVAppId[]; extern const char kInfinitePainterAppId[]; extern const char kLightRoomAppId[]; extern const char kPlayBooksAppId[]; @@ -45,7 +47,6 @@ extern const char kYoutubeAppId[]; extern const char kYoutubeMusicAppId[]; extern const char kYoutubeMusicWebApkAppId[]; -extern const char kAndroidContactsAppId[]; // Observes ARC app launches. class AppLaunchObserver : public base::CheckedObserver {
diff --git a/chrome/browser/ui/ash/desks/desks_client.cc b/chrome/browser/ui/ash/desks/desks_client.cc index 56c3e4e2..5539ce8 100644 --- a/chrome/browser/ui/ash/desks/desks_client.cc +++ b/chrome/browser/ui/ash/desks/desks_client.cc
@@ -45,7 +45,7 @@ "The maximum number of desks is already open."; constexpr char kMissingTemplateDataError[] = "The desk template has invalid or missing data."; -constexpr char kStorageError[] = "The operation failed due to a storage error."; +constexpr char kStorageError[] = "Storage error."; constexpr char kNoCurrentUserError[] = "There is no active profile."; constexpr char kBadProfileError[] = "Either the profile is not valid or there is not an active proflile."; @@ -292,8 +292,10 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } -void DesksClient::LaunchDeskTemplate(const std::string& template_uuid, - LaunchDeskTemplateCallback callback) { +void DesksClient::LaunchDeskTemplate( + const std::string& template_uuid, + LaunchDeskCallback callback, + const std::u16string& customized_desk_name) { base::Time launch_started = base::Time::Now(); if (!active_profile_) { @@ -303,16 +305,26 @@ if (launch_template_for_test_) { OnGetTemplateForDeskLaunch( - std::move(callback), base::Time(), + std::move(callback), customized_desk_name, base::Time(), desks_storage::DeskModel::GetEntryByUuidStatus::kOk, launch_template_for_test_->Clone()); return; } GetDeskModel()->GetEntryByUUID( - template_uuid, base::BindOnce(&DesksClient::OnGetTemplateForDeskLaunch, - weak_ptr_factory_.GetWeakPtr(), - std::move(callback), launch_started)); + template_uuid, + base::BindOnce(&DesksClient::OnGetTemplateForDeskLaunch, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + customized_desk_name, launch_started)); +} + +void DesksClient::LaunchEmptyDesk(LaunchDeskCallback callback, + const std::u16string& customized_desk_name) { + desks_controller_->CreateNewDeskForTemplate( + /*activate_desk=*/true, + base::BindOnce(&DesksClient::OnLaunchEmptyDesk, + weak_ptr_factory_.GetWeakPtr(), std::move(callback)), + customized_desk_name); } void DesksClient::RemoveDesk(const base::GUID& desk_uuid, @@ -342,7 +354,7 @@ return; } - std::move(callback).Run(""); + std::move(callback).Run(/*error=*/""); } void DesksClient::GetAllDesks(GetAllDesksCallback callback) { @@ -465,7 +477,8 @@ } void DesksClient::OnGetTemplateForDeskLaunch( - LaunchDeskTemplateCallback callback, + LaunchDeskCallback callback, + std::u16string customized_desk_name, base::Time time_launch_started, desks_storage::DeskModel::GetEntryByUuidStatus status, std::unique_ptr<ash::DeskTemplate> entry) { @@ -477,15 +490,20 @@ const auto template_name = entry->template_name(); const bool activate_desk = entry->type() == ash::DeskTemplateType::kTemplate; desks_controller_->CreateNewDeskForTemplate( - template_name, activate_desk, - base::BindOnce(&DesksClient::OnCreateAndActivateNewDesk, + activate_desk, + base::BindOnce(&DesksClient::OnCreateAndActivateNewDeskForTemplate, weak_ptr_factory_.GetWeakPtr(), std::move(entry), - std::move(callback), time_launch_started)); + std::move(callback), time_launch_started), + // We prioritize `customized_desk_name` over `template_name`. An example + // is that for call center application use case, we launch the same + // template for different customer and assign desk name to be customer's + // name. + customized_desk_name.empty() ? template_name : customized_desk_name); } -void DesksClient::OnCreateAndActivateNewDesk( +void DesksClient::OnCreateAndActivateNewDeskForTemplate( std::unique_ptr<ash::DeskTemplate> desk_template, - LaunchDeskTemplateCallback callback, + LaunchDeskCallback callback, base::Time time_launch_started, const ash::Desk* new_desk) { if (new_desk == nullptr) { @@ -509,6 +527,17 @@ std::move(callback).Run("", new_desk->uuid()); } +void DesksClient::OnLaunchEmptyDesk(LaunchDeskCallback callback, + const ash::Desk* new_desk) { + if (!new_desk) { + // This will only fail if the number of desks is at a maximum. + std::move(callback).Run(kMaximumDesksOpenedError, {}); + return; + } + + std::move(callback).Run(/*error=*/"", new_desk->uuid()); +} + void DesksClient::OnCaptureActiveDeskAndSaveTemplate( DesksClient::CaptureActiveDeskAndSaveTemplateCallback callback, std::unique_ptr<ash::DeskTemplate> desk_template,
diff --git a/chrome/browser/ui/ash/desks/desks_client.h b/chrome/browser/ui/ash/desks/desks_client.h index 89a45f8..69a4247 100644 --- a/chrome/browser/ui/ash/desks/desks_client.h +++ b/chrome/browser/ui/ash/desks/desks_client.h
@@ -109,17 +109,28 @@ Profile* profile, GetTemplateJsonCallback callback); - using LaunchDeskTemplateCallback = + using LaunchDeskCallback = base::OnceCallback<void(std::string error, const base::GUID& desk_uuid)>; - // Launches the desk template with |template_uuid| as a new desk. - // |template_uuid| should be the unique id for an existing desk template. If + // Launches the desk template with `template_uuid` as a new desk. + // `template_uuid` should be the unique id for an existing desk template. If // no such id can be found or we are at the max desk limit (currently is 8) - // so can't create new desk for the desk template, |callback| will be invoked - // with a description of the error and the new desk uuid. + // so can't create new desk for the desk template, `callback` will be invoked + // with a description of the error and the new desk uuid. If + // `customized_desk_name` is provided, desk name will be set to + // `customized_desk_name` or `customized_desk_name ({counter})` to resolve + // naming conflicts. Otherwise, desk name will be set to auto generated name. // TODO(crbug.com/1286515): This will be removed with the extension. Avoid // further uses of this method. - void LaunchDeskTemplate(const std::string& template_uuid, - LaunchDeskTemplateCallback callback); + void LaunchDeskTemplate( + const std::string& template_uuid, + LaunchDeskCallback callback, + const std::u16string& customized_desk_name = std::u16string()); + + // Launches an empty new desk. Desk name will be set to `customized_desk_name` + // variant if it's provided, otherwise will be set to auto generated name. + void LaunchEmptyDesk( + LaunchDeskCallback callback, + const std::u16string& customized_desk_name = std::u16string()); using CloseAllCallBack = base::OnceCallback<void(std::string error)>; // Remove a desk, close all windows if `close_all` set to true, otherwise @@ -154,19 +165,25 @@ // Launches DeskTemplate after retrieval from storage. void OnGetTemplateForDeskLaunch( - LaunchDeskTemplateCallback callback, + LaunchDeskCallback callback, + std::u16string customized_desk_name, base::Time time_launch_started, desks_storage::DeskModel::GetEntryByUuidStatus status, std::unique_ptr<ash::DeskTemplate> entry); - // Callback function that is ran after a desk is created, or has failed to be - // created. - void OnCreateAndActivateNewDesk( + // Callback function that is run after a desk is created for a template, or + // has failed to be created. + void OnCreateAndActivateNewDeskForTemplate( std::unique_ptr<ash::DeskTemplate> desk_template, - LaunchDeskTemplateCallback callback, + LaunchDeskCallback callback, base::Time time_launch_started, const ash::Desk* new_desk); + // Callback function that is run after a desk is created, or has failed to + // be created. + void OnLaunchEmptyDesk(LaunchDeskCallback callback, + const ash::Desk* new_desk); + // Callback function that allows the |CaptureActiveDeskAndSaveTemplate| // |callback| to be called as a |desks_storage::AddOrUpdateEntryCallback|. void OnCaptureActiveDeskAndSaveTemplate(
diff --git a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc index 6544080..75d0538 100644 --- a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc +++ b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
@@ -43,6 +43,7 @@ #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h" #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h" +#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/policy/policy_test_utils.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" @@ -2107,6 +2108,53 @@ })); } +// Tests launch an empty desk with `desk_name` provided. +IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, + LaunchEmptyDeskWithProvidedName) { + auto* desks_controller = ash::DesksController::Get(); + // Should have 1 default active desk. + EXPECT_EQ(1, desks_controller->desks().size()); + + base::RunLoop loop; + std::u16string desk_name(u"test"); + DesksClient::Get()->LaunchEmptyDesk( + base::BindLambdaForTesting( + [&](std::string error, const base::GUID& desk_uuid) { + EXPECT_TRUE(error.empty()); + // Launch one template, desk size should increase by 1. + EXPECT_EQ(2, desks_controller->desks().size()); + // `desk_name` should be set as provided + EXPECT_EQ(desk_name, desks_controller->desks().back()->name()); + // `desk_uuid` should be returned. + EXPECT_TRUE(desk_uuid.AsLowercaseString().size() > 0); + loop.Quit(); + }), + desk_name); + loop.Run(); +} + +// Tests launch an empty desk with default name. +IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, + LaunchEmptyDeskWithDefaultName) { + auto* desks_controller = ash::DesksController::Get(); + // Should have 1 default active desk. + EXPECT_EQ(1, desks_controller->desks().size()); + + base::RunLoop loop; + DesksClient::Get()->LaunchEmptyDesk(base::BindLambdaForTesting( + [&](std::string error, const base::GUID& desk_uuid) { + EXPECT_TRUE(error.empty()); + // Launch one template, desk size should increase by 1. + EXPECT_EQ(2, desks_controller->desks().size()); + // `desk_name` should be set as default desk name + EXPECT_EQ(u"Desk 2", desks_controller->desks().back()->name()); + // `desk_uuid` should be returned. + EXPECT_TRUE(desk_uuid.AsLowercaseString().size() > 0); + loop.Quit(); + })); + loop.Run(); +} + class DesksTemplatesClientArcTest : public InProcessBrowserTest { public: DesksTemplatesClientArcTest() { @@ -2360,3 +2408,10 @@ EXPECT_FALSE( ContainUuidInTemplates(kTestAdminTemplateUuid, GetDeskTemplates())); } + +using DesksExtensionApiTest = extensions::ExtensionApiTest; +IN_PROC_BROWSER_TEST_F(DesksExtensionApiTest, TestDesksClientExtension) { + // This loads and runs an extension from + // chrome/test/data/extensions/api_test/wm_desks_private. + ASSERT_TRUE(RunExtensionTest("wm_desks_private")); +}
diff --git a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc index 9072920..d8354be 100644 --- a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc +++ b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -30,14 +30,14 @@ #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Internal builds add an extra accelerator for the Feedback app. // The total number of Chrome accelerators (available on Chrome OS). -constexpr int kChromeAcceleratorsTotalNum = 102; +constexpr int kChromeAcceleratorsTotalNum = 103; // The hash of Chrome accelerators (available on Chrome OS). -constexpr char kChromeAcceleratorsHash[] = "672b2d00632c66337b6323da9c75e3a2"; +constexpr char kChromeAcceleratorsHash[] = "c4e99672a6945b80f84be385899c7fa5"; #else // The total number of Chrome accelerators (available on Chrome OS). -constexpr int kChromeAcceleratorsTotalNum = 101; +constexpr int kChromeAcceleratorsTotalNum = 102; // The hash of Chrome accelerators (available on Chrome OS). -constexpr char kChromeAcceleratorsHash[] = "7143dc8ef5efe3fc6047e864f589386f"; +constexpr char kChromeAcceleratorsHash[] = "9a7ba4b726beaba00d7e038ea2ed9c53"; #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) const char* BooleanToString(bool value) {
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index b292a6b1..c582ceb8 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -105,6 +105,16 @@ #include "ui/ozone/public/ozone_platform.h" #endif +// TODO(https://crbug.com/1331331): Clean this up after the deprecation period. +#if BUILDFLAG(ENABLE_PRINTING) +#include "chrome/browser/infobars/simple_alert_infobar_creator.h" +#include "chrome/browser/ui/accelerator_utils.h" +#include "chrome/grit/generated_resources.h" +#include "components/infobars/content/content_infobar_manager.h" +#include "components/vector_icons/vector_icons.h" +#include "ui/base/l10n/l10n_util.h" +#endif + using WebExposedIsolationLevel = content::RenderFrameHost::WebExposedIsolationLevel; @@ -160,6 +170,28 @@ return true; } +#if BUILDFLAG(ENABLE_PRINTING) +// TODO(https://crbug.com/1331331): Clean this up after the deprecation period. +void ShowDeprecatedBasicPrintInfoBar(Browser* browser) { + ui::AcceleratorProvider* provider = + chrome::AcceleratorProviderForBrowser(browser); + + ui::Accelerator accelerator; + bool success = + provider->GetAcceleratorForCommandId(IDC_BASIC_PRINT, &accelerator); + DCHECK(success); + + auto message = l10n_util::GetStringFUTF16( + IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT, accelerator.GetShortcutText()); + CreateSimpleAlertInfoBar( + infobars::ContentInfoBarManager::FromWebContents( + browser->tab_strip_model()->GetActiveWebContents()), + infobars::InfoBarDelegate::BASIC_PRINT_DEPRECATED_ACCELERATOR_DELEGATE, + &vector_icons::kWarningIcon, message, + /*auto_expire=*/false, /*should_animate=*/true); +} +#endif // BUILDFLAG(ENABLE_PRINTING) + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -576,6 +608,9 @@ break; #if BUILDFLAG(ENABLE_PRINTING) + case IDC_BASIC_PRINT_DEPRECATED: + ShowDeprecatedBasicPrintInfoBar(browser_); + [[fallthrough]]; case IDC_BASIC_PRINT: base::RecordAction(base::UserMetricsAction("Accel_Advanced_Print")); BasicPrint(browser_); @@ -1594,6 +1629,8 @@ bool print_enabled = CanPrint(browser_); command_updater_.UpdateCommandEnabled(IDC_PRINT, print_enabled); #if BUILDFLAG(ENABLE_PRINTING) + command_updater_.UpdateCommandEnabled(IDC_BASIC_PRINT_DEPRECATED, + CanBasicPrint(browser_)); command_updater_.UpdateCommandEnabled(IDC_BASIC_PRINT, CanBasicPrint(browser_)); #endif
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc index ee8f5ff..7b38682 100644 --- a/chrome/browser/ui/browser_live_tab_context.cc +++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/closed_tab_cache.h" #include "chrome/browser/sessions/closed_tab_cache_service_factory.h" +#include "chrome/browser/sessions/session_service_utils.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" @@ -29,6 +30,7 @@ #include "chrome/common/buildflags.h" #include "components/sessions/content/content_live_tab.h" #include "components/sessions/content/content_platform_specific_tab_data.h" +#include "components/sessions/core/session_types.h" #include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" #include "content/public/browser/navigation_controller.h" @@ -76,6 +78,11 @@ return browser_->session_id(); } +sessions::SessionWindow::WindowType BrowserLiveTabContext::GetWindowType() + const { + return WindowTypeForBrowserType(browser_->type()); +} + int BrowserLiveTabContext::GetTabCount() const { return browser_->tab_strip_model()->count(); } @@ -282,6 +289,7 @@ // static sessions::LiveTabContext* BrowserLiveTabContext::Create( Profile* profile, + sessions::SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state, @@ -291,10 +299,17 @@ std::unique_ptr<Browser::CreateParams> create_params; if (ShouldCreateAppWindowForAppName(profile, app_name)) { // Only trusted app popup windows should ever be restored. - create_params = std::make_unique<Browser::CreateParams>( - Browser::CreateParams::CreateForApp(app_name, true /* trusted_source */, - bounds, profile, - true /* user_gesture */)); + if (type == sessions::SessionWindow::TYPE_APP_POPUP) { + create_params = std::make_unique<Browser::CreateParams>( + Browser::CreateParams::CreateForAppPopup( + app_name, /*trusted_source=*/true, bounds, profile, + /*user_gesture=*/true)); + } else { + create_params = std::make_unique<Browser::CreateParams>( + Browser::CreateParams::CreateForApp(app_name, /*trusted_source=*/true, + bounds, profile, + /*user_gesture=*/true)); + } } else { create_params = std::make_unique<Browser::CreateParams>( Browser::CreateParams(profile, true));
diff --git a/chrome/browser/ui/browser_live_tab_context.h b/chrome/browser/ui/browser_live_tab_context.h index e9eeed4..2c06347c 100644 --- a/chrome/browser/ui/browser_live_tab_context.h +++ b/chrome/browser/ui/browser_live_tab_context.h
@@ -40,6 +40,7 @@ // Overridden from LiveTabContext: void ShowBrowserWindow() override; SessionID GetSessionID() const override; + sessions::SessionWindow::WindowType GetWindowType() const override; int GetTabCount() const override; int GetSelectedIndex() const override; std::string GetAppName() const override; @@ -86,6 +87,7 @@ // see Browser::Create static sessions::LiveTabContext* Create( Profile* profile, + sessions::SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state,
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm index 0b6a8b9b..8bc0261 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -30,6 +30,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/image_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/color/color_provider.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_util_mac.h" @@ -345,11 +346,11 @@ // Set the icon of the group to the group color circle. AppController* controller = base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - const auto& theme = [controller lastActiveThemeProvider]; - const int color_id = - GetTabGroupContextMenuColorIdDeprecated(group->visual_data.color()); + const auto& color_provider = [controller lastActiveColorProvider]; + const ui::ColorId color_id = + GetTabGroupContextMenuColorId(group->visual_data.color()); gfx::ImageSkia group_icon = gfx::CreateVectorIcon( - kTabGroupIcon, gfx::kFaviconSize, theme.GetColor(color_id)); + kTabGroupIcon, gfx::kFaviconSize, color_provider.GetColor(color_id)); // Create the submenu. base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] init]);
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm index d386d34..55e367c1 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -68,7 +68,6 @@ protected: void SetUp() override { BrowserWithTestWindowTest::SetUp(); - appController_.reset([[AppController alloc] init]); [appController_ setLastProfileForTesting:profile()]; previousApplicationDelegate_ = [NSApp delegate];
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h index 3893e98..5db6f618c 100644 --- a/chrome/browser/ui/color/chrome_color_id.h +++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -306,93 +306,54 @@ E(kColorTabHoverCardForeground, \ ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND) \ /* The colors used for tab groups in the tabstrip. */ \ - E(kColorTabGroupTabStripFrameActiveGrey, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY) \ - E(kColorTabGroupTabStripFrameActiveBlue, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE) \ - E(kColorTabGroupTabStripFrameActiveRed, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED) \ - E(kColorTabGroupTabStripFrameActiveYellow, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW) \ - E(kColorTabGroupTabStripFrameActiveGreen, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN) \ - E(kColorTabGroupTabStripFrameActivePink, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK) \ - E(kColorTabGroupTabStripFrameActivePurple, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE) \ - E(kColorTabGroupTabStripFrameActiveCyan, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN) \ - E(kColorTabGroupTabStripFrameActiveOrange, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE) \ - E(kColorTabGroupTabStripFrameInactiveGrey, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY) \ - E(kColorTabGroupTabStripFrameInactiveBlue, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE) \ - E(kColorTabGroupTabStripFrameInactiveRed, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED) \ - E(kColorTabGroupTabStripFrameInactiveYellow, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW) \ - E(kColorTabGroupTabStripFrameInactiveGreen, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN) \ - E(kColorTabGroupTabStripFrameInactivePink, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK) \ - E(kColorTabGroupTabStripFrameInactivePurple, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE) \ - E(kColorTabGroupTabStripFrameInactiveCyan, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN) \ - E(kColorTabGroupTabStripFrameInactiveOrange, \ - ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveGrey) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveBlue) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveRed) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveYellow) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveGreen) \ + E_CPONLY(kColorTabGroupTabStripFrameActivePink) \ + E_CPONLY(kColorTabGroupTabStripFrameActivePurple) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveCyan) \ + E_CPONLY(kColorTabGroupTabStripFrameActiveOrange) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveGrey) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveBlue) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveRed) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveYellow) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveGreen) \ + E_CPONLY(kColorTabGroupTabStripFrameInactivePink) \ + E_CPONLY(kColorTabGroupTabStripFrameInactivePurple) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveCyan) \ + E_CPONLY(kColorTabGroupTabStripFrameInactiveOrange) \ /* The colors used for tab groups in the bubble dialog view. */ \ - E(kColorTabGroupDialogGrey, ThemeProperties::COLOR_TAB_GROUP_DIALOG_GREY) \ - E(kColorTabGroupDialogBlue, ThemeProperties::COLOR_TAB_GROUP_DIALOG_BLUE) \ - E(kColorTabGroupDialogRed, ThemeProperties::COLOR_TAB_GROUP_DIALOG_RED) \ - E(kColorTabGroupDialogYellow, \ - ThemeProperties::COLOR_TAB_GROUP_DIALOG_YELLOW) \ - E(kColorTabGroupDialogGreen, ThemeProperties::COLOR_TAB_GROUP_DIALOG_GREEN) \ - E(kColorTabGroupDialogPink, ThemeProperties::COLOR_TAB_GROUP_DIALOG_PINK) \ - E(kColorTabGroupDialogPurple, \ - ThemeProperties::COLOR_TAB_GROUP_DIALOG_PURPLE) \ - E(kColorTabGroupDialogCyan, ThemeProperties::COLOR_TAB_GROUP_DIALOG_CYAN) \ - E(kColorTabGroupDialogOrange, \ - ThemeProperties::COLOR_TAB_GROUP_DIALOG_ORANGE) \ + E_CPONLY(kColorTabGroupDialogGrey) \ + E_CPONLY(kColorTabGroupDialogBlue) \ + E_CPONLY(kColorTabGroupDialogRed) \ + E_CPONLY(kColorTabGroupDialogYellow) \ + E_CPONLY(kColorTabGroupDialogGreen) \ + E_CPONLY(kColorTabGroupDialogPink) \ + E_CPONLY(kColorTabGroupDialogPurple) \ + E_CPONLY(kColorTabGroupDialogCyan) \ + E_CPONLY(kColorTabGroupDialogOrange) \ /* The colors used for tab groups in the context submenu. */ \ - E(kColorTabGroupContextMenuBlue, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE) \ - E(kColorTabGroupContextMenuCyan, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN) \ - E(kColorTabGroupContextMenuGreen, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN) \ - E(kColorTabGroupContextMenuGrey, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_GREY) \ - E(kColorTabGroupContextMenuOrange, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE) \ - E(kColorTabGroupContextMenuPink, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_PINK) \ - E(kColorTabGroupContextMenuPurple, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE) \ - E(kColorTabGroupContextMenuRed, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_RED) \ - E(kColorTabGroupContextMenuYellow, \ - ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW) \ + E_CPONLY(kColorTabGroupContextMenuBlue) \ + E_CPONLY(kColorTabGroupContextMenuCyan) \ + E_CPONLY(kColorTabGroupContextMenuGreen) \ + E_CPONLY(kColorTabGroupContextMenuGrey) \ + E_CPONLY(kColorTabGroupContextMenuOrange) \ + E_CPONLY(kColorTabGroupContextMenuPink) \ + E_CPONLY(kColorTabGroupContextMenuPurple) \ + E_CPONLY(kColorTabGroupContextMenuRed) \ + E_CPONLY(kColorTabGroupContextMenuYellow) \ /* The colors used for saved tab group chips on the bookmark bar. */ \ - E(kColorTabGroupBookmarkBarGrey, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY) \ - E(kColorTabGroupBookmarkBarBlue, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE) \ - E(kColorTabGroupBookmarkBarRed, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_RED) \ - E(kColorTabGroupBookmarkBarYellow, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW) \ - E(kColorTabGroupBookmarkBarGreen, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN) \ - E(kColorTabGroupBookmarkBarPink, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK) \ - E(kColorTabGroupBookmarkBarPurple, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE) \ - E(kColorTabGroupBookmarkBarCyan, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN) \ - E(kColorTabGroupBookmarkBarOrange, \ - ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE) \ + E_CPONLY(kColorTabGroupBookmarkBarGrey) \ + E_CPONLY(kColorTabGroupBookmarkBarBlue) \ + E_CPONLY(kColorTabGroupBookmarkBarRed) \ + E_CPONLY(kColorTabGroupBookmarkBarYellow) \ + E_CPONLY(kColorTabGroupBookmarkBarGreen) \ + E_CPONLY(kColorTabGroupBookmarkBarPink) \ + E_CPONLY(kColorTabGroupBookmarkBarPurple) \ + E_CPONLY(kColorTabGroupBookmarkBarCyan) \ + E_CPONLY(kColorTabGroupBookmarkBarOrange) \ E(kColorTabStrokeFrameActive, \ ThemeProperties::COLOR_TAB_STROKE_FRAME_ACTIVE) \ E(kColorTabStrokeFrameInactive, \
diff --git a/chrome/browser/ui/tabs/tab_group_theme.cc b/chrome/browser/ui/tabs/tab_group_theme.cc index 728572d..5ad43a7 100644 --- a/chrome/browser/ui/tabs/tab_group_theme.cc +++ b/chrome/browser/ui/tabs/tab_group_theme.cc
@@ -13,37 +13,37 @@ using TP = ThemeProperties; using TabGroupColorId = tab_groups::TabGroupColorId; -int GetTabGroupTabStripColorId(TabGroupColorId group_color_id, - bool active_frame) { +ui::ColorId GetTabGroupTabStripColorId(TabGroupColorId group_color_id, + bool active_frame) { static constexpr auto group_id_map = base::MakeFixedFlatMap<TabGroupColorId, std::array<int, 2>>({ {TabGroupColorId::kGrey, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY}}, + {kColorTabGroupTabStripFrameInactiveGrey, + kColorTabGroupTabStripFrameActiveGrey}}, {TabGroupColorId::kBlue, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE}}, + {kColorTabGroupTabStripFrameInactiveGrey, + kColorTabGroupTabStripFrameActiveBlue}}, {TabGroupColorId::kRed, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED}}, + {kColorTabGroupTabStripFrameInactiveRed, + kColorTabGroupTabStripFrameActiveRed}}, {TabGroupColorId::kYellow, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW}}, + {kColorTabGroupTabStripFrameInactiveYellow, + kColorTabGroupTabStripFrameActiveYellow}}, {TabGroupColorId::kGreen, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN}}, + {kColorTabGroupTabStripFrameInactiveGreen, + kColorTabGroupTabStripFrameActiveGreen}}, {TabGroupColorId::kPink, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK}}, + {kColorTabGroupTabStripFrameInactivePink, + kColorTabGroupTabStripFrameActivePink}}, {TabGroupColorId::kPurple, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE}}, + {kColorTabGroupTabStripFrameInactivePink, + kColorTabGroupTabStripFrameActivePurple}}, {TabGroupColorId::kCyan, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN}}, + {kColorTabGroupTabStripFrameInactiveCyan, + kColorTabGroupTabStripFrameActiveCyan}}, {TabGroupColorId::kOrange, - {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE, - TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE}}, + {kColorTabGroupTabStripFrameInactiveOrange, + kColorTabGroupTabStripFrameActiveOrange}}, }); return group_id_map.at(group_color_id)[active_frame]; @@ -85,18 +85,18 @@ return group_id_map.at(group_color_id)[active_frame]; } -int GetTabGroupDialogColorId(TabGroupColorId group_color_id) { +ui::ColorId GetTabGroupDialogColorId(TabGroupColorId group_color_id) { static constexpr auto group_id_map = base::MakeFixedFlatMap<TabGroupColorId, int>({ - {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_DIALOG_GREY}, - {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_DIALOG_BLUE}, - {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_DIALOG_RED}, - {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_DIALOG_YELLOW}, - {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_DIALOG_GREEN}, - {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_DIALOG_PINK}, - {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_DIALOG_PURPLE}, - {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_DIALOG_CYAN}, - {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_DIALOG_ORANGE}, + {TabGroupColorId::kGrey, kColorTabGroupDialogGrey}, + {TabGroupColorId::kBlue, kColorTabGroupDialogBlue}, + {TabGroupColorId::kRed, kColorTabGroupDialogRed}, + {TabGroupColorId::kYellow, kColorTabGroupDialogYellow}, + {TabGroupColorId::kGreen, kColorTabGroupDialogGreen}, + {TabGroupColorId::kPink, kColorTabGroupDialogPink}, + {TabGroupColorId::kPurple, kColorTabGroupDialogPurple}, + {TabGroupColorId::kCyan, kColorTabGroupDialogCyan}, + {TabGroupColorId::kOrange, kColorTabGroupDialogOrange}, }); return group_id_map.at(group_color_id); @@ -119,35 +119,19 @@ return group_id_map.at(group_color_id); } -int GetTabGroupContextMenuColorIdDeprecated(TabGroupColorId group_color_id) { +ui::ColorId GetTabGroupBookmarkColorId( + tab_groups::TabGroupColorId group_color_id) { static constexpr auto group_id_map = base::MakeFixedFlatMap<TabGroupColorId, int>({ - {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY}, - {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE}, - {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED}, - {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW}, - {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN}, - {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK}, - {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE}, - {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN}, - {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE}, - }); - - return group_id_map.at(group_color_id); -} - -int GetTabGroupBookmarkColorId(tab_groups::TabGroupColorId group_color_id) { - static constexpr auto group_id_map = - base::MakeFixedFlatMap<TabGroupColorId, int>({ - {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY}, - {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE}, - {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED}, - {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW}, - {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN}, - {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK}, - {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE}, - {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN}, - {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE}, + {TabGroupColorId::kGrey, kColorTabGroupBookmarkBarGrey}, + {TabGroupColorId::kBlue, kColorTabGroupBookmarkBarBlue}, + {TabGroupColorId::kRed, kColorTabGroupBookmarkBarRed}, + {TabGroupColorId::kYellow, kColorTabGroupBookmarkBarYellow}, + {TabGroupColorId::kGreen, kColorTabGroupBookmarkBarGreen}, + {TabGroupColorId::kPink, kColorTabGroupBookmarkBarPink}, + {TabGroupColorId::kPurple, kColorTabGroupBookmarkBarPurple}, + {TabGroupColorId::kCyan, kColorTabGroupBookmarkBarCyan}, + {TabGroupColorId::kOrange, kColorTabGroupBookmarkBarOrange}, }); return group_id_map.at(group_color_id);
diff --git a/chrome/browser/ui/tabs/tab_group_theme.h b/chrome/browser/ui/tabs/tab_group_theme.h index be5a1ed..2c56bd5 100644 --- a/chrome/browser/ui/tabs/tab_group_theme.h +++ b/chrome/browser/ui/tabs/tab_group_theme.h
@@ -8,23 +8,21 @@ #include "components/tab_groups/tab_group_color.h" #include "ui/color/color_id.h" -int GetTabGroupTabStripColorId(tab_groups::TabGroupColorId group_color_id, - bool active_frame); +ui::ColorId GetTabGroupTabStripColorId( + tab_groups::TabGroupColorId group_color_id, + bool active_frame); ui::ColorId GetThumbnailTabStripTabGroupColorId( tab_groups::TabGroupColorId group_color_id, bool active_frame); -int GetTabGroupDialogColorId(tab_groups::TabGroupColorId group_color_id); +ui::ColorId GetTabGroupDialogColorId( + tab_groups::TabGroupColorId group_color_id); ui::ColorId GetTabGroupContextMenuColorId( tab_groups::TabGroupColorId group_color_id); -// TODO(crbug.com/1292029): Remove this function which returns color id for -// ThemeService, not for ColorProvider. -int GetTabGroupContextMenuColorIdDeprecated( +ui::ColorId GetTabGroupBookmarkColorId( tab_groups::TabGroupColorId group_color_id); -int GetTabGroupBookmarkColorId(tab_groups::TabGroupColorId group_color_id); - #endif // CHROME_BROWSER_UI_TABS_TAB_GROUP_THEME_H_
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc index 8003938..08a8b7a 100644 --- a/chrome/browser/ui/views/accelerator_table.cc +++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -201,7 +201,9 @@ {ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK}, {ui::VKEY_LEFT, ui::EF_ALTGR_DOWN, IDC_BACK}, #if BUILDFLAG(ENABLE_PRINTING) - {ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT}, + {ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, + IDC_BASIC_PRINT_DEPRECATED}, + {ui::VKEY_P, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT}, #endif // ENABLE_PRINTING {ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS}, {ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc index 0d5cf2e..1acd818e 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc
@@ -121,16 +121,16 @@ } void SavedTabGroupButton::OnPaintBackground(gfx::Canvas* canvas) { - const ui::ThemeProvider* const tp = GetThemeProvider(); + const ui::ColorProvider* const cp = GetColorProvider(); gfx::PointF center_point_f = gfx::PointF(width() / 2, height() / 2); gfx::RectF rect_f = gfx::RectF(width(), height()); rect_f.Inset(1.0f); // Relies on logic in theme_helper.cc to determine dark/light palette. SkColor background_color = - tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); + cp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); SkColor text_and_outline_color = - tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); + cp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); SetEnabledTextColors(text_and_outline_color); // Draw background. @@ -176,11 +176,11 @@ // We don't always have a theme provider (ui tests, for example). SkColor text_color = gfx::kPlaceholderColor; - const ui::ThemeProvider* const tp = GetThemeProvider(); - if (tp) { + const ui::ColorProvider* const cp = GetColorProvider(); + if (cp) { SkColor background_color = - tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); - text_color = tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); + cp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_)); + text_color = cp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_)); text_color = color_utils::PickGoogleColor( text_color, background_color, color_utils::kMinimumReadableContrastRatio);
diff --git a/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc b/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc index bde82fc..38e8ab09b 100644 --- a/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc +++ b/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc
@@ -59,8 +59,17 @@ auto bubble = std::make_unique<views::BubbleDialogModelHost>( dialog_builder.Build(), anchor_view, views::BubbleBorder::TOP_RIGHT); + // Hover card should not become active window when hovering over request + // button in an inactive window. Setting this to false creates the need to + // explicitly hide the hovercard. + bubble->SetCanActivate(false); request_access_bubble = bubble.get(); - views::BubbleDialogDelegate::CreateBubble(std::move(bubble))->Show(); + + auto* widget = views::BubbleDialogDelegate::CreateBubble(std::move(bubble)); + // Ensure the hover card Widget assumes the highest z-order to avoid occlusion + // by other secondary UI Widgets + widget->StackAtTop(); + widget->Show(); } // static
diff --git a/chrome/browser/ui/views/tabs/color_picker_view.cc b/chrome/browser/ui/views/tabs/color_picker_view.cc index 7ea92f03..75a4f024 100644 --- a/chrome/browser/ui/views/tabs/color_picker_view.cc +++ b/chrome/browser/ui/views/tabs/color_picker_view.cc
@@ -150,7 +150,7 @@ DCHECK_EQ(bounds.width(), bounds.height()); const SkColor color = - GetThemeProvider()->GetColor(GetTabGroupDialogColorId(color_id_)); + GetColorProvider()->GetColor(GetTabGroupDialogColorId(color_id_)); cc::PaintFlags flags; flags.setStyle(cc::PaintFlags::kFill_Style);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 5e00e54..995bf8c 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1601,7 +1601,7 @@ SkColor TabStrip::GetPaintedGroupColor( const tab_groups::TabGroupColorId& color_id) const { - return GetThemeProvider()->GetColor( + return GetColorProvider()->GetColor( GetTabGroupTabStripColorId(color_id, ShouldPaintAsActiveFrame())); }
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc index 1948075..e830fbb 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -9,7 +9,6 @@ #include "base/metrics/histogram_macros.h" #include "chrome/browser/accessibility/accessibility_state_utils.h" #include "chrome/browser/image_fetcher/image_decoder_impl.h" -#include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/ui/monogram_utils.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" #include "chrome/browser/ui/views/hover_button.h" @@ -19,9 +18,11 @@ #include "content/public/browser/storage_partition.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "skia/ext/image_operations.h" +#include "third_party/skia/include/core/SkPath.h" #include "ui/accessibility/ax_role_properties.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/gfx/canvas.h" #include "ui/gfx/image/canvas_image_source.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/views/accessibility/view_accessibility.h" @@ -95,6 +96,11 @@ LetterAvatarImageSkiaSource(const std::u16string& letter, int size) : gfx::CanvasImageSource(gfx::Size(size, size)), letter_(letter) {} + LetterAvatarImageSkiaSource(const LetterAvatarImageSkiaSource&) = delete; + LetterAvatarImageSkiaSource& operator=(const LetterAvatarImageSkiaSource&) = + delete; + ~LetterAvatarImageSkiaSource() override = default; + void Draw(gfx::Canvas* canvas) override { monogram::DrawMonogramInCanvas(canvas, size().width(), size().width(), letter_, SK_ColorWHITE, SK_ColorGRAY); @@ -104,6 +110,48 @@ const std::u16string letter_; }; +// A CanvasImageSource that draws a circle cropped avatar. +class AvatarImageSkiaSource : public gfx::CanvasImageSource { + public: + AvatarImageSkiaSource(gfx::ImageSkia avatar, int canvas_edge_size) + : gfx::CanvasImageSource(gfx::Size(canvas_edge_size, canvas_edge_size)) { + // Resize `avatar` so that it completely fills the canvas. + float height_ratio = ((float)avatar.height() / (float)avatar.width()); + int scaled_width = canvas_edge_size; + int scaled_height = canvas_edge_size; + if (height_ratio >= 1.0f) + scaled_height = floor(canvas_edge_size * height_ratio); + else + scaled_width = floor(canvas_edge_size / height_ratio); + avatar_ = gfx::ImageSkiaOperations::CreateResizedImage( + avatar, skia::ImageOperations::RESIZE_BEST, + gfx::Size(scaled_width, scaled_height)); + } + + AvatarImageSkiaSource(const AvatarImageSkiaSource&) = delete; + AvatarImageSkiaSource& operator=(const AvatarImageSkiaSource&) = delete; + ~AvatarImageSkiaSource() override = default; + + // CanvasImageSource override: + void Draw(gfx::Canvas* canvas) override { + int canvas_edge_size = size().width(); + + // Center the avatar in the canvas. + int x = (canvas_edge_size - avatar_.width()) / 2; + int y = (canvas_edge_size - avatar_.height()) / 2; + + SkPath circular_mask; + circular_mask.addCircle(SkIntToScalar(canvas_edge_size / 2), + SkIntToScalar(canvas_edge_size / 2), + SkIntToScalar(canvas_edge_size / 2)); + canvas->ClipPath(circular_mask, true); + canvas->DrawImageInt(avatar_, x, y); + } + + private: + gfx::ImageSkia avatar_; +}; + void SendAccessibilityEvent(views::Widget* widget, std::u16string announcement) { if (!widget) @@ -428,17 +476,16 @@ const std::u16string& account_name, const gfx::Image& image, const image_fetcher::RequestMetadata& metadata) { - ui::ImageModel avatar; + gfx::ImageSkia avatar; if (image.IsEmpty()) { std::u16string letter = account_name; if (letter.length() > 0) letter = base::i18n::ToUpper(account_name.substr(0, 1)); - avatar = ui::ImageModel::FromImageSkia( - gfx::CanvasImageSource::MakeImageSkia<LetterAvatarImageSkiaSource>( - letter, kDesiredAvatarSize)); + avatar = gfx::CanvasImageSource::MakeImageSkia<LetterAvatarImageSkiaSource>( + letter, kDesiredAvatarSize); } else { - avatar = ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon( - image, kDesiredAvatarSize, kDesiredAvatarSize, profiles::SHAPE_CIRCLE)); + avatar = gfx::CanvasImageSource::MakeImageSkia<AvatarImageSkiaSource>( + image.AsImageSkia(), kDesiredAvatarSize); } image_view->SetImage(avatar); }
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc index 372ddc8..627acbe 100644 --- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc +++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -189,14 +189,15 @@ return app_id; } -Browser* LaunchWebAppBrowser(Profile* profile, const AppId& app_id) { +Browser* LaunchWebAppBrowser(Profile* profile, + const AppId& app_id, + WindowOpenDisposition disposition) { content::WebContents* web_contents = apps::AppServiceProxyFactory::GetForProfile(profile) ->BrowserAppLauncher() ->LaunchAppWithParamsForTesting(apps::AppLaunchParams( app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::CURRENT_TAB, - apps::mojom::LaunchSource::kFromTest)); + disposition, apps::mojom::LaunchSource::kFromTest)); EXPECT_TRUE(web_contents); Browser* browser = chrome::FindBrowserWithWebContents(web_contents); EXPECT_TRUE(AppBrowserController::IsForWebApp(browser, app_id)); @@ -204,11 +205,14 @@ } // Launches the app, waits for the app url to load. -Browser* LaunchWebAppBrowserAndWait(Profile* profile, const AppId& app_id) { +Browser* LaunchWebAppBrowserAndWait(Profile* profile, + const AppId& app_id, + WindowOpenDisposition disposition) { ui_test_utils::UrlLoadObserver url_observer( WebAppProvider::GetForTest(profile)->registrar().GetAppLaunchUrl(app_id), content::NotificationService::AllSources()); - Browser* const app_browser = LaunchWebAppBrowser(profile, app_id); + Browser* const app_browser = + LaunchWebAppBrowser(profile, app_id, disposition); url_observer.Wait(); return app_browser; }
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h index ce6eaf6..7efe369 100644 --- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h +++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
@@ -17,6 +17,7 @@ #include "chrome/browser/web_applications/web_app_install_manager.h" #include "chrome/browser/web_applications/web_app_install_manager_observer.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/window_open_disposition.h" class Browser; class GURL; @@ -48,11 +49,18 @@ // Navigates to |app_url|, verifies WebApp installability, and installs app. AppId InstallWebAppFromManifest(Browser* browser, const GURL& app_url); -// Launches a new app window for |app| in |profile|. -Browser* LaunchWebAppBrowser(Profile*, const AppId&); +// Launches a new app window for |app| in |profile| with specified +// |disposition|. +Browser* LaunchWebAppBrowser( + Profile*, + const AppId&, + WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB); // Launches the app, waits for the app url to load. -Browser* LaunchWebAppBrowserAndWait(Profile*, const AppId&); +Browser* LaunchWebAppBrowserAndWait( + Profile*, + const AppId&, + WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB); // Launches a new tab for |app| in |profile|. Browser* LaunchBrowserForWebAppInTab(Profile*, const AppId&);
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index b4cd7581..7efefed 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -837,6 +837,30 @@ EXPECT_TRUE(restored_browser->is_type_app()); } + +// Tests that app popup windows are correctly restored. +IN_PROC_BROWSER_TEST_F(WebAppTabRestoreBrowserTest, RestoreAppPopupWindow) { + const GURL app_url = GetSecureAppURL(); + const AppId app_id = InstallPWA(app_url); + Browser* const app_browser = web_app::LaunchWebAppBrowserAndWait( + profile(), app_id, WindowOpenDisposition::NEW_POPUP); + + ASSERT_TRUE(app_browser->is_type_app_popup()); + app_browser->window()->Close(); + + content::WebContentsAddedObserver new_contents_observer; + + sessions::TabRestoreService* const service = + TabRestoreServiceFactory::GetForProfile(profile()); + service->RestoreMostRecentEntry(nullptr); + + content::WebContents* const restored_web_contents = + new_contents_observer.GetWebContents(); + Browser* const restored_browser = + chrome::FindBrowserWithWebContents(restored_web_contents); + + EXPECT_TRUE(restored_browser->is_type_app_popup()); +} #endif // !BUILDFLAG(IS_CHROMEOS_LACROS) // Test navigating to an out of scope url on the same origin causes the url
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 70a13e9c..0ca5602 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -93,7 +93,7 @@ #if BUILDFLAG(IS_MAC) const char16_t kBasicPrintShortcut[] = u"\u0028\u21e7\u2318\u0050\u0029"; #elif !BUILDFLAG(IS_CHROMEOS) -const char16_t kBasicPrintShortcut[] = u"(Ctrl+Shift+P)"; +const char16_t kBasicPrintShortcut[] = u"(Ctrl+Alt+P)"; #endif constexpr char kInvalidArgsForDidStartPreview[] =
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 107c3f52..d58ec07 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1654700057-293efac59be5a3cdb9b1198d0d15440ca2bd2da2.profdata +chrome-win32-main-1654711203-dd1524393825bce89244c153ae7bb5d820cccb69.profdata
diff --git a/chrome/common/extensions/api/file_browser_handler_internal.json b/chrome/common/extensions/api/file_browser_handler_internal.json index cf2585a..472e3eb 100644 --- a/chrome/common/extensions/api/file_browser_handler_internal.json +++ b/chrome/common/extensions/api/file_browser_handler_internal.json
@@ -28,6 +28,25 @@ "type": "boolean" } } + }, + { + "id": "FileEntryInfoForGetFile", + "type": "object", + "description": "Information needed to build a file entry using DirectoryEntry.getFile() that will be returned through the API.", + "properties": { + "fileSystemId": { + "type": "string" + }, + "baseName": { + "type": "string" + }, + "entryId": { + "type": "string" + }, + "isDirectory": { + "type": "boolean" + } + } } ], @@ -72,6 +91,11 @@ "$ref": "FileEntryInfo", "optional": true, "description": "Selected file entry." + }, + "entryForGetFile": { + "$ref": "FileEntryInfoForGetFile", + "optional": true, + "description": "Selected file entry for DirectoryEngry.getFile() consumption." } } }
diff --git a/chrome/common/extensions/api/wm_desks_private.idl b/chrome/common/extensions/api/wm_desks_private.idl index e8f388b..3c9f227 100644 --- a/chrome/common/extensions/api/wm_desks_private.idl +++ b/chrome/common/extensions/api/wm_desks_private.idl
@@ -10,6 +10,8 @@ // The unique id for a desk template. Used internally to identify a desk // template. DOMString templateUuid; + + // User readable name of the desk template. DOMString templateName; }; @@ -19,18 +21,28 @@ boolean combineDesks; }; - dictionary Desk { + dictionary Desk { // Unique ID for a desk. DOMString deskUuid; + // User readable name of the desk. DOMString deskName; }; + // Launch desk options + dictionary LaunchOptions { + // Unique identifier for a template + DOMString? templateUuid; + + // User readable name of the desk + DOMString? deskName; +}; + callback CaptureDeskAndSaveTemplateCallback = void (DeskTemplate deskTemplate); callback GetSavedDeskTemplatesCallback = void (DeskTemplate[] deskTemplates); - callback LaunchDeskTemplateCallback = void (DOMString deskId); + callback DeskIdCallback = void (DOMString deskId); callback VoidCallback = void (); callback GetDeskTemplateJsonCallback = void (DOMString templateJson); callback GetAllDesksCallback = void (Desk[] desks); @@ -61,12 +73,11 @@ static void deleteDeskTemplate(DOMString templateUuid, VoidCallback callback); - // Launches the desk template with |templateUuid| as a new desk. - // |templateId| should be the unique id for an existing desk template. If - // no such id can be found or a new desk can't be created, an error will be - // returned. - static void launchDeskTemplate(DOMString templateUuid, - LaunchDeskTemplateCallback callback); + // Launches a desk, if `templateUuid` is present in the options, launches a desk + // template, otherwise launches an empty desk. If `deskName` is present in the options, + // using provided name as desk name, otherwise launches with auto generated name. + static void launchDesk(LaunchOptions launchOptions, + DeskIdCallback callback); // Gets the template associated with the templateUuid and returns its JSON // representation. Returns an error if either the template could not be
diff --git a/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js b/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js index 1e8859bf..d73b306 100644 --- a/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js
@@ -12,9 +12,20 @@ const fileBrowserHandlerInternal = getInternalApi('fileBrowserHandlerInternal'); const GetIsolatedFileSystem = fileSystemHelpers.GetIsolatedFileSystem; -// Using Promise-like interface: We're avoiding Promise for safety, and $Promise -// does not support the desired feature (Promise.allSettled()). -function GetFileEntry(resolve, reject, item) { +/** + * Adapter to get a FileEntry or DirectoryEntry from |item| passed from API + * callback, via calls to GetExternalFileEntry() or get{Directory,File}(). + * Ideally we'd use Promise.allSettled() to process multiple files, but since + * $Promise.allSettled() does not exist, so callbacks are used instead. + * @param {function(!Entry): void} resolve Receiver for resulting Entry. + * @param {function(string): void} reject Receiver for error message. + * @param {boolean} canCreate For getFile() flow only: Whether to grant + * permission to create file if it's missing. Side effect: The file gets + * created if missing. + * @param {!Object} item Key-value pair passed from API callback, containing + * data for GetExternalFileEntry() or get{Directory,File}() flows. + */ +function GetFileEntry(resolve, reject, canCreate, item) { if (item.hasOwnProperty('fileSystemName')) { // Legacy flow for Ash. Errors (such as nonexistent file) are not detected // here. These only arise downstream when the resulting Entry gets used. @@ -31,12 +42,15 @@ reject(err.message); }); } else { - fs.root.getFile(item.baseName, {}, (fileEntry) => { - entryIdManager.registerEntry(item.entryId, fileEntry); - resolve(fileEntry); - }, (err) => { - reject(err.message); - }); + fs.root.getFile( + item.baseName, canCreate ? {create: true} : {}, + (fileEntry) => { + entryIdManager.registerEntry(item.entryId, fileEntry); + resolve(fileEntry); + }, + (err) => { + reject(err.message); + }); } } else { reject('Unknown file entry object.'); @@ -74,7 +88,9 @@ if (--barrier === 0) onFinish(); }; for (let i = 0; i < fileList.length; ++i) { - GetFileEntry(onResolve.bind(null, i), onReject, fileList[i]); + GetFileEntry( + onResolve.bind(null, i), onReject, + /*canCreate*/ false, /*item*/ fileList[i]); } }); @@ -86,13 +102,25 @@ function internalCallback(externalCallback, internalResult) { if (!externalCallback) return; - var result = undefined; + let result = undefined; if (internalResult) { result = { success: internalResult.success, entry: null }; - if (internalResult.success) - result.entry = GetExternalFileEntry(internalResult.entry); + if (internalResult.success) { + GetFileEntry( + (fileEntry) => { + result.entry = fileEntry; + externalCallback(result); + }, + (message) => { + result.success = false; + result.entry = null; + externalCallback(result); + }, + /*canCreate*/ true, + /*item*/ internalResult.entry || internalResult.entryForGetFile); + return; + } } - externalCallback(result); }
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc index 44c7e52..94bacf6 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
@@ -59,8 +59,7 @@ page_link_domain_phishing_(features::kPageLinkDomain + std::string("phishing.com")), page_term_login_(features::kPageTerm + std::string("login")), - page_text_(u"login"), - phishy_score_(PhishingClassifier::kInvalidScore) {} + page_text_(u"login") {} void SetUp() override { ChromeRenderViewTest::SetUp(); @@ -183,6 +182,7 @@ csd_model_builder.add_max_shingles_per_page(100); csd_model_builder.add_shingle_size(3); csd_model_builder.add_tflite_metadata(tflite_metadata_flat); + csd_model_builder.add_dom_model_version(123); builder.Finish(csd_model_builder.Finish()); std::string model_str(reinterpret_cast<char*>(builder.GetBufferPointer()), @@ -240,6 +240,7 @@ model.set_max_words_per_term(1); model.set_max_shingles_per_page(100); model.set_shingle_size(3); + model.set_dom_model_version(123); base::File tflite_model; if (use_tflite) { @@ -306,14 +307,11 @@ // Completion callback for classification. void ClassificationFinished(const ClientPhishingRequest& verdict) { - phishy_score_ = verdict.client_score(); + verdict_ = verdict; for (int i = 0; i < verdict.feature_map_size(); ++i) { feature_map_.AddRealFeature(verdict.feature_map(i).name(), verdict.feature_map(i).value()); } - is_phishing_ = verdict.is_phishing(); - is_dom_match_ = verdict.is_dom_match(); - run_loop_.Quit(); } @@ -339,10 +337,8 @@ std::u16string page_text_; // Outputs of phishing classifier. + ClientPhishingRequest verdict_; FeatureMap feature_map_; - float phishy_score_; - bool is_phishing_; - bool is_dom_match_; // A DiscardableMemoryAllocator is needed for certain Skia operations. base::TestDiscardableMemoryAllocator test_allocator_; @@ -360,8 +356,8 @@ AllOf(Contains(Pair(url_tld_token_net_, 1.0)), Contains(Pair(page_link_domain_phishing_, 1.0)), Contains(Pair(page_term_login_, 1.0)))); - EXPECT_FLOAT_EQ(0.5, phishy_score_); - EXPECT_TRUE(is_phishing_); + EXPECT_FLOAT_EQ(0.5, verdict_.client_score()); + EXPECT_TRUE(verdict_.is_phishing()); } TEST_P(PhishingClassifierTest, TestClassificationOfPhishingDotComHttps) { @@ -377,8 +373,8 @@ AllOf(Contains(Pair(url_tld_token_net_, 1.0)), Contains(Pair(page_link_domain_phishing_, 1.0)), Contains(Pair(page_term_login_, 1.0)))); - EXPECT_FLOAT_EQ(0.5, phishy_score_); - EXPECT_TRUE(is_phishing_); + EXPECT_FLOAT_EQ(0.5, verdict_.client_score()); + EXPECT_TRUE(verdict_.is_phishing()); } TEST_P(PhishingClassifierTest, TestClassificationOfSafeDotComHttp) { @@ -392,9 +388,9 @@ Contains(Pair(page_term_login_, 1.0)))); EXPECT_THAT(feature_map_.features(), Not(Contains(Pair(page_link_domain_phishing_, 1.0)))); - EXPECT_GE(phishy_score_, 0.0); - EXPECT_LT(phishy_score_, 0.5); - EXPECT_FALSE(is_phishing_); + EXPECT_GE(verdict_.client_score(), 0.0); + EXPECT_LT(verdict_.client_score(), 0.5); + EXPECT_FALSE(verdict_.is_phishing()); } TEST_P(PhishingClassifierTest, TestClassificationOfSafeDotComHttps) { @@ -409,9 +405,9 @@ Contains(Pair(page_term_login_, 1.0)))); EXPECT_THAT(feature_map_.features(), Not(Contains(Pair(page_link_domain_phishing_, 1.0)))); - EXPECT_GE(phishy_score_, 0.0); - EXPECT_LT(phishy_score_, 0.5); - EXPECT_FALSE(is_phishing_); + EXPECT_GE(verdict_.client_score(), 0.0); + EXPECT_LT(verdict_.client_score(), 0.5); + EXPECT_FALSE(verdict_.is_phishing()); } TEST_P(PhishingClassifierTest, TestClassificationWhenNoTld) { @@ -420,8 +416,8 @@ RunPhishingClassifier(&page_text_); EXPECT_EQ(0U, feature_map_.features().size()); - EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score_); - EXPECT_FALSE(is_phishing_); + EXPECT_EQ(PhishingClassifier::kInvalidScore, verdict_.client_score()); + EXPECT_FALSE(verdict_.is_phishing()); } TEST_P(PhishingClassifierTest, TestClassificationWhenSchemeNotSupported) { @@ -431,8 +427,8 @@ RunPhishingClassifier(&page_text_); EXPECT_EQ(0U, feature_map_.features().size()); - EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score_); - EXPECT_FALSE(is_phishing_); + EXPECT_EQ(PhishingClassifier::kInvalidScore, verdict_.client_score()); + EXPECT_FALSE(verdict_.is_phishing()); } TEST_P(PhishingClassifierTest, DisableDetection) { @@ -448,9 +444,9 @@ "<html><body><a href=\"http://phishing.com/\">login</a></body></html>"); RunPhishingClassifier(&page_text_); - EXPECT_NE(PhishingClassifier::kInvalidScore, phishy_score_); - EXPECT_TRUE(is_phishing_); - EXPECT_TRUE(is_dom_match_); + EXPECT_NE(PhishingClassifier::kInvalidScore, verdict_.client_score()); + EXPECT_TRUE(verdict_.is_phishing()); + EXPECT_TRUE(verdict_.is_dom_match()); } TEST_P(PhishingClassifierTest, TestSafePagesAreNotDomMatches) { @@ -458,9 +454,18 @@ "<html><body><a href=\"http://safe.com/\">login</a></body></html>"); RunPhishingClassifier(&page_text_); - EXPECT_NE(PhishingClassifier::kInvalidScore, phishy_score_); - EXPECT_FALSE(is_phishing_); - EXPECT_FALSE(is_dom_match_); + EXPECT_NE(PhishingClassifier::kInvalidScore, verdict_.client_score()); + EXPECT_FALSE(verdict_.is_phishing()); + EXPECT_FALSE(verdict_.is_dom_match()); +} + +TEST_P(PhishingClassifierTest, TestDomModelVersionPopulated) { + LoadHtml( + GURL("http://host.net"), + "<html><body><a href=\"http://phishing.com/\">login</a></body></html>"); + RunPhishingClassifier(&page_text_); + + EXPECT_EQ(verdict_.dom_model_version(), 123); } INSTANTIATE_TEST_SUITE_P(CSDModelTypes,
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc index 351a9ff7..df5dfb3 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
@@ -132,6 +132,7 @@ void(const SkBitmap& bitmap, base::OnceCallback<void(std::vector<double>)> callback)); MOCK_CONST_METHOD0(model_version, int()); + MOCK_CONST_METHOD0(dom_model_version, int()); MOCK_CONST_METHOD0(HasVisualTfLiteModel, bool()); MOCK_CONST_METHOD0(find_page_word_callback, base::RepeatingCallback<bool(uint32_t)>());
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a956dd80..b984d3b2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6126,6 +6126,7 @@ "../browser/android/contextualsearch/contextual_search_delegate_unittest.cc", "../browser/android/contextualsearch/contextual_search_field_trial_unittest.cc", "../browser/android/customtabs/detached_resource_request_unittest.cc", + "../browser/android/customtabs/tab_interaction_recorder_android_unittest.cc", "../browser/android/explore_sites/block_site_task_unittest.cc", "../browser/android/explore_sites/clear_activities_task_unittest.cc", "../browser/android/explore_sites/clear_catalog_task_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 28b8557..e3dd8b9d 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -48,7 +48,6 @@ "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", ] } @@ -225,7 +224,7 @@ ":chrome_java_test_pagecontroller", "//base:base_java_test_support", "//base:base_junit_test_support", - "//third_party/ub-uiautomator:ub_uiautomator_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", ] } @@ -391,11 +390,11 @@ "//third_party/androidx:androidx_core_core_java", "//third_party/androidx:androidx_fragment_fragment_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/blink/public:blink_headers_java", "//third_party/blink/public/mojom:mojom_platform_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:ui_java", "//ui/android:ui_java_test_support", "//url:gurl_java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java index 0e00cbf..f6ceb0f5b 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java
@@ -6,7 +6,7 @@ import static org.chromium.chrome.test.pagecontroller.utils.Ui2Locators.withText; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiObject2; import org.chromium.chrome.R; import org.chromium.chrome.test.pagecontroller.controllers.ElementController;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java index 22bfcdc..f240225 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java
@@ -4,11 +4,10 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; - import androidx.annotation.NonNull; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import java.util.List;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java index 06ee054..9abb345 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
@@ -4,10 +4,10 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.junit.Before; import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java index aeecaa7d..08850bc 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java
@@ -4,11 +4,10 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; - import androidx.annotation.NonNull; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import java.util.List;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java index 33fd1ef..51bb4bb 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
@@ -4,10 +4,10 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.junit.Before; import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java index f5dfb7c5..9649e84 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java
@@ -4,11 +4,10 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; - import androidx.annotation.NonNull; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import java.util.Arrays; import java.util.List;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java index a9d2cab..dab8038 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
@@ -10,8 +10,8 @@ import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.matchesByDepth; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.junit.Before; import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java index ff69f5f5..560255b0 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java
@@ -4,10 +4,9 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; - import androidx.annotation.Nullable; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import java.util.List; @@ -20,7 +19,7 @@ * * @param device The device to search under. * @return The first node found by the locator, or null if none is found. - * @throws android.support.test.uiautomator.StaleObjectException + * @throws androidx.test.uiautomator.StaleObjectException */ @Nullable UiObject2 locateOne(UiDevice device); @@ -30,7 +29,7 @@ * * @param root The node to search under. * @return The first node found by the locator, or null if none is found. - * @throws android.support.test.uiautomator.StaleObjectException + * @throws androidx.test.uiautomator.StaleObjectException */ @Nullable UiObject2 locateOne(UiObject2 root); @@ -40,7 +39,7 @@ * * @param device The device to search under. * @return All nodes found, or an empty list of none are found. - * @throws android.support.test.uiautomator.StaleObjectException + * @throws androidx.test.uiautomator.StaleObjectException */ List<UiObject2> locateAll(UiDevice device); @@ -49,7 +48,7 @@ * * @param root The node to search under. * @return All nodes found, or an empty list of none are found. - * @throws android.support.test.uiautomator.StaleObjectException + * @throws androidx.test.uiautomator.StaleObjectException */ List<UiObject2> locateAll(UiObject2 root); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java index aaaece6e..eccb4c1 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java
@@ -4,10 +4,9 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; - import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import java.util.List;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java index 0893985..c69a986 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
@@ -8,8 +8,8 @@ import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.assertLocatorResults; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.junit.Before; import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java index 1628fd8..a5d8286 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java
@@ -4,10 +4,9 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; - import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import java.util.ArrayList; import java.util.Arrays;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java index a9eeafe3..9c5df1f4 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
@@ -8,8 +8,8 @@ import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.assertLocatorResults; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.junit.Before; import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java index 642bcd7..c7427164 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java
@@ -7,9 +7,9 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.mockito.ArgumentMatcher;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java index 22389b5..3eff745 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java
@@ -6,11 +6,11 @@ import android.content.res.Resources; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.By; import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import androidx.test.uiautomator.By; import java.util.regex.Pattern;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java index e781e3b..49bcbfb 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
@@ -13,8 +13,9 @@ import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.matchesByField; import android.content.res.Resources; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; + +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.junit.After; import org.junit.Before;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java index 59b6ff1..9985997 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java
@@ -13,10 +13,10 @@ import android.os.Process; import android.os.RemoteException; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; import androidx.annotation.NonNull; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.chromium.base.Log;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java index 02676227..43bcbffd 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java
@@ -4,7 +4,7 @@ package org.chromium.chrome.test.pagecontroller.utils; -import android.support.test.uiautomator.UiObject2; +import androidx.test.uiautomator.UiObject2; /** * Exception class that represents an unexpected failure when trying to find
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java index 8dc5b42..d0358e3 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java
@@ -5,12 +5,12 @@ package org.chromium.chrome.test.pagecontroller.utils; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.StaleObjectException; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.test.uiautomator.StaleObjectException; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.chromium.base.test.util.TimeoutTimer;
diff --git a/chrome/test/base/chromeos/ash_browser_test_starter.cc b/chrome/test/base/chromeos/ash_browser_test_starter.cc index d631d72f..e24c3970 100644 --- a/chrome/test/base/chromeos/ash_browser_test_starter.cc +++ b/chrome/test/base/chromeos/ash_browser_test_starter.cc
@@ -26,7 +26,7 @@ AshBrowserTestStarter::AshBrowserTestStarter() = default; AshBrowserTestStarter::~AshBrowserTestStarter() = default; -bool AshBrowserTestStarter::HasLacrosArgument() { +bool AshBrowserTestStarter::HasLacrosArgument() const { return base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kLacrosChromePath); }
diff --git a/chrome/test/base/chromeos/ash_browser_test_starter.h b/chrome/test/base/chromeos/ash_browser_test_starter.h index f4ca460..a5e96d19 100644 --- a/chrome/test/base/chromeos/ash_browser_test_starter.h +++ b/chrome/test/base/chromeos/ash_browser_test_starter.h
@@ -22,7 +22,7 @@ // Returns whether the --lacros-chrome-path is provided. // If returns false, we should not do any Lacros related testing // because the Lacros instance is not provided. - bool HasLacrosArgument(); + bool HasLacrosArgument() const; // Prepares ash so it can work with Lacros. You should call this // in SetUpInProcessBrowserTestFixture().
diff --git a/chrome/test/data/extensions/api_test/wm_desks_private/background.js b/chrome/test/data/extensions/api_test/wm_desks_private/background.js index 564c0dc2..8c11093 100644 --- a/chrome/test/data/extensions/api_test/wm_desks_private/background.js +++ b/chrome/test/data/extensions/api_test/wm_desks_private/background.js
@@ -1,6 +1,7 @@ // Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +var templateUuid; // Basic browser tests for the wmDesksPrivate API. chrome.test.runTests([ @@ -13,7 +14,36 @@ chrome.test.callbackPass(function(deskTemplate) { chrome.test.assertEq(typeof deskTemplate, 'object'); chrome.test.assertTrue(deskTemplate.hasOwnProperty('templateUuid')); + templateUuid = deskTemplate.templateUuid; chrome.test.assertTrue(deskTemplate.hasOwnProperty('templateName')); })); }, + + // Test launch empty desk with a desk name. + function testLaunchEmptyDeskWithName() { + // Launch empty desk with `deskName` + chrome.wmDesksPrivate.launchDesk({ "deskName": "test" }, + chrome.test.callbackPass(function (result) { + // Desk uuid should be returned. + chrome.test.assertEq(typeof result, 'string'); + })); + }, + + // Test launch a desk template to a new desk. + function testLaunchDeskTemplate() { + // Launch template to a new desk + chrome.wmDesksPrivate.launchDesk({ "templateUuid": templateUuid }, + chrome.test.callbackPass(function (result) { + // Desk uuid should be returned. + chrome.test.assertEq(typeof result, 'string'); + })); + }, + + // Test launch + function testLaunchDeskTemplateWithInvalidID() { + // Launch invalid template Uuid + chrome.wmDesksPrivate.launchDesk({ "templateUuid": "abcd" }, + // Launch desk fail with invalid templateUuid + chrome.test.callbackFail("Storage error.")); + } ]);
diff --git a/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts index 6aa419f1..ff7a332e 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
@@ -32,7 +32,10 @@ const routerMock = TestBrowserProxy.fromClass(PersonalizationRouter); setup(() => { - loadTimeData.overrideValues({isAmbientModeAllowed: true}); + loadTimeData.overrideValues({ + isAmbientModeAllowed: true, + isAmbientModeAnimationEnabled: true, + }); const mocks = baseSetup(); ambientProvider = mocks.ambientProvider; personalizationStore = mocks.personalizationStore;
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts index 61ef921..524ff15 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts
@@ -44,7 +44,7 @@ assertEquals( personalizationThemeElement.i18n('themeLabel'), - personalizationThemeElement.shadowRoot!.querySelector('p')!.innerText); + personalizationThemeElement.shadowRoot!.querySelector('h2')!.innerText); }); test('sets color mode in store on first load', async () => {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts index c4f9f4f..6fac054 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts
@@ -7,10 +7,8 @@ import 'chrome://personalization/strings.m.js'; import 'chrome://webui-test/mojo_webui_test_support.js'; -import {WallpaperPreview} from 'chrome://personalization/trusted/personalization_app.js'; - +import {WallpaperPreview, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js'; import {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; - import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/test_util.js'; import {baseSetup, initElement} from './personalization_app_test_utils.js'; @@ -118,4 +116,29 @@ assertEquals( null, wallpaperPreviewElement.shadowRoot!.querySelector('img')); }); + + test('shows managed icon when wallpaper is kPolicy', async () => { + // Start with non-managed wallpaper. + personalizationStore.data.wallpaper.currentSelected = + wallpaperProvider.currentWallpaper; + + wallpaperPreviewElement = initElement(WallpaperPreview); + await waitAfterNextRender(wallpaperPreviewElement); + + function getManagedIcon(): HTMLElement|null { + return wallpaperPreviewElement!.shadowRoot!.querySelector( + `iron-icon[icon='personalization:managed']`); + } + + assertEquals(null, getManagedIcon(), 'no managed icon visible'); + + personalizationStore.data.wallpaper.currentSelected = { + ...personalizationStore.data.wallpaper.currentSelected, + type: WallpaperType.kPolicy + }; + personalizationStore.notifyObservers(); + await waitAfterNextRender(wallpaperPreviewElement); + + assertTrue(!!getManagedIcon(), 'managed icon is shown'); + }); });
diff --git a/chrome/test/data/webui/chromeos/scanning/loading_page_test.js b/chrome/test/data/webui/chromeos/scanning/loading_page_test.js index 0e810f6..601d346 100644 --- a/chrome/test/data/webui/chromeos/scanning/loading_page_test.js +++ b/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
@@ -7,32 +7,54 @@ import {AppState} from 'chrome://scanning/scanning_app_types.js'; import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; +import {MockController} from '../../mock_controller.js'; import {flushTasks, isVisible} from '../../test_util.js'; +import {FakeMediaQueryList} from './scanning_app_test_utils.js'; + export function loadingPageTest() { const scanningSrcBase = 'chrome://scanning/'; /** @type {?LoadingPageElement} */ let loadingPage = null; + /** @type {{createFunctionMock: Function, reset: Function}} */ + let mockController; + + /** @type {?FakeMediaQueryList} */ + let fakePrefersColorSchemeDarkMediaQuery = null; + /** - * @suppress {visibility} * @param {boolean} enabled + * @return {!Promise} */ - function setIsDarkModeEnabled_(enabled) { + function setFakePrefersColorSchemeDark(enabled) { assertTrue(!!loadingPage); - loadingPage.isDarkModeEnabled_ = enabled; + fakePrefersColorSchemeDarkMediaQuery.matches = enabled; + + return flushTasks(); } + setup(() => { loadingPage = /** @type {!LoadingPageElement} */ ( document.createElement('loading-page')); assertTrue(!!loadingPage); loadingPage.appState = AppState.GETTING_SCANNERS; + + // Setup mock for matchMedia. + mockController = new MockController(); + const mockMatchMedia = + mockController.createFunctionMock(window, 'matchMedia'); + fakePrefersColorSchemeDarkMediaQuery = + new FakeMediaQueryList('(prefers-color-scheme: dark)'); + mockMatchMedia.returnValue = fakePrefersColorSchemeDarkMediaQuery; + document.body.appendChild(loadingPage); }); teardown(() => { + mockController.reset(); loadingPage.remove(); loadingPage = null; }); @@ -88,14 +110,12 @@ loadingPage.$$('#noScannersDiv img'))); // Setup UI to display no scanners div. - setIsDarkModeEnabled_(false); loadingPage.appState = AppState.NO_SCANNERS; - await flushTasks(); + await setFakePrefersColorSchemeDark(false); assertEquals(getNoScannersSvg().src, lightModeSvg); // Mock media query state for dark mode. - setIsDarkModeEnabled_(true); - await flushTasks(); + await setFakePrefersColorSchemeDark(true); assertEquals(getNoScannersSvg().src, darkModeSvg); }); @@ -107,14 +127,12 @@ (/** @type {!HTMLImageElement} */ (loadingPage.$$('#loadingDiv img'))); // Setup UI to display no scanners div. - setIsDarkModeEnabled_(false); loadingPage.appState = AppState.NO_SCANNERS; - await flushTasks(); + await setFakePrefersColorSchemeDark(false); assertEquals(getLoadingSvg().src, lightModeSvg); // Mock media query state for dark mode. - setIsDarkModeEnabled_(true); - await flushTasks(); + await setFakePrefersColorSchemeDark(true); assertEquals(getLoadingSvg().src, darkModeSvg); }); }
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js index 5e98dc6..4dd716f 100644 --- a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js +++ b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
@@ -11,8 +11,10 @@ import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js'; import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js'; +import {MockController} from '../../mock_controller.js'; import {flushTasks, isVisible, waitAfterNextRender} from '../../test_util.js'; +import {FakeMediaQueryList} from './scanning_app_test_utils.js'; import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js'; /** @implements {ash.common.mojom.AccessibilityFeaturesInterface} */ @@ -62,13 +64,21 @@ /** @type {!HTMLElement} */ let cancelingProgress; + /** @type {{createFunctionMock: Function, reset: Function}} */ + let mockController; + + /** @type {?FakeMediaQueryList} */ + let fakePrefersColorSchemeDarkMediaQuery; + /** - * @suppress {visibility} * @param {boolean} enabled + * @return {!Promise} */ - function setIsDarkModeEnabled_(enabled) { + function setFakePrefersColorSchemeDark(enabled) { assertTrue(!!scanPreview); - scanPreview.isDarkModeEnabled_ = enabled; + fakePrefersColorSchemeDarkMediaQuery.matches = enabled; + + return flushTasks(); } setup(() => { @@ -78,6 +88,15 @@ document.createElement('scan-preview')); assertTrue(!!scanPreview); ScanningBrowserProxyImpl.instance_ = new TestScanningBrowserProxy(); + + // Setup mock for matchMedia. + mockController = new MockController(); + const mockMatchMedia = + mockController.createFunctionMock(window, 'matchMedia'); + fakePrefersColorSchemeDarkMediaQuery = + new FakeMediaQueryList('(prefers-color-scheme: dark)'); + mockMatchMedia.returnValue = fakePrefersColorSchemeDarkMediaQuery; + document.body.appendChild(scanPreview); helpOrProgress = @@ -96,6 +115,7 @@ if (scanPreview) { scanPreview.remove(); } + mockController.reset(); scanPreview = null; }); @@ -431,13 +451,11 @@ (/** @type {!HTMLImageElement} */ (scanPreview.$$('#readyToScanImg'))); // Mock media query state for light mode. - setIsDarkModeEnabled_(false); - await flushTasks(); + await setFakePrefersColorSchemeDark(false); assertEquals(getReadyToScanSvg().src, lightModeSvg); // Mock media query state for dark mode. - setIsDarkModeEnabled_(true); - await flushTasks(); + await setFakePrefersColorSchemeDark(true); assertEquals(getReadyToScanSvg().src, darkModeSvg); }); }
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js index 447f8e31e..a75fd35 100644 --- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js +++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import {alphabeticalCompare} from 'chrome://scanning/scanning_app_util.js'; -import {assertTrue} from '../../chai_assert.js'; + +import {assertEquals, assertTrue} from '../../chai_assert.js'; import {flushTasks} from '../../test_util.js'; /** @@ -76,3 +77,64 @@ select.dispatchEvent(new CustomEvent('change')); return flushTasks(); } + +/** @typedef {function(string, {media: string, matches: boolean})} */ +let MediaQueryListEventListener; + +/** + * Fake MediaQueryList for mocking behavior of |window.matchMedia|. + * @extends {EventTarget} + * @implements {MediaQueryList} + * @suppress {checkTypes} Type checker incorrectly states class cannot be + * extended. + */ +export class FakeMediaQueryList extends EventTarget { + constructor(media) { + super(); + /** @type {string} */ + this.media_ = media; + /** @type {boolean} */ + this.matches_ = false; + /** @type {?MediaQueryListEventListener} */ + this.listener_ = null; + } + + /** @param {!Function} listener */ + addListener(listener) { + this.listener_ = listener; + } + + /** @param {!Function} listener */ + removeListener(listener) { + this.listener_ = null; + } + + onchange() { + if (!this.listener_) { + return; + } + + this.listener_(new window.MediaQueryListEvent( + 'change', {media: this.media_, matches: this.matches_})); + } + + /** @return {string} */ + get media() { + return this.media_; + } + + /** @return {boolean} */ + get matches() { + return this.matches_; + } + + /** @param {boolean} matches */ + set matches(matches) { + if (this.matches_ === matches) { + return; + } + + this.matches_ = matches; + this.onchange(); + } +}
diff --git a/chrome/updater/app/app_server_unittest.cc b/chrome/updater/app/app_server_unittest.cc index cae1065..05c8b47 100644 --- a/chrome/updater/app/app_server_unittest.cc +++ b/chrome/updater/app/app_server_unittest.cc
@@ -65,8 +65,8 @@ void ClearPrefs() { const UpdaterScope updater_scope = GetUpdaterScope(); for (const absl::optional<base::FilePath>& path : - {GetBaseDataDirectory(updater_scope), - GetVersionedDataDirectory(updater_scope)}) { + {GetBaseDirectory(updater_scope), + GetVersionedDirectory(updater_scope)}) { ASSERT_TRUE(path); ASSERT_TRUE( base::DeleteFile(path->Append(FILE_PATH_LITERAL("prefs.json"))));
diff --git a/chrome/updater/app/app_uninstall.cc b/chrome/updater/app/app_uninstall.cc index accf14f..1341c0c 100644 --- a/chrome/updater/app/app_uninstall.cc +++ b/chrome/updater/app/app_uninstall.cc
@@ -43,7 +43,7 @@ // given `scope`. void UninstallOtherVersions(UpdaterScope scope) { const absl::optional<base::FilePath> updater_folder_path = - GetBaseInstallDirectory(scope); + GetUpdaterFolderPath(scope); if (!updater_folder_path) { LOG(ERROR) << "Failed to get updater folder path."; return; @@ -52,7 +52,7 @@ base::FileEnumerator::DIRECTORIES); for (base::FilePath version_folder_path = file_enumerator.Next(); !version_folder_path.empty() && - version_folder_path != GetVersionedInstallDirectory(scope); + version_folder_path != GetVersionedUpdaterFolderPath(scope); version_folder_path = file_enumerator.Next()) { const base::FilePath version_executable_path = version_folder_path.Append(GetExecutableRelativePath());
diff --git a/chrome/updater/app/server/win/server.cc b/chrome/updater/app/server/win/server.cc index b8751866..eef6290 100644 --- a/chrome/updater/app/server/win/server.cc +++ b/chrome/updater/app/server/win/server.cc
@@ -293,7 +293,7 @@ std::unique_ptr<WorkItemList> list(WorkItem::CreateWorkItemList()); const absl::optional<base::FilePath> versioned_directory = - GetVersionedDataDirectory(updater_scope()); + GetVersionedDirectory(updater_scope()); if (!versioned_directory) return false;
diff --git a/chrome/updater/constants.h b/chrome/updater/constants.h index f7da595..26b7f02 100644 --- a/chrome/updater/constants.h +++ b/chrome/updater/constants.h
@@ -265,7 +265,7 @@ constexpr int kErrorFailedToDeleteDataFolder = 17; // Failed to get versioned updater folder path. -constexpr int kErrorFailedToGetVersionedInstallDirectory = 18; +constexpr int kErrorFailedToGetVersionedUpdaterFolderPath = 18; // Failed to get the installed app bundle path. constexpr int kErrorFailedToGetAppBundlePath = 19;
diff --git a/chrome/updater/crash_client.cc b/chrome/updater/crash_client.cc index 055b8c7f..9ab37b9 100644 --- a/chrome/updater/crash_client.cc +++ b/chrome/updater/crash_client.cc
@@ -56,7 +56,7 @@ base::PathService::Get(base::FILE_EXE, &handler_path); const absl::optional<base::FilePath> database_path = - GetVersionedDataDirectory(updater_scope); + GetVersionedDirectory(updater_scope); if (!database_path) { LOG(ERROR) << "Failed to get the database path."; return false;
diff --git a/chrome/updater/crash_reporter.cc b/chrome/updater/crash_reporter.cc index 89d3c4b..66077bb 100644 --- a/chrome/updater/crash_reporter.cc +++ b/chrome/updater/crash_reporter.cc
@@ -73,7 +73,7 @@ base::PathService::Get(base::FILE_EXE, &handler_path); const absl::optional<base::FilePath> database_path = - GetVersionedDataDirectory(updater_scope); + GetVersionedDirectory(updater_scope); if (!database_path) { LOG(ERROR) << "Failed to get the database path."; return;
diff --git a/chrome/updater/device_management/dm_storage.cc b/chrome/updater/device_management/dm_storage.cc index 1c22bed..a9df20a 100644 --- a/chrome/updater/device_management/dm_storage.cc +++ b/chrome/updater/device_management/dm_storage.cc
@@ -205,7 +205,7 @@ scoped_refptr<DMStorage> GetDefaultDMStorage() { const absl::optional<base::FilePath> updater_versioned_path = - GetVersionedDataDirectory(GetUpdaterScope()); + GetVersionedDirectory(GetUpdaterScope()); if (!updater_versioned_path) return nullptr;
diff --git a/chrome/updater/external_constants_builder.cc b/chrome/updater/external_constants_builder.cc index c2ed04c1..70aa4e1 100644 --- a/chrome/updater/external_constants_builder.cc +++ b/chrome/updater/external_constants_builder.cc
@@ -119,7 +119,7 @@ bool ExternalConstantsBuilder::Overwrite() { const absl::optional<base::FilePath> base_path = - GetBaseDataDirectory(GetUpdaterScope()); + GetBaseDirectory(GetUpdaterScope()); if (!base_path) { LOG(ERROR) << "Can't find base directory; can't save constant overrides."; return false;
diff --git a/chrome/updater/external_constants_builder_unittest.cc b/chrome/updater/external_constants_builder_unittest.cc index 5535672b..4b3b354 100644 --- a/chrome/updater/external_constants_builder_unittest.cc +++ b/chrome/updater/external_constants_builder_unittest.cc
@@ -28,7 +28,7 @@ void DeleteOverridesFile() { const absl::optional<base::FilePath> target = - GetBaseDataDirectory(GetUpdaterScope()); + GetBaseDirectory(GetUpdaterScope()); if (!target) { LOG(ERROR) << "Could not get base directory to clean out overrides file."; return;
diff --git a/chrome/updater/external_constants_override.cc b/chrome/updater/external_constants_override.cc index db025e4..5186281 100644 --- a/chrome/updater/external_constants_override.cc +++ b/chrome/updater/external_constants_override.cc
@@ -152,7 +152,7 @@ ExternalConstantsOverrider::FromDefaultJSONFile( scoped_refptr<ExternalConstants> next_provider) { const absl::optional<base::FilePath> data_dir_path = - GetBaseDataDirectory(GetUpdaterScope()); + GetBaseDirectory(GetUpdaterScope()); if (!data_dir_path) { LOG(ERROR) << "Cannot find app data path."; return nullptr;
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc index d0a4415..03dc024 100644 --- a/chrome/updater/installer.cc +++ b/chrome/updater/installer.cc
@@ -41,7 +41,7 @@ // identified by the |app_id|. absl::optional<base::FilePath> GetAppInstallDir(UpdaterScope scope, const std::string& app_id) { - absl::optional<base::FilePath> app_install_dir = GetBaseDataDirectory(scope); + absl::optional<base::FilePath> app_install_dir = GetBaseDirectory(scope); if (!app_install_dir) return absl::nullopt;
diff --git a/chrome/updater/mac/setup/keystone.mm b/chrome/updater/mac/setup/keystone.mm index 8fce8b3..e5ba527 100644 --- a/chrome/updater/mac/setup/keystone.mm +++ b/chrome/updater/mac/setup/keystone.mm
@@ -70,9 +70,9 @@ if (!base::SetPosixFilePermissions( GetLibraryFolderPath(scope)->Append(COMPANY_SHORTNAME_STRING), kPermissionsMask) || - !base::SetPosixFilePermissions(*GetBaseInstallDirectory(scope), + !base::SetPosixFilePermissions(*GetUpdaterFolderPath(scope), kPermissionsMask) || - !base::SetPosixFilePermissions(*GetVersionedInstallDirectory(scope), + !base::SetPosixFilePermissions(*GetVersionedUpdaterFolderPath(scope), kPermissionsMask) || !base::SetPosixFilePermissions(dest_path, kPermissionsMask)) { LOG(ERROR) << "Failed to set permissions to drwxr-xr-x at "
diff --git a/chrome/updater/mac/setup/setup.mm b/chrome/updater/mac/setup/setup.mm index a0166ab..a307780 100644 --- a/chrome/updater/mac/setup/setup.mm +++ b/chrome/updater/mac/setup/setup.mm
@@ -101,9 +101,9 @@ if (!base::SetPosixFilePermissions( GetLibraryFolderPath(scope)->Append(COMPANY_SHORTNAME_STRING), kPermissionsMask) || - !base::SetPosixFilePermissions(*GetBaseInstallDirectory(scope), + !base::SetPosixFilePermissions(*GetUpdaterFolderPath(scope), kPermissionsMask) || - !base::SetPosixFilePermissions(*GetVersionedInstallDirectory(scope), + !base::SetPosixFilePermissions(*GetVersionedUpdaterFolderPath(scope), kPermissionsMask)) { LOG(ERROR) << "Failed to set permissions to drwxr-xr-x at " << dest_path.value().c_str(); @@ -317,15 +317,15 @@ } bool DeleteInstallFolder(UpdaterScope scope) { - return DeleteFolder(GetBaseInstallDirectory(scope)); + return DeleteFolder(GetUpdaterFolderPath(scope)); } bool DeleteCandidateInstallFolder(UpdaterScope scope) { - return DeleteFolder(GetVersionedInstallDirectory(scope)); + return DeleteFolder(GetVersionedUpdaterFolderPath(scope)); } bool DeleteDataFolder(UpdaterScope scope) { - return DeleteFolder(GetBaseDataDirectory(scope)); + return DeleteFolder(GetBaseDirectory(scope)); } void CleanAfterInstallFailure(UpdaterScope scope) { @@ -359,10 +359,10 @@ int DoSetup(UpdaterScope scope) { const absl::optional<base::FilePath> dest_path = - GetVersionedInstallDirectory(scope); + GetVersionedUpdaterFolderPath(scope); if (!dest_path) - return kErrorFailedToGetVersionedInstallDirectory; + return kErrorFailedToGetVersionedUpdaterFolderPath; if (!CopyBundle(*dest_path, scope)) return kErrorFailedToCopyBundle; @@ -408,9 +408,9 @@ int PromoteCandidate(UpdaterScope scope) { const absl::optional<base::FilePath> dest_path = - GetVersionedInstallDirectory(scope); + GetVersionedUpdaterFolderPath(scope); if (!dest_path) - return kErrorFailedToGetVersionedInstallDirectory; + return kErrorFailedToGetVersionedUpdaterFolderPath; const base::FilePath updater_executable_path = dest_path->Append(GetExecutableRelativePath()); @@ -428,36 +428,34 @@ #pragma mark Uninstall int UninstallCandidate(UpdaterScope scope) { - int error = kErrorOk; - - if (!DeleteCandidateInstallFolder(scope) || - !DeleteFolder(GetVersionedDataDirectory(scope))) { - error = kErrorFailedToDeleteFolder; - } + if (!DeleteCandidateInstallFolder(scope)) + return kErrorFailedToDeleteFolder; if (!RemoveUpdateWakeJobFromLaunchd(scope)) - error = kErrorFailedToRemoveWakeJobFromLaunchd; + return kErrorFailedToRemoveWakeJobFromLaunchd; // Removing the Update Internal job has to be the last step because launchd is // likely to terminate the current process. Clients should expect the // connection to invalidate (possibly with an interruption beforehand) as a // result of service uninstallation. if (!RemoveUpdateServiceInternalJobFromLaunchd(scope)) - error = kErrorFailedToRemoveUpdateServiceInternalJobFromLaunchd; + return kErrorFailedToRemoveUpdateServiceInternalJobFromLaunchd; - return error; + return kErrorOk; } int Uninstall(UpdaterScope scope) { VLOG(1) << base::CommandLine::ForCurrentProcess()->GetCommandLineString() << " : " << __func__; - int exit = UninstallCandidate(scope); + const int exit = UninstallCandidate(scope); + if (exit != kErrorOk) + return exit; if (!RemoveUpdateServiceJobFromLaunchd(scope)) - exit = kErrorFailedToRemoveActiveUpdateServiceJobFromLaunchd; + return kErrorFailedToRemoveActiveUpdateServiceJobFromLaunchd; if (!DeleteInstallFolder(scope)) - exit = kErrorFailedToDeleteFolder; + return kErrorFailedToDeleteFolder; base::ThreadPool::PostTask(FROM_HERE, {base::MayBlock(), base::WithBaseSyncPrimitives()}, @@ -468,7 +466,7 @@ // it is not always possible to delete the data folder. DeleteDataFolder(scope); - return exit; + return kErrorOk; } } // namespace updater
diff --git a/chrome/updater/prefs.cc b/chrome/updater/prefs.cc index 97dca73..6e9c350 100644 --- a/chrome/updater/prefs.cc +++ b/chrome/updater/prefs.cc
@@ -94,7 +94,7 @@ return nullptr; const absl::optional<base::FilePath> global_prefs_dir = - GetBaseDataDirectory(scope); + GetBaseDirectory(scope); if (!global_prefs_dir) return nullptr; VLOG(1) << "global_prefs_dir: " << global_prefs_dir; @@ -117,7 +117,7 @@ scoped_refptr<LocalPrefs> CreateLocalPrefs(UpdaterScope scope) { const absl::optional<base::FilePath> local_prefs_dir = - GetVersionedDataDirectory(scope); + GetVersionedDirectory(scope); if (!local_prefs_dir) return nullptr;
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc index 959a1d9..987ca959 100644 --- a/chrome/updater/test/integration_tests_impl.cc +++ b/chrome/updater/test/integration_tests_impl.cc
@@ -291,7 +291,7 @@ // Invoke the wake client of that version. base::CommandLine command_line( - GetVersionedInstallDirectory(scope, active_version) + GetVersionedUpdaterFolderPathForVersion(scope, active_version) ->Append(GetExecutableRelativePath())); command_line.AppendSwitch(kWakeSwitch); int exit_code = -1;
diff --git a/chrome/updater/test/integration_tests_mac.mm b/chrome/updater/test/integration_tests_mac.mm index 39399253..d1d1d780 100644 --- a/chrome/updater/test/integration_tests_mac.mm +++ b/chrome/updater/test/integration_tests_mac.mm
@@ -266,7 +266,7 @@ Launchd::Type launchd_type = LaunchdType(scope); absl::optional<base::FilePath> versioned_folder_path = - GetVersionedInstallDirectory(scope); + GetVersionedUpdaterFolderPath(scope); EXPECT_TRUE(versioned_folder_path); if (versioned_folder_path) EXPECT_FALSE(base::PathExists(*versioned_folder_path));
diff --git a/chrome/updater/util.cc b/chrome/updater/util.cc index 7422271..7aa105d 100644 --- a/chrome/updater/util.cc +++ b/chrome/updater/util.cc
@@ -101,7 +101,7 @@ } // namespace -absl::optional<base::FilePath> GetBaseDataDirectory(UpdaterScope scope) { +absl::optional<base::FilePath> GetBaseDirectory(UpdaterScope scope) { absl::optional<base::FilePath> app_data_dir; #if BUILDFLAG(IS_WIN) base::FilePath path; @@ -130,9 +130,8 @@ return product_data_dir; } -absl::optional<base::FilePath> GetVersionedDataDirectory(UpdaterScope scope) { - const absl::optional<base::FilePath> product_dir = - GetBaseDataDirectory(scope); +absl::optional<base::FilePath> GetVersionedDirectory(UpdaterScope scope) { + const absl::optional<base::FilePath> product_dir = GetBaseDirectory(scope); if (!product_dir) { LOG(ERROR) << "Failed to get the base directory."; return absl::nullopt; @@ -147,18 +146,19 @@ return versioned_dir; } -absl::optional<base::FilePath> GetVersionedInstallDirectory( +absl::optional<base::FilePath> GetVersionedUpdaterFolderPathForVersion( UpdaterScope scope, const base::Version& version) { - const absl::optional<base::FilePath> path = GetBaseInstallDirectory(scope); + const absl::optional<base::FilePath> path = GetUpdaterFolderPath(scope); if (!path) return absl::nullopt; return path->AppendASCII(version.GetString()); } -absl::optional<base::FilePath> GetVersionedInstallDirectory( +absl::optional<base::FilePath> GetVersionedUpdaterFolderPath( UpdaterScope scope) { - return GetVersionedInstallDirectory(scope, base::Version(kUpdaterVersion)); + return GetVersionedUpdaterFolderPathForVersion( + scope, base::Version(kUpdaterVersion)); } TagParsingResult::TagParsingResult() = default; @@ -225,7 +225,7 @@ void InitLogging(UpdaterScope updater_scope) { logging::LoggingSettings settings; const absl::optional<base::FilePath> log_dir = - GetBaseDataDirectory(updater_scope); + GetBaseDirectory(updater_scope); if (!log_dir) { LOG(ERROR) << "Error getting base dir."; return; @@ -264,7 +264,7 @@ #if BUILDFLAG(IS_LINUX) // TODO(crbug.com/1276188) - implement the functions below. -absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) { +absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope) { NOTIMPLEMENTED(); return absl::nullopt; }
diff --git a/chrome/updater/util.h b/chrome/updater/util.h index dc0a2a7..90016bbb 100644 --- a/chrome/updater/util.h +++ b/chrome/updater/util.h
@@ -43,32 +43,34 @@ enum class UpdaterScope; -// Returns the base data directory common to all versions of the updater. For +// Returns the base directory common to all versions of the updater. For // instance, this function may return %localappdata%\Chromium\ChromiumUpdater -// for a user install. Creates the directory if it does not exist. -absl::optional<base::FilePath> GetBaseDataDirectory(UpdaterScope scope); +// for a user install. +absl::optional<base::FilePath> GetBaseDirectory(UpdaterScope scope); -// Returns the versioned data directory under which the running version of the -// updater stores its data. For instance, this function may return -// %localappdata%\Chromium\ChromiumUpdater\1.2.3.4 for a user install. Creates -// the directory if it does not exit. -absl::optional<base::FilePath> GetVersionedDataDirectory(UpdaterScope scope); +// Returns a versioned directory under which the running version of the updater +// stores its files and data. For instance, this function may return +// %localappdata%\Chromium\ChromiumUpdater\1.2.3.4 for a user install. +absl::optional<base::FilePath> GetVersionedDirectory(UpdaterScope scope); -// Returns the versioned install directory under which the program stores its -// executables. For example, on macOS this function may return -// ~/Library/Google/GoogleUpdater/88.0.4293.0 (/Library for system). Does not -// create the directory if it does not exist. -absl::optional<base::FilePath> GetVersionedInstallDirectory( +// For user installations: +// ~/Library/Google/GoogleUpdater/88.0.4293.0 +// For system installations: +// /Library/Google/GoogleUpdater/88.0.4293.0 +absl::optional<base::FilePath> GetVersionedUpdaterFolderPathForVersion( UpdaterScope scope, const base::Version& version); -// Simpler form of GetVersionedInstallDirectory for the currently running -// version of the updater. -absl::optional<base::FilePath> GetVersionedInstallDirectory(UpdaterScope scope); +// The same as GetVersionedUpdaterFolderPathForVersion, where the version is +// kUpdaterVersion. +absl::optional<base::FilePath> GetVersionedUpdaterFolderPath( + UpdaterScope scope); -// Returns the base install directory common to all versions of the updater. -// Does not create the directory if it does not exist. -absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope); +// For user installations: +// ~/Library/Google/GoogleUpdater +// For system installations: +// /Library/Google/GoogleUpdater +absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope); #if BUILDFLAG(IS_MAC) // For example: ~/Library/Google/GoogleUpdater/88.0.4293.0/GoogleUpdater.app
diff --git a/chrome/updater/util_mac.mm b/chrome/updater/util_mac.mm index ca0fba64..d755f00 100644 --- a/chrome/updater/util_mac.mm +++ b/chrome/updater/util_mac.mm
@@ -63,7 +63,7 @@ return exit_code <= 1; } -absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) { +absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope) { absl::optional<base::FilePath> path = GetLibraryFolderPath(scope); if (!path) return absl::nullopt; @@ -74,14 +74,14 @@ UpdaterScope scope, const base::Version& version) { absl::optional<base::FilePath> path = - GetVersionedInstallDirectory(scope, version); + GetVersionedUpdaterFolderPathForVersion(scope, version); if (!path) return absl::nullopt; return path->Append(ExecutableFolderPath()); } absl::optional<base::FilePath> GetUpdaterAppBundlePath(UpdaterScope scope) { - absl::optional<base::FilePath> path = GetVersionedInstallDirectory(scope); + absl::optional<base::FilePath> path = GetVersionedUpdaterFolderPath(scope); if (!path) return absl::nullopt; return path->Append( @@ -89,7 +89,7 @@ } absl::optional<base::FilePath> GetUpdaterExecutablePath(UpdaterScope scope) { - absl::optional<base::FilePath> path = GetVersionedInstallDirectory(scope); + absl::optional<base::FilePath> path = GetVersionedUpdaterFolderPath(scope); if (!path) return absl::nullopt; return path->Append(ExecutableFolderPath())
diff --git a/chrome/updater/util_win.cc b/chrome/updater/util_win.cc index 99a524d..f04f08ff 100644 --- a/chrome/updater/util_win.cc +++ b/chrome/updater/util_win.cc
@@ -46,7 +46,7 @@ return std::string(); } -absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) { +absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope) { base::FilePath app_data_dir; if (!base::PathService::Get(scope == UpdaterScope::kSystem ? base::DIR_PROGRAM_FILES
diff --git a/chrome/updater/win/setup/setup.cc b/chrome/updater/win/setup/setup.cc index 345c798..ca57f339 100644 --- a/chrome/updater/win/setup/setup.cc +++ b/chrome/updater/win/setup/setup.cc
@@ -118,9 +118,9 @@ return -1; } const absl::optional<base::FilePath> versioned_dir = - GetVersionedDataDirectory(scope); + GetVersionedDirectory(scope); if (!versioned_dir) { - LOG(ERROR) << "GetVersionedDataDirectory failed."; + LOG(ERROR) << "GetVersionedDirectory failed."; return -1; } base::FilePath exe_path;
diff --git a/chrome/updater/win/setup/uninstall.cc b/chrome/updater/win/setup/uninstall.cc index acf1716..0407a60 100644 --- a/chrome/updater/win/setup/uninstall.cc +++ b/chrome/updater/win/setup/uninstall.cc
@@ -94,14 +94,14 @@ int RunUninstallScript(UpdaterScope scope, bool uninstall_all) { const absl::optional<base::FilePath> versioned_dir = - GetVersionedDataDirectory(scope); + GetVersionedDirectory(scope); if (!versioned_dir) { - LOG(ERROR) << "GetVersionedDataDirectory failed."; + LOG(ERROR) << "GetVersionedDirectory failed."; return kErrorNoVersionedDirectory; } - const absl::optional<base::FilePath> base_dir = GetBaseDataDirectory(scope); + const absl::optional<base::FilePath> base_dir = GetBaseDirectory(scope); if (scope == UpdaterScope::kSystem && !base_dir) { - LOG(ERROR) << "GetBaseDataDirectory failed."; + LOG(ERROR) << "GetBaseDirectory failed."; return kErrorNoBaseDirectory; }
diff --git a/chrome/updater/win/task_scheduler_unittest.cc b/chrome/updater/win/task_scheduler_unittest.cc index 231de494..f1741b9 100644 --- a/chrome/updater/win/task_scheduler_unittest.cc +++ b/chrome/updater/win/task_scheduler_unittest.cc
@@ -105,7 +105,7 @@ void DeleteLogFile() { const absl::optional<base::FilePath> log_dir = - GetBaseDataDirectory(GetTestScope()); + GetBaseDirectory(GetTestScope()); if (log_dir) { base::DeleteFile(log_dir->Append(FILE_PATH_LITERAL("updater.log"))); }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 024eec11..ae0de0b 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -14844.0.0 \ No newline at end of file +14906.0.0 \ No newline at end of file
diff --git a/chromeos/ash/components/cros_elements/BUILD.gn b/chromeos/ash/components/cros_elements/BUILD.gn index 54fccc2..7be00d3 100644 --- a/chromeos/ash/components/cros_elements/BUILD.gn +++ b/chromeos/ash/components/cros_elements/BUILD.gn
@@ -13,7 +13,7 @@ input_files = [ "button/button.js" ] - deps = [ "button" ] + public_deps = [ "button" ] input_files_base_dir = rebase_path(target_gen_dir, root_build_dir) resource_path_prefix = "cros_elements"
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 6084cd3..bf2ef769 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -3127,7 +3127,7 @@ Install is complete. Preparing to restart... </message> <message name="IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE" desc="The message when firmware installation is complete and the device has rebooted."> - Installation complete. + Install is complete. You can now remove your USB drive or SD card. </message> <!-- Onboarding update page --> <message name="IDS_SHIMLESS_RMA_ONBOARDING_UPDATE_PROGRESS" translateable="false" desc="The update progress label.">
diff --git a/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1 b/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1 index f08963f..f58f76e 100644 --- a/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1
@@ -1 +1 @@ -752fac072ce209d2098651bc8f10558d36f9e3bc \ No newline at end of file +d252ae7b76c89138f4afa159557c2942b9b85d1a \ No newline at end of file
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc index 9a04086..0e8d0520 100644 --- a/chromeos/dbus/session_manager/fake_session_manager_client.cc +++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -408,7 +408,8 @@ } bool FakeSessionManagerClient::RequestBrowserDataMigration( - const cryptohome::AccountIdentifier& cryptohome_id) { + const cryptohome::AccountIdentifier& cryptohome_id, + const bool is_move) { request_browser_data_migration_called_ = true; return true;
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h index 9f4a5e9d..112f53ea 100644 --- a/chromeos/dbus/session_manager/fake_session_manager_client.h +++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -104,7 +104,8 @@ void NotifyLockScreenShown() override; void NotifyLockScreenDismissed() override; bool RequestBrowserDataMigration( - const cryptohome::AccountIdentifier& cryptohome_id) override; + const cryptohome::AccountIdentifier& cryptohome_id, + const bool is_move) override; void RetrieveActiveSessions(ActiveSessionsCallback callback) override; void RetrieveDevicePolicy(RetrievePolicyCallback callback) override; RetrievePolicyResponseType BlockingRetrieveDevicePolicy(
diff --git a/chromeos/dbus/session_manager/session_manager_client.cc b/chromeos/dbus/session_manager/session_manager_client.cc index 22f1e236..c140b00 100644 --- a/chromeos/dbus/session_manager/session_manager_client.cc +++ b/chromeos/dbus/session_manager/session_manager_client.cc
@@ -25,6 +25,7 @@ #include "base/memory/writable_shared_memory_region.h" #include "base/path_service.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/unguessable_token.h" #include "chromeos/dbus/common/blocking_method_caller.h" @@ -403,18 +404,24 @@ } bool RequestBrowserDataMigration( - const cryptohome::AccountIdentifier& cryptohome_id) override { + const cryptohome::AccountIdentifier& cryptohome_id, + const bool is_move) override { dbus::MethodCall method_call( login_manager::kSessionManagerInterface, login_manager::kSessionManagerStartBrowserDataMigration); dbus::MessageWriter writer(&method_call); writer.AppendString(cryptohome_id.account_id()); + writer.AppendBool(is_move); dbus::ScopedDBusError error; std::unique_ptr<dbus::Response> response = blocking_method_caller_->CallMethodAndBlockWithError(&method_call, &error); if (!response) { - LOG(ERROR) << "RequestBrowserDataMigration failed."; + LOG(ERROR) << "RequestBrowserDataMigration failed" + << (error.is_set() + ? base::StringPrintf(" :%s:%s", error.name(), + error.message()) + : "."); return false; }
diff --git a/chromeos/dbus/session_manager/session_manager_client.h b/chromeos/dbus/session_manager/session_manager_client.h index 3552da8..325f342 100644 --- a/chromeos/dbus/session_manager/session_manager_client.h +++ b/chromeos/dbus/session_manager/session_manager_client.h
@@ -258,7 +258,8 @@ // successful. The callback is passed true if the DBus call is successful and // false otherwise. virtual bool RequestBrowserDataMigration( - const cryptohome::AccountIdentifier& cryptohome_id) = 0; + const cryptohome::AccountIdentifier& cryptohome_id, + const bool is_move) = 0; // Map that is used to describe the set of active user sessions where |key| // is cryptohome id and |value| is user_id_hash.
diff --git a/chromeos/ui/base/window_properties.cc b/chromeos/ui/base/window_properties.cc index ae4e673..aecb0790 100644 --- a/chromeos/ui/base/window_properties.cc +++ b/chromeos/ui/base/window_properties.cc
@@ -55,6 +55,6 @@ kWindowStateTypeKey, WindowStateType::kDefault) -DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowFloatTypeKey, false) +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowToggleFloatKey, false) } // namespace chromeos
diff --git a/chromeos/ui/base/window_properties.h b/chromeos/ui/base/window_properties.h index 5911b7b..31c7119 100644 --- a/chromeos/ui/base/window_properties.h +++ b/chromeos/ui/base/window_properties.h
@@ -116,9 +116,9 @@ COMPONENT_EXPORT(CHROMEOS_UI_BASE) extern const ui::ClassProperty<WindowStateType>* const kWindowStateTypeKey; -// A property key to indicate Float window state. +// A property key to toggle Float window state change. COMPONENT_EXPORT(CHROMEOS_UI_BASE) -extern const ui::ClassProperty<bool>* const kWindowFloatTypeKey; +extern const ui::ClassProperty<bool>* const kWindowToggleFloatKey; // A property key whose value is shown in alt-tab/overview mode. If non-value // is set, the window's title is used.
diff --git a/chromeos/ui/base/window_state_type.cc b/chromeos/ui/base/window_state_type.cc index 03f7469..3ae0cbf 100644 --- a/chromeos/ui/base/window_state_type.cc +++ b/chromeos/ui/base/window_state_type.cc
@@ -34,6 +34,8 @@ return stream << "kTrustedPinned"; case WindowStateType::kPip: return stream << "kPip"; + case WindowStateType::kFloated: + return stream << "kFloated"; } NOTREACHED(); @@ -69,6 +71,7 @@ case WindowStateType::kPrimarySnapped: case WindowStateType::kAutoPositioned: case WindowStateType::kPip: + case WindowStateType::kFloated: return ui::SHOW_STATE_NORMAL; case WindowStateType::kMinimized:
diff --git a/chromeos/ui/base/window_state_type.h b/chromeos/ui/base/window_state_type.h index a64dfb8e..a04337dc 100644 --- a/chromeos/ui/base/window_state_type.h +++ b/chromeos/ui/base/window_state_type.h
@@ -44,6 +44,11 @@ // A window in Picture-in-Picture mode (PIP). kPip, + + // A window is floated on top of other windows (except PIP). When a window is + // floated, users are allowed to change the position and size of the window. + // One floated window is allowed per desk. + kFloated, }; COMPONENT_EXPORT(CHROMEOS_UI_BASE)
diff --git a/chromeos/ui/wm/window_util.cc b/chromeos/ui/wm/window_util.cc index 13decb2..8563ad04 100644 --- a/chromeos/ui/wm/window_util.cc +++ b/chromeos/ui/wm/window_util.cc
@@ -12,8 +12,8 @@ void ToggleFloating(aura::Window* window) { DCHECK(window); - const bool window_float_state = window->GetProperty(kWindowFloatTypeKey); - window->SetProperty(kWindowFloatTypeKey, !window_float_state); + const bool window_float_state = window->GetProperty(kWindowToggleFloatKey); + window->SetProperty(kWindowToggleFloatKey, !window_float_state); } } // namespace chromeos
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc index bdfb015f..5aa6ca0 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
@@ -204,7 +204,6 @@ web_data_backend_->CommitChanges(); if (offer_data_changed) { - // TODO(crbug.com/1112095): Add enum to indicate what actually changed. web_data_backend_->NotifyOfMultipleAutofillChanges(); } }
diff --git a/components/browser_sync/sync_api_component_factory_impl.cc b/components/browser_sync/sync_api_component_factory_impl.cc index 928e19cb..bd709095 100644 --- a/components/browser_sync/sync_api_component_factory_impl.cc +++ b/components/browser_sync/sync_api_component_factory_impl.cc
@@ -222,8 +222,6 @@ // Wallet offer data is enabled by default. Register unless explicitly // disabled. - // TODO(crbug.com/1112095): Currently the offer data depends on Wallet data - // sync, but revisit after other offer types are implemented. if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) && !disabled_types.Has(syncer::AUTOFILL_WALLET_OFFER)) { controllers.push_back(CreateWalletModelTypeController(
diff --git a/components/desks_storage/core/desk_sync_bridge.cc b/components/desks_storage/core/desk_sync_bridge.cc index 23483ac02..24da0bf 100644 --- a/components/desks_storage/core/desk_sync_bridge.cc +++ b/components/desks_storage/core/desk_sync_bridge.cc
@@ -365,6 +365,8 @@ case chromeos::WindowStateType::kPinned: case chromeos::WindowStateType::kTrustedPinned: case chromeos::WindowStateType::kPip: + // TODO(crbug.com/1331825): Float state support for desk template. + case chromeos::WindowStateType::kFloated: return WindowState::WorkspaceDeskSpecifics_WindowState_NORMAL; case chromeos::WindowStateType::kMinimized: return WindowState::WorkspaceDeskSpecifics_WindowState_MINIMIZED;
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h index ae830e5..8717d40 100644 --- a/components/infobars/core/infobar_delegate.h +++ b/components/infobars/core/infobar_delegate.h
@@ -180,6 +180,7 @@ IOS_PERMISSIONS_INFOBAR_DELEGATE = 108, SUPPORTED_LINKS_INFOBAR_DELEGATE_CHROMEOS = 109, AUTOFILL_VIRTUAL_CARD_ENROLLMENT_INFOBAR_DELEGATE_MOBILE = 110, + BASIC_PRINT_DEPRECATED_ACCELERATOR_DELEGATE = 111, }; // Describes navigation events, used to decide whether infobars should be
diff --git a/components/paint_preview/player/android/BUILD.gn b/components/paint_preview/player/android/BUILD.gn index 8974933..f573976 100644 --- a/components/paint_preview/player/android/BUILD.gn +++ b/components/paint_preview/player/android/BUILD.gn
@@ -145,9 +145,9 @@ "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/androidx:androidx_test_uiautomator_uiautomator_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit", - "//third_party/ub-uiautomator:ub_uiautomator_java", "//ui/android:ui_java_test_support", "//url:gurl_java", ]
diff --git a/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java b/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java index 2b335aba..40133c3 100644 --- a/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java +++ b/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
@@ -8,14 +8,14 @@ import android.os.Build; import android.os.Build.VERSION_CODES; import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; import android.util.Size; import android.view.View; import android.view.ViewGroup; import androidx.test.filters.MediumTest; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; import org.hamcrest.Matchers; import org.junit.Assert;
diff --git a/components/reporting/storage/storage_queue.cc b/components/reporting/storage/storage_queue.cc index dce572d6..d2e9af5 100644 --- a/components/reporting/storage/storage_queue.cc +++ b/components/reporting/storage/storage_queue.cc
@@ -317,8 +317,8 @@ options_.directory(), /*recursive=*/false, base::FileEnumerator::FILES, base::StrCat({options_.file_prefix(), FILE_PATH_LITERAL(".*")})); - base::FilePath full_name; - while (full_name = dir_enum.Next(), !full_name.empty()) { + for (auto full_name = dir_enum.Next(); !full_name.empty(); + full_name = dir_enum.Next()) { const auto file_sequencing_id_result = AddDataFile(full_name, dir_enum.GetInfo()); if (!file_sequencing_id_result.ok()) {
diff --git a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc index 7251778..052ea0f 100644 --- a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
@@ -1029,6 +1029,8 @@ dict.SetBoolean("is_phishing", cpr.is_phishing()); if (cpr.has_model_version()) dict.SetInteger("model_version", cpr.model_version()); + if (cpr.has_dom_model_version()) + dict.SetInteger("dom_model_version", cpr.dom_model_version()); base::Value::ListStorage features; for (const auto& feature : cpr.feature_map()) {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc index a2a1ee9..0e8954fdc 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
@@ -205,6 +205,10 @@ return flatbuffer_model_->version(); } +int FlatBufferModelScorer::dom_model_version() const { + return flatbuffer_model_->dom_model_version(); +} + bool FlatBufferModelScorer::has_page_term(const std::string& str) const { const flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>* hashes = flatbuffer_model_->hashes();
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h index a81c1a1..a34974a 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h +++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
@@ -56,6 +56,7 @@ #endif int model_version() const override; + int dom_model_version() const override; size_t max_words_per_term() const override; uint32_t murmurhash3_seed() const override; size_t max_shingles_per_page() const override;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc index 9c03565..c382b71 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
@@ -272,6 +272,7 @@ std::unique_ptr<ClientPhishingRequest> verdict = std::make_unique<ClientPhishingRequest>(); verdict->set_model_version(scorer->model_version()); + verdict->set_dom_model_version(scorer->dom_model_version()); verdict->set_url(main_frame->GetDocument().Url().GetString().Utf8()); for (const auto& it : features_->features()) { bool result = hashed_features.AddRealFeature(
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc index 48a3314..1ca421ec 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
@@ -127,6 +127,10 @@ return model_.version(); } +int ProtobufModelScorer::dom_model_version() const { + return model_.dom_model_version(); +} + bool Scorer::HasVisualTfLiteModel() const { return visual_tflite_model_.IsValid(); }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h index 0a6bf37e..4243d3ee 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h +++ b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
@@ -54,6 +54,7 @@ #endif int model_version() const override; + int dom_model_version() const override; base::RepeatingCallback<bool(uint32_t)> find_page_word_callback() const override; base::RepeatingCallback<bool(const std::string&)> find_page_term_callback()
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h index d33e394..1461ed2 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h +++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
@@ -81,6 +81,8 @@ // Returns the version number of the loaded client model. virtual int model_version() const = 0; + virtual int dom_model_version() const = 0; + bool HasVisualTfLiteModel() const; // -- Accessors used by the page feature extractor ---------------------------
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc b/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc index 2bbb8af..7dcd9f3 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
@@ -84,6 +84,7 @@ csd_model_builder.add_max_shingles_per_page(10); csd_model_builder.add_shingle_size(3); csd_model_builder.add_tflite_metadata(tflite_metadata_flat); + csd_model_builder.add_dom_model_version(123); builder.Finish(csd_model_builder.Finish()); return std::string(reinterpret_cast<char*>(builder.GetBufferPointer()), @@ -139,6 +140,7 @@ model_.set_murmur_hash_seed(12345U); model_.set_max_shingles_per_page(10); model_.set_shingle_size(3); + model_.set_dom_model_version(123); } void TearDown() override { @@ -348,4 +350,23 @@ EXPECT_DOUBLE_EQ(0.77729986117469119, scorer->ComputeScore(features)); } +TEST_F(PhishingScorerTest, DomModelVersionProtobuffer) { + std::unique_ptr<Scorer> scorer; + scorer = + ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()); + ASSERT_TRUE(scorer.get() != nullptr); + EXPECT_EQ(scorer->dom_model_version(), 123); +} + +TEST_F(PhishingScorerTest, DomModelVersionFlatbuffer) { + std::unique_ptr<Scorer> scorer; + std::string flatbuffer = GetFlatBufferString(); + base::MappedReadOnlyRegion mapped_region = + GetMappedReadOnlyRegionWithData(flatbuffer); + scorer = FlatBufferModelScorer::Create(mapped_region.region.Duplicate(), + base::File()); + ASSERT_TRUE(scorer.get() != nullptr); + EXPECT_EQ(scorer->dom_model_version(), 123); +} + } // namespace safe_browsing
diff --git a/components/safe_browsing/core/common/fbs/client_model.fbs b/components/safe_browsing/core/common/fbs/client_model.fbs index 2cc0998..7bb1c2272 100644 --- a/components/safe_browsing/core/common/fbs/client_model.fbs +++ b/components/safe_browsing/core/common/fbs/client_model.fbs
@@ -39,6 +39,7 @@ tflite_model_input_width: int (deprecated); tflite_model_input_height: int (deprecated); tflite_metadata:safe_browsing.flat.TfLiteModelMetadata; + dom_model_version:int; } root_type ClientSideModel;
diff --git a/components/safe_browsing/core/common/proto/client_model.proto b/components/safe_browsing/core/common/proto/client_model.proto index 3c74599e..920711a57 100644 --- a/components/safe_browsing/core/common/proto/client_model.proto +++ b/components/safe_browsing/core/common/proto/client_model.proto
@@ -70,9 +70,11 @@ // Page terms in page_term contain at most this many page words. required int32 max_words_per_term = 5; - // Model version number. Every model that we train should have a different - // version number and it should always be larger than the previous model - // version. + optional int32 dom_model_version = 18; + + // The overall client model version number. Every model update should have a + // different version number and it should always be larger than the previous + // model version. optional int32 version = 6; // List of known bad IP subnets. @@ -107,7 +109,7 @@ optional TfLiteModelMetadata tflite_metadata = 17; - // next available tag number: 18 + // next available tag number: 19 } message TfLiteModelMetadata {
diff --git a/components/safe_browsing/core/common/proto/csd.proto b/components/safe_browsing/core/common/proto/csd.proto index 34e9e613..4112daa 100644 --- a/components/safe_browsing/core/common/proto/csd.proto +++ b/components/safe_browsing/core/common/proto/csd.proto
@@ -160,6 +160,9 @@ // sent to the scorer and which resulted in client_score being computed. repeated Feature feature_map = 5; + // The version of the DOM model used for classification + optional int32 dom_model_version = 27; + // The version number of the model that was used to compute the client-score. // Copied from ClientSideModel.version(). optional int32 model_version = 6; @@ -227,7 +230,7 @@ // users. optional VisualFeatures visual_features = 26; - // next available tag number: 27. + // next available tag number: 28. } message ClientPhishingResponse {
diff --git a/components/sessions/core/live_tab_context.h b/components/sessions/core/live_tab_context.h index fff5e758..db697a8 100644 --- a/components/sessions/core/live_tab_context.h +++ b/components/sessions/core/live_tab_context.h
@@ -36,6 +36,7 @@ // TODO(blundell): Rename. virtual void ShowBrowserWindow() = 0; virtual SessionID GetSessionID() const = 0; + virtual SessionWindow::WindowType GetWindowType() const = 0; virtual int GetTabCount() const = 0; virtual int GetSelectedIndex() const = 0; virtual std::string GetAppName() const = 0;
diff --git a/components/sessions/core/tab_restore_service.h b/components/sessions/core/tab_restore_service.h index 80a2722..5e7ecb5 100644 --- a/components/sessions/core/tab_restore_service.h +++ b/components/sessions/core/tab_restore_service.h
@@ -146,6 +146,9 @@ // Entry: size_t EstimateMemoryUsage() const override; + // Type of window. + SessionWindow::WindowType type; + // The tabs that comprised the window, in order. std::vector<std::unique_ptr<Tab>> tabs;
diff --git a/components/sessions/core/tab_restore_service_client.h b/components/sessions/core/tab_restore_service_client.h index 9d9c10c8..029b9ca0 100644 --- a/components/sessions/core/tab_restore_service_client.h +++ b/components/sessions/core/tab_restore_service_client.h
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/files/file_path.h" #include "components/sessions/core/session_id.h" +#include "components/sessions/core/session_types.h" #include "components/sessions/core/sessions_export.h" #include "ui/base/ui_base_types.h" @@ -28,7 +29,6 @@ class LiveTab; class LiveTabContext; -struct SessionWindow; // Callback from TabRestoreServiceClient::GetLastSession. // The second parameter is the id of the window that was last active. @@ -47,6 +47,7 @@ // functionality). virtual LiveTabContext* CreateLiveTabContext( LiveTabContext* existing_context, + SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state,
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc index d946a538..aa7c9c3 100644 --- a/components/sessions/core/tab_restore_service_helper.cc +++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -193,6 +193,7 @@ closing_contexts_.insert(context); auto window = std::make_unique<Window>(); + window->type = context->GetWindowType(); window->selected_tab_index = context->GetSelectedIndex(); window->timestamp = TimeNow(); window->app_name = context->GetAppName(); @@ -489,8 +490,9 @@ // restored. if (entry_id_matches_restore_id || !window.app_name.empty()) { context = client_->CreateLiveTabContext( - context, window.app_name, window.bounds, window.show_state, - window.workspace, window.user_title, window.extra_data); + context, window.type, window.app_name, window.bounds, + window.show_state, window.workspace, window.user_title, + window.extra_data); base::flat_map<tab_groups::TabGroupId, tab_groups::TabGroupId> new_group_ids; @@ -878,8 +880,9 @@ tab_index = tab.tabstrip_index; } else { context = client_->CreateLiveTabContext( - context, std::string(), gfx::Rect(), ui::SHOW_STATE_NORMAL, - std::string(), std::string(), std::map<std::string, std::string>()); + context, SessionWindow::TYPE_NORMAL, std::string(), gfx::Rect(), + ui::SHOW_STATE_NORMAL, std::string(), std::string(), + std::map<std::string, std::string>()); if (tab.browser_id) UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID()); }
diff --git a/components/sessions/core/tab_restore_service_impl.cc b/components/sessions/core/tab_restore_service_impl.cc index 7c7f7f9b..35f2ba5 100644 --- a/components/sessions/core/tab_restore_service_impl.cc +++ b/components/sessions/core/tab_restore_service_impl.cc
@@ -238,6 +238,24 @@ return false; } +// Converts an int to a window type. Returns true on success, false otherwise. +bool DeserializeWindowType(int type_int, + sessions::SessionWindow::WindowType* type) { + switch (static_cast<sessions::SessionWindow::WindowType>(type_int)) { + case sessions::SessionWindow::TYPE_NORMAL: + case sessions::SessionWindow::TYPE_POPUP: + case sessions::SessionWindow::TYPE_APP: + case sessions::SessionWindow::TYPE_DEVTOOLS: + case sessions::SessionWindow::TYPE_APP_POPUP: +#if BUILDFLAG(IS_CHROMEOS_ASH) + case sessions::SessionWindow::TYPE_CUSTOM_TAB: +#endif + *type = static_cast<sessions::SessionWindow::WindowType>(type_int); + return true; + } + return false; +} + // Superset of WindowPayloadObsolete/WindowPayloadObsolete2 and the other fields // that can appear in the Pickle version of a Window command. This is used as a // convenient destination for parsing the various fields in a WindowCommand. @@ -259,6 +277,8 @@ int window_height = 0; int window_show_state = 0; std::string workspace; + + int type = 0; }; std::unique_ptr<sessions::TabRestoreService::Window> @@ -267,6 +287,7 @@ int32_t* num_tabs) { WindowCommandFields fields; ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT; + auto type = sessions::SessionWindow::TYPE_NORMAL; if (command->id() == kCommandWindow) { std::unique_ptr<base::Pickle> pickle(command->PayloadAsPickle()); @@ -291,6 +312,14 @@ return nullptr; } + // New field in M104, use default if it fails to read. + // TODO(crbug.com/1332968): After some time (say M114), this code can be + // added into parsing above which fails when ReadInt() fails. + if (!it.ReadInt(&parsed_fields.type)) { + parsed_fields.type = + static_cast<int>(sessions::SessionWindow::TYPE_NORMAL); + } + // Validate the parameters. If the entire pickles parses but any of the // validation fails assume corruption. if (parsed_fields.window_width < 0 || parsed_fields.window_height < 0) @@ -302,6 +331,10 @@ return nullptr; } + // Validate window type. + if (!DeserializeWindowType(parsed_fields.type, &type)) { + return nullptr; + } // New fields added to the pickle in later versions would be parsed and // validated here. @@ -346,6 +379,7 @@ // Create the Window entry. std::unique_ptr<sessions::TabRestoreService::Window> window = std::make_unique<sessions::TabRestoreService::Window>(); + window->type = type; window->selected_tab_index = fields.selected_tab_index; window->timestamp = base::Time::FromDeltaSinceWindowsEpoch( base::Microseconds(fields.timestamp)); @@ -489,6 +523,7 @@ // Creates a window close command. static std::unique_ptr<SessionCommand> CreateWindowCommand( SessionID window_id, + SessionWindow::WindowType type, int selected_tab_index, int num_tabs, const gfx::Rect& bounds, @@ -764,7 +799,7 @@ return; // No tabs to persist. command_storage_manager_->ScheduleCommand(CreateWindowCommand( - window.id, std::min(real_selected_tab, valid_tab_count - 1), + window.id, window.type, std::min(real_selected_tab, valid_tab_count - 1), valid_tab_count, window.bounds, window.show_state, window.workspace, window.timestamp)); @@ -874,6 +909,7 @@ std::unique_ptr<SessionCommand> TabRestoreServiceImpl::PersistenceDelegate::CreateWindowCommand( SessionID window_id, + SessionWindow::WindowType type, int selected_tab_index, int num_tabs, const gfx::Rect& bounds, @@ -903,6 +939,8 @@ else pickle.WriteString(std::string()); + pickle.WriteInt(type); + std::unique_ptr<SessionCommand> command( new SessionCommand(kCommandWindow, pickle)); return command; @@ -1335,6 +1373,8 @@ bool TabRestoreServiceImpl::PersistenceDelegate::ConvertSessionWindowToWindow( SessionWindow* session_window, Window* window) { + window->type = session_window->type; + // The group visual datas must be stored in both |window| and each // grouped tab. std::map<tab_groups::TabGroupId, tab_groups::TabGroupVisualData>
diff --git a/components/viz/README.md b/components/viz/README.md index d6a63a63..1170d45 100644 --- a/components/viz/README.md +++ b/components/viz/README.md
@@ -131,13 +131,6 @@ compositor (typically thought of as SwapBuffers), as well as the use of overlays. -The source code is split into two build targets, -``components/viz/service:service`` and -``components/viz/service:gpu_service_dependencies``. The latter is -code that requires being run in the gpu process, thus could not work -if the viz service is located elsewhere. This is forward-looking code -as the viz service is moving into the gpu process always. - | Can depend on: | |:--------------------------------------| | viz/common/* | @@ -187,12 +180,6 @@ deallocating) gpu memory buffers, setting up a channel for the command buffer, etc. -Similar to ``service/display_embedder`` this is split into two targets in -the build system. Code that must run in the gpu process is compiled in -the ``components/viz/service:gpu_service_dependencies`` build target, -and the rest is compiled in ``components/viz/service:service``. As all -code moves to the gpu process, these two build targets will merge. - | Can depend on: | |:----------------------| | viz/common/* |
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 33e1f40f..10d10f49 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -39,6 +39,8 @@ "display/display.cc", "display/display.h", "display/display_client.h", + "display/display_compositor_memory_and_task_controller.cc", + "display/display_compositor_memory_and_task_controller.h", "display/display_damage_tracker.cc", "display/display_damage_tracker.h", "display/display_resource_provider.cc", @@ -98,13 +100,38 @@ "display_embedder/buffer_queue.h", "display_embedder/compositor_gpu_thread.cc", "display_embedder/compositor_gpu_thread.h", + "display_embedder/image_context_impl.cc", + "display_embedder/image_context_impl.h", "display_embedder/in_process_gpu_memory_buffer_manager.cc", "display_embedder/in_process_gpu_memory_buffer_manager.h", + "display_embedder/output_presenter.cc", + "display_embedder/output_presenter.h", + "display_embedder/output_presenter_gl.cc", + "display_embedder/output_presenter_gl.h", "display_embedder/output_surface_provider.h", "display_embedder/output_surface_provider_impl.cc", "display_embedder/output_surface_provider_impl.h", "display_embedder/server_shared_bitmap_manager.cc", "display_embedder/server_shared_bitmap_manager.h", + "display_embedder/skia_output_device.cc", + "display_embedder/skia_output_device.h", + "display_embedder/skia_output_device_buffer_queue.cc", + "display_embedder/skia_output_device_buffer_queue.h", + "display_embedder/skia_output_device_gl.cc", + "display_embedder/skia_output_device_gl.h", + "display_embedder/skia_output_device_offscreen.cc", + "display_embedder/skia_output_device_offscreen.h", + "display_embedder/skia_output_device_webview.cc", + "display_embedder/skia_output_device_webview.h", + "display_embedder/skia_output_surface_dependency.h", + "display_embedder/skia_output_surface_dependency_impl.cc", + "display_embedder/skia_output_surface_dependency_impl.h", + "display_embedder/skia_output_surface_impl.cc", + "display_embedder/skia_output_surface_impl.h", + "display_embedder/skia_output_surface_impl_on_gpu.cc", + "display_embedder/skia_output_surface_impl_on_gpu.h", + "display_embedder/skia_render_copy_results.cc", + "display_embedder/skia_render_copy_results.h", "display_embedder/software_output_surface.cc", "display_embedder/software_output_surface.h", "display_embedder/vsync_parameter_listener.cc", @@ -148,6 +175,8 @@ "frame_sinks/video_capture/video_frame_pool.h", "frame_sinks/video_detector.cc", "frame_sinks/video_detector.h", + "gl/gpu_service_impl.cc", + "gl/gpu_service_impl.h", "hit_test/hit_test_aggregator.cc", "hit_test/hit_test_aggregator.h", "hit_test/hit_test_aggregator_delegate.h", @@ -189,8 +218,6 @@ defines = [ "VIZ_SERVICE_IMPLEMENTATION" ] - allow_circular_includes_from = [ ":gpu_service_dependencies" ] - deps = [ "//build:chromecast_buildflags", "//build:chromeos_buildflags", @@ -198,13 +225,12 @@ "//cc/paint", "//components/crash/core/common:crash_key", "//components/power_scheduler", - "//gpu/command_buffer/client:gles2_cmd_helper", - "//gpu/command_buffer/client:gles2_implementation", - "//gpu/command_buffer/client:raster", # Note that dependency on //gpu/ipc/client is for GpuMemoryBufferImpl. This # dependency should not be in public_deps. "//components/viz/common", + "//gpu/command_buffer/client", + "//gpu/config", "//gpu/ipc/client", "//gpu/ipc/common:common", "//gpu/ipc/common:surface_handle_type", @@ -224,14 +250,20 @@ ] public_deps = [ - ":gpu_service_dependencies", "//base", "//cc", "//cc/debug", "//components/viz/common", - "//gpu/command_buffer/client:gles2_interface", + "//gpu/command_buffer/service:gles2", + "//gpu/ipc:gl_in_process_context", + "//gpu/ipc/service", + "//gpu/vulkan:buildflags", + "//media/gpu/ipc/service", + "//media/mojo/services", "//services/viz/privileged/mojom/compositing", + "//services/viz/privileged/mojom/gl", "//services/viz/public/mojom", + "//skia", "//ui/base/prediction", "//ui/gfx", "//ui/gfx/geometry", @@ -239,6 +271,18 @@ ] if (is_chromeos_ash) { + sources += [ + "display_embedder/output_surface_unified.cc", + "display_embedder/output_surface_unified.h", + ] + + deps += [ + "//components/chromeos_camera:jpeg_encode_accelerator_service", + "//components/chromeos_camera:mjpeg_decode_accelerator_service", + "//gpu/command_buffer/service:gles2", + "//media/mojo/services", + ] + if (use_v4l2_codec || use_vaapi) { deps += [ "//ash/components/arc/video_accelerator" ] } @@ -325,85 +369,6 @@ "display_embedder/output_device_backing.h", "display_embedder/software_output_device_win.cc", "display_embedder/software_output_device_win.h", - ] - } - - if (is_chromeos_ash) { - sources += [ - "display_embedder/output_surface_unified.cc", - "display_embedder/output_surface_unified.h", - ] - } - - if (enable_vulkan) { - deps += [ "//gpu/vulkan" ] - } -} - -# The gpu_service_dependencies source set contains source files that -# use the service side GL library (ui/gl), while the rest of -# viz/service use the client side GL library. This split is needed -# because the two GL libraries are incompatible and can't compile -# together in jumbo builds. -# -# Long term all service code is moving to be in the gpu process and -# then this build target will no longer be needed. -viz_source_set("gpu_service_dependencies") { - sources = [ - "display/display_compositor_memory_and_task_controller.cc", - "display/display_compositor_memory_and_task_controller.h", - "display_embedder/image_context_impl.cc", - "display_embedder/image_context_impl.h", - "display_embedder/output_presenter.cc", - "display_embedder/output_presenter.h", - "display_embedder/output_presenter_gl.cc", - "display_embedder/output_presenter_gl.h", - "display_embedder/skia_output_device.cc", - "display_embedder/skia_output_device.h", - "display_embedder/skia_output_device_buffer_queue.cc", - "display_embedder/skia_output_device_buffer_queue.h", - "display_embedder/skia_output_device_gl.cc", - "display_embedder/skia_output_device_gl.h", - "display_embedder/skia_output_device_offscreen.cc", - "display_embedder/skia_output_device_offscreen.h", - "display_embedder/skia_output_device_webview.cc", - "display_embedder/skia_output_device_webview.h", - "display_embedder/skia_output_surface_dependency.h", - "display_embedder/skia_output_surface_dependency_impl.cc", - "display_embedder/skia_output_surface_dependency_impl.h", - "display_embedder/skia_output_surface_impl.cc", - "display_embedder/skia_output_surface_impl.h", - "display_embedder/skia_output_surface_impl_on_gpu.cc", - "display_embedder/skia_output_surface_impl_on_gpu.h", - "display_embedder/skia_render_copy_results.cc", - "display_embedder/skia_render_copy_results.h", - "gl/gpu_service_impl.cc", - "gl/gpu_service_impl.h", - ] - - public_deps = [ - "//gpu/command_buffer/service:gles2", - "//gpu/ipc:gl_in_process_context", - "//gpu/ipc/service", - "//gpu/vulkan:buildflags", - "//media/gpu/ipc/service", - "//media/mojo/services", - "//services/viz/privileged/mojom/gl", - "//skia", - "//ui/latency:latency", - ] - - defines = [ "VIZ_SERVICE_IMPLEMENTATION" ] - - deps = [ - "//base", - "//build:chromeos_buildflags", - "//gpu/config", - "//third_party/libyuv", - ] - - if (is_win) { - sources += [ "gl/info_collection_gpu_service_impl.cc", "gl/info_collection_gpu_service_impl.h", ] @@ -419,34 +384,25 @@ ] } - if (is_chromeos_ash) { - deps += [ - "//components/chromeos_camera:jpeg_encode_accelerator_service", - "//components/chromeos_camera:mjpeg_decode_accelerator_service", - "//gpu/command_buffer/service:gles2", - "//media/mojo/services", + if (is_fuchsia) { + sources += [ + "display_embedder/output_presenter_fuchsia.cc", + "display_embedder/output_presenter_fuchsia.h", ] - if (use_v4l2_codec || use_vaapi) { - deps += [ "//ash/components/arc/video_accelerator" ] - } } if (use_vaapi) { deps += [ "//media/gpu/vaapi" ] } - if (use_ozone) { - deps += [ "//ui/ozone" ] - } - if (enable_vulkan) { + deps += [ "//gpu/vulkan" ] + sources += [ "display_embedder/skia_output_device_vulkan.cc", "display_embedder/skia_output_device_vulkan.h", ] - public_deps += [ "//gpu/vulkan" ] - if (is_android) { sources += [ "display_embedder/skia_output_device_vulkan_secondary_cb.cc", @@ -486,13 +442,6 @@ "//third_party/dawn/src/dawn/native", ] } - - if (is_fuchsia) { - sources += [ - "display_embedder/output_presenter_fuchsia.cc", - "display_embedder/output_presenter_fuchsia.h", - ] - } } viz_source_set("unit_tests") { @@ -564,7 +513,6 @@ "//components/viz/test:test_suite", "//components/viz/test:test_support", "//gpu/command_buffer/client", - "//gpu/command_buffer/client:gles2_implementation", "//gpu/ipc:gl_in_process_context", "//gpu/ipc/service", "//media",
diff --git a/components/viz/service/display/DEPS b/components/viz/service/display/DEPS index 057df66329..ca3f9db 100644 --- a/components/viz/service/display/DEPS +++ b/components/viz/service/display/DEPS
@@ -16,7 +16,7 @@ "+components/viz/service/display_embedder/overlay_candidate_validator_win.h", "+components/viz/service/display_embedder/skia_output_surface_dependency.h", "+components/viz/common", - "+gpu/command_buffer/client", + "+gpu/command_buffer/client/shared_image_interface.h", "+gpu/command_buffer/common", "+gpu/command_buffer/service", "+gpu/GLES2",
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index 66657ef..07d38ad 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -48,8 +48,6 @@ #include "components/viz/service/display/surface_aggregator.h" #include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_manager.h" -#include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/ipc/scheduler_sequence.h" #include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/viz/service/display/output_surface.cc b/components/viz/service/display/output_surface.cc index 9354f7d..643a191 100644 --- a/components/viz/service/display/output_surface.cc +++ b/components/viz/service/display/output_surface.cc
@@ -15,8 +15,6 @@ #include "components/viz/service/display/output_surface_client.h" #include "components/viz/service/display/output_surface_frame.h" #include "gpu/GLES2/gl2extchromium.h" -#include "gpu/command_buffer/client/context_support.h" -#include "gpu/command_buffer/client/gles2_interface.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/swap_result.h"
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 22af7c5..32312f8 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -45,7 +45,6 @@ #include "components/viz/test/test_in_process_context_provider.h" #include "components/viz/test/test_shared_bitmap_manager.h" #include "components/viz/test/test_types.h" -#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "media/base/video_frame.h" @@ -61,8 +60,6 @@ #include "ui/gfx/geometry/mask_filter_info.h" #include "ui/gfx/test/icc_profiles.h" -using gpu::gles2::GLES2Interface; - namespace viz { namespace {
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index fbd06e7..7d5298d 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -45,7 +45,6 @@ #include "components/viz/service/display/renderer_utils.h" #include "components/viz/service/display/resource_fence.h" #include "components/viz/service/display/skia_output_surface.h" -#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/shared_image_interface.h" #include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/common/sync_token.h"
diff --git a/components/viz/service/display_embedder/DEPS b/components/viz/service/display_embedder/DEPS index 6f48eb9..c8b25c2 100644 --- a/components/viz/service/display_embedder/DEPS +++ b/components/viz/service/display_embedder/DEPS
@@ -19,7 +19,9 @@ "+components/viz/service/display/skia_output_surface.h", "+components/viz/service/display/software_output_device.h", "+components/viz/service/gl/gpu_service_impl.h", - "+gpu/command_buffer/client", + "+gpu/command_buffer/client/gpu_memory_buffer_manager.h", + "+gpu/command_buffer/client/shared_image_interface.h", + "+gpu/command_buffer/client/shared_memory_limits.h", "+gpu/command_buffer/common", "+gpu/command_buffer/service", "+gpu/config",
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index a8e80937a9..0f9b617 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -38,7 +38,6 @@ #include "gpu/ipc/common/gpu_memory_buffer_support.h" #include "gpu/ipc/common/gpu_peak_memory.h" #include "gpu/ipc/common/memory_stats.h" -#include "gpu/ipc/in_process_command_buffer.h" #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager.h" #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
diff --git a/components/viz/service/main/viz_compositor_thread_runner_impl.cc b/components/viz/service/main/viz_compositor_thread_runner_impl.cc index 4ae77f1..6b7d8fc 100644 --- a/components/viz/service/main/viz_compositor_thread_runner_impl.cc +++ b/components/viz/service/main/viz_compositor_thread_runner_impl.cc
@@ -28,7 +28,6 @@ #include "components/viz/service/performance_hint/hint_session.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/config/gpu_switches.h" -#include "gpu/ipc/command_buffer_task_executor.h" #include "gpu/ipc/scheduler_sequence.h" #include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 0dee896..481a733 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -146,7 +146,6 @@ "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/client:gles2_interface", "//gpu/command_buffer/client:raster_interface", - "//gpu/ipc:gl_in_process_context", "//gpu/ipc/host", "//gpu/vulkan:buildflags", "//media",
diff --git a/content/browser/aggregation_service/aggregatable_report.cc b/content/browser/aggregation_service/aggregatable_report.cc index 4fc4c13..b6930322 100644 --- a/content/browser/aggregation_service/aggregatable_report.cc +++ b/content/browser/aggregation_service/aggregatable_report.cc
@@ -22,6 +22,7 @@ #include "base/rand_util.h" #include "base/ranges/algorithm.h" #include "base/strings/abseil_string_number_conversions.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/time/time.h" @@ -208,9 +209,9 @@ // Encrypts the `plaintext` with HPKE using the processing url's // `public_key`. Returns empty vector if the encryption fails. std::vector<uint8_t> EncryptWithHpke( - const std::vector<uint8_t>& plaintext, - const std::vector<uint8_t>& public_key, - const std::vector<uint8_t>& authenticated_info) { + base::span<const uint8_t> plaintext, + base::span<const uint8_t> public_key, + base::span<const uint8_t> authenticated_info) { bssl::ScopedEVP_HPKE_CTX sender_context; // This vector will hold the encapsulated shared secret "enc" followed by the @@ -505,18 +506,13 @@ return absl::nullopt; } - std::vector<uint8_t> authenticated_info(kDomainSeparationPrefix.begin(), - kDomainSeparationPrefix.end()); - - // No null terminator should have been copied. - DCHECK(!authenticated_info.empty()); - DCHECK_NE(authenticated_info.back(), 0); - std::string encoded_shared_info = report_request.shared_info().SerializeAsJson(); - authenticated_info.insert(authenticated_info.end(), - encoded_shared_info.begin(), - encoded_shared_info.end()); + + std::string authenticated_info_str = + base::StrCat({kDomainSeparationPrefix, encoded_shared_info}); + base::span<const uint8_t> authenticated_info = + base::as_bytes(base::make_span(authenticated_info_str)); std::vector<AggregatableReport::AggregationServicePayload> encrypted_payloads; DCHECK_EQ(unencrypted_payloads.size(), num_processing_urls);
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.cc b/content/browser/aggregation_service/aggregation_service_test_utils.cc index 9d057b9f..8d2de6e 100644 --- a/content/browser/aggregation_service/aggregation_service_test_utils.cc +++ b/content/browser/aggregation_service/aggregation_service_test_utils.cc
@@ -13,6 +13,7 @@ #include <vector> #include "base/base64.h" +#include "base/check.h" #include "base/containers/contains.h" #include "base/containers/span.h" #include "base/files/file_path.h" @@ -302,18 +303,19 @@ } std::vector<uint8_t> DecryptPayloadWithHpke( - const std::vector<uint8_t>& payload, + base::span<const uint8_t> payload, const EVP_HPKE_KEY& key, const std::string& expected_serialized_shared_info) { - base::span<const uint8_t> enc = - base::make_span(payload).subspan(0, X25519_PUBLIC_VALUE_LEN); + base::span<const uint8_t> enc = payload.subspan(0, X25519_PUBLIC_VALUE_LEN); - std::vector<uint8_t> authenticated_info( - AggregatableReport::kDomainSeparationPrefix.begin(), - AggregatableReport::kDomainSeparationPrefix.end()); - authenticated_info.insert(authenticated_info.end(), - expected_serialized_shared_info.begin(), - expected_serialized_shared_info.end()); + std::string authenticated_info_str = + base::StrCat({AggregatableReport::kDomainSeparationPrefix, + expected_serialized_shared_info}); + base::span<const uint8_t> authenticated_info = + base::as_bytes(base::make_span(authenticated_info_str)); + + // No null terminators should have been copied when concatenating the strings. + DCHECK(!base::Contains(authenticated_info_str, '\0')); bssl::ScopedEVP_HPKE_CTX recipient_context; if (!EVP_HPKE_CTX_setup_recipient( @@ -327,7 +329,7 @@ } base::span<const uint8_t> ciphertext = - base::make_span(payload).subspan(X25519_PUBLIC_VALUE_LEN); + payload.subspan(X25519_PUBLIC_VALUE_LEN); std::vector<uint8_t> plaintext(ciphertext.size()); size_t plaintext_len;
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.h b/content/browser/aggregation_service/aggregation_service_test_utils.h index ccb03f9..33d9249 100644 --- a/content/browser/aggregation_service/aggregation_service_test_utils.h +++ b/content/browser/aggregation_service/aggregation_service_test_utils.h
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/containers/span.h" #include "base/threading/sequence_bound.h" #include "content/browser/aggregation_service/aggregatable_report.h" #include "content/browser/aggregation_service/aggregation_service_key_storage.h" @@ -76,7 +77,7 @@ // Returns empty vector in the case of an error. std::vector<uint8_t> DecryptPayloadWithHpke( - const std::vector<uint8_t>& payload, + base::span<const uint8_t> payload, const EVP_HPKE_KEY& key, const std::string& expected_serialized_shared_info);
diff --git a/content/browser/file_system_access/file_system_access.proto b/content/browser/file_system_access/file_system_access.proto index fceead4..a54ddbb 100644 --- a/content/browser/file_system_access/file_system_access.proto +++ b/content/browser/file_system_access/file_system_access.proto
@@ -44,6 +44,9 @@ // The path to the file or directory relative to the root of the origin's // sandboxed file system. required bytes virtual_path = 1; + // The storage bucket ID. Will be populated only if the non-default bucket + // is being used. + optional int64 bucket_id = 2; } // Used to serialize any File System Access handle, for example when a handle is
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc index a938af7b..3b60d30 100644 --- a/content/browser/file_system_access/file_system_access_manager_impl.cc +++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
@@ -21,9 +21,13 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/bind_post_task.h" +#include "base/task/sequenced_task_runner.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" +#include "components/services/storage/public/cpp/buckets/bucket_id.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/browser/file_system_access/file_system_access.pb.h" #include "content/browser/file_system_access/file_system_access_access_handle_host_impl.h" #include "content/browser/file_system_access/file_system_access_data_transfer_token_impl.h" @@ -55,6 +59,7 @@ #include "third_party/blink/public/mojom/file_system_access/file_system_access_data_transfer_token.mojom.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-forward.h" +#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" #include "ui/shell_dialogs/select_file_dialog.h" #include "url/gurl.h" #include "url/origin.h" @@ -793,7 +798,9 @@ } else if (url.type() == storage::kFileSystemTypeTemporary) { base::FilePath virtual_path = url.virtual_path(); data.mutable_sandboxed()->set_virtual_path(SerializePath(virtual_path)); - + if (url.bucket().has_value() && !url.bucket()->is_default) { + data.mutable_sandboxed()->set_bucket_id(url.bucket()->id.value()); + } } else { NOTREACHED(); } @@ -805,6 +812,22 @@ std::move(callback).Run(result); } +void FileSystemAccessManagerImpl::DidGetSandboxedBucketForDeserializeHandle( + const FileSystemAccessHandleData& data, + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token, + const storage::FileSystemURL& url) { + auto permission_grant = + base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>( + PermissionStatus::GRANTED, base::FilePath()); + CreateTransferTokenImpl( + url, url.storage_key(), + SharedHandleState(permission_grant, permission_grant), + data.handle_type() == FileSystemAccessHandleData::kDirectory + ? HandleType::kDirectory + : HandleType::kFile, + std::move(token)); +} + void FileSystemAccessManagerImpl::DeserializeHandle( const blink::StorageKey& storage_key, const std::vector<uint8_t>& bits, @@ -825,17 +848,30 @@ DeserializePath(data.sandboxed().virtual_path()); storage::FileSystemURL url = context()->CreateCrackedFileSystemURL( storage_key, storage::kFileSystemTypeTemporary, virtual_path); - - auto permission_grant = - base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>( - PermissionStatus::GRANTED, base::FilePath()); - CreateTransferTokenImpl( - url, storage_key, - SharedHandleState(permission_grant, permission_grant), - data.handle_type() == FileSystemAccessHandleData::kDirectory - ? HandleType::kDirectory - : HandleType::kFile, - std::move(token)); + if (!data.sandboxed().has_bucket_id()) { + // Use the default storage bucket. + DidGetSandboxedBucketForDeserializeHandle(data, std::move(token), url); + } else { + // Apply a custom bucket override. + auto bucket_callback = base::BindOnce( + [](storage::FileSystemURL url, + base::OnceCallback<void(const storage::FileSystemURL&)> callback, + storage::QuotaErrorOr<storage::BucketInfo> result) { + if (!result.ok()) { + // Drop `token`, and directly return. + return; + } + url.SetBucket(result->ToBucketLocator()); + std::move(callback).Run(url); + }, + url, + base::BindOnce(&FileSystemAccessManagerImpl:: + DidGetSandboxedBucketForDeserializeHandle, + weak_factory_.GetWeakPtr(), data, std::move(token))); + context_->quota_manager_proxy()->GetBucketById( + storage::BucketId::FromUnsafeValue(data.sandboxed().bucket_id()), + base::SequencedTaskRunnerHandle::Get(), std::move(bucket_callback)); + } break; } case FileSystemAccessHandleData::kLocal:
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h index 4e6e23b..71972047 100644 --- a/content/browser/file_system_access/file_system_access_manager_impl.h +++ b/content/browser/file_system_access/file_system_access_manager_impl.h
@@ -16,8 +16,11 @@ #include "base/threading/sequence_bound.h" #include "base/types/pass_key.h" #include "components/download/public/common/quarantine_connection.h" +#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/quota_error_or.h" #include "components/services/storage/public/mojom/file_system_access_context.mojom.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" +#include "content/browser/file_system_access/file_system_access.pb.h" #include "content/browser/file_system_access/file_system_access_write_lock_manager.h" #include "content/browser/file_system_access/file_system_chooser.h" #include "content/common/content_export.h" @@ -453,10 +456,14 @@ void DidResolveForSerializeHandle( SerializeHandleCallback callback, FileSystemAccessTransferTokenImpl* resolved_token); + void DidGetSandboxedBucketForDeserializeHandle( + const FileSystemAccessHandleData& data, + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token, + const storage::FileSystemURL& url); - // FileSystemAccessCapacityAllocationHosts may reserve too much capacity from - // the quota system. This function determines the file's actual size and - // corrects its capacity usage in the quota system. + // FileSystemAccessCapacityAllocationHosts may reserve too much capacity + // from the quota system. This function determines the file's actual size + // and corrects its capacity usage in the quota system. void CleanupAccessHandleCapacityAllocation(const storage::FileSystemURL& url, int64_t allocated_file_size, base::OnceClosure callback);
diff --git a/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc b/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc index d3b2bb78..80f3c829a 100644 --- a/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc +++ b/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc
@@ -18,6 +18,8 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "components/services/storage/public/cpp/buckets/bucket_id.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/browser/file_system_access/file_system_access_data_transfer_token_impl.h" #include "content/browser/file_system_access/file_system_access_directory_handle_impl.h" #include "content/browser/file_system_access/file_system_access_file_handle_impl.h" @@ -323,6 +325,19 @@ blink::mojom::FileSystemAccessStatus::kOk); } + storage::BucketLocator CreateBucketForTesting() { + base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>> + bucket_future; + quota_manager_proxy_->CreateBucketForTesting( + kTestStorageKey, "custom_bucket", blink::mojom::StorageType::kTemporary, + base::SequencedTaskRunnerHandle::Get(), bucket_future.GetCallback()); + auto bucket = bucket_future.Take(); + EXPECT_TRUE(bucket.ok()); + LOG(INFO) << "Created bucket " + << bucket->ToBucketLocator().id.GetUnsafeValue(); + return bucket->ToBucketLocator(); + } + protected: const GURL kTestURL = GURL("https://example.com/test"); const blink::StorageKey kTestStorageKey = @@ -427,6 +442,32 @@ ASSERT_TRUE(root); } +TEST_F(FileSystemAccessManagerImplTest, GetSandboxedFileSystem_BadBucket) { + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> + directory_remote; + FileSystemAccessManagerImpl::BindingContext binding_context = { + kTestStorageKey, kTestURL, web_contents_->GetMainFrame()->GetGlobalId()}; + const auto bucket = storage::BucketLocator( + storage::BucketId(12), kTestStorageKey, + blink::mojom::StorageType::kUnknown, /*is_default=*/false); + + base::test::TestFuture< + blink::mojom::FileSystemAccessErrorPtr, + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle>> + handle_future; + manager_->GetSandboxedFileSystem(binding_context, bucket, + handle_future.GetCallback()); + EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOk, + handle_future.Get<0>()->status); + + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> root( + std::move(std::get<1>(handle_future.Take()))); + // Currently we intentionally return a non-functional file/directory handle + // in the case of a bad bucket override, as there is currently no better way + // of representing a handle to a bucket that no longer exists. + ASSERT_TRUE(root); +} + TEST_F(FileSystemAccessManagerImplTest, GetSandboxedFileSystem_Permissions) { base::test::TestFuture< blink::mojom::FileSystemAccessErrorPtr, @@ -707,7 +748,8 @@ file_system_context_.get(), test_file_url, 3)); } -TEST_F(FileSystemAccessManagerImplTest, SerializeHandle_SandboxedFile) { +TEST_F(FileSystemAccessManagerImplTest, + SerializeHandle_SandboxedFile_DefaultBucket) { auto test_file_url = file_system_context_->CreateCrackedFileSystemURL( kTestStorageKey, storage::kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("test/foo/bar")); @@ -720,6 +762,7 @@ FileSystemAccessTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); + ASSERT_FALSE(token->url().bucket().has_value()); EXPECT_EQ(test_file_url, token->url()); EXPECT_EQ(HandleType::kFile, token->type()); @@ -731,7 +774,35 @@ EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus()); } -TEST_F(FileSystemAccessManagerImplTest, SerializeHandle_SandboxedDirectory) { +TEST_F(FileSystemAccessManagerImplTest, + SerializeHandle_SandboxedFile_CustomBucket) { + auto test_file_url = file_system_context_->CreateCrackedFileSystemURL( + kTestStorageKey, storage::kFileSystemTypeTemporary, + base::FilePath::FromUTF8Unsafe("test/foo/bar")); + test_file_url.SetBucket(CreateBucketForTesting()); + FileSystemAccessFileHandleImpl file(manager_.get(), kBindingContext, + test_file_url, {ask_grant_, ask_grant_}); + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; + manager_->CreateTransferToken(file, + token_remote.InitWithNewPipeAndPassReceiver()); + + FileSystemAccessTransferTokenImpl* token = + SerializeAndDeserializeToken(std::move(token_remote)); + ASSERT_TRUE(token); + ASSERT_TRUE(token->url().bucket().has_value()); + EXPECT_EQ(test_file_url, token->url()); + EXPECT_EQ(HandleType::kFile, token->type()); + + // Deserialized sandboxed filesystem handles should always be readable and + // writable. + ASSERT_TRUE(token->GetReadGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus()); + ASSERT_TRUE(token->GetWriteGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus()); +} + +TEST_F(FileSystemAccessManagerImplTest, + SerializeHandle_SandboxedDirectory_DefaultBucket) { auto test_file_url = file_system_context_->CreateCrackedFileSystemURL( kTestStorageKey, storage::kFileSystemTypeTemporary, base::FilePath::FromUTF8Unsafe("hello/world/")); @@ -744,6 +815,34 @@ FileSystemAccessTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); + ASSERT_FALSE(token->url().bucket().has_value()); + EXPECT_EQ(test_file_url, token->url()); + EXPECT_EQ(HandleType::kDirectory, token->type()); + + // Deserialized sandboxed filesystem handles should always be readable and + // writable. + ASSERT_TRUE(token->GetReadGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus()); + ASSERT_TRUE(token->GetWriteGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus()); +} + +TEST_F(FileSystemAccessManagerImplTest, + SerializeHandle_SandboxedDirectory_CustomBucket) { + auto test_file_url = file_system_context_->CreateCrackedFileSystemURL( + kTestStorageKey, storage::kFileSystemTypeTemporary, + base::FilePath::FromUTF8Unsafe("hello/world/")); + test_file_url.SetBucket(CreateBucketForTesting()); + FileSystemAccessDirectoryHandleImpl directory( + manager_.get(), kBindingContext, test_file_url, {ask_grant_, ask_grant_}); + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; + manager_->CreateTransferToken(directory, + token_remote.InitWithNewPipeAndPassReceiver()); + + FileSystemAccessTransferTokenImpl* token = + SerializeAndDeserializeToken(std::move(token_remote)); + ASSERT_TRUE(token); + ASSERT_TRUE(token->url().bucket().has_value()); EXPECT_EQ(test_file_url, token->url()); EXPECT_EQ(HandleType::kDirectory, token->type());
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index de397aaf..96895bf 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -38,7 +38,6 @@ #include "gpu/config/gpu_finch_features.h" #include "gpu/ipc/common/gpu_client_ids.h" #include "gpu/ipc/common/gpu_watchdog_timeout.h" -#include "gpu/ipc/in_process_command_buffer.h" #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h" #if BUILDFLAG(IS_MAC)
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 8ca8002..954aa49 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -66,7 +66,6 @@ #include "gpu/ipc/common/gpu_client_ids.h" #include "gpu/ipc/common/result_codes.h" #include "gpu/ipc/host/shader_disk_cache.h" -#include "gpu/ipc/in_process_command_buffer.h" #include "media/base/media_switches.h" #include "media/media_buildflags.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller.h b/content/browser/renderer_host/input/synthetic_gesture_controller.h index a9f9de8..f4c1479 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller.h +++ b/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -155,7 +155,7 @@ // truly robust. https://crbug.com/985374. bool renderer_known_to_be_initialized_ = false; - base::RepeatingTimer dispatch_timer_; + base::MetronomeTimer dispatch_timer_; base::WeakPtrFactory<SyntheticGestureController> weak_ptr_factory_{this}; };
diff --git a/content/test/data/media/canplaytype_test.js b/content/test/data/media/canplaytype_test.js index 14224e8..21ab9f3 100644 --- a/content/test/data/media/canplaytype_test.js +++ b/content/test/data/media/canplaytype_test.js
@@ -1263,6 +1263,27 @@ if (!testMimeCodec('video/mp4; codecs="avc1.42E052"', P_MAYBE)) return false; + // Levels 6 (0x3C), 6.1 (0x3D), 6.2 (0x3E). + if (!testMimeCodec('video/mp4; codecs="avc1.42E03B"', P_MAYBE)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E03C"', P_PROBABLY)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E03D"', P_PROBABLY)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E03E"', P_PROBABLY)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E03F"', P_MAYBE)) + return false; + // Verify that decimal representations of levels are not supported. + if (!testMimeCodec('video/mp4; codecs="avc1.42E006"', P_MAYBE)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E060"', P_MAYBE)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E061"', P_MAYBE)) + return false; + if (!testMimeCodec('video/mp4; codecs="avc1.42E062"', P_MAYBE)) + return false; + return true; }
diff --git a/device/bluetooth/dbus/bluetooth_device_client.cc b/device/bluetooth/dbus/bluetooth_device_client.cc index ed4cec2..a133049 100644 --- a/device/bluetooth/dbus/bluetooth_device_client.cc +++ b/device/bluetooth/dbus/bluetooth_device_client.cc
@@ -28,9 +28,11 @@ namespace { +#if BUILDFLAG(IS_CHROMEOS_ASH) // TODO(b/213229904): Remove this constant and replace with // |bluetooth_device::kDisconnectOld| once it has been uprev'd. constexpr char kDisconnectOldPlaceholder[] = "DisconnectOld"; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) // Value returned for the the RSSI or TX power if it cannot be read. const int kUnknownPower = 127; @@ -377,7 +379,7 @@ ? bluetooth_device::kDisconnect : kDisconnectOldPlaceholder; #else // BUILDFLAG(IS_CHROMEOS_ASH) - const char* method_name = kDisconnectOldPlaceholder; + const char* method_name = bluetooth_device::kDisconnect; #endif // BUILDFLAG(IS_CHROMEOS_ASH) dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface, method_name);
diff --git a/extensions/browser/extension_frame_host_browsertest.cc b/extensions/browser/extension_frame_host_browsertest.cc index 2378420..bdd70af 100644 --- a/extensions/browser/extension_frame_host_browsertest.cc +++ b/extensions/browser/extension_frame_host_browsertest.cc
@@ -162,7 +162,8 @@ ExtensionWebContentsObserver* observer = extensions_browser_client_->GetExtensionWebContentsObserver( host->host_contents()); - static_cast<TestExtensionFrameHost*>(observer->extension_frame_host_.get()) + static_cast<TestExtensionFrameHost*>( + observer->extension_frame_host_for_testing()) ->SetInvalidRequest(method_name); }
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 8c9128e..c4ca2a3 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1622,7 +1622,7 @@ WMDESKSPRIVATE_UPDATEDESKTEMPLATE = 1559, WMDESKSPRIVATE_GETSAVEDDESKTEMPLATES = 1560, WMDESKSPRIVATE_DELETEDESKTEMPLATE = 1561, - WMDESKSPRIVATE_LAUNCHDESKTEMPLATE = 1562, + WMDESKSPRIVATE_LAUNCHDESK = 1562, AUTOTESTPRIVATE_SETSHELFICONPIN = 1563, SCRIPTING_GETREGISTEREDCONTENTSCRIPTS = 1564, OS_TELEMETRY_GETVPDINFO = 1565, @@ -1719,7 +1719,7 @@ ACCESSIBILITY_PRIVATE_INSTALLPUMPKINFORDICTATION = 1656, BOOKMARKMANAGERPRIVATE_OPENINNEWTAB = 1657, BOOKMARKMANAGERPRIVATE_OPENINNEWWINDOW = 1658, - WMDESKSPRIVATE_REMOVEDESKANDCLOSEWINDOWS = 1659, + WMDESKSPRIVATE_REMOVEDESK = 1659, SHAREDSTORAGEPRIVATE_GET = 1660, SHAREDSTORAGEPRIVATE_SET = 1661, SHAREDSTORAGEPRIVATE_REMOVE = 1662,
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h index 7beed9b2..16ce6db 100644 --- a/extensions/browser/extension_web_contents_observer.h +++ b/extensions/browser/extension_web_contents_observer.h
@@ -101,6 +101,10 @@ // ExtensionWebContentsObserver has already been initialized. void ListenToWindowIdChangesFrom(sessions::SessionTabHelper* helper); + ExtensionFrameHost* extension_frame_host_for_testing() { + return extension_frame_host_.get(); + } + protected: explicit ExtensionWebContentsObserver(content::WebContents* web_contents); ~ExtensionWebContentsObserver() override; @@ -144,8 +148,6 @@ private: using PassKey = base::PassKey<ExtensionWebContentsObserver>; - friend class ExtensionFrameHostBrowserTest; - void OnWindowIdChanged(const SessionID& id); // The BrowserContext associated with the WebContents being observed.
diff --git a/gpu/ipc/BUILD.gn b/gpu/ipc/BUILD.gn index c418f42..6948ed2a 100644 --- a/gpu/ipc/BUILD.gn +++ b/gpu/ipc/BUILD.gn
@@ -31,12 +31,6 @@ deps = [ "//base", "//base/third_party/dynamic_annotations", - - # crbug.com/799267: crash_key needs to be added explicitly for Windows and - # Mac even though it's not directly referenced, because it's being - # implicitly depended upon by gpu/config/gpu_crash_keys.h but deps (even - # public ones) are not transitive for static libraries. - "//components/crash/core/common:crash_key", "//gpu/command_buffer/client", "//gpu/command_buffer/client:gles2_cmd_helper", "//gpu/command_buffer/client:gles2_implementation",
diff --git a/infra/config/generated/builders/try/win7-blink-rel/properties.json b/infra/config/generated/builders/try/win7-blink-rel/properties.json deleted file mode 100644 index be0cfff..0000000 --- a/infra/config/generated/builders/try/win7-blink-rel/properties.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "$build/goma": { - "enable_ats": false, - "rpc_extra_params": "?prod", - "server_host": "goma.chromium.org", - "use_luci_auth": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.blink", - "recipe": "chromium_trybot" -} \ No newline at end of file
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index 5682bd2..3439600d 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -1926,10 +1926,6 @@ includable_only: true } builders { - name: "chromium/try/win7-blink-rel" - includable_only: true - } - builders { name: "chromium/try/win7-rel" location_regexp: ".+/[+]/sandbox/win/.+" location_regexp: ".+/[+]/sandbox/policy/win/.+"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 95ec790..7bb415f 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -75429,96 +75429,6 @@ } } builders { - name: "win7-blink-rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/win7-blink-rel/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.blink",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - caches { - name: "win_toolchain" - path: "win_toolchain" - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { name: "win7-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index ea14bc3..32a87ca1 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -16405,9 +16405,6 @@ name: "buildbucket/luci.chromium.try/win32-official" } builders { - name: "buildbucket/luci.chromium.try/win7-blink-rel" - } - builders { name: "buildbucket/luci.chromium.try/win7-rel" } builders { @@ -16479,9 +16476,6 @@ builders { name: "buildbucket/luci.chromium.try/win11-blink-rel" } - builders { - name: "buildbucket/luci.chromium.try/win7-blink-rel" - } builder_view_only: true } consoles {
diff --git a/infra/config/subprojects/chromium/try/tryserver.blink.star b/infra/config/subprojects/chromium/try/tryserver.blink.star index 738beb9..987870b 100644 --- a/infra/config/subprojects/chromium/try/tryserver.blink.star +++ b/infra/config/subprojects/chromium/try/tryserver.blink.star
@@ -86,13 +86,6 @@ builderless = True, ) -try_.builder( - name = "win7-blink-rel", - goma_backend = goma.backend.RBE_PROD, - os = os.WINDOWS_ANY, - builderless = True, -) - blink_mac_builder( name = "mac10.13-blink-rel", )
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index e90cb694..5877623 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -942,6 +942,10 @@ flag_descriptions::kDefaultBrowserIntentsShowSettingsName, flag_descriptions::kDefaultBrowserIntentsShowSettingsDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDefaultBrowserIntentsShowSettings)}, + {"enable-discover-feed-ghost-cards", + flag_descriptions::kEnableDiscoverFeedGhostCardsName, + flag_descriptions::kEnableDiscoverFeedGhostCardsDescription, + flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDiscoverFeedGhostCardsEnabled)}, }; 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 97622a325..68223d4 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -225,6 +225,11 @@ const char kEnableDiscoverFeedPreviewDescription[] = "Enable showing a live preview for discover feed long-press menu."; +const char kEnableDiscoverFeedGhostCardsName[] = + "Enable discover feed ghost cards"; +const char kEnableDiscoverFeedGhostCardsDescription[] = + "Show ghost cards when refreshing the discover feed."; + const char kEnableDiscoverFeedShorterCacheName[] = "Enable discover feed shorter cache"; const char kEnableDiscoverFeedShorterCacheDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index def07b45..0d4204fe 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -209,6 +209,11 @@ extern const char kEnableDiscoverFeedPreviewName[]; extern const char kEnableDiscoverFeedPreviewDescription[]; +// Title and description for the flag to show ghost cards when refreshing the +// discover feed. +extern const char kEnableDiscoverFeedGhostCardsName[]; +extern const char kEnableDiscoverFeedGhostCardsDescription[]; + // Title and description for the flag to shorten the cache. extern const char kEnableDiscoverFeedShorterCacheName[]; extern const char kEnableDiscoverFeedShorterCacheDescription[];
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h index 6677d2a..abb1caa 100644 --- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h +++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
@@ -30,6 +30,7 @@ // TabRestoreServiceClient: sessions::LiveTabContext* CreateLiveTabContext( sessions::LiveTabContext* existing_context, + sessions::SessionWindow::WindowType type, const std::string& app_name, const gfx::Rect& bounds, ui::WindowShowState show_state,
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm index c751263..cc36cf0 100644 --- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm +++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
@@ -62,6 +62,7 @@ sessions::LiveTabContext* IOSChromeTabRestoreServiceClient::CreateLiveTabContext( sessions::LiveTabContext* /* existing_context */, + sessions::SessionWindow::WindowType type, const std::string& /* app_name */, const gfx::Rect& /* bounds */, ui::WindowShowState /* show_state */,
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.h b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h index 4df9b3e..e7bd7bf 100644 --- a/ios/chrome/browser/sessions/live_tab_context_browser_agent.h +++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h
@@ -31,6 +31,7 @@ // Sessions::LiveTabContext: void ShowBrowserWindow() override; SessionID GetSessionID() const override; + sessions::SessionWindow::WindowType GetWindowType() const override; int GetTabCount() const override; int GetSelectedIndex() const override; std::string GetAppName() const override;
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm index f85dec4..654d3bc 100644 --- a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm +++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm
@@ -41,6 +41,12 @@ return session_id_; } +sessions::SessionWindow::WindowType LiveTabContextBrowserAgent::GetWindowType() + const { + // Not supported by iOS. + return sessions::SessionWindow::TYPE_NORMAL; +} + int LiveTabContextBrowserAgent::GetTabCount() const { return web_state_list_->count(); }
diff --git a/ios/chrome/browser/ui/activity_services/BUILD.gn b/ios/chrome/browser/ui/activity_services/BUILD.gn index bddbd163..9980d20 100644 --- a/ios/chrome/browser/ui/activity_services/BUILD.gn +++ b/ios/chrome/browser/ui/activity_services/BUILD.gn
@@ -44,6 +44,7 @@ "//ios/chrome/browser/ui/util:url_with_title", "//ios/chrome/browser/web", "//ios/chrome/browser/web_state_list", + "//ios/web/public/js_messaging", "//ui/base", "//url", ]
diff --git a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h index 6a6ff80..01d66a0f 100644 --- a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h +++ b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h
@@ -15,6 +15,10 @@ namespace activity_services { +// Script to access the canonical URL from a web page. This script shouldn't be +// used directly, but is exposed for testing purposes. +extern const char16_t kCanonicalURLScript[]; + // Retrieves the canonical URL in the web page represented by `web_state`. // This method is asynchronous and the URL is returned by calling the // `completion` block.
diff --git a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm index 2d67b61..c5b7183e 100644 --- a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm +++ b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm
@@ -10,6 +10,8 @@ #include "base/values.h" #include "components/ui_metrics/canonical_url_share_metrics_types.h" #import "ios/chrome/browser/procedural_block_types.h" +#include "ios/web/public/js_messaging/web_frame.h" +#import "ios/web/public/js_messaging/web_frame_util.h" #import "ios/web/public/web_state.h" #include "url/gurl.h" @@ -18,12 +20,6 @@ #endif namespace { -// Script to access the canonical URL from a web page. -const char16_t kCanonicalURLScript[] = - u"(function() {" - u" var linkNode = document.querySelector(\"link[rel='canonical']\");" - u" return linkNode ? linkNode.getAttribute(\"href\") : \"\";" - u"})()"; // Logs `result` in the Mobile.CanonicalURLResult histogram. void LogCanonicalUrlResultHistogram(ui_metrics::CanonicalURLResult result) { @@ -62,6 +58,13 @@ } // namespace namespace activity_services { + +const char16_t kCanonicalURLScript[] = + u"(function() {" + u" var linkNode = document.querySelector(\"link[rel='canonical']\");" + u" return linkNode ? linkNode.getAttribute(\"href\") : \"\";" + u"})()"; + void RetrieveCanonicalUrl(web::WebState* web_state, ProceduralBlockWithURL completion) { // Do not use the canonical URL if the page is not secured with HTTPS. @@ -72,6 +75,12 @@ return; } + web::WebFrame* main_frame = web::GetMainFrame(web_state); + if (!main_frame) { + completion(GURL::EmptyGURL()); + return; + } + void (^javascript_completion)(const base::Value*) = ^(const base::Value* value) { GURL canonical_url = UrlFromValue(value); @@ -94,7 +103,7 @@ completion(canonical_url); }; - web_state->ExecuteJavaScript(kCanonicalURLScript, - base::BindOnce(javascript_completion)); + main_frame->ExecuteJavaScript(kCanonicalURLScript, + base::BindOnce(javascript_completion)); } } // namespace activity_services
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_feature.h b/ios/chrome/browser/ui/ntp/new_tab_page_feature.h index 8bc0c6ce..accff4a 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_feature.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_feature.h
@@ -11,6 +11,9 @@ // the feed context menu. extern const base::Feature kEnableDiscoverFeedPreview; +// Feature flag to show ghost cards when refreshing the discover feed. +extern const base::Feature kDiscoverFeedGhostCardsEnabled; + // Feature flag to enable shorter cache so that more ghost cards appear. extern const base::Feature kEnableDiscoverFeedShorterCache;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm b/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm index c83976eb..d52ac642 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm
@@ -16,6 +16,9 @@ const base::Feature kEnableDiscoverFeedAppFlows{ "EnableDiscoverFeedAppFlows", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDiscoverFeedGhostCardsEnabled{ + "DiscoverFeedGhostCardsEnabled", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kEnableDiscoverFeedShorterCache{ "EnableDiscoverFeedShorterCache", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -44,9 +47,6 @@ const base::Feature kEnableFeedAblation{"FeedAblationEnabled", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kDiscoverFeedGhostCardsEnabled{ - "DiscoverFeedGhostCardsEnabled", base::FEATURE_DISABLED_BY_DEFAULT}; - bool IsDiscoverFeedPreviewEnabled() { return base::FeatureList::IsEnabled(kEnableDiscoverFeedPreview); } @@ -55,6 +55,10 @@ return base::FeatureList::IsEnabled(kEnableDiscoverFeedAppFlows); } +bool IsDiscoverFeedGhostCardsEnabled() { + return base::FeatureList::IsEnabled(kDiscoverFeedGhostCardsEnabled); +} + bool IsDiscoverFeedShorterCacheEnabled() { return base::FeatureList::IsEnabled(kEnableDiscoverFeedShorterCache); } @@ -70,7 +74,3 @@ bool IsFeedAblationEnabled() { return base::FeatureList::IsEnabled(kEnableFeedAblation); } - -bool IsDiscoverFeedGhostCardsEnabled() { - return base::FeatureList::IsEnabled(kDiscoverFeedGhostCardsEnabled); -}
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm index 98613c57..2694540 100644 --- a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
@@ -9,6 +9,7 @@ #import "base/ios/block_types.h" #import "base/strings/sys_string_conversions.h" +#import "base/test/ios/wait_util.h" #import "base/values.h" #import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" @@ -17,6 +18,7 @@ #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/ui/activity_services/activity_params.h" +#import "ios/chrome/browser/ui/activity_services/canonical_url_retriever.h" #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h" #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.h" @@ -34,6 +36,8 @@ #import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/chrome/test/scoped_key_window.h" #import "ios/web/public/test/fakes/fake_navigation_manager.h" +#import "ios/web/public/test/fakes/fake_web_frame.h" +#import "ios/web/public/test/fakes/fake_web_frames_manager.h" #import "ios/web/public/test/fakes/fake_web_state.h" #import "ios/web/public/test/web_task_environment.h" #import "ios/web/public/web_state.h" @@ -49,23 +53,11 @@ #error "This file requires ARC support." #endif +using base::test::ios::kWaitForActionTimeout; +using base::test::ios::WaitUntilConditionOrTimeout; using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; -namespace { - -class MockWebState : public web::FakeWebState { - public: - MockWebState() : web::FakeWebState() { - SetNavigationManager(std::make_unique<web::FakeNavigationManager>()); - } - - MOCK_METHOD2(ExecuteJavaScript, - void(const std::u16string&, JavaScriptResultCallback)); -}; - -} // namespace - // Test fixture for testing SharingCoordinator. class SharingCoordinatorTest : public BookmarkIOSUnitTest { protected: @@ -112,16 +104,22 @@ // Create a test web state. GURL test_url = GURL("https://example.com"); base::Value url_value = base::Value(test_url.spec()); - auto test_web_state = std::make_unique<MockWebState>(); + auto test_web_state = std::make_unique<web::FakeWebState>(); + test_web_state->SetNavigationManager( + std::make_unique<web::FakeNavigationManager>()); test_web_state->SetCurrentURL(test_url); test_web_state->SetBrowserState(browser_->GetBrowserState()); - EXPECT_CALL(*test_web_state, ExecuteJavaScript(testing::_, testing::_)) - .WillOnce(testing::Invoke( - [&](const std::u16string& javascript, - base::OnceCallback<void(const base::Value*)> callback) { - std::move(callback).Run(&url_value); - })); + auto frames_manager = std::make_unique<web::FakeWebFramesManager>(); + web::FakeWebFramesManager* frames_manager_ptr = frames_manager.get(); + test_web_state->SetWebFramesManager(std::move(frames_manager)); + + auto main_frame = web::FakeWebFrame::CreateMainWebFrame(test_url); + web::FakeWebFrame* main_frame_ptr = main_frame.get(); + frames_manager_ptr->AddWebFrame(std::move(main_frame)); + + main_frame_ptr->AddResultForExecutedJs( + &url_value, activity_services::kCanonicalURLScript); AppendNewWebState(std::move(test_web_state)); @@ -134,11 +132,13 @@ params:params originView:fake_origin_view_]; + __block bool completion_handler_called = false; id vc_partial_mock = OCMPartialMock(base_view_controller_); [[vc_partial_mock expect] presentViewController:[OCMArg checkWithBlock:^BOOL( UIViewController* viewController) { if ([viewController isKindOfClass:[UIActivityViewController class]]) { + completion_handler_called = true; return YES; } return NO; @@ -148,6 +148,11 @@ [coordinator start]; + EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool { + base::RunLoop().RunUntilIdle(); + return completion_handler_called; + })); + // Verify that the positioning is correct. auto activityHandler = static_cast<id<ActivityServicePositioner, ActivityServicePresentation>>(
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 37c8bdc..0cefa12 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 @@ -9a117bef0efc4128cfb05e3566ecf34d46007f5a \ No newline at end of file +6bf982611d5c4df13a2a694e07b182da931b7609 \ 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 76c11a3..6b986d0 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 @@ -fb4f4d655a9af0e5f535880df2b870ca606135a5 \ No newline at end of file +0a2ee68f386929280534369f3858b2ec6497d6e4 \ 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 7c6b2fe..a911838 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 @@ -a8f1f7cb363771d05030693363b73933abbba92c \ No newline at end of file +f597692672207e9c5fbc1f0435591aca9471a21d \ 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 866c5a8..02f99a7 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 @@ -72b79f580d22e73ecb7e2d2f16d748faa7b2cb21 \ No newline at end of file +383e79d3130539196d27a4fbccec41dd7f6ab488 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index 0316cf1..d400f68 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -18a78ea8199b44e099777cc994bc7acc9760e62b \ No newline at end of file +35e93d58bb31865b013d3f32a6b3e8aaa9321cf5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index 2ad1973..7e7bc63c 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -80cc21c2c57a8b0831a196d56120d42227b47cd7 \ No newline at end of file +b4e9292d84fc93cb2a16a05cb6f04b53a5d145cc \ 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 604be80c..657c385 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 @@ -f478a85c3680bdf12332e7ec730ec9fd02834790 \ No newline at end of file +06408c87551305288ac232f7bf2576926f78eabc \ 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 e159fcc..d4304aa 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 @@ -bd14906db5ced5528879650bb682ca1d9f438b0c \ No newline at end of file +e7fe7e2eb02066dc5c52bdee3dd2190fc0e21c69 \ 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 46f828b..983c18b 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 @@ -e8832202c32bb95a748f359947dd32cbc7f9476f \ No newline at end of file +346f2fa38431c6da6d0a2280443f260df8f9810a \ 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 332151d..2d2a5d88 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 @@ -329293142b22e0528d2ea84e579e6ff8ad9bbff8 \ No newline at end of file +0ee06675c5b8b389b607774ef0f62431b3e7c389 \ No newline at end of file
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index 57cf724..43a6e646 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -73,6 +73,7 @@ "src/components/BottomNavigation/src/MaterialBottomNavigation+BottomNavigationController.h", "src/components/BottomNavigation/src/MaterialBottomNavigation.h", "src/components/BottomNavigation/src/PerformantShadowMigration/MDCBottomNavigationBar+ShadowsPrivate.h", + "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+ItemView.h", "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+Private.h", "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.h", "src/components/BottomNavigation/src/private/MDCBottomNavigationLargeItemDialogView.h", @@ -300,6 +301,7 @@ "src/components/Ripple/src/private/MDCRippleLayerDelegate.h", "src/components/ScalableFontDescriptor/src/MDCScalableFontDescriptor.h", "src/components/ScalableFontDescriptor/src/MaterialScalableFontDescriptor.h", + "src/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h", "src/components/Shadow/src/MDCShadow.h", "src/components/Shadow/src/MDCShadowsCollection.h", "src/components/Shadow/src/MaterialShadow.h", @@ -650,6 +652,7 @@ "src/components/Ripple/src/private", "src/components/ScalableFontDescriptor/src", "src/components/Shadow/src", + "src/components/Shadow/src/Animations", "src/components/ShadowElevations/src", "src/components/ShadowLayer/src", "src/components/ShapeLibrary/src", @@ -817,6 +820,8 @@ "src/components/BottomNavigation/src/MaterialBottomNavigation+BottomNavigationController.h", "src/components/BottomNavigation/src/MaterialBottomNavigation.h", "src/components/BottomNavigation/src/PerformantShadowMigration/MDCBottomNavigationBar+ShadowsPrivate.h", + "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+ItemView.h", + "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+ItemView.m", "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+Private.h", "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.h", "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.m", @@ -1162,6 +1167,8 @@ "src/components/ScalableFontDescriptor/src/MDCScalableFontDescriptor.h", "src/components/ScalableFontDescriptor/src/MDCScalableFontDescriptor.m", "src/components/ScalableFontDescriptor/src/MaterialScalableFontDescriptor.h", + "src/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h", + "src/components/Shadow/src/Animations/UIView+MDCShadowAnimations.m", "src/components/Shadow/src/MDCShadow.h", "src/components/Shadow/src/MDCShadow.m", "src/components/Shadow/src/MDCShadowsCollection.h",
diff --git a/ios/web/public/test/fakes/fake_web_frame.h b/ios/web/public/test/fakes/fake_web_frame.h index afd7f82..1152700 100644 --- a/ios/web/public/test/fakes/fake_web_frame.h +++ b/ios/web/public/test/fakes/fake_web_frame.h
@@ -57,6 +57,13 @@ virtual void AddJsResultForFunctionCall(base::Value* js_result, const std::string& function_name) = 0; + // Sets |js_result| that will be passed into callback for |executed_js| + // call through ExecuteJavaScript API. + // NOTE: The caller is responsible for keeping |js_result| alive for as + // long as this instance lives. + virtual void AddResultForExecutedJs(base::Value* js_result, + const std::u16string& executed_js) = 0; + virtual void set_force_timeout(bool force_timeout) = 0; // Sets return value |can_call_function_| of CanCallJavaScriptFunction(),
diff --git a/ios/web/test/fakes/fake_web_frame_impl.cc b/ios/web/test/fakes/fake_web_frame_impl.cc index 566c01ca..10a69602 100644 --- a/ios/web/test/fakes/fake_web_frame_impl.cc +++ b/ios/web/test/fakes/fake_web_frame_impl.cc
@@ -155,14 +155,31 @@ const std::u16string& script, base::OnceCallback<void(const base::Value*)> callback) { java_script_calls_.push_back(script); - return false; + + const base::Value* result = executed_js_result_map_[script]; + + if (!callback.is_null()) { + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); + } + + return result != nullptr; } bool FakeWebFrameImpl::ExecuteJavaScript( const std::u16string& script, base::OnceCallback<void(const base::Value*, bool)> callback) { java_script_calls_.push_back(script); - return false; + + const base::Value* result = executed_js_result_map_[script]; + bool success = result != nullptr; + + if (!callback.is_null()) { + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result, success)); + } + + return success; } void FakeWebFrameImpl::AddJsResultForFunctionCall( @@ -171,6 +188,12 @@ result_map_[function_name] = js_result; } +void FakeWebFrameImpl::AddResultForExecutedJs( + base::Value* js_result, + const std::u16string& executed_js) { + executed_js_result_map_[executed_js] = js_result; +} + JavaScriptContentWorld* FakeWebFrameImpl::last_received_content_world() { return last_received_content_world_; }
diff --git a/ios/web/test/fakes/fake_web_frame_impl.h b/ios/web/test/fakes/fake_web_frame_impl.h index 556a98b..d081ce5 100644 --- a/ios/web/test/fakes/fake_web_frame_impl.h +++ b/ios/web/test/fakes/fake_web_frame_impl.h
@@ -56,6 +56,8 @@ void set_browser_state(BrowserState* browser_state) override; void AddJsResultForFunctionCall(base::Value* js_result, const std::string& function_name) override; + void AddResultForExecutedJs(base::Value* js_result, + const std::u16string& executed_js) override; void set_force_timeout(bool force_timeout) override; void set_can_call_function(bool can_call_function) override; void set_call_java_script_function_callback( @@ -90,6 +92,9 @@ // by JavaScript function |name| expected to be passed into // CallJavaScriptFunction(). std::map<std::string, base::Value*> result_map_; + // Map holding values to be passed in ExecuteJavaScript() callback. Keyed by + // by JavaScript expected to be passed to ExecuteJavaScript(). + std::map<std::u16string, base::Value*> executed_js_result_map_; // The frame identifier which uniquely identifies this frame across the // application's lifetime. std::string frame_id_;
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc index 5aaa7a1..0ba71149 100644 --- a/media/base/mime_util_internal.cc +++ b/media/base/mime_util_internal.cc
@@ -130,7 +130,8 @@ (level_idc >= 20 && level_idc <= 22) || (level_idc >= 30 && level_idc <= 32) || (level_idc >= 40 && level_idc <= 42) || - (level_idc >= 50 && level_idc <= 52)); + (level_idc >= 50 && level_idc <= 52) || + (level_idc >= 60 && level_idc <= 62)); } // Make a default ParsedCodecResult. Values should indicate "unspecified"
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index 60475b69d..56a4a9a6 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -775,18 +775,19 @@ if (!src_frame.IsMappable() || !dst_frame.IsMappable()) return EncoderStatus::Codes::kUnsupportedFrameFormat; - // I420A can only be produced from I420A. - if (dst_frame.format() == PIXEL_FORMAT_I420A && - src_frame.format() != PIXEL_FORMAT_I420A) { - return EncoderStatus::Codes::kUnsupportedFrameFormat; - } - - if ((dst_frame.format() == PIXEL_FORMAT_I420 || + if ((dst_frame.format() == PIXEL_FORMAT_I420A || + dst_frame.format() == PIXEL_FORMAT_I420 || dst_frame.format() == PIXEL_FORMAT_NV12) && (src_frame.format() == PIXEL_FORMAT_XBGR || src_frame.format() == PIXEL_FORMAT_XRGB || src_frame.format() == PIXEL_FORMAT_ABGR || src_frame.format() == PIXEL_FORMAT_ARGB)) { + if (!media::IsOpaque(dst_frame.format()) && + media::IsOpaque(src_frame.format())) { + // We can drop an alpha channel, but we don't add it out of nothing. + return EncoderStatus::Codes::kUnsupportedFrameFormat; + } + // libyuv's RGB to YUV methods always output BT.601. dst_frame.set_color_space(gfx::ColorSpace::CreateREC601()); @@ -812,7 +813,8 @@ src_stride = stride; } - if (dst_frame.format() == PIXEL_FORMAT_I420) { + if (dst_frame.format() == PIXEL_FORMAT_I420 || + dst_frame.format() == PIXEL_FORMAT_I420A) { auto convert_fn = (src_frame.format() == PIXEL_FORMAT_XBGR || src_frame.format() == PIXEL_FORMAT_ABGR) ? libyuv::ABGRToI420 @@ -827,6 +829,17 @@ dst_frame.visible_rect().width(), dst_frame.visible_rect().height()); if (error) return EncoderStatus::Codes::kFormatConversionError; + + if (dst_frame.format() == PIXEL_FORMAT_I420A) { + // Convert alpha channel separately + libyuv::ARGBExtractAlpha( + src_data, src_stride, + dst_frame.visible_data(media::VideoFrame::kAPlane), + dst_frame.stride(media::VideoFrame::kAPlane), + dst_frame.visible_rect().width(), + dst_frame.visible_rect().height()); + } + return OkStatus(); }
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc index 4938dcf..79263cd0 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.cc +++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -678,9 +678,9 @@ #error "Unsupported platform" #endif -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) // viable_candidate should always be set unless using L1 protected content, - // which isn't an option on linux or lacros. + // which isn't an option on linux. CHECK(viable_candidate); #endif
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn index 50d81e48..6a635eff 100644 --- a/media/gpu/v4l2/BUILD.gn +++ b/media/gpu/v4l2/BUILD.gn
@@ -160,6 +160,7 @@ sources = [ "test/av1_decoder.cc", "test/av1_decoder.h", + "test/av1_pix_fmt.h", "test/v4l2_ioctl_shim.cc", "test/v4l2_ioctl_shim.h", "test/v4l2_stateless_decoder.cc",
diff --git a/media/gpu/v4l2/test/av1_decoder.cc b/media/gpu/v4l2/test/av1_decoder.cc index 399e1cf2..8911ccf 100644 --- a/media/gpu/v4l2/test/av1_decoder.cc +++ b/media/gpu/v4l2/test/av1_decoder.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "media/filters/ivf_parser.h" +#include "media/gpu/v4l2/test/av1_pix_fmt.h" namespace media {
diff --git a/media/gpu/v4l2/test/av1_decoder.h b/media/gpu/v4l2/test/av1_decoder.h index 800c746..240f38a5 100644 --- a/media/gpu/v4l2/test/av1_decoder.h +++ b/media/gpu/v4l2/test/av1_decoder.h
@@ -5,12 +5,12 @@ #ifndef MEDIA_GPU_V4L2_TEST_AV1_DECODER_H_ #define MEDIA_GPU_V4L2_TEST_AV1_DECODER_H_ -#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h" #include "media/gpu/v4l2/test/video_decoder.h" #include <set> #include "media/filters/ivf_parser.h" +#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h" // For libgav1::ObuSequenceHeader. absl::optional demands ObuSequenceHeader to // fulfill std::is_trivially_constructible if it is forward-declared. But // ObuSequenceHeader doesn't. @@ -22,18 +22,6 @@ // base/logging.h for ChromeOS. #define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); -// TODO(stevecho): This is temporary until the change to define -// V4L2_PIX_FMT_AV1_FRAME lands in videodev2.h. -// https://patchwork.linuxtv.org/project/linux-media/patch/20210810220552.298140-2-daniel.almeida@collabora.com/ -#ifndef V4L2_PIX_FMT_AV1 -#define V4L2_PIX_FMT_AV1 v4l2_fourcc('A', 'V', '0', '1') /* AV1 */ -#endif -#ifndef V4L2_PIX_FMT_AV1_FRAME -#define V4L2_PIX_FMT_AV1_FRAME \ - v4l2_fourcc('A', 'V', '1', 'F') /* AV1 parsed frame \ - */ -#endif - namespace media { namespace v4l2_test {
diff --git a/media/gpu/v4l2/test/av1_pix_fmt.h b/media/gpu/v4l2/test/av1_pix_fmt.h new file mode 100644 index 0000000..ca272b5 --- /dev/null +++ b/media/gpu/v4l2/test/av1_pix_fmt.h
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_V4L2_TEST_AV1_PIX_FMT_H_ +#define MEDIA_GPU_V4L2_TEST_AV1_PIX_FMT_H_ + +// TODO(stevecho): This is temporary until the change to define +// V4L2_PIX_FMT_AV1_FRAME lands in videodev2.h. +// https://patchwork.linuxtv.org/project/linux-media/patch/20210810220552.298140-2-daniel.almeida@collabora.com/ +#ifndef V4L2_PIX_FMT_AV1 +#define V4L2_PIX_FMT_AV1 v4l2_fourcc('A', 'V', '0', '1') /* AV1 */ +#endif +#ifndef V4L2_PIX_FMT_AV1_FRAME +#define V4L2_PIX_FMT_AV1_FRAME \ + v4l2_fourcc('A', 'V', '1', 'F') /* AV1 parsed frame \ + */ +#endif + +#endif // MEDIA_GPU_V4L2_TEST_VIDEO_DECODER_H_
diff --git a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc index fbe3784c..fbfcb5c9 100644 --- a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc +++ b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
@@ -18,6 +18,7 @@ #include "media/base/video_types.h" #include "media/filters/ivf_parser.h" #include "media/gpu/v4l2/test/av1_decoder.h" +#include "media/gpu/v4l2/test/av1_pix_fmt.h" #include "media/gpu/v4l2/test/video_decoder.h" #include "media/gpu/v4l2/test/vp9_decoder.h" @@ -64,23 +65,6 @@ } // namespace -// For stateless API, fourcc |VP9F| is needed instead of |VP90| for VP9 codec. -// Fourcc |AV1F| is needed instead of |AV10| for AV1 codec. -// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt-compressed.html -// Converts fourcc |VP90| or |AV01| from file header to fourcc |VP9F| or |AV1F|, -// which is a format supported on driver. -uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc) { - if (header_fourcc == V4L2_PIX_FMT_VP9) { - LOG(INFO) << "OUTPUT format mapped from VP90 to VP9F."; - return V4L2_PIX_FMT_VP9_FRAME; - } else if (header_fourcc == V4L2_PIX_FMT_AV1) { - LOG(INFO) << "OUTPUT format mapped from AV01 to AV1F."; - return V4L2_PIX_FMT_AV1_FRAME; - } - - return header_fourcc; -} - // Computes the md5 of given I420 data |yuv_plane| and prints the md5 to stdout. // This functionality is needed for tast tests. void ComputeAndPrintMd5hash(const std::vector<char>& yuv_plane) { @@ -108,7 +92,8 @@ VLOG(1) << "Creating decoder with codec " << media::FourccToString(file_header.fourcc); - const auto driver_codec_fourcc = FileFourccToDriverFourcc(file_header.fourcc); + const auto driver_codec_fourcc = + media::v4l2_test::FileFourccToDriverFourcc(file_header.fourcc); if (driver_codec_fourcc == V4L2_PIX_FMT_AV1_FRAME) { return Av1Decoder::Create(std::move(ivf_parser), file_header);
diff --git a/media/gpu/v4l2/test/video_decoder.cc b/media/gpu/v4l2/test/video_decoder.cc index c86241d..aedd3c7 100644 --- a/media/gpu/v4l2/test/video_decoder.cc +++ b/media/gpu/v4l2/test/video_decoder.cc
@@ -4,8 +4,11 @@ #include "media/gpu/v4l2/test/video_decoder.h" +#include <linux/videodev2.h> + #include "base/bits.h" #include "base/logging.h" +#include "media/gpu/v4l2/test/av1_pix_fmt.h" namespace media { namespace v4l2_test { @@ -93,6 +96,18 @@ } // namespace +uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc) { + if (header_fourcc == V4L2_PIX_FMT_VP9) { + LOG(INFO) << "OUTPUT format mapped from VP90 to VP9F."; + return V4L2_PIX_FMT_VP9_FRAME; + } else if (header_fourcc == V4L2_PIX_FMT_AV1) { + LOG(INFO) << "OUTPUT format mapped from AV01 to AV1F."; + return V4L2_PIX_FMT_AV1_FRAME; + } + + return header_fourcc; +} + VideoDecoder::VideoDecoder(std::unique_ptr<IvfParser> ivf_parser, std::unique_ptr<V4L2IoctlShim> v4l2_ioctl, std::unique_ptr<V4L2Queue> OUTPUT_queue,
diff --git a/media/gpu/v4l2/test/video_decoder.h b/media/gpu/v4l2/test/video_decoder.h index abbf3c5a..718fd0dd 100644 --- a/media/gpu/v4l2/test/video_decoder.h +++ b/media/gpu/v4l2/test/video_decoder.h
@@ -5,13 +5,19 @@ #ifndef MEDIA_GPU_V4L2_TEST_VIDEO_DECODER_H_ #define MEDIA_GPU_V4L2_TEST_VIDEO_DECODER_H_ -#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h" - #include "media/filters/ivf_parser.h" +#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h" namespace media { namespace v4l2_test { +// For stateless API, fourcc |VP9F| is needed instead of |VP90| for VP9 codec. +// Fourcc |AV1F| is needed instead of |AV10| for AV1 codec. +// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt-compressed.html +// Converts fourcc |VP90| or |AV01| from file header to fourcc |VP9F| or |AV1F|, +// which is a format supported on driver. +uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc); + // VideoDecoder decodes encoded IVF streams using v4l2 ioctl calls. class VideoDecoder { public:
diff --git a/net/base/auth.cc b/net/base/auth.cc index 3af2751..9f27cdd3 100644 --- a/net/base/auth.cc +++ b/net/base/auth.cc
@@ -6,8 +6,7 @@ namespace net { -AuthChallengeInfo::AuthChallengeInfo() : is_proxy(false) { -} +AuthChallengeInfo::AuthChallengeInfo() = default; AuthChallengeInfo::AuthChallengeInfo(const AuthChallengeInfo& other) = default;
diff --git a/net/base/auth.h b/net/base/auth.h index 19676512..6bf76347 100644 --- a/net/base/auth.h +++ b/net/base/auth.h
@@ -26,7 +26,7 @@ bool MatchesExceptPath(const AuthChallengeInfo& other) const; // Whether this came from a server or a proxy. - bool is_proxy; + bool is_proxy = false; // The service issuing the challenge. url::SchemeHostPort challenger;
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc index 3f0dce8..0882163 100644 --- a/net/base/directory_lister.cc +++ b/net/base/directory_lister.cc
@@ -97,8 +97,7 @@ : dir_(dir), type_(type), origin_task_runner_(base::SequencedTaskRunnerHandle::Get().get()), - lister_(lister), - cancelled_(0) { + lister_(lister) { DCHECK(lister_); }
diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h index 9f87940..3701a5a 100644 --- a/net/base/directory_lister.h +++ b/net/base/directory_lister.h
@@ -124,7 +124,7 @@ // Set to 1 on cancellation. Used both to abort listing files early on the // worker pool thread for performance reasons and to ensure |lister_| isn't // called after cancellation on the origin thread. - base::subtle::Atomic32 cancelled_; + base::subtle::Atomic32 cancelled_ = 0; }; // Call into the corresponding DirectoryListerDelegate. Must not be called
diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc index 9d5aedf..3b6ac1c 100644 --- a/net/base/directory_lister_unittest.cc +++ b/net/base/directory_lister_unittest.cc
@@ -36,12 +36,7 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { public: explicit ListerDelegate(DirectoryLister::ListingType type) - : cancel_lister_on_list_file_(false), - cancel_lister_on_list_done_(false), - lister_(nullptr), - done_(false), - error_(-1), - type_(type) {} + : lister_(nullptr), type_(type) {} // When set to true, this signals that the directory list operation should be // cancelled (And the run loop quit) in the first call to OnListFile. @@ -114,16 +109,16 @@ bool done() const { return done_; } private: - bool cancel_lister_on_list_file_; - bool cancel_lister_on_list_done_; + bool cancel_lister_on_list_file_ = false; + bool cancel_lister_on_list_done_ = false; // This is owned by the individual tests, rather than the ListerDelegate. raw_ptr<DirectoryLister> lister_; base::RunLoop run_loop; - bool done_; - int error_; + bool done_ = false; + int error_ = -1; DirectoryLister::ListingType type_; std::vector<base::FileEnumerator::FileInfo> file_list_; @@ -134,9 +129,7 @@ class DirectoryListerTest : public PlatformTest, public WithTaskEnvironment { public: - DirectoryListerTest() - : total_created_file_system_objects_in_temp_root_dir_(0), - created_file_system_objects_in_temp_root_dir_(0) {} + DirectoryListerTest() = default; void SetUp() override { // Randomly create a directory structure of depth 3 in a temporary root @@ -188,9 +181,9 @@ private: // Number of files and directories created in SetUp, excluding // |temp_root_dir_| itself. Includes all nested directories and their files. - int total_created_file_system_objects_in_temp_root_dir_; + int total_created_file_system_objects_in_temp_root_dir_ = 0; // Number of files and directories created directly in |temp_root_dir_|. - int created_file_system_objects_in_temp_root_dir_; + int created_file_system_objects_in_temp_root_dir_ = 0; base::ScopedTempDir temp_root_dir_; };
diff --git a/net/base/elements_upload_data_stream.cc b/net/base/elements_upload_data_stream.cc index a5f3189..1f5d616 100644 --- a/net/base/elements_upload_data_stream.cc +++ b/net/base/elements_upload_data_stream.cc
@@ -19,9 +19,7 @@ std::vector<std::unique_ptr<UploadElementReader>> element_readers, int64_t identifier) : UploadDataStream(false, identifier), - element_readers_(std::move(element_readers)), - element_index_(0), - read_error_(OK) {} + element_readers_(std::move(element_readers)) {} ElementsUploadDataStream::~ElementsUploadDataStream() = default;
diff --git a/net/base/elements_upload_data_stream.h b/net/base/elements_upload_data_stream.h index 0806a9e..d2e7388 100644 --- a/net/base/elements_upload_data_stream.h +++ b/net/base/elements_upload_data_stream.h
@@ -13,6 +13,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/upload_data_stream.h" @@ -77,10 +78,10 @@ // Index of the current upload element (i.e. the element currently being // read). The index is used as a cursor to iterate over elements in // |upload_data_|. - size_t element_index_; + size_t element_index_ = 0; // Set to actual error if read fails, otherwise set to net::OK. - int read_error_; + int read_error_ = OK; base::WeakPtrFactory<ElementsUploadDataStream> weak_ptr_factory_{this}; };
diff --git a/net/base/elements_upload_data_stream_unittest.cc b/net/base/elements_upload_data_stream_unittest.cc index af44f0a..b586bf0 100644 --- a/net/base/elements_upload_data_stream_unittest.cc +++ b/net/base/elements_upload_data_stream_unittest.cc
@@ -71,9 +71,7 @@ MockUploadElementReader(int content_length, bool is_in_memory) : content_length_(content_length), bytes_remaining_(content_length), - is_in_memory_(is_in_memory), - init_result_(OK), - read_result_(OK) {} + is_in_memory_(is_in_memory) {} ~MockUploadElementReader() override = default; @@ -134,10 +132,10 @@ bool is_in_memory_; // Result value returned from Init(). - int init_result_; + int init_result_ = OK; // Result value returned from Read(). - int read_result_; + int read_result_ = OK; }; } // namespace
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc index a05b8e5..59194e81 100644 --- a/net/base/file_stream_unittest.cc +++ b/net/base/file_stream_unittest.cc
@@ -502,10 +502,7 @@ int* total_bytes_written, int* total_bytes_read, std::string* data_read) - : result_(0), - have_result_(false), - waiting_for_result_(false), - stream_(stream), + : stream_(stream), total_bytes_written_(total_bytes_written), total_bytes_read_(total_bytes_read), data_read_(data_read), @@ -588,9 +585,9 @@ base::RunLoop::QuitCurrentWhenIdleDeprecated(); } - int result_; - bool have_result_; - bool waiting_for_result_; + int result_ = 0; + bool have_result_ = false; + bool waiting_for_result_ = false; raw_ptr<FileStream> stream_; raw_ptr<int> total_bytes_written_; raw_ptr<int> total_bytes_read_; @@ -645,10 +642,7 @@ class TestWriteCloseCompletionCallback { public: TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written) - : result_(0), - have_result_(false), - waiting_for_result_(false), - stream_(stream), + : stream_(stream), total_bytes_written_(total_bytes_written), drainable_( base::MakeRefCounted<DrainableIOBuffer>(CreateTestDataBuffer(), @@ -699,9 +693,9 @@ base::RunLoop::QuitCurrentWhenIdleDeprecated(); } - int result_; - bool have_result_; - bool waiting_for_result_; + int result_ = 0; + bool have_result_ = false; + bool waiting_for_result_ = false; raw_ptr<FileStream> stream_; raw_ptr<int> total_bytes_written_; scoped_refptr<DrainableIOBuffer> drainable_;
diff --git a/net/base/host_mapping_rules.cc b/net/base/host_mapping_rules.cc index de2fd4d..3cd8027 100644 --- a/net/base/host_mapping_rules.cc +++ b/net/base/host_mapping_rules.cc
@@ -21,11 +21,11 @@ namespace net { struct HostMappingRules::MapRule { - MapRule() : replacement_port(-1) {} + MapRule() = default; std::string hostname_pattern; std::string replacement_hostname; - int replacement_port; + int replacement_port = -1; }; struct HostMappingRules::ExclusionRule {
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc index cb133519..78d4cf4 100644 --- a/net/base/io_buffer.cc +++ b/net/base/io_buffer.cc
@@ -102,11 +102,7 @@ data_ = nullptr; } -GrowableIOBuffer::GrowableIOBuffer() - : IOBuffer(), - capacity_(0), - offset_(0) { -} +GrowableIOBuffer::GrowableIOBuffer() = default; void GrowableIOBuffer::SetCapacity(int capacity) { DCHECK_GE(capacity, 0);
diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h index 047c9f4..2de7d9e 100644 --- a/net/base/io_buffer.h +++ b/net/base/io_buffer.h
@@ -215,8 +215,8 @@ ~GrowableIOBuffer() override; std::unique_ptr<char, base::FreeDeleter> real_data_; - int capacity_; - int offset_; + int capacity_ = 0; + int offset_ = 0; }; // This versions allows a pickle to be used as the storage for a write-style
diff --git a/net/base/load_timing_info.cc b/net/base/load_timing_info.cc index 5ce74ca..7471f5c5 100644 --- a/net/base/load_timing_info.cc +++ b/net/base/load_timing_info.cc
@@ -12,8 +12,7 @@ LoadTimingInfo::ConnectTiming::~ConnectTiming() = default; -LoadTimingInfo::LoadTimingInfo() - : socket_reused(false), socket_log_id(NetLogSource::kInvalidId) {} +LoadTimingInfo::LoadTimingInfo() : socket_log_id(NetLogSource::kInvalidId) {} LoadTimingInfo::LoadTimingInfo(const LoadTimingInfo& other) = default;
diff --git a/net/base/load_timing_info.h b/net/base/load_timing_info.h index 759559b..98e1225 100644 --- a/net/base/load_timing_info.h +++ b/net/base/load_timing_info.h
@@ -119,7 +119,7 @@ // Responding to a proxy AUTH challenge is never considered to be reusing a // socket, since a connection to the host wasn't established when the // challenge was received. - bool socket_reused; + bool socket_reused = false; // Unique socket ID, can be used to identify requests served by the same // socket. For connections tunnelled over SPDY proxies, this is the ID of
diff --git a/net/base/lookup_string_in_fixed_set.cc b/net/base/lookup_string_in_fixed_set.cc index b726fb9..8b08b27 100644 --- a/net/base/lookup_string_in_fixed_set.cc +++ b/net/base/lookup_string_in_fixed_set.cc
@@ -71,7 +71,7 @@ FixedSetIncrementalLookup::FixedSetIncrementalLookup(const unsigned char* graph, size_t length) - : pos_(graph), end_(graph + length), pos_is_label_character_(false) {} + : pos_(graph), end_(graph + length) {} FixedSetIncrementalLookup::FixedSetIncrementalLookup( const FixedSetIncrementalLookup& other) = default;
diff --git a/net/base/lookup_string_in_fixed_set.h b/net/base/lookup_string_in_fixed_set.h index f27c704..9d6e4ba 100644 --- a/net/base/lookup_string_in_fixed_set.h +++ b/net/base/lookup_string_in_fixed_set.h
@@ -152,7 +152,7 @@ // Contains the current decoder state. If true, |pos_| points to a label // character or a return code. If false, |pos_| points to a sequence of // offsets that indicate the child nodes of the current state. - bool pos_is_label_character_; + bool pos_is_label_character_ = false; }; } // namespace net
diff --git a/net/base/mock_network_change_notifier.cc b/net/base/mock_network_change_notifier.cc index 952f7c8d..427bf4f 100644 --- a/net/base/mock_network_change_notifier.cc +++ b/net/base/mock_network_change_notifier.cc
@@ -104,9 +104,6 @@ std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier) : NetworkChangeNotifier(NetworkChangeCalculatorParams(), dns_config_notifier.get()), - force_network_handles_supported_(false), - connection_type_(CONNECTION_UNKNOWN), - connection_cost_(CONNECTION_COST_UNKNOWN), dns_config_notifier_(std::move(dns_config_notifier)) {} ScopedMockNetworkChangeNotifier::ScopedMockNetworkChangeNotifier()
diff --git a/net/base/mock_network_change_notifier.h b/net/base/mock_network_change_notifier.h index 24e01598..67295ce 100644 --- a/net/base/mock_network_change_notifier.h +++ b/net/base/mock_network_change_notifier.h
@@ -82,9 +82,9 @@ MockNetworkChangeNotifier( std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier); - bool force_network_handles_supported_; - ConnectionType connection_type_; - ConnectionCost connection_cost_; + bool force_network_handles_supported_ = false; + ConnectionType connection_type_ = CONNECTION_UNKNOWN; + ConnectionCost connection_cost_ = CONNECTION_COST_UNKNOWN; bool use_default_connection_cost_implementation_ = false; NetworkChangeNotifier::NetworkList connected_networks_; std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_;
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index ce8fad5e4..1dd4055 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -107,10 +107,7 @@ public IPAddressObserver { public: explicit NetworkChangeCalculator(const NetworkChangeCalculatorParams& params) - : params_(params), - have_announced_(false), - last_announced_connection_type_(CONNECTION_NONE), - pending_connection_type_(CONNECTION_NONE) { + : params_(params) { DCHECK(g_network_change_notifier); AddConnectionTypeObserver(this); AddConnectionCostObserver(this); @@ -180,11 +177,11 @@ const NetworkChangeCalculatorParams params_; // Indicates if NotifyObserversOfNetworkChange has been called yet. - bool have_announced_; + bool have_announced_ = false; // Last value passed to NotifyObserversOfNetworkChange. - ConnectionType last_announced_connection_type_; + ConnectionType last_announced_connection_type_ = CONNECTION_NONE; // Value to pass to NotifyObserversOfNetworkChange when Notify is called. - ConnectionType pending_connection_type_; + ConnectionType pending_connection_type_ = CONNECTION_NONE; // Used to delay notifications so duplicates can be combined. base::OneShotTimer timer_;
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc index 096d57e6..5a21d36 100644 --- a/net/base/network_change_notifier_linux.cc +++ b/net/base/network_change_notifier_linux.cc
@@ -44,7 +44,8 @@ void OnLinkChanged(); // Used to detect online/offline state and IP address changes. internal::AddressTrackerLinux address_tracker_; - NetworkChangeNotifier::ConnectionType last_type_; + NetworkChangeNotifier::ConnectionType last_type_ = + NetworkChangeNotifier::CONNECTION_NONE; }; NetworkChangeNotifierLinux::BlockingThreadObjects::BlockingThreadObjects( @@ -57,8 +58,7 @@ &NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged, base::Unretained(this)), base::DoNothing(), - ignored_interfaces), - last_type_(NetworkChangeNotifier::CONNECTION_NONE) {} + ignored_interfaces) {} void NetworkChangeNotifierLinux::BlockingThreadObjects::Init() { address_tracker_.Init();
diff --git a/net/base/prioritized_dispatcher_unittest.cc b/net/base/prioritized_dispatcher_unittest.cc index ae9effc..0f5ba3e 100644 --- a/net/base/prioritized_dispatcher_unittest.cc +++ b/net/base/prioritized_dispatcher_unittest.cc
@@ -41,11 +41,7 @@ char tag, Priority priority, std::string* log) - : dispatcher_(dispatcher), - tag_(tag), - priority_(priority), - running_(false), - log_(log) {} + : dispatcher_(dispatcher), tag_(tag), priority_(priority), log_(log) {} bool running() const { return running_; @@ -134,7 +130,7 @@ Priority priority_; PrioritizedDispatcher::Handle handle_; - bool running_; + bool running_ = false; raw_ptr<std::string> log_; };
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc index cccaedb0..c282bd2 100644 --- a/net/base/upload_data_stream.cc +++ b/net/base/upload_data_stream.cc
@@ -35,13 +35,7 @@ } // namespace UploadDataStream::UploadDataStream(bool is_chunked, int64_t identifier) - : total_size_(0), - current_position_(0), - identifier_(identifier), - is_chunked_(is_chunked), - initialized_successfully_(false), - is_eof_(false) { -} + : identifier_(identifier), is_chunked_(is_chunked) {} UploadDataStream::~UploadDataStream() = default;
diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h index a1b6bd2..89eeef08 100644 --- a/net/base/upload_data_stream.h +++ b/net/base/upload_data_stream.h
@@ -133,17 +133,17 @@ // at least once before every call to InitInternal. virtual void ResetInternal() = 0; - uint64_t total_size_; - uint64_t current_position_; + uint64_t total_size_ = 0; + uint64_t current_position_ = 0; const int64_t identifier_; const bool is_chunked_; // True if the initialization was successful. - bool initialized_successfully_; + bool initialized_successfully_ = false; - bool is_eof_; + bool is_eof_ = false; CompletionOnceCallback callback_;
diff --git a/net/cert/caching_cert_verifier.cc b/net/cert/caching_cert_verifier.cc index ee2ec1d9..d2c1ead3 100644 --- a/net/cert/caching_cert_verifier.cc +++ b/net/cert/caching_cert_verifier.cc
@@ -23,11 +23,7 @@ } // namespace CachingCertVerifier::CachingCertVerifier(std::unique_ptr<CertVerifier> verifier) - : verifier_(std::move(verifier)), - config_id_(0u), - cache_(kMaxCacheEntries), - requests_(0u), - cache_hits_(0u) { + : verifier_(std::move(verifier)), cache_(kMaxCacheEntries) { CertDatabase::GetInstance()->AddObserver(this); } @@ -72,7 +68,7 @@ ClearCache(); } -CachingCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} +CachingCertVerifier::CachedResult::CachedResult() = default; CachingCertVerifier::CachedResult::~CachedResult() = default;
diff --git a/net/cert/caching_cert_verifier.h b/net/cert/caching_cert_verifier.h index 8fc1afa..ce06e6eb 100644 --- a/net/cert/caching_cert_verifier.h +++ b/net/cert/caching_cert_verifier.h
@@ -67,7 +67,7 @@ CachedResult(); ~CachedResult(); - int error; // The return value of CertVerifier::Verify. + int error = ERR_FAILED; // The return value of CertVerifier::Verify. CertVerifyResult result; // The output of CertVerifier::Verify. }; @@ -129,11 +129,11 @@ std::unique_ptr<CertVerifier> verifier_; - uint32_t config_id_; + uint32_t config_id_ = 0u; CertVerificationCache cache_; - uint64_t requests_; - uint64_t cache_hits_; + uint64_t requests_ = 0u; + uint64_t cache_hits_ = 0u; }; } // namespace net
diff --git a/net/cert/coalescing_cert_verifier.cc b/net/cert/coalescing_cert_verifier.cc index a7c003ee..a8878f0 100644 --- a/net/cert/coalescing_cert_verifier.cc +++ b/net/cert/coalescing_cert_verifier.cc
@@ -380,10 +380,7 @@ CoalescingCertVerifier::CoalescingCertVerifier( std::unique_ptr<CertVerifier> verifier) - : verifier_(std::move(verifier)), - config_id_(0), - requests_(0), - inflight_joins_(0) {} + : verifier_(std::move(verifier)) {} CoalescingCertVerifier::~CoalescingCertVerifier() = default;
diff --git a/net/cert/coalescing_cert_verifier.h b/net/cert/coalescing_cert_verifier.h index 40686b1..1625a86b7 100644 --- a/net/cert/coalescing_cert_verifier.h +++ b/net/cert/coalescing_cert_verifier.h
@@ -70,9 +70,9 @@ std::unique_ptr<CertVerifier> verifier_; - uint32_t config_id_; - uint64_t requests_; - uint64_t inflight_joins_; + uint32_t config_id_ = 0; + uint64_t requests_ = 0; + uint64_t inflight_joins_ = 0; }; } // namespace net
diff --git a/net/cert/crl_set.cc b/net/cert/crl_set.cc index 2579030..cc9e6c5 100644 --- a/net/cert/crl_set.cc +++ b/net/cert/crl_set.cc
@@ -197,10 +197,7 @@ } // namespace -CRLSet::CRLSet() - : sequence_(0), - not_after_(0) { -} +CRLSet::CRLSet() = default; CRLSet::~CRLSet() = default;
diff --git a/net/cert/crl_set.h b/net/cert/crl_set.h index f260a060..b629ea46 100644 --- a/net/cert/crl_set.h +++ b/net/cert/crl_set.h
@@ -114,10 +114,10 @@ friend class base::RefCountedThreadSafe<CRLSet>; - uint32_t sequence_; + uint32_t sequence_ = 0; // not_after_ contains the time, in UNIX epoch seconds, after which the // CRLSet should be considered stale, or 0 if no such time was given. - uint64_t not_after_; + uint64_t not_after_ = 0; // crls_ is a map from the SHA-256 hash of an X.501 subject name to a list // of revoked serial numbers. CRLList crls_;
diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc index 5c46e05..56b41a54 100644 --- a/net/cert/ct_log_verifier.cc +++ b/net/cert/ct_log_verifier.cc
@@ -67,10 +67,7 @@ } CTLogVerifier::CTLogVerifier(std::string description) - : description_(std::move(description)), - hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE), - signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS), - public_key_(nullptr) {} + : description_(std::move(description)), public_key_(nullptr) {} bool CTLogVerifier::Verify(const ct::SignedEntryData& entry, const ct::SignedCertificateTimestamp& sct) const {
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h index fafc972..69ea252 100644 --- a/net/cert/ct_log_verifier.h +++ b/net/cert/ct_log_verifier.h
@@ -91,8 +91,10 @@ std::string key_id_; std::string description_; - ct::DigitallySigned::HashAlgorithm hash_algorithm_; - ct::DigitallySigned::SignatureAlgorithm signature_algorithm_; + ct::DigitallySigned::HashAlgorithm hash_algorithm_ = + ct::DigitallySigned::HASH_ALGO_NONE; + ct::DigitallySigned::SignatureAlgorithm signature_algorithm_ = + ct::DigitallySigned::SIG_ALGO_ANONYMOUS; raw_ptr<EVP_PKEY> public_key_; };
diff --git a/net/cert/mock_cert_verifier.cc b/net/cert/mock_cert_verifier.cc index 25d5531f..e47554e2 100644 --- a/net/cert/mock_cert_verifier.cc +++ b/net/cert/mock_cert_verifier.cc
@@ -81,8 +81,7 @@ base::WeakPtrFactory<MockRequest> weak_factory_{this}; }; -MockCertVerifier::MockCertVerifier() - : default_result_(ERR_CERT_INVALID), async_(false) {} +MockCertVerifier::MockCertVerifier() = default; MockCertVerifier::~MockCertVerifier() { // Reset the callbacks for any outstanding MockRequests to fulfill the
diff --git a/net/cert/mock_cert_verifier.h b/net/cert/mock_cert_verifier.h index f653fe37..de9e42e 100644 --- a/net/cert/mock_cert_verifier.h +++ b/net/cert/mock_cert_verifier.h
@@ -70,9 +70,9 @@ int VerifyImpl(const RequestParams& params, CertVerifyResult* verify_result); - int default_result_; + int default_result_ = ERR_CERT_INVALID; RuleList rules_; - bool async_; + bool async_ = false; base::OnceClosureList request_list_; };
diff --git a/net/cert/mock_client_cert_verifier.cc b/net/cert/mock_client_cert_verifier.cc index 4de56a5..3b23e51 100644 --- a/net/cert/mock_client_cert_verifier.cc +++ b/net/cert/mock_client_cert_verifier.cc
@@ -18,8 +18,7 @@ int rv; }; -MockClientCertVerifier::MockClientCertVerifier() - : default_result_(ERR_CERT_INVALID) {} +MockClientCertVerifier::MockClientCertVerifier() = default; MockClientCertVerifier::~MockClientCertVerifier() = default;
diff --git a/net/cert/mock_client_cert_verifier.h b/net/cert/mock_client_cert_verifier.h index 81026b7..166643f7 100644 --- a/net/cert/mock_client_cert_verifier.h +++ b/net/cert/mock_client_cert_verifier.h
@@ -9,6 +9,7 @@ #include <memory> #include "net/base/completion_once_callback.h" +#include "net/base/net_errors.h" #include "net/cert/client_cert_verifier.h" namespace net { @@ -45,7 +46,7 @@ struct Rule; typedef std::list<Rule> RuleList; - int default_result_; + int default_result_ = ERR_CERT_INVALID; RuleList rules_; };
diff --git a/net/cert/signed_certificate_timestamp.cc b/net/cert/signed_certificate_timestamp.cc index 4b2567b..aa33089 100644 --- a/net/cert/signed_certificate_timestamp.cc +++ b/net/cert/signed_certificate_timestamp.cc
@@ -28,8 +28,7 @@ return lhs->version < rhs->version; } -SignedCertificateTimestamp::SignedCertificateTimestamp() - : version(V1), origin(SCT_EMBEDDED) {} +SignedCertificateTimestamp::SignedCertificateTimestamp() = default; SignedCertificateTimestamp::~SignedCertificateTimestamp() = default; @@ -78,7 +77,7 @@ return sct; } -SignedEntryData::SignedEntryData() : type(LOG_ENTRY_TYPE_X509) {} +SignedEntryData::SignedEntryData() = default; SignedEntryData::~SignedEntryData() = default; @@ -88,8 +87,7 @@ tbs_certificate.clear(); } -DigitallySigned::DigitallySigned() - : hash_algorithm(HASH_ALGO_NONE), signature_algorithm(SIG_ALGO_ANONYMOUS) {} +DigitallySigned::DigitallySigned() = default; DigitallySigned::~DigitallySigned() = default;
diff --git a/net/cert/signed_certificate_timestamp.h b/net/cert/signed_certificate_timestamp.h index 5378cc1c..50d5a02a 100644 --- a/net/cert/signed_certificate_timestamp.h +++ b/net/cert/signed_certificate_timestamp.h
@@ -48,7 +48,7 @@ ~SignedEntryData(); void Reset(); - Type type; + Type type = LOG_ENTRY_TYPE_X509; // Set if type == LOG_ENTRY_TYPE_X509 std::string leaf_certificate; @@ -87,8 +87,8 @@ HashAlgorithm other_hash_algorithm, SignatureAlgorithm other_signature_algorithm) const; - HashAlgorithm hash_algorithm; - SignatureAlgorithm signature_algorithm; + HashAlgorithm hash_algorithm = HASH_ALGO_NONE; + SignatureAlgorithm signature_algorithm = SIG_ALGO_ANONYMOUS; // 'signature' field. std::string signature_data; }; @@ -128,12 +128,12 @@ static scoped_refptr<SignedCertificateTimestamp> CreateFromPickle( base::PickleIterator* iter); - Version version; + Version version = V1; std::string log_id; base::Time timestamp; std::string extensions; DigitallySigned signature; - Origin origin; + Origin origin = SCT_EMBEDDED; // The log description is not one of the SCT fields, but a user-readable // name defined alongside the log key. It should not participate // in equality checks as the log's description could change while
diff --git a/net/cert_net/cert_net_fetcher_url_request.cc b/net/cert_net/cert_net_fetcher_url_request.cc index 8819618..e570758 100644 --- a/net/cert_net/cert_net_fetcher_url_request.cc +++ b/net/cert_net/cert_net_fetcher_url_request.cc
@@ -295,8 +295,8 @@ bool operator<(const RequestParams& other) const; GURL url; - HttpMethod http_method; - size_t max_response_bytes; + HttpMethod http_method = HTTP_METHOD_GET; + size_t max_response_bytes = 0; // If set to a value <= 0 then means "no timeout". base::TimeDelta timeout; @@ -304,8 +304,7 @@ // IMPORTANT: When adding fields to this structure, update operator<(). }; -CertNetFetcherURLRequest::RequestParams::RequestParams() - : http_method(HTTP_METHOD_GET), max_response_bytes(0) {} +CertNetFetcherURLRequest::RequestParams::RequestParams() = default; bool CertNetFetcherURLRequest::RequestParams::operator<( const RequestParams& other) const {
diff --git a/net/cert_net/cert_net_fetcher_url_request_unittest.cc b/net/cert_net/cert_net_fetcher_url_request_unittest.cc index 3def9a1..08092a4a 100644 --- a/net/cert_net/cert_net_fetcher_url_request_unittest.cc +++ b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
@@ -235,8 +235,7 @@ : public CertNetFetcherURLRequestTest, public WithTaskEnvironment { public: - CertNetFetcherURLRequestTestWithSecureDnsInterceptor() - : invoked_interceptor_(false) {} + CertNetFetcherURLRequestTestWithSecureDnsInterceptor() = default; void SetUp() override { URLRequestFilter::GetInstance()->AddHostnameInterceptor( @@ -249,7 +248,7 @@ bool invoked_interceptor() { return invoked_interceptor_; } private: - bool invoked_interceptor_; + bool invoked_interceptor_ = false; }; // Helper to start an AIA fetch using default parameters.
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc index 8555811..12de7b5 100644 --- a/net/cookies/cookie_monster_perftest.cc +++ b/net/cookies/cookie_monster_perftest.cc
@@ -72,7 +72,7 @@ class CookieTestCallback { public: - CookieTestCallback() : has_run_(false) {} + CookieTestCallback() = default; protected: void WaitForCallback() { @@ -88,7 +88,7 @@ void Run() { has_run_ = true; } - bool has_run_; + bool has_run_ = false; }; class SetCookieCallback : public CookieTestCallback {
diff --git a/net/cookies/cookie_monster_store_test.cc b/net/cookies/cookie_monster_store_test.cc index 3812429..1bc8e95 100644 --- a/net/cookies/cookie_monster_store_test.cc +++ b/net/cookies/cookie_monster_store_test.cc
@@ -30,8 +30,7 @@ CookieStoreCommand::CookieStoreCommand(CookieStoreCommand&& other) = default; CookieStoreCommand::~CookieStoreCommand() = default; -MockPersistentCookieStore::MockPersistentCookieStore() - : store_load_commands_(false), load_return_value_(true), loaded_(false) {} +MockPersistentCookieStore::MockPersistentCookieStore() = default; void MockPersistentCookieStore::SetLoadExpectation( bool return_value, @@ -135,9 +134,7 @@ out_list->push_back(std::move(cookie)); } -MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() - : loaded_(false) { -} +MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() = default; void MockSimplePersistentCookieStore::Load( LoadedCallback loaded_callback,
diff --git a/net/cookies/cookie_monster_store_test.h b/net/cookies/cookie_monster_store_test.h index 8f3b96a..6250ebb 100644 --- a/net/cookies/cookie_monster_store_test.h +++ b/net/cookies/cookie_monster_store_test.h
@@ -119,14 +119,14 @@ private: CommandList commands_; - bool store_load_commands_; + bool store_load_commands_ = false; // Deferred result to use when Load() is called. - bool load_return_value_; + bool load_return_value_ = true; std::vector<std::unique_ptr<CanonicalCookie>> load_result_; // Indicates if the store has been fully loaded to avoid returning duplicate // cookies. - bool loaded_; + bool loaded_ = false; }; // Helper to build a single CanonicalCookie. @@ -177,7 +177,7 @@ // Indicates if the store has been fully loaded to avoid return duplicate // cookies in subsequent load requests - bool loaded_; + bool loaded_ = false; }; // Helper function for creating a CookieMonster backed by a
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc index 6982534..31c9538 100644 --- a/net/cookies/cookie_store_test_helpers.cc +++ b/net/cookies/cookie_store_test_helpers.cc
@@ -75,7 +75,6 @@ : cookie_monster_(new CookieMonster(nullptr /* store */, nullptr /* netlog */, false /* first_party_sets_enabled */)), - did_run_(false), result_(CookieAccessResult(CookieInclusionStatus( CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE))) {} @@ -216,7 +215,7 @@ // // FlushablePersistentStore // -FlushablePersistentStore::FlushablePersistentStore() : flush_count_(0) {} +FlushablePersistentStore::FlushablePersistentStore() = default; void FlushablePersistentStore::Load(LoadedCallback loaded_callback, const NetLogWithSource& /* net_log */) { @@ -259,7 +258,7 @@ // // CallbackCounter // -CallbackCounter::CallbackCounter() : callback_count_(0) {} +CallbackCounter::CallbackCounter() = default; void CallbackCounter::Callback() { base::AutoLock lock(callback_count_lock_);
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h index fcb3997..03ecacf 100644 --- a/net/cookies/cookie_store_test_helpers.h +++ b/net/cookies/cookie_store_test_helpers.h
@@ -119,7 +119,7 @@ std::unique_ptr<CookieMonster> cookie_monster_; DelayedCookieMonsterChangeDispatcher change_dispatcher_; - bool did_run_; + bool did_run_ = false; CookieAccessResult result_; std::string cookie_; std::string cookie_line_; @@ -169,7 +169,7 @@ private: ~FlushablePersistentStore() override; - int flush_count_; + int flush_count_ = 0; base::Lock flush_count_lock_; // Protects |flush_count_|. }; @@ -184,7 +184,7 @@ friend class base::RefCountedThreadSafe<CallbackCounter>; ~CallbackCounter(); - int callback_count_; + int callback_count_ = 0; base::Lock callback_count_lock_; // Protects |callback_count_|. };
diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc index 058d610..171551d 100644 --- a/net/disk_cache/blockfile/backend_impl.cc +++ b/net/disk_cache/blockfile/backend_impl.cc
@@ -158,7 +158,6 @@ background_queue_(this, FallbackToInternalIfNull(cache_thread)), path_(path), block_files_(path), - mask_(0), user_flags_(0), net_log_(net_log) { TRACE_EVENT0("disk_cache", "BackendImpl::BackendImpl");
diff --git a/net/disk_cache/blockfile/entry_impl.cc b/net/disk_cache/blockfile/entry_impl.cc index ccfe4aa..01859bad 100644 --- a/net/disk_cache/blockfile/entry_impl.cc +++ b/net/disk_cache/blockfile/entry_impl.cc
@@ -104,8 +104,7 @@ // total memory used under control. class EntryImpl::UserBuffer { public: - explicit UserBuffer(BackendImpl* backend) - : backend_(backend->GetWeakPtr()), offset_(0), grow_allowed_(true) { + explicit UserBuffer(BackendImpl* backend) : backend_(backend->GetWeakPtr()) { buffer_.reserve(kMaxBlockSize); } @@ -148,9 +147,9 @@ bool GrowBuffer(int required, int limit); base::WeakPtr<BackendImpl> backend_; - int offset_; + int offset_ = 0; std::vector<char> buffer_; - bool grow_allowed_; + bool grow_allowed_ = true; }; bool EntryImpl::UserBuffer::PreWrite(int offset, int len) { @@ -318,9 +317,7 @@ : entry_(nullptr, Addr(0)), node_(nullptr, Addr(0)), backend_(backend->GetWeakPtr()), - doomed_(false), - read_only_(read_only), - dirty_(false) { + read_only_(read_only) { entry_.LazyInit(backend->File(address), address); for (int i = 0; i < kNumStreams; i++) { unreported_size_[i] = 0;
diff --git a/net/disk_cache/blockfile/entry_impl.h b/net/disk_cache/blockfile/entry_impl.h index aee2aac7..b758719 100644 --- a/net/disk_cache/blockfile/entry_impl.h +++ b/net/disk_cache/blockfile/entry_impl.h
@@ -305,9 +305,9 @@ scoped_refptr<File> files_[kNumStreams + 1]; mutable std::string key_; // Copy of the key. int unreported_size_[kNumStreams]; // Bytes not reported yet to the backend. - bool doomed_; // True if this entry was removed from the cache. + bool doomed_ = false; // True if this entry was removed from the cache. bool read_only_; // True if not yet writing. - bool dirty_; // True if we detected that this is a dirty entry. + bool dirty_ = false; // True if we detected that this is a dirty entry. std::unique_ptr<SparseControl> sparse_; // Support for sparse entries. };
diff --git a/net/disk_cache/blockfile/eviction.cc b/net/disk_cache/blockfile/eviction.cc index 9061488e..e3236dc 100644 --- a/net/disk_cache/blockfile/eviction.cc +++ b/net/disk_cache/blockfile/eviction.cc
@@ -79,7 +79,7 @@ // The real initialization happens during Init(), init_ is the only member that // has to be initialized here. -Eviction::Eviction() : backend_(nullptr), init_(false) {} +Eviction::Eviction() : backend_(nullptr) {} Eviction::~Eviction() = default;
diff --git a/net/disk_cache/blockfile/eviction.h b/net/disk_cache/blockfile/eviction.h index a33b5919..92e60c6 100644 --- a/net/disk_cache/blockfile/eviction.h +++ b/net/disk_cache/blockfile/eviction.h
@@ -83,7 +83,7 @@ bool first_trim_; bool trimming_; bool delay_trim_; - bool init_; + bool init_ = false; bool test_mode_; base::WeakPtrFactory<Eviction> ptr_factory_{this}; };
diff --git a/net/disk_cache/blockfile/in_flight_io.cc b/net/disk_cache/blockfile/in_flight_io.cc index a894e285..6d4d742e 100644 --- a/net/disk_cache/blockfile/in_flight_io.cc +++ b/net/disk_cache/blockfile/in_flight_io.cc
@@ -15,8 +15,7 @@ namespace disk_cache { BackgroundIO::BackgroundIO(InFlightIO* controller) - : result_(-1), - io_completed_(base::WaitableEvent::ResetPolicy::MANUAL, + : io_completed_(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED), controller_(controller) {} @@ -38,8 +37,7 @@ // --------------------------------------------------------------------------- InFlightIO::InFlightIO() - : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()), - running_(false) {} + : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} InFlightIO::~InFlightIO() = default;
diff --git a/net/disk_cache/blockfile/in_flight_io.h b/net/disk_cache/blockfile/in_flight_io.h index 76bdea5d..320775a3 100644 --- a/net/disk_cache/blockfile/in_flight_io.h +++ b/net/disk_cache/blockfile/in_flight_io.h
@@ -61,7 +61,7 @@ // thread. void NotifyController(); - int result_; // Final operation result. + int result_ = -1; // Final operation result. private: friend class base::RefCountedThreadSafe<BackgroundIO>; @@ -137,7 +137,7 @@ IOList io_list_; // List of pending, in-flight io operations. scoped_refptr<base::SequencedTaskRunner> callback_task_runner_; - bool running_; // True after the first posted operation completes. + bool running_ = false; // True after the first posted operation completes. #if DCHECK_IS_ON() bool single_thread_ = false; // True if we only have one thread. #endif
diff --git a/net/disk_cache/blockfile/mapped_file.h b/net/disk_cache/blockfile/mapped_file.h index 1291843..d5fb298 100644 --- a/net/disk_cache/blockfile/mapped_file.h +++ b/net/disk_cache/blockfile/mapped_file.h
@@ -28,7 +28,7 @@ // time). class NET_EXPORT_PRIVATE MappedFile : public File { public: - MappedFile() : File(true), init_(false) {} + MappedFile() : File(true) {} MappedFile(const MappedFile&) = delete; MappedFile& operator=(const MappedFile&) = delete; @@ -56,7 +56,7 @@ private: ~MappedFile() override; - bool init_; + bool init_ = false; #if BUILDFLAG(IS_WIN) HANDLE section_; #endif
diff --git a/net/disk_cache/blockfile/rankings.cc b/net/disk_cache/blockfile/rankings.cc index e2bc135..0b8a068 100644 --- a/net/disk_cache/blockfile/rankings.cc +++ b/net/disk_cache/blockfile/rankings.cc
@@ -218,7 +218,7 @@ memset(this, 0, sizeof(Iterator)); } -Rankings::Rankings() : init_(false) {} +Rankings::Rankings() = default; Rankings::~Rankings() = default;
diff --git a/net/disk_cache/blockfile/rankings.h b/net/disk_cache/blockfile/rankings.h index 6f5b79c3..e942120 100644 --- a/net/disk_cache/blockfile/rankings.h +++ b/net/disk_cache/blockfile/rankings.h
@@ -206,7 +206,7 @@ void IncrementCounter(List list); void DecrementCounter(List list); - bool init_; + bool init_ = false; bool count_lists_; Addr heads_[LAST_ELEMENT]; Addr tails_[LAST_ELEMENT];
diff --git a/net/disk_cache/blockfile/sparse_control.cc b/net/disk_cache/blockfile/sparse_control.cc index 56a5026..f797e63 100644 --- a/net/disk_cache/blockfile/sparse_control.cc +++ b/net/disk_cache/blockfile/sparse_control.cc
@@ -68,7 +68,7 @@ public disk_cache::FileIOCallback { public: ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name) - : backend_(backend->GetWeakPtr()), name_(name), signature_(0) {} + : backend_(backend->GetWeakPtr()), name_(name) {} ChildrenDeleter(const ChildrenDeleter&) = delete; ChildrenDeleter& operator=(const ChildrenDeleter&) = delete; @@ -89,7 +89,7 @@ base::WeakPtr<disk_cache::BackendImpl> backend_; std::string name_; disk_cache::Bitmap children_map_; - int64_t signature_; + int64_t signature_ = 0; std::unique_ptr<char[]> buffer_; }; @@ -203,18 +203,7 @@ SparseControl::SparseControl(EntryImpl* entry) : entry_(entry), child_(nullptr), - operation_(kNoOperation), - pending_(false), - finished_(false), - init_(false), - range_found_(false), - abort_(false), - child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32), - offset_(0), - buf_len_(0), - child_offset_(0), - child_len_(0), - result_(0) { + child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32) { memset(&sparse_header_, 0, sizeof(sparse_header_)); memset(&child_data_, 0, sizeof(child_data_)); }
diff --git a/net/disk_cache/blockfile/sparse_control.h b/net/disk_cache/blockfile/sparse_control.h index 30cc6a3..1ddcb39 100644 --- a/net/disk_cache/blockfile/sparse_control.h +++ b/net/disk_cache/blockfile/sparse_control.h
@@ -157,12 +157,12 @@ raw_ptr<EntryImpl> entry_; // The sparse entry. scoped_refptr<EntryImpl> child_; // The current child entry. - SparseOperation operation_; - bool pending_; // True if any child IO operation returned pending. - bool finished_; - bool init_; - bool range_found_; // True if GetAvailableRange found something. - bool abort_; // True if we should abort the current operation ASAP. + SparseOperation operation_ = kNoOperation; + bool pending_ = false; // True if any child IO operation returned pending. + bool finished_ = false; + bool init_ = false; + bool range_found_ = false; // True if GetAvailableRange found something. + bool abort_ = false; // True if we should abort the current operation ASAP. SparseHeader sparse_header_; // Data about the children of entry_. Bitmap children_map_; // The actual bitmap of children. @@ -171,12 +171,12 @@ CompletionOnceCallback user_callback_; std::vector<CompletionOnceCallback> abort_callbacks_; - int64_t offset_; // Current sparse offset. + int64_t offset_ = 0; // Current sparse offset. scoped_refptr<net::DrainableIOBuffer> user_buf_; - int buf_len_; // Bytes to read or write. - int child_offset_; // Offset to use for the current child. - int child_len_; // Bytes to read or write for this child. - int result_; + int buf_len_ = 0; // Bytes to read or write. + int child_offset_ = 0; // Offset to use for the current child. + int child_len_ = 0; // Bytes to read or write for this child. + int result_ = 0; }; } // namespace disk_cache
diff --git a/net/disk_cache/blockfile/storage_block-inl.h b/net/disk_cache/blockfile/storage_block-inl.h index d83cab2..bb1ba39 100644 --- a/net/disk_cache/blockfile/storage_block-inl.h +++ b/net/disk_cache/blockfile/storage_block-inl.h
@@ -18,12 +18,7 @@ template <typename T> StorageBlock<T>::StorageBlock(MappedFile* file, Addr address) - : data_(nullptr), - file_(file), - address_(address), - modified_(false), - own_data_(false), - extended_(false) { + : data_(nullptr), file_(file), address_(address) { if (address.num_blocks() > 1) extended_ = true; DCHECK(!address.is_initialized() || sizeof(*data_) == address.BlockSize())
diff --git a/net/disk_cache/blockfile/storage_block.h b/net/disk_cache/blockfile/storage_block.h index 3166e3b..e1e3acf 100644 --- a/net/disk_cache/blockfile/storage_block.h +++ b/net/disk_cache/blockfile/storage_block.h
@@ -97,9 +97,10 @@ raw_ptr<T> data_; raw_ptr<MappedFile> file_; Addr address_; - bool modified_; - bool own_data_; // Is data_ owned by this object or shared with someone else. - bool extended_; // Used to store an entry of more than one block. + bool modified_ = false; + bool own_data_ = + false; // Is data_ owned by this object or shared with someone else. + bool extended_ = false; // Used to store an entry of more than one block. }; } // namespace disk_cache
diff --git a/net/disk_cache/disk_cache.cc b/net/disk_cache/disk_cache.cc index 771ea949..6f820bdd 100644 --- a/net/disk_cache/disk_cache.cc +++ b/net/disk_cache/disk_cache.cc
@@ -70,7 +70,7 @@ const base::FilePath path_; disk_cache::ResetHandling reset_handling_; - bool retry_; + bool retry_ = false; int64_t max_bytes_; net::CacheType type_; net::BackendType backend_type_; @@ -104,7 +104,6 @@ net::CompletionOnceCallback callback) : path_(path), reset_handling_(reset_handling), - retry_(false), max_bytes_(max_bytes), type_(type), backend_type_(backend_type),
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc index cb30c80..9d18ab21 100644 --- a/net/disk_cache/disk_cache_test_base.cc +++ b/net/disk_cache/disk_cache_test_base.cc
@@ -81,20 +81,7 @@ } DiskCacheTestWithCache::DiskCacheTestWithCache() - : cache_impl_(nullptr), - simple_cache_impl_(nullptr), - mem_cache_(nullptr), - mask_(0), - size_(0), - type_(net::DISK_CACHE), - memory_only_(false), - simple_cache_mode_(false), - simple_cache_wait_for_index_(true), - force_creation_(false), - new_eviction_(false), - first_cleanup_(true), - integrity_(true), - use_current_thread_(false) {} + : cache_impl_(nullptr), simple_cache_impl_(nullptr), mem_cache_(nullptr) {} DiskCacheTestWithCache::~DiskCacheTestWithCache() = default;
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index 3060b05..1b8ec71c 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h
@@ -202,17 +202,17 @@ raw_ptr<disk_cache::SimpleBackendImpl> simple_cache_impl_; raw_ptr<disk_cache::MemBackendImpl> mem_cache_; - uint32_t mask_; - int64_t size_; - net::CacheType type_; - bool memory_only_; - bool simple_cache_mode_; - bool simple_cache_wait_for_index_; - bool force_creation_; - bool new_eviction_; - bool first_cleanup_; - bool integrity_; - bool use_current_thread_; + uint32_t mask_ = 0; + int64_t size_ = 0; + net::CacheType type_ = net::DISK_CACHE; + bool memory_only_ = false; + bool simple_cache_mode_ = false; + bool simple_cache_wait_for_index_ = true; + bool force_creation_ = false; + bool new_eviction_ = false; + bool first_cleanup_ = true; + bool integrity_ = true; + bool use_current_thread_ = false; // This is intentionally left uninitialized, to be used by any test. bool success_;
diff --git a/net/disk_cache/disk_cache_test_util.cc b/net/disk_cache/disk_cache_test_util.cc index 6ae1262..ad1fb22 100644 --- a/net/disk_cache/disk_cache_test_util.cc +++ b/net/disk_cache/disk_cache_test_util.cc
@@ -109,13 +109,7 @@ // ----------------------------------------------------------------------- -MessageLoopHelper::MessageLoopHelper() - : num_callbacks_(0), - num_iterations_(0), - last_(0), - completed_(false), - callback_reused_error_(false), - callbacks_called_(0) {} +MessageLoopHelper::MessageLoopHelper() = default; MessageLoopHelper::~MessageLoopHelper() = default;
diff --git a/net/disk_cache/disk_cache_test_util.h b/net/disk_cache/disk_cache_test_util.h index 46ac0ac..c3586a1 100644 --- a/net/disk_cache/disk_cache_test_util.h +++ b/net/disk_cache/disk_cache_test_util.h
@@ -129,14 +129,14 @@ void TimerExpired(); std::unique_ptr<base::RunLoop> run_loop_; - int num_callbacks_; - int num_iterations_; - int last_; - bool completed_; + int num_callbacks_ = 0; + int num_iterations_ = 0; + int last_ = 0; + bool completed_ = false; // True if a callback was called/reused more than expected. - bool callback_reused_error_; - int callbacks_called_; + bool callback_reused_error_ = false; + int callbacks_called_ = 0; }; // -----------------------------------------------------------------------
diff --git a/net/disk_cache/memory/mem_backend_impl.cc b/net/disk_cache/memory/mem_backend_impl.cc index 63d62769..f59f772 100644 --- a/net/disk_cache/memory/mem_backend_impl.cc +++ b/net/disk_cache/memory/mem_backend_impl.cc
@@ -45,8 +45,6 @@ MemBackendImpl::MemBackendImpl(net::NetLog* net_log) : Backend(net::MEMORY_CACHE), custom_clock_for_testing_(nullptr), - max_size_(0), - current_size_(0), net_log_(net_log), memory_pressure_listener_( FROM_HERE,
diff --git a/net/disk_cache/memory/mem_backend_impl.h b/net/disk_cache/memory/mem_backend_impl.h index 396bba5..b0cebfb3 100644 --- a/net/disk_cache/memory/mem_backend_impl.h +++ b/net/disk_cache/memory/mem_backend_impl.h
@@ -148,8 +148,8 @@ // most recently used. base::LinkedList<MemEntryImpl> lru_list_; - int32_t max_size_; // Maximum data size for this instance. - int32_t current_size_; + int32_t max_size_ = 0; // Maximum data size for this instance. + int32_t current_size_ = 0; raw_ptr<net::NetLog> net_log_; base::OnceClosure post_cleanup_callback_;
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc index 6b3b591..cec9824 100644 --- a/net/disk_cache/simple/simple_backend_impl.cc +++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -86,15 +86,12 @@ struct BarrierContext { explicit BarrierContext(net::CompletionOnceCallback final_callback, int expected) - : final_callback_(std::move(final_callback)), - expected(expected), - count(0), - had_error(false) {} + : final_callback_(std::move(final_callback)), expected(expected) {} net::CompletionOnceCallback final_callback_; const int expected; - int count; - bool had_error; + int count = 0; + bool had_error = false; }; void BarrierCompletionCallbackImpl(
diff --git a/net/disk_cache/simple/simple_file_tracker.cc b/net/disk_cache/simple/simple_file_tracker.cc index 4b67514..45a78305 100644 --- a/net/disk_cache/simple/simple_file_tracker.cc +++ b/net/disk_cache/simple/simple_file_tracker.cc
@@ -109,7 +109,7 @@ } } -SimpleFileTracker::TrackedFiles::TrackedFiles() : in_lru(false) { +SimpleFileTracker::TrackedFiles::TrackedFiles() { std::fill(state, state + kSimpleEntryTotalFileCount, TF_NO_REGISTRATION); }
diff --git a/net/disk_cache/simple/simple_file_tracker.h b/net/disk_cache/simple/simple_file_tracker.h index 2728e557..d9bf2d0 100644 --- a/net/disk_cache/simple/simple_file_tracker.h +++ b/net/disk_cache/simple/simple_file_tracker.h
@@ -186,7 +186,7 @@ // true if position_in_lru is valid. For entries where we closed everything, // we try not to keep them in the LRU so that we don't have to constantly // rescan them. - bool in_lru; + bool in_lru = false; }; // Marks the file that was previously returned by Acquire as eligible for
diff --git a/net/disk_cache/simple/simple_index_file.cc b/net/disk_cache/simple/simple_index_file.cc index 2d4ec8c2..c60d833 100644 --- a/net/disk_cache/simple/simple_index_file.cc +++ b/net/disk_cache/simple/simple_index_file.cc
@@ -224,10 +224,7 @@ } // namespace -SimpleIndexLoadResult::SimpleIndexLoadResult() - : did_load(false), - index_write_reason(SimpleIndex::INDEX_WRITE_REASON_MAX), - flush_required(false) {} +SimpleIndexLoadResult::SimpleIndexLoadResult() = default; SimpleIndexLoadResult::~SimpleIndexLoadResult() = default;
diff --git a/net/disk_cache/simple/simple_index_file.h b/net/disk_cache/simple/simple_index_file.h index b13435b8..53cda96 100644 --- a/net/disk_cache/simple/simple_index_file.h +++ b/net/disk_cache/simple/simple_index_file.h
@@ -33,11 +33,12 @@ ~SimpleIndexLoadResult(); void Reset(); - bool did_load; + bool did_load = false; SimpleIndex::EntrySet entries; - SimpleIndex::IndexWriteToDiskReason index_write_reason; + SimpleIndex::IndexWriteToDiskReason index_write_reason = + SimpleIndex::INDEX_WRITE_REASON_MAX; SimpleIndex::IndexInitMethod init_method; - bool flush_required; + bool flush_required = false; }; // Simple Index File format is a pickle of IndexMetadata and EntryMetadata
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc index 2f45685..4102a28b 100644 --- a/net/disk_cache/simple/simple_synchronous_entry.cc +++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -116,9 +116,7 @@ class SimpleSynchronousEntry::PrefetchData final { public: explicit PrefetchData(size_t file_size) - : file_size_(file_size), - offset_in_file_(0), - earliest_requested_offset_(file_size) {} + : file_size_(file_size), earliest_requested_offset_(file_size) {} // Returns true if the specified range within the file has been completely // prefetched. Returns false if any part of the range has not been @@ -186,7 +184,7 @@ // Prefer to read the prefetch data into a stack buffer to minimize // memory pressure on the OS disk cache. base::StackVector<char, 1024> buffer_; - size_t offset_in_file_; + size_t offset_in_file_ = 0; size_t earliest_requested_offset_; }; @@ -299,10 +297,7 @@ SimpleEntryCreationResults::SimpleEntryCreationResults( SimpleEntryStat entry_stat) - : sync_entry(nullptr), - entry_stat(entry_stat), - result(net::OK), - created(false) {} + : sync_entry(nullptr), entry_stat(entry_stat) {} SimpleEntryCreationResults::~SimpleEntryCreationResults() = default; @@ -319,10 +314,7 @@ SimpleSynchronousEntry::ReadRequest::ReadRequest(int index_p, int offset_p, int buf_len_p) - : index(index_p), - offset(offset_p), - buf_len(buf_len_p), - request_update_crc(false) {} + : index(index_p), offset(offset_p), buf_len(buf_len_p) {} SimpleSynchronousEntry::WriteRequest::WriteRequest(int index_p, int offset_p,
diff --git a/net/disk_cache/simple/simple_synchronous_entry.h b/net/disk_cache/simple/simple_synchronous_entry.h index 568df6d0..bf29e5e 100644 --- a/net/disk_cache/simple/simple_synchronous_entry.h +++ b/net/disk_cache/simple/simple_synchronous_entry.h
@@ -23,6 +23,7 @@ #include "base/strings/string_piece_forward.h" #include "base/time/time.h" #include "net/base/cache_type.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/disk_cache/simple/simple_entry_format.h" #include "net/disk_cache/simple/simple_file_tracker.h" @@ -112,8 +113,8 @@ SimpleEntryStat entry_stat; int32_t computed_trailer_prefetch_size = -1; - int result; - bool created; + int result = net::OK; + bool created = false; }; struct SimpleEntryCloseResults { @@ -144,15 +145,15 @@ // Partial CRC of data immediately preceeding this read. Only relevant if // request_update_crc is set. uint32_t previous_crc32; - bool request_update_crc; + bool request_update_crc = false; bool request_verify_crc; // only relevant if request_update_crc is set }; struct ReadResult { - ReadResult() : crc_updated(false) {} + ReadResult() = default; int result; uint32_t updated_crc32; // only relevant if crc_updated set - bool crc_updated; + bool crc_updated = false; }; struct WriteRequest { @@ -173,10 +174,10 @@ }; struct WriteResult { - WriteResult() : crc_updated(false) {} + WriteResult() = default; int result; uint32_t updated_crc32; // only relevant if crc_updated set - bool crc_updated; + bool crc_updated = false; }; struct SparseRequest {
diff --git a/net/dns/address_sorter_posix_unittest.cc b/net/dns/address_sorter_posix_unittest.cc index 9a4a319..6bd613d 100644 --- a/net/dns/address_sorter_posix_unittest.cc +++ b/net/dns/address_sorter_posix_unittest.cc
@@ -43,7 +43,7 @@ class TestUDPClientSocket : public DatagramClientSocket { public: explicit TestUDPClientSocket(const AddressMapping* mapping) - : mapping_(mapping), connected_(false) {} + : mapping_(mapping) {} TestUDPClientSocket(const TestUDPClientSocket&) = delete; TestUDPClientSocket& operator=(const TestUDPClientSocket&) = delete; @@ -139,7 +139,7 @@ private: NetLogWithSource net_log_; raw_ptr<const AddressMapping> mapping_; - bool connected_; + bool connected_ = false; IPEndPoint local_endpoint_; };
diff --git a/net/dns/dns_config_service.cc b/net/dns/dns_config_service.cc index 1aafa73..d1df61f0 100644 --- a/net/dns/dns_config_service.cc +++ b/net/dns/dns_config_service.cc
@@ -30,12 +30,7 @@ DnsConfigService::DnsConfigService( base::FilePath::StringPieceType hosts_file_path, absl::optional<base::TimeDelta> config_change_delay) - : watch_failed_(false), - have_config_(false), - have_hosts_(false), - need_update_(false), - last_sent_empty_(true), - config_change_delay_(config_change_delay), + : config_change_delay_(config_change_delay), hosts_file_path_(hosts_file_path) { DETACH_FROM_SEQUENCE(sequence_checker_); }
diff --git a/net/dns/dns_config_service.h b/net/dns/dns_config_service.h index bed76def..d4aa1802 100644 --- a/net/dns/dns_config_service.h +++ b/net/dns/dns_config_service.h
@@ -205,15 +205,15 @@ // True if any of the necessary watchers failed. In that case, the service // will communicate changes via OnTimeout, but will only send empty DnsConfig. - bool watch_failed_; + bool watch_failed_ = false; // True after On*Read, before Invalidate*. Tells if the config is complete. - bool have_config_; - bool have_hosts_; + bool have_config_ = false; + bool have_hosts_ = false; // True if receiver needs to be updated when the config becomes complete. - bool need_update_; + bool need_update_ = false; // True if the last config sent was empty (instead of |dns_config_|). // Set when |timer_| expires. - bool last_sent_empty_; + bool last_sent_empty_ = true; const absl::optional<base::TimeDelta> config_change_delay_; const base::FilePath hosts_file_path_;
diff --git a/net/dns/dns_hosts.cc b/net/dns/dns_hosts.cc index 06541a7..ab2cf0d 100644 --- a/net/dns/dns_hosts.cc +++ b/net/dns/dns_hosts.cc
@@ -29,8 +29,6 @@ : text_(text), data_(text.data()), end_(text.size()), - pos_(0), - token_is_ip_(false), comma_mode_(comma_mode) {} HostsParser(const HostsParser&) = delete; @@ -127,9 +125,9 @@ const char* data_; const size_t end_; - size_t pos_; + size_t pos_ = 0; StringPiece token_; - bool token_is_ip_; + bool token_is_ip_ = false; const ParseHostsCommaMode comma_mode_; };
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc index 3a97987..8196946 100644 --- a/net/dns/dns_transaction.cc +++ b/net/dns/dns_transaction.cc
@@ -200,7 +200,6 @@ std::unique_ptr<DnsQuery> query, DnsUdpTracker* udp_tracker) : DnsAttempt(server_index), - next_state_(STATE_NONE), socket_(std::move(socket)), server_(server), query_(std::move(query)), @@ -349,7 +348,7 @@ std::move(callback_).Run(rv); } - State next_state_; + State next_state_ = STATE_NONE; base::TimeTicks start_time_; std::unique_ptr<DatagramClientSocket> socket_; @@ -649,12 +648,10 @@ std::unique_ptr<StreamSocket> socket, std::unique_ptr<DnsQuery> query) : DnsAttempt(server_index), - next_state_(STATE_NONE), socket_(std::move(socket)), query_(std::move(query)), length_buffer_( - base::MakeRefCounted<IOBufferWithSize>(sizeof(uint16_t))), - response_length_(0) {} + base::MakeRefCounted<IOBufferWithSize>(sizeof(uint16_t))) {} DnsTCPAttempt(const DnsTCPAttempt&) = delete; DnsTCPAttempt& operator=(const DnsTCPAttempt&) = delete; @@ -878,7 +875,7 @@ base::BindOnce(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); } - State next_state_; + State next_state_ = STATE_NONE; base::TimeTicks start_time_; std::unique_ptr<StreamSocket> socket_; @@ -886,7 +883,7 @@ scoped_refptr<IOBufferWithSize> length_buffer_; scoped_refptr<DrainableIOBuffer> buffer_; - uint16_t response_length_; + uint16_t response_length_ = 0; std::unique_ptr<DnsResponse> response_; CompletionOnceCallback callback_; @@ -1118,11 +1115,7 @@ secure_dns_mode_(secure_dns_mode), fast_timeout_(fast_timeout), net_log_(net_log), - qnames_initial_size_(0), - attempts_count_(0), - had_tcp_retry_(false), - resolve_context_(resolve_context->AsSafeRef()), - request_priority_(DEFAULT_PRIORITY) { + resolve_context_(resolve_context->AsSafeRef()) { DCHECK(session_.get()); DCHECK(!hostname_.empty()); DCHECK(!IsIPLiteral(hostname_)); @@ -1684,15 +1677,15 @@ // Search list of fully-qualified DNS names to query next (in DNS format). base::circular_deque<std::string> qnames_; - size_t qnames_initial_size_; + size_t qnames_initial_size_ = 0; // List of attempts for the current name. std::vector<std::unique_ptr<DnsAttempt>> attempts_; // Count of attempts, not reset when |attempts_| vector is cleared. - int attempts_count_; + int attempts_count_ = 0; // Records when an attempt was retried via TCP due to a truncation error. - bool had_tcp_retry_; + bool had_tcp_retry_ = false; // Iterator to get the index of the DNS server for each search query. std::unique_ptr<DnsServerIterator> dns_server_iterator_; @@ -1701,7 +1694,7 @@ std::unique_ptr<base::ElapsedTimer> time_from_start_; base::SafeRef<ResolveContext> resolve_context_; - RequestPriority request_priority_; + RequestPriority request_priority_ = DEFAULT_PRIORITY; THREAD_CHECKER(thread_checker_); };
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc index 67d9ff6b..43ac7d35 100644 --- a/net/dns/dns_transaction_unittest.cc +++ b/net/dns/dns_transaction_unittest.cc
@@ -443,8 +443,6 @@ ResponseModifierCallback response_modifier = ResponseModifierCallback(), UrlRequestStartedCallback on_start = UrlRequestStartedCallback()) : URLRequestJob(request), - content_length_(0), - leftover_data_len_(0), data_provider_(data_provider), response_modifier_(response_modifier), on_start_(on_start) { @@ -585,9 +583,9 @@ return data_len; } - const int content_length_; + const int content_length_ = 0; const char* leftover_data_; - int leftover_data_len_; + int leftover_data_len_ = 0; raw_ptr<SocketDataProvider> data_provider_; const ResponseModifierCallback response_modifier_; const UrlRequestStartedCallback on_start_; @@ -2354,8 +2352,7 @@ class CookieCallback { public: - CookieCallback() - : result_(false), loop_to_quit_(std::make_unique<base::RunLoop>()) {} + CookieCallback() : loop_to_quit_(std::make_unique<base::RunLoop>()) {} void SetCookieCallback(CookieAccessResult result) { result_ = result.status.IsInclude(); @@ -2380,7 +2377,7 @@ private: net::CookieList list_; - bool result_; + bool result_ = false; std::unique_ptr<base::RunLoop> loop_to_quit_; }; @@ -2548,7 +2545,7 @@ class CountingObserver : public net::NetLog::ThreadSafeObserver { public: - CountingObserver() : count_(0), dict_count_(0) {} + CountingObserver() = default; ~CountingObserver() override { if (net_log()) @@ -2566,8 +2563,8 @@ int dict_count() const { return dict_count_; } private: - int count_; - int dict_count_; + int count_ = 0; + int dict_count_ = 0; }; // Flaky on MSAN. https://crbug.com/1245953
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index dea347e..3c4ca83 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -630,8 +630,6 @@ HostCache::HostCache(size_t max_entries) : max_entries_(max_entries), - network_changes_(0), - restore_size_(0), delegate_(nullptr), tick_clock_(base::DefaultTickClock::GetInstance()) {}
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index 07637c8..70d453ef 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -526,10 +526,10 @@ // a resolved result entry. EntryMap entries_; size_t max_entries_; - int network_changes_; + int network_changes_ = 0; // Number of cache entries that were restored in the last call to // RestoreFromListValue(). Used in histograms. - size_t restore_size_; + size_t restore_size_ = 0; raw_ptr<PersistenceDelegate> delegate_; // Shared tick clock, overridden for testing.
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 599b0c4..de7c47e 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -144,8 +144,6 @@ MockHostResolverProc() : HostResolverProc(nullptr), - num_requests_waiting_(0), - num_slots_available_(0), requests_waiting_(&lock_), slots_available_(&lock_) {} @@ -273,8 +271,8 @@ mutable base::Lock lock_; std::map<ResolveKey, AddressList> rules_; CaptureList capture_list_; - unsigned num_requests_waiting_; - unsigned num_slots_available_; + unsigned num_requests_waiting_ = 0; + unsigned num_slots_available_ = 0; base::ConditionVariable requests_waiting_; base::ConditionVariable slots_available_; }; @@ -358,11 +356,7 @@ int total_attempts) : HostResolverProc(previous), attempt_number_to_resolve_(attempt_number_to_resolve), - current_attempt_number_(0), total_attempts_(total_attempts), - total_attempts_resolved_(0), - resolved_attempt_number_(0), - num_attempts_waiting_(0), all_done_(&lock_), blocked_attempt_signal_(&lock_) {} @@ -458,11 +452,11 @@ private: int attempt_number_to_resolve_; - int current_attempt_number_; // Incremented whenever Resolve is called. + int current_attempt_number_ = 0; // Incremented whenever Resolve is called. int total_attempts_; - int total_attempts_resolved_; - int resolved_attempt_number_; - int num_attempts_waiting_; + int total_attempts_resolved_ = 0; + int resolved_attempt_number_ = 0; + int num_attempts_waiting_ = 0; // All attempts wait for right attempt to be resolve. base::Lock lock_;
diff --git a/net/dns/host_resolver_proc.cc b/net/dns/host_resolver_proc.cc index a205f62..a98cbf2 100644 --- a/net/dns/host_resolver_proc.cc +++ b/net/dns/host_resolver_proc.cc
@@ -258,8 +258,7 @@ size_t in_max_retry_attempts) : resolver_proc(resolver_proc), max_retry_attempts(in_max_retry_attempts), - unresponsive_delay(kDnsDefaultUnresponsiveDelay), - retry_factor(2) { + unresponsive_delay(kDnsDefaultUnresponsiveDelay) { // Maximum of 4 retry attempts for host resolution. static const size_t kDefaultMaxRetryAttempts = 4u; if (max_retry_attempts == HostResolver::ManagerOptions::kDefaultRetryAttempts)
diff --git a/net/dns/host_resolver_proc.h b/net/dns/host_resolver_proc.h index cff9f64..2d7fd449 100644 --- a/net/dns/host_resolver_proc.h +++ b/net/dns/host_resolver_proc.h
@@ -177,7 +177,7 @@ base::TimeDelta unresponsive_delay; // Factor to grow |unresponsive_delay| when we re-re-try. - uint32_t retry_factor; + uint32_t retry_factor = 2; }; } // namespace net
diff --git a/net/dns/mdns_client_impl.cc b/net/dns/mdns_client_impl.cc index 624912d6..2bd3b82 100644 --- a/net/dns/mdns_client_impl.cc +++ b/net/dns/mdns_client_impl.cc
@@ -62,8 +62,7 @@ MDnsConnection* connection) : socket_(std::move(socket)), connection_(connection), - response_(dns_protocol::kMaxMulticastSize), - send_in_progress_(false) {} + response_(dns_protocol::kMaxMulticastSize) {} MDnsConnection::SocketHandler::~SocketHandler() = default; @@ -496,9 +495,7 @@ name_(name), clock_(clock), client_(client), - delegate_(delegate), - started_(false), - active_refresh_(false) {} + delegate_(delegate) {} MDnsListenerImpl::~MDnsListenerImpl() { if (started_) { @@ -628,7 +625,6 @@ name_(name), callback_(callback), client_(client), - started_(false), flags_(flags) { DCHECK((flags_ & MDnsTransaction::FLAG_MASK) == flags_); DCHECK(flags_ & MDnsTransaction::QUERY_CACHE ||
diff --git a/net/dns/mdns_client_impl.h b/net/dns/mdns_client_impl.h index 2bca834d..d21c1dbb 100644 --- a/net/dns/mdns_client_impl.h +++ b/net/dns/mdns_client_impl.h
@@ -103,7 +103,7 @@ IPEndPoint recv_addr_; DnsResponse response_; IPEndPoint multicast_addr_; - bool send_in_progress_; + bool send_in_progress_ = false; base::queue<std::pair<scoped_refptr<IOBuffer>, unsigned>> send_queue_; }; @@ -293,8 +293,8 @@ base::Time last_update_; uint32_t ttl_; - bool started_; - bool active_refresh_; + bool started_ = false; + bool active_refresh_ = false; base::CancelableRepeatingClosure next_refresh_; }; @@ -360,7 +360,7 @@ raw_ptr<MDnsClientImpl> client_; - bool started_; + bool started_ = false; int flags_; };
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 6ac17d0a..6d33a9c 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -144,9 +144,7 @@ priority_(parameters_.initial_priority), host_resolver_flags_(ParametersToHostResolverFlags(parameters_)), resolve_error_info_(ResolveErrorInfo(ERR_IO_PENDING)), - id_(0), - resolver_(resolver), - complete_(false) {} + resolver_(resolver) {} RequestImpl(const RequestImpl&) = delete; RequestImpl& operator=(const RequestImpl&) = delete; @@ -382,13 +380,13 @@ ResolveErrorInfo resolve_error_info_; // Used while stored with the resolver for async resolution. Otherwise 0. - size_t id_; + size_t id_ = 0; CompletionOnceCallback callback_; // Use a WeakPtr as the resolver may be destroyed while there are still // outstanding request objects. base::WeakPtr<MockHostResolverBase> resolver_; - bool complete_; + bool complete_ = false; }; class MockHostResolverBase::ProbeRequestImpl @@ -882,11 +880,7 @@ MockHostResolverBase::MockHostResolverBase(bool use_caching, int cache_invalidation_num, RuleResolver rule_resolver) - : last_request_priority_(DEFAULT_PRIORITY), - last_secure_dns_policy_(SecureDnsPolicy::kAllow), - synchronous_mode_(false), - ondemand_mode_(false), - rule_resolver_(std::move(rule_resolver)), + : rule_resolver_(std::move(rule_resolver)), initial_cache_invalidation_num_(cache_invalidation_num), tick_clock_(base::DefaultTickClock::GetInstance()), state_(base::MakeRefCounted<State>()) { @@ -1147,8 +1141,7 @@ RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous, bool allow_fallback) - : HostResolverProc(previous, allow_fallback), - modifications_allowed_(true) {} + : HostResolverProc(previous, allow_fallback) {} void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern, const std::string& replacement) {
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h index fb00c7b7..06f57b1 100644 --- a/net/dns/mock_host_resolver.h +++ b/net/dns/mock_host_resolver.h
@@ -413,11 +413,11 @@ void AddListener(MdnsListenerImpl* listener); void RemoveCancelledListener(MdnsListenerImpl* listener); - RequestPriority last_request_priority_; + RequestPriority last_request_priority_ = DEFAULT_PRIORITY; absl::optional<NetworkIsolationKey> last_request_network_isolation_key_; - SecureDnsPolicy last_secure_dns_policy_; - bool synchronous_mode_; - bool ondemand_mode_; + SecureDnsPolicy last_secure_dns_policy_ = SecureDnsPolicy::kAllow; + bool synchronous_mode_ = false; + bool ondemand_mode_ = false; RuleResolver rule_resolver_; std::unique_ptr<HostCache> cache_; @@ -626,7 +626,7 @@ base::Lock rule_lock_; // Whether changes are allowed. - bool modifications_allowed_; + bool modifications_allowed_ = true; }; // Create rules that map all requests to localhost.
diff --git a/net/dns/record_rdata.cc b/net/dns/record_rdata.cc index 26b46cb..8e969a1 100644 --- a/net/dns/record_rdata.cc +++ b/net/dns/record_rdata.cc
@@ -54,8 +54,7 @@ } } -SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) { -} +SrvRecordRdata::SrvRecordRdata() = default; SrvRecordRdata::~SrvRecordRdata() = default;
diff --git a/net/dns/record_rdata.h b/net/dns/record_rdata.h index 8e4b4e6f..6097b96b 100644 --- a/net/dns/record_rdata.h +++ b/net/dns/record_rdata.h
@@ -68,9 +68,9 @@ private: SrvRecordRdata(); - uint16_t priority_; - uint16_t weight_; - uint16_t port_; + uint16_t priority_ = 0; + uint16_t weight_ = 0; + uint16_t port_ = 0; std::string target_; };
diff --git a/net/dns/resolve_context.cc b/net/dns/resolve_context.cc index 1eca1bc..52ffae34 100644 --- a/net/dns/resolve_context.cc +++ b/net/dns/resolve_context.cc
@@ -119,7 +119,7 @@ ResolveContext::ServerStats::ServerStats( std::unique_ptr<base::SampleVector> buckets) - : last_failure_count(0), rtt_histogram(std::move(buckets)) {} + : rtt_histogram(std::move(buckets)) {} ResolveContext::ServerStats::ServerStats(ServerStats&&) = default;
diff --git a/net/dns/resolve_context.h b/net/dns/resolve_context.h index d9c0e756..f915332 100644 --- a/net/dns/resolve_context.h +++ b/net/dns/resolve_context.h
@@ -206,7 +206,7 @@ ~ServerStats(); // Count of consecutive failures after last success. - int last_failure_count; + int last_failure_count = 0; // True if any success has ever been recorded for this server for the // current connection.
diff --git a/net/dns/serial_worker.cc b/net/dns/serial_worker.cc index 5a3444b7f..ee0a6c3 100644 --- a/net/dns/serial_worker.cc +++ b/net/dns/serial_worker.cc
@@ -49,8 +49,7 @@ SerialWorker::SerialWorker(int max_number_of_retries, const net::BackoffEntry::Policy* backoff_policy) - : state_(State::kIdle), - max_number_of_retries_(max_number_of_retries), + : max_number_of_retries_(max_number_of_retries), backoff_entry_(backoff_policy ? backoff_policy : &kDefaultBackoffPolicy) { }
diff --git a/net/dns/serial_worker.h b/net/dns/serial_worker.h index b7076be..c226fe6 100644 --- a/net/dns/serial_worker.h +++ b/net/dns/serial_worker.h
@@ -117,7 +117,7 @@ void RerunWork(std::unique_ptr<WorkItem> work_item); - State state_; + State state_ = State::kIdle; // Max retries and backoff entry to control timing. const int max_number_of_retries_;
diff --git a/net/dns/serial_worker_unittest.cc b/net/dns/serial_worker_unittest.cc index e04b0f1..d5e7e7f 100644 --- a/net/dns/serial_worker_unittest.cc +++ b/net/dns/serial_worker_unittest.cc
@@ -168,8 +168,7 @@ work_allowed_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), work_called_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - work_running_(false) {} + base::WaitableEvent::InitialState::NOT_SIGNALED) {} // Helpers for tests. @@ -212,7 +211,7 @@ base::WaitableEvent work_called_; // Protected by read_lock_. Used to verify that read calls are serialized. - bool work_running_; + bool work_running_ = false; base::Lock work_lock_; int work_finished_calls_ = 0;
diff --git a/net/extras/preload_data/decoder.cc b/net/extras/preload_data/decoder.cc index 6fa8122..3db5c680 100644 --- a/net/extras/preload_data/decoder.cc +++ b/net/extras/preload_data/decoder.cc
@@ -11,11 +11,7 @@ namespace extras { PreloadDecoder::BitReader::BitReader(const uint8_t* bytes, size_t num_bits) - : bytes_(bytes), - num_bits_(num_bits), - num_bytes_((num_bits + 7) / 8), - current_byte_index_(0), - num_bits_used_(8) {} + : bytes_(bytes), num_bits_(num_bits), num_bytes_((num_bits + 7) / 8) {} // Next sets |*out| to the next bit from the input. It returns false if no // more bits are available or true otherwise.
diff --git a/net/extras/preload_data/decoder.h b/net/extras/preload_data/decoder.h index 84fa144..b6076ac 100644 --- a/net/extras/preload_data/decoder.h +++ b/net/extras/preload_data/decoder.h
@@ -79,12 +79,12 @@ const size_t num_bits_; const size_t num_bytes_; // current_byte_index_ contains the current byte offset in |bytes_|. - size_t current_byte_index_; + size_t current_byte_index_ = 0; // current_byte_ contains the current byte of the input. uint8_t current_byte_; // num_bits_used_ contains the number of bits of |current_byte_| that have // been read. - unsigned num_bits_used_; + unsigned num_bits_used_ = 8; }; // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc index 058bae6e..945082c 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -263,10 +263,7 @@ kCompatibleVersionNumber, std::move(background_task_runner), std::move(client_task_runner)), - num_pending_(0), restore_old_session_cookies_(restore_old_session_cookies), - num_priority_waiting_(0), - total_priority_requests_(0), crypto_(crypto_delegate) {} Backend(const Backend&) = delete; @@ -401,7 +398,7 @@ typedef std::map<CanonicalCookie::UniqueCookieKey, PendingOperationsForKey> PendingOperationsMap; PendingOperationsMap pending_ GUARDED_BY(lock_); - PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_); + PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_) = 0; // Guard |cookies_|, |pending_|, |num_pending_|. base::Lock lock_; @@ -423,9 +420,9 @@ // Guards the following metrics-related properties (only accessed when // starting/completing priority loads or completing the total load). base::Lock metrics_lock_; - int num_priority_waiting_ GUARDED_BY(metrics_lock_); + int num_priority_waiting_ GUARDED_BY(metrics_lock_) = 0; // The total number of priority requests. - int total_priority_requests_ GUARDED_BY(metrics_lock_); + int total_priority_requests_ GUARDED_BY(metrics_lock_) = 0; // The time when |num_priority_waiting_| incremented to 1. base::Time current_priority_wait_start_ GUARDED_BY(metrics_lock_); // The cumulative duration of time when |num_priority_waiting_| was greater
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc index e48be61..f4e67841 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
@@ -58,8 +58,7 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test { public: SQLitePersistentCookieStorePerfTest() - : seed_multiple_(1), - test_start_(base::Time::Now()), + : test_start_(base::Time::Now()), loaded_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), key_loaded_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, @@ -146,7 +145,7 @@ } protected: - int seed_multiple_; + int seed_multiple_ = 1; base::Time test_start_; base::test::TaskEnvironment task_environment_; const scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc index bfe43d4d..6d6e470 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -65,7 +65,7 @@ bool DecryptString(const std::string& ciphertext, std::string* plaintext) override; - bool should_encrypt_; + bool should_encrypt_ = true; private: std::unique_ptr<crypto::SymmetricKey> key_; @@ -73,8 +73,7 @@ }; CookieCryptor::CookieCryptor() - : should_encrypt_(true), - key_(crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2( + : key_(crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2( crypto::SymmetricKey::AES, "password", "saltiest",
diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc index 21fca6e..e1fa9d9 100644 --- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc +++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc
@@ -144,8 +144,7 @@ kCurrentVersionNumber, kCompatibleVersionNumber, background_task_runner, - client_task_runner), - num_pending_(0) {} + client_task_runner) {} Backend(const Backend&) = delete; Backend& operator=(const Backend&) = delete; @@ -302,7 +301,7 @@ // Total number of pending operations (may not match the sum of the number of // elements in the pending operations queues, due to operation coalescing). - size_t num_pending_ GUARDED_BY(lock_); + size_t num_pending_ GUARDED_BY(lock_) = 0; // Queue of pending operations pertaining to NEL policies, keyed on origin. QueueType<NetworkErrorLoggingService::NelPolicyKey, NelPolicyInfo>
diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc index 283d1a14..f7cc3a2 100644 --- a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc +++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
@@ -28,8 +28,6 @@ scoped_refptr<base::SequencedTaskRunner> client_task_runner) : path_(path), histogram_tag_(std::move(histogram_tag)), - initialized_(false), - corruption_detected_(false), current_version_number_(current_version_number), compatible_version_number_(compatible_version_number), background_task_runner_(std::move(background_task_runner)),
diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.h b/net/extras/sqlite/sqlite_persistent_store_backend_base.h index 09c8374..9f391f2 100644 --- a/net/extras/sqlite/sqlite_persistent_store_backend_base.h +++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.h
@@ -174,10 +174,10 @@ const std::string histogram_tag_; // Whether the database has been initialized. - bool initialized_; + bool initialized_ = false; // Whether the KillDatabase callback has been scheduled. - bool corruption_detected_; + bool corruption_detected_ = false; // Current version number of the database. Must be greater than 0. const int current_version_number_;
diff --git a/net/filter/brotli_source_stream.cc b/net/filter/brotli_source_stream.cc index 8adf3bf..5e708779 100644 --- a/net/filter/brotli_source_stream.cc +++ b/net/filter/brotli_source_stream.cc
@@ -23,12 +23,7 @@ class BrotliSourceStream : public FilterSourceStream { public: explicit BrotliSourceStream(std::unique_ptr<SourceStream> upstream) - : FilterSourceStream(SourceStream::TYPE_BROTLI, std::move(upstream)), - decoding_status_(DecodingStatus::DECODING_IN_PROGRESS), - used_memory_(0), - used_memory_maximum_(0), - consumed_bytes_(0), - produced_bytes_(0) { + : FilterSourceStream(SourceStream::TYPE_BROTLI, std::move(upstream)) { brotli_state_ = BrotliDecoderCreateInstance(AllocateMemory, FreeMemory, this); CHECK(brotli_state_); @@ -169,12 +164,12 @@ raw_ptr<BrotliDecoderState> brotli_state_; - DecodingStatus decoding_status_; + DecodingStatus decoding_status_ = DecodingStatus::DECODING_IN_PROGRESS; - size_t used_memory_; - size_t used_memory_maximum_; - size_t consumed_bytes_; - size_t produced_bytes_; + size_t used_memory_ = 0; + size_t used_memory_maximum_ = 0; + size_t consumed_bytes_ = 0; + size_t produced_bytes_ = 0; }; } // namespace
diff --git a/net/filter/filter_source_stream.cc b/net/filter/filter_source_stream.cc index 6691053f..f3b00880 100644 --- a/net/filter/filter_source_stream.cc +++ b/net/filter/filter_source_stream.cc
@@ -30,11 +30,7 @@ FilterSourceStream::FilterSourceStream(SourceType type, std::unique_ptr<SourceStream> upstream) - : SourceStream(type), - upstream_(std::move(upstream)), - next_state_(STATE_NONE), - output_buffer_size_(0), - upstream_end_reached_(false) { + : SourceStream(type), upstream_(std::move(upstream)) { DCHECK(upstream_); }
diff --git a/net/filter/filter_source_stream.h b/net/filter/filter_source_stream.h index a62509e..6450a55f 100644 --- a/net/filter/filter_source_stream.h +++ b/net/filter/filter_source_stream.h
@@ -97,7 +97,7 @@ // |upstream_| to |this_|. std::unique_ptr<SourceStream> upstream_; - State next_state_; + State next_state_ = STATE_NONE; // Buffer for reading data out of |upstream_| and then for use by |this| // before the filtered data is returned through Read(). @@ -110,11 +110,11 @@ // Not null if there is a pending Read. scoped_refptr<IOBuffer> output_buffer_; - int output_buffer_size_; + int output_buffer_size_ = 0; CompletionOnceCallback callback_; // Reading from |upstream_| has returned 0 byte or an error code. - bool upstream_end_reached_; + bool upstream_end_reached_ = false; }; } // namespace net
diff --git a/net/filter/filter_source_stream_unittest.cc b/net/filter/filter_source_stream_unittest.cc index f21fc96..bba8fab 100644 --- a/net/filter/filter_source_stream_unittest.cc +++ b/net/filter/filter_source_stream_unittest.cc
@@ -177,8 +177,7 @@ NoOutputSourceStream(std::unique_ptr<SourceStream> upstream, size_t expected_input_size) : TestFilterSourceStreamBase(std::move(upstream)), - expected_input_size_(expected_input_size), - consumed_all_input_(false) {} + expected_input_size_(expected_input_size) {} NoOutputSourceStream(const NoOutputSourceStream&) = delete; NoOutputSourceStream& operator=(const NoOutputSourceStream&) = delete; @@ -201,7 +200,7 @@ private: // Expected remaining bytes to be received from |upstream|. int expected_input_size_; - bool consumed_all_input_; + bool consumed_all_input_ = false; }; // A FilterSourceStream return an error code in FilterData().
diff --git a/net/filter/gzip_source_stream.cc b/net/filter/gzip_source_stream.cc index 32b89e2..e68bd1a 100644 --- a/net/filter/gzip_source_stream.cc +++ b/net/filter/gzip_source_stream.cc
@@ -53,10 +53,7 @@ GzipSourceStream::GzipSourceStream(std::unique_ptr<SourceStream> upstream, SourceStream::SourceType type) - : FilterSourceStream(type, std::move(upstream)), - gzip_footer_bytes_left_(0), - input_state_(STATE_START), - replay_state_(STATE_COMPRESSED_BODY) {} + : FilterSourceStream(type, std::move(upstream)) {} bool GzipSourceStream::Init() { zlib_stream_ = std::make_unique<z_stream>();
diff --git a/net/filter/gzip_source_stream.h b/net/filter/gzip_source_stream.h index 5774d0a..80633e4 100644 --- a/net/filter/gzip_source_stream.h +++ b/net/filter/gzip_source_stream.h
@@ -102,13 +102,13 @@ GZipHeader gzip_header_; // Tracks how many bytes of gzip footer are yet to be filtered. - size_t gzip_footer_bytes_left_; + size_t gzip_footer_bytes_left_ = 0; // Tracks the state of the input stream. - InputState input_state_; + InputState input_state_ = STATE_START; // Used when replaying data. - InputState replay_state_; + InputState replay_state_ = STATE_COMPRESSED_BODY; }; } // namespace net
diff --git a/net/log/file_net_log_observer.cc b/net/log/file_net_log_observer.cc index bde6ccc..f92b834 100644 --- a/net/log/file_net_log_observer.cc +++ b/net/log/file_net_log_observer.cc
@@ -173,7 +173,7 @@ // runner's local queue is swapped with the shared write queue. // // |lock_| must be acquired to read or write to this. - uint64_t memory_; + uint64_t memory_ = 0; // Indicates the maximum amount of memory that the |queue_| is allowed to // use. @@ -317,7 +317,7 @@ // Counter for the events file currently being written into. See // FileNumberToIndex() for an explanation of what "number" vs "index" mean. - size_t current_event_file_number_; + size_t current_event_file_number_ = 0; // Indicates the maximum size of each individual events file. May be kNoLimit // to indicate that it can grow arbitrarily large. @@ -325,7 +325,7 @@ // Whether any bytes were written for events. This is used to properly format // JSON (events list shouldn't end with a comma). - bool wrote_event_bytes_; + bool wrote_event_bytes_ = false; // Task runner for doing file operations. const scoped_refptr<base::SequencedTaskRunner> task_runner_; @@ -516,7 +516,7 @@ } FileNetLogObserver::WriteQueue::WriteQueue(uint64_t memory_max) - : memory_(0), memory_max_(memory_max) {} + : memory_max_(memory_max) {} size_t FileNetLogObserver::WriteQueue::AddEntryToQueue( std::unique_ptr<std::string> event) { @@ -554,9 +554,7 @@ : final_log_path_(log_path), inprogress_dir_path_(inprogress_dir_path), total_num_event_files_(total_num_event_files), - current_event_file_number_(0), max_event_file_size_(max_event_file_size), - wrote_event_bytes_(false), task_runner_(std::move(task_runner)) { DCHECK_EQ(pre_existing_log_file.has_value(), log_path.empty()); DCHECK_EQ(IsBounded(), !inprogress_dir_path.empty());
diff --git a/net/log/net_log.cc b/net/log/net_log.cc index dd76223..2bb696e 100644 --- a/net/log/net_log.cc +++ b/net/log/net_log.cc
@@ -14,8 +14,7 @@ namespace net { -NetLog::ThreadSafeObserver::ThreadSafeObserver() - : capture_mode_(NetLogCaptureMode::kDefault), net_log_(nullptr) {} +NetLog::ThreadSafeObserver::ThreadSafeObserver() : net_log_(nullptr) {} NetLog::ThreadSafeObserver::~ThreadSafeObserver() { // Make sure we aren't watching a NetLog on destruction. Because the NetLog
diff --git a/net/log/net_log.h b/net/log/net_log.h index 9a6fc19..a89dbc56 100644 --- a/net/log/net_log.h +++ b/net/log/net_log.h
@@ -136,7 +136,7 @@ friend class NetLog; // Both of these values are only modified by the NetLog. - NetLogCaptureMode capture_mode_; + NetLogCaptureMode capture_mode_ = NetLogCaptureMode::kDefault; raw_ptr<NetLog> net_log_; };
diff --git a/net/log/net_log_unittest.cc b/net/log/net_log_unittest.cc index 7ef0ca73..b0de08e 100644 --- a/net/log/net_log_unittest.cc +++ b/net/log/net_log_unittest.cc
@@ -186,7 +186,7 @@ class CountingObserver : public NetLog::ThreadSafeObserver { public: - CountingObserver() : count_(0) {} + CountingObserver() = default; ~CountingObserver() override { if (net_log()) @@ -198,7 +198,7 @@ int count() const { return count_; } private: - int count_; + int count_ = 0; }; class LoggingObserver : public NetLog::ThreadSafeObserver {
diff --git a/net/network_error_logging/mock_persistent_nel_store.cc b/net/network_error_logging/mock_persistent_nel_store.cc index 468c241..1d252d5 100644 --- a/net/network_error_logging/mock_persistent_nel_store.cc +++ b/net/network_error_logging/mock_persistent_nel_store.cc
@@ -50,8 +50,7 @@ return !(lhs == rhs); } -MockPersistentNelStore::MockPersistentNelStore() - : load_started_(false), policy_count_(0), queued_policy_count_delta_(0) {} +MockPersistentNelStore::MockPersistentNelStore() = default; MockPersistentNelStore::~MockPersistentNelStore() = default;
diff --git a/net/network_error_logging/mock_persistent_nel_store.h b/net/network_error_logging/mock_persistent_nel_store.h index 0843586..7dc9835 100644 --- a/net/network_error_logging/mock_persistent_nel_store.h +++ b/net/network_error_logging/mock_persistent_nel_store.h
@@ -104,15 +104,15 @@ std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies_; // Set when LoadNelPolicies() is called. - bool load_started_; + bool load_started_ = false; // Simulates the total number of policies that would be stored in the store. // Updated when pre-stored policies are added, and when Flush() is called. - int policy_count_; + int policy_count_ = 0; // Simulates the delta to be added to |policy_count_| the next time Flush() is // called. Reset to 0 when Flush() is called. - int queued_policy_count_delta_; + int queued_policy_count_delta_ = 0; }; bool operator==(const MockPersistentNelStore::Command& lhs,
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc index 092b70f..37b4dee 100644 --- a/net/network_error_logging/network_error_logging_service.cc +++ b/net/network_error_logging/network_error_logging_service.cc
@@ -155,7 +155,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { public: explicit NetworkErrorLoggingServiceImpl(PersistentNelStore* store) - : store_(store), started_loading_policies_(false), initialized_(false) { + : store_(store) { if (!PoliciesArePersisted()) initialized_ = true; } @@ -319,7 +319,7 @@ // Set to true when we have told the store to load NEL policies. This is to // make sure we don't try to load policies multiple times. - bool started_loading_policies_; + bool started_loading_policies_ = false; // Set to true when the NEL service has been initialized. Before // initialization is complete, commands to the NEL service (i.e. public @@ -328,7 +328,7 @@ // there is no PersistentNelStore. If there is a store, then initialization is // complete when the NEL policies have finished being loaded from the store // (either successfully or unsuccessfully). - bool initialized_; + bool initialized_ = false; // Backlog of tasks waiting on initialization. std::vector<base::OnceClosure> task_backlog_; @@ -1043,8 +1043,6 @@ } NetworkErrorLoggingService::NetworkErrorLoggingService() - : clock_(base::DefaultClock::GetInstance()), - reporting_service_(nullptr), - shut_down_(false) {} + : clock_(base::DefaultClock::GetInstance()), reporting_service_(nullptr) {} } // namespace net
diff --git a/net/network_error_logging/network_error_logging_service.h b/net/network_error_logging/network_error_logging_service.h index ad226da..fa56764 100644 --- a/net/network_error_logging/network_error_logging_service.h +++ b/net/network_error_logging/network_error_logging_service.h
@@ -293,7 +293,7 @@ // Unowned: raw_ptr<const base::Clock> clock_; raw_ptr<ReportingService> reporting_service_; - bool shut_down_; + bool shut_down_ = false; }; // Persistent storage for NEL policies.
diff --git a/net/nqe/event_creator.cc b/net/nqe/event_creator.cc index 341d4059..f415567 100644 --- a/net/nqe/event_creator.cc +++ b/net/nqe/event_creator.cc
@@ -72,9 +72,7 @@ } // namespace -EventCreator::EventCreator(NetLogWithSource net_log) - : net_log_(net_log), - past_effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {} +EventCreator::EventCreator(NetLogWithSource net_log) : net_log_(net_log) {} EventCreator::~EventCreator() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/net/nqe/event_creator.h b/net/nqe/event_creator.h index a63aa7b..7a614cb 100644 --- a/net/nqe/event_creator.h +++ b/net/nqe/event_creator.h
@@ -44,7 +44,8 @@ NetLogWithSource net_log_; // The effective connection type when the net log event was last added. - EffectiveConnectionType past_effective_connection_type_; + EffectiveConnectionType past_effective_connection_type_ = + EFFECTIVE_CONNECTION_TYPE_UNKNOWN; // The network quality when the net log event was last added. NetworkQuality past_network_quality_;
diff --git a/net/nqe/network_qualities_prefs_manager_unittest.cc b/net/nqe/network_qualities_prefs_manager_unittest.cc index f3b78412..d1e484da 100644 --- a/net/nqe/network_qualities_prefs_manager_unittest.cc +++ b/net/nqe/network_qualities_prefs_manager_unittest.cc
@@ -27,7 +27,7 @@ class TestPrefDelegate : public NetworkQualitiesPrefsManager::PrefDelegate { public: - TestPrefDelegate() : write_count_(0), read_count_(0) {} + TestPrefDelegate() = default; TestPrefDelegate(const TestPrefDelegate&) = delete; TestPrefDelegate& operator=(const TestPrefDelegate&) = delete; @@ -63,8 +63,8 @@ private: // Number of times prefs were written and read, respectively.. - size_t write_count_; - size_t read_count_; + size_t write_count_ = 0; + size_t read_count_ = 0; // Current value of the prefs. base::Value::Dict value_;
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index f5f02357..376fccd 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -93,9 +93,6 @@ std::unique_ptr<NetworkQualityEstimatorParams> params, NetLog* net_log) : params_(std::move(params)), - end_to_end_rtt_observation_count_at_last_ect_computation_(0), - use_localhost_requests_(false), - disable_offline_check_(false), tick_clock_(base::DefaultTickClock::GetInstance()), last_connection_change_(tick_clock_->NowTicks()), current_network_id_(nqe::internal::NetworkID( @@ -123,16 +120,7 @@ tick_clock_, params_->weight_multiplier_per_second(), 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/)}, - effective_connection_type_at_last_main_frame_( - EFFECTIVE_CONNECTION_TYPE_UNKNOWN), effective_connection_type_recomputation_interval_(base::Seconds(10)), - rtt_observations_size_at_last_ect_computation_(0), - throughput_observations_size_at_last_ect_computation_(0), - transport_rtt_observation_count_last_ect_computation_(0), - new_rtt_observations_since_last_ect_computation_(0), - new_throughput_observations_since_last_ect_computation_(0), - effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), - cached_estimate_applied_(false), net_log_(NetLogWithSource::Make( net_log, net::NetLogSourceType::NETWORK_QUALITY_ESTIMATOR)),
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h index 1f1fa80..d0f263c 100644 --- a/net/nqe/network_quality_estimator.h +++ b/net/nqe/network_quality_estimator.h
@@ -414,7 +414,7 @@ const std::unique_ptr<NetworkQualityEstimatorParams> params_; // Number of end to end RTT samples available when the ECT was last computed. - size_t end_to_end_rtt_observation_count_at_last_ect_computation_; + size_t end_to_end_rtt_observation_count_at_last_ect_computation_ = 0; // Current count of active peer to peer connections. uint32_t p2p_connections_count_ = 0u; @@ -542,12 +542,12 @@ // Determines if the requests to local host can be used in estimating the // network quality. Set to true only for tests. - bool use_localhost_requests_; + bool use_localhost_requests_ = false; // When set to true, the device offline check is disabled when computing the // effective connection type or when writing the prefs. Set to true only for // testing. - bool disable_offline_check_; + bool disable_offline_check_ = false; // Tick clock used by the network quality estimator. raw_ptr<const base::TickClock> tick_clock_; @@ -576,7 +576,8 @@ // Estimated network quality when the transaction for the last main frame // request was started. nqe::internal::NetworkQuality estimated_quality_at_last_main_frame_; - EffectiveConnectionType effective_connection_type_at_last_main_frame_; + EffectiveConnectionType effective_connection_type_at_last_main_frame_ = + EFFECTIVE_CONNECTION_TYPE_UNKNOWN; // Observer lists for round trip times and throughput measurements. base::ObserverList<RTTObserver>::Unchecked rtt_observer_list_; @@ -599,19 +600,19 @@ // Number of RTT and bandwidth samples available when effective connection // type was last recomputed. - size_t rtt_observations_size_at_last_ect_computation_; - size_t throughput_observations_size_at_last_ect_computation_; + size_t rtt_observations_size_at_last_ect_computation_ = 0; + size_t throughput_observations_size_at_last_ect_computation_ = 0; // Number of transport RTT samples available when the ECT was last computed. - size_t transport_rtt_observation_count_last_ect_computation_; + size_t transport_rtt_observation_count_last_ect_computation_ = 0; // Number of RTT observations received since the effective connection type was // last computed. - size_t new_rtt_observations_since_last_ect_computation_; + size_t new_rtt_observations_since_last_ect_computation_ = 0; // Number of throughput observations received since the effective connection // type was last computed. - size_t new_throughput_observations_since_last_ect_computation_; + size_t new_throughput_observations_since_last_ect_computation_ = 0; // Current estimate of the network quality. nqe::internal::NetworkQuality network_quality_; @@ -621,14 +622,15 @@ // events. It is also updated every time there is network traffic (provided // the last computation was more than // |effective_connection_type_recomputation_interval_| ago). - EffectiveConnectionType effective_connection_type_; + EffectiveConnectionType effective_connection_type_ = + EFFECTIVE_CONNECTION_TYPE_UNKNOWN; // Stores the qualities of different networks. std::unique_ptr<nqe::internal::NetworkQualityStore> network_quality_store_; // True if a cached RTT or throughput estimate was available and the // corresponding observation has been added on the current network. - bool cached_estimate_applied_; + bool cached_estimate_applied_ = false; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc index 5f8d556d..2cb3bfa 100644 --- a/net/nqe/network_quality_estimator_params.cc +++ b/net/nqe/network_quality_estimator_params.cc
@@ -431,7 +431,6 @@ GetPersistentCacheReadingEnabled(params_)), min_socket_watcher_notification_interval_( GetMinSocketWatcherNotificationInterval(params_)), - lower_bound_http_rtt_transport_rtt_multiplier_(1.0), upper_bound_http_rtt_endtoend_rtt_multiplier_( GetDoubleValueForVariationParamWithDefaultValue( params_, @@ -482,19 +481,16 @@ params_, "socket_watchers_min_notification_interval_msec", 200))), - use_end_to_end_rtt_(true), upper_bound_typical_kbps_multiplier_( GetDoubleValueForVariationParamWithDefaultValue( params_, "upper_bound_typical_kbps_multiplier", 3.5)), - adjust_rtt_based_on_rtt_counts_( GetStringValueForVariationParamWithDefaultValue( params_, "adjust_rtt_based_on_rtt_counts", - "false") == "true"), - use_small_responses_(false) { + "false") == "true") { DCHECK(hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ == -1 || hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ > 0); DCHECK(hanging_request_http_rtt_upper_bound_http_rtt_multiplier_ == -1 ||
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h index 6872f51..3a34c0b 100644 --- a/net/nqe/network_quality_estimator_params.h +++ b/net/nqe/network_quality_estimator_params.h
@@ -272,7 +272,7 @@ const bool forced_effective_connection_type_on_cellular_only_; bool persistent_cache_reading_enabled_; const base::TimeDelta min_socket_watcher_notification_interval_; - const double lower_bound_http_rtt_transport_rtt_multiplier_; + const double lower_bound_http_rtt_transport_rtt_multiplier_ = 1.0; const double upper_bound_http_rtt_endtoend_rtt_multiplier_; const int hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_; const int hanging_request_http_rtt_upper_bound_http_rtt_multiplier_; @@ -285,11 +285,11 @@ const base::TimeDelta hanging_request_min_duration_; const bool add_default_platform_observations_; const base::TimeDelta socket_watchers_min_notification_interval_; - const bool use_end_to_end_rtt_; + const bool use_end_to_end_rtt_ = true; const double upper_bound_typical_kbps_multiplier_; const bool adjust_rtt_based_on_rtt_counts_; - bool use_small_responses_; + bool use_small_responses_ = false; // Default network quality observations obtained from |params_|. nqe::internal::NetworkQuality
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc index 9613337..db6acb0a 100644 --- a/net/nqe/network_quality_estimator_unittest.cc +++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -113,9 +113,7 @@ public: TestRTTAndThroughputEstimatesObserver() : http_rtt_(nqe::internal::InvalidRTT()), - transport_rtt_(nqe::internal::InvalidRTT()), - downstream_throughput_kbps_(nqe::internal::INVALID_RTT_THROUGHPUT), - notifications_received_(0) {} + transport_rtt_(nqe::internal::InvalidRTT()) {} // RTTAndThroughputEstimatesObserver implementation: void OnRTTOrThroughputEstimatesComputed( @@ -139,8 +137,8 @@ private: base::TimeDelta http_rtt_; base::TimeDelta transport_rtt_; - int32_t downstream_throughput_kbps_; - int notifications_received_; + int32_t downstream_throughput_kbps_ = nqe::internal::INVALID_RTT_THROUGHPUT; + int notifications_received_ = 0; }; class TestRTTObserver : public NetworkQualityEstimator::RTTObserver { @@ -2182,8 +2180,7 @@ TestNetworkQualitiesCacheObserver() : network_id_(net::NetworkChangeNotifier::CONNECTION_UNKNOWN, std::string(), - INT32_MIN), - notification_received_(0) {} + INT32_MIN) {} TestNetworkQualitiesCacheObserver(const TestNetworkQualitiesCacheObserver&) = delete; @@ -2210,7 +2207,7 @@ private: nqe::internal::NetworkID network_id_; - size_t notification_received_; + size_t notification_received_ = 0; }; TEST_F(NetworkQualityEstimatorTest, CacheObserver) {
diff --git a/net/nqe/socket_watcher.cc b/net/nqe/socket_watcher.cc index 6ad5756..09404b7c 100644 --- a/net/nqe/socket_watcher.cc +++ b/net/nqe/socket_watcher.cc
@@ -71,7 +71,6 @@ (!address_list.empty() && address_list.front().address().IsPubliclyRoutable())), tick_clock_(tick_clock), - first_quic_rtt_notification_received_(false), host_(CalculateIPHash(address_list)) { DCHECK(tick_clock_); DCHECK(last_rtt_notification_.is_null());
diff --git a/net/nqe/socket_watcher.h b/net/nqe/socket_watcher.h index 9d20409..5d3ebda 100644 --- a/net/nqe/socket_watcher.h +++ b/net/nqe/socket_watcher.h
@@ -106,7 +106,7 @@ // True if the first RTT notification from the QUIC connection has been // received. - bool first_quic_rtt_notification_received_; + bool first_quic_rtt_notification_received_ = false; // A unique identifier for the remote host that this socket connects to. const absl::optional<IPHash> host_;
diff --git a/net/nqe/socket_watcher_factory.cc b/net/nqe/socket_watcher_factory.cc index 884ea77..64b095a0 100644 --- a/net/nqe/socket_watcher_factory.cc +++ b/net/nqe/socket_watcher_factory.cc
@@ -21,7 +21,6 @@ const base::TickClock* tick_clock) : task_runner_(std::move(task_runner)), min_notification_interval_(min_notification_interval), - allow_rtt_private_address_(false), updated_rtt_observation_callback_(updated_rtt_observation_callback), should_notify_rtt_callback_(should_notify_rtt_callback), tick_clock_(tick_clock) {
diff --git a/net/nqe/socket_watcher_factory.h b/net/nqe/socket_watcher_factory.h index 80fb3c6..d3d4598 100644 --- a/net/nqe/socket_watcher_factory.h +++ b/net/nqe/socket_watcher_factory.h
@@ -87,7 +87,7 @@ // True if socket watchers constructed by this factory can use the RTT from // the sockets that are connected to the private addresses. - bool allow_rtt_private_address_; + bool allow_rtt_private_address_ = false; // Called every time a new RTT observation is available. OnUpdatedRTTAvailableCallback updated_rtt_observation_callback_;
diff --git a/net/nqe/throughput_analyzer.cc b/net/nqe/throughput_analyzer.cc index d83e6f0..08657ae4 100644 --- a/net/nqe/throughput_analyzer.cc +++ b/net/nqe/throughput_analyzer.cc
@@ -59,10 +59,6 @@ tick_clock_(tick_clock), last_connection_change_(tick_clock_->NowTicks()), window_start_time_(base::TimeTicks()), - bits_received_at_window_start_(0), - total_response_content_size_(0), - disable_throughput_measurements_(false), - use_localhost_requests_for_tests_(false), net_log_(net_log) { DCHECK(tick_clock_); DCHECK(network_quality_estimator_);
diff --git a/net/nqe/throughput_analyzer.h b/net/nqe/throughput_analyzer.h index 784f0d11..51d4cd02 100644 --- a/net/nqe/throughput_analyzer.h +++ b/net/nqe/throughput_analyzer.h
@@ -218,7 +218,7 @@ // Number of bits received prior to |start_| as reported by // NetworkActivityMonitor. - int64_t bits_received_at_window_start_; + int64_t bits_received_at_window_start_ = 0; // Container that holds active requests that reduce the accuracy of // throughput computation. These requests are not used in throughput @@ -234,7 +234,7 @@ ResponseContentSizes response_content_sizes_; // The running total of response content size for all inflight requests. - int64_t total_response_content_size_; + int64_t total_response_content_size_ = 0; // Last time when the check for hanging requests was run. base::TimeTicks last_hanging_request_check_; @@ -243,11 +243,11 @@ // observations until Chromium is restarted. This may happen if the throughput // analyzer has lost track of the requests that degrade throughput computation // accuracy. - bool disable_throughput_measurements_; + bool disable_throughput_measurements_ = false; // Determines if the requests to local host can be used in estimating the // network quality. Set to true only for tests. - bool use_localhost_requests_for_tests_; + bool use_localhost_requests_for_tests_ = false; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/net/nqe/throughput_analyzer_unittest.cc b/net/nqe/throughput_analyzer_unittest.cc index b24ca93..a156ce3a 100644 --- a/net/nqe/throughput_analyzer_unittest.cc +++ b/net/nqe/throughput_analyzer_unittest.cc
@@ -80,9 +80,7 @@ &TestThroughputAnalyzer::OnNewThroughputObservationAvailable, base::Unretained(this)), tick_clock, - NetLogWithSource::Make(NetLogSourceType::NONE)), - throughput_observations_received_(0), - bits_received_(0) {} + NetLogWithSource::Make(NetLogSourceType::NONE)) {} TestThroughputAnalyzer(const TestThroughputAnalyzer&) = delete; TestThroughputAnalyzer& operator=(const TestThroughputAnalyzer&) = delete; @@ -110,9 +108,9 @@ using internal::ThroughputAnalyzer::IsHangingWindow; private: - int throughput_observations_received_; + int throughput_observations_received_ = 0; - int64_t bits_received_; + int64_t bits_received_ = 0; }; using ThroughputAnalyzerTest = TestWithTaskEnvironment;
diff --git a/net/ntlm/ntlm_buffer_writer.cc b/net/ntlm/ntlm_buffer_writer.cc index efbbfb4..8f3f7221 100644 --- a/net/ntlm/ntlm_buffer_writer.cc +++ b/net/ntlm/ntlm_buffer_writer.cc
@@ -16,7 +16,7 @@ namespace ntlm { NtlmBufferWriter::NtlmBufferWriter(size_t buffer_len) - : buffer_(buffer_len, 0), cursor_(0) {} + : buffer_(buffer_len, 0) {} NtlmBufferWriter::~NtlmBufferWriter() = default;
diff --git a/net/ntlm/ntlm_buffer_writer.h b/net/ntlm/ntlm_buffer_writer.h index f0afd00..00745ce 100644 --- a/net/ntlm/ntlm_buffer_writer.h +++ b/net/ntlm/ntlm_buffer_writer.h
@@ -188,7 +188,7 @@ uint8_t* GetBufferPtrAtCursor() { return GetBufferPtr() + GetCursor(); } std::vector<uint8_t> buffer_; - size_t cursor_; + size_t cursor_ = 0; }; } // namespace ntlm
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.cc b/net/proxy_resolution/configured_proxy_resolution_service.cc index 04d8766..f1cab35 100644 --- a/net/proxy_resolution/configured_proxy_resolution_service.cc +++ b/net/proxy_resolution/configured_proxy_resolution_service.cc
@@ -419,10 +419,7 @@ class ConfiguredProxyResolutionService::InitProxyResolver { public: InitProxyResolver() - : proxy_resolver_factory_(nullptr), - proxy_resolver_(nullptr), - next_state_(State::kNone), - quick_check_enabled_(true) {} + : proxy_resolver_factory_(nullptr), proxy_resolver_(nullptr) {} InitProxyResolver(const InitProxyResolver&) = delete; InitProxyResolver& operator=(const InitProxyResolver&) = delete; @@ -607,8 +604,8 @@ std::unique_ptr<ProxyResolverFactory::Request> create_resolver_request_; raw_ptr<std::unique_ptr<ProxyResolver>> proxy_resolver_; CompletionOnceCallback callback_; - State next_state_; - bool quick_check_enabled_; + State next_state_ = State::kNone; + bool quick_check_enabled_ = true; }; // ConfiguredProxyResolutionService::PacFileDeciderPoller @@ -837,8 +834,6 @@ bool quick_check_enabled) : config_service_(std::move(config_service)), resolver_factory_(std::move(resolver_factory)), - current_state_(STATE_NONE), - permanent_error_(OK), net_log_(net_log), stall_proxy_auto_config_delay_( base::Milliseconds(kDelayAfterNetworkChangesMs)),
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.h b/net/proxy_resolution/configured_proxy_resolution_service.h index 054b75d..83b5ee33 100644 --- a/net/proxy_resolution/configured_proxy_resolution_service.h +++ b/net/proxy_resolution/configured_proxy_resolution_service.h
@@ -19,6 +19,7 @@ #include "base/threading/thread_checker.h" #include "net/base/completion_once_callback.h" #include "net/base/load_states.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/network_change_notifier.h" #include "net/log/net_log_with_source.h" @@ -392,11 +393,11 @@ // Helper to poll the PAC script for changes. std::unique_ptr<PacFileDeciderPoller> script_poller_; - State current_state_; + State current_state_ = STATE_NONE; // Either OK or an ERR_* value indicating that a permanent error (e.g. // failed to fetch the PAC script) prevents proxy resolution. - int permanent_error_; + int permanent_error_ = OK; // This is the log where any events generated by |init_proxy_resolver_| are // sent to.
diff --git a/net/proxy_resolution/mock_pac_file_fetcher.cc b/net/proxy_resolution/mock_pac_file_fetcher.cc index 77436d3..3aebe8bb 100644 --- a/net/proxy_resolution/mock_pac_file_fetcher.cc +++ b/net/proxy_resolution/mock_pac_file_fetcher.cc
@@ -14,8 +14,7 @@ namespace net { -MockPacFileFetcher::MockPacFileFetcher() - : pending_request_text_(nullptr), is_shutdown_(false) {} +MockPacFileFetcher::MockPacFileFetcher() : pending_request_text_(nullptr) {} MockPacFileFetcher::~MockPacFileFetcher() = default;
diff --git a/net/proxy_resolution/mock_pac_file_fetcher.h b/net/proxy_resolution/mock_pac_file_fetcher.h index 5c4f14a7..c3142a187 100644 --- a/net/proxy_resolution/mock_pac_file_fetcher.h +++ b/net/proxy_resolution/mock_pac_file_fetcher.h
@@ -46,7 +46,7 @@ CompletionOnceCallback pending_request_callback_; raw_ptr<std::u16string> pending_request_text_; base::OnceClosure on_fetch_complete_; - bool is_shutdown_; + bool is_shutdown_ = false; }; } // namespace net
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/net/proxy_resolution/multi_threaded_proxy_resolver.cc index f7dd6639..8ff6ab4 100644 --- a/net/proxy_resolution/multi_threaded_proxy_resolver.cc +++ b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
@@ -162,7 +162,7 @@ class Job : public base::RefCountedThreadSafe<Job> { public: - Job() : executor_(nullptr), was_cancelled_(false) {} + Job() : executor_(nullptr) {} void set_executor(Executor* executor) { executor_ = executor; @@ -209,7 +209,7 @@ private: raw_ptr<Executor> executor_; - bool was_cancelled_; + bool was_cancelled_ = false; }; class MultiThreadedProxyResolver::RequestImpl : public ProxyResolver::Request { @@ -281,8 +281,7 @@ results_(results), net_log_(net_log), url_(url), - network_isolation_key_(network_isolation_key), - was_waiting_for_thread_(false) { + network_isolation_key_(network_isolation_key) { DCHECK(callback_); } @@ -348,7 +347,7 @@ // Usable from within DoQuery on the worker thread. ProxyInfo results_buf_; - bool was_waiting_for_thread_; + bool was_waiting_for_thread_ = false; }; // Executor ----------------------------------------
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc index c792a46..30a80e5 100644 --- a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc +++ b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
@@ -111,7 +111,7 @@ WILL_BLOCK, }; - BlockableProxyResolver() : state_(State::NONE), condition_(&lock_) {} + BlockableProxyResolver() : condition_(&lock_) {} BlockableProxyResolver(const BlockableProxyResolver&) = delete; BlockableProxyResolver& operator=(const BlockableProxyResolver&) = delete; @@ -172,7 +172,7 @@ } private: - State state_; + State state_ = State::NONE; base::Lock lock_; base::ConditionVariable condition_; };
diff --git a/net/proxy_resolution/network_delegate_error_observer_unittest.cc b/net/proxy_resolution/network_delegate_error_observer_unittest.cc index e30b0295..e545a905 100644 --- a/net/proxy_resolution/network_delegate_error_observer_unittest.cc +++ b/net/proxy_resolution/network_delegate_error_observer_unittest.cc
@@ -23,7 +23,7 @@ class TestNetworkDelegate : public NetworkDelegateImpl { public: - TestNetworkDelegate() : got_pac_error_(false) {} + TestNetworkDelegate() = default; ~TestNetworkDelegate() override = default; bool got_pac_error() const { return got_pac_error_; } @@ -34,7 +34,7 @@ got_pac_error_ = true; } - bool got_pac_error_; + bool got_pac_error_ = false; }; // Check that the OnPACScriptError method can be called from an arbitrary
diff --git a/net/proxy_resolution/pac_file_decider.cc b/net/proxy_resolution/pac_file_decider.cc index 6b4a2f5..b779e60 100644 --- a/net/proxy_resolution/pac_file_decider.cc +++ b/net/proxy_resolution/pac_file_decider.cc
@@ -92,13 +92,8 @@ NetLog* net_log) : pac_file_fetcher_(pac_file_fetcher), dhcp_pac_file_fetcher_(dhcp_pac_file_fetcher), - current_pac_source_index_(0u), - pac_mandatory_(false), - next_state_(STATE_NONE), - net_log_( - NetLogWithSource::Make(net_log, NetLogSourceType::PAC_FILE_DECIDER)), - fetch_pac_bytes_(false), - quick_check_enabled_(true) {} + net_log_(NetLogWithSource::Make(net_log, + NetLogSourceType::PAC_FILE_DECIDER)) {} PacFileDecider::~PacFileDecider() { if (next_state_ != STATE_NONE)
diff --git a/net/proxy_resolution/pac_file_decider.h b/net/proxy_resolution/pac_file_decider.h index f9aed53b..ca8debdd 100644 --- a/net/proxy_resolution/pac_file_decider.h +++ b/net/proxy_resolution/pac_file_decider.h
@@ -186,24 +186,24 @@ CompletionOnceCallback callback_; - size_t current_pac_source_index_; + size_t current_pac_source_index_ = 0u; // Filled when the PAC script fetch completes. std::u16string pac_script_; // Flag indicating whether the caller requested a mandatory PAC script // (i.e. fallback to direct connections are prohibited). - bool pac_mandatory_; + bool pac_mandatory_ = false; // Whether we have an existing custom PAC URL. bool have_custom_pac_url_; PacSourceList pac_sources_; - State next_state_; + State next_state_ = STATE_NONE; NetLogWithSource net_log_; - bool fetch_pac_bytes_; + bool fetch_pac_bytes_ = false; base::TimeDelta wait_delay_; base::OneShotTimer wait_timer_; @@ -211,7 +211,7 @@ net::MutableNetworkTrafficAnnotationTag traffic_annotation_; // Whether to do DNS quick check - bool quick_check_enabled_; + bool quick_check_enabled_ = true; // Results. ProxyConfigWithAnnotation effective_config_;
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.cc b/net/proxy_resolution/pac_file_fetcher_impl.cc index c0ffd19..e2a9114f 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl.cc +++ b/net/proxy_resolution/pac_file_fetcher_impl.cc
@@ -318,9 +318,6 @@ PacFileFetcherImpl::PacFileFetcherImpl(URLRequestContext* url_request_context) : url_request_context_(url_request_context), buf_(base::MakeRefCounted<IOBuffer>(kBufSize)), - next_id_(0), - cur_request_id_(0), - result_code_(OK), result_text_(nullptr), max_response_bytes_(kDefaultMaxResponseBytes), max_duration_(kDefaultMaxDuration) {
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.h b/net/proxy_resolution/pac_file_fetcher_impl.h index e52fd0e..32ef8e61 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl.h +++ b/net/proxy_resolution/pac_file_fetcher_impl.h
@@ -116,7 +116,7 @@ scoped_refptr<IOBuffer> buf_; // The next ID to use for |cur_request_| (monotonically increasing). - int next_id_; + int next_id_ = 0; // The current (in progress) request, or NULL. std::unique_ptr<URLRequest> cur_request_; @@ -124,13 +124,13 @@ // State for current request (only valid when |cur_request_| is not NULL): // Unique ID for the current request. - int cur_request_id_; + int cur_request_id_ = 0; // Callback to invoke on completion of the fetch. CompletionOnceCallback callback_; // Holds the error condition that was hit on the current request, or OK. - int result_code_; + int result_code_ = OK; // Holds the bytes read so far. Will not exceed |max_response_bytes|. std::string bytes_read_so_far_;
diff --git a/net/proxy_resolution/polling_proxy_config_service.cc b/net/proxy_resolution/polling_proxy_config_service.cc index 01d66b4..a21d4cd 100644 --- a/net/proxy_resolution/polling_proxy_config_service.cc +++ b/net/proxy_resolution/polling_proxy_config_service.cc
@@ -28,11 +28,7 @@ const NetworkTrafficAnnotationTag& traffic_annotation) : get_config_func_(get_config_func), poll_interval_(poll_interval), - traffic_annotation_(traffic_annotation), - have_initialized_origin_runner_(false), - has_config_(false), - poll_task_outstanding_(false), - poll_task_queued_(false) {} + traffic_annotation_(traffic_annotation) {} // Called when the parent PollingProxyConfigService is destroyed // (observers should not be called past this point). @@ -159,10 +155,10 @@ base::Lock lock_; scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; - bool have_initialized_origin_runner_; - bool has_config_; - bool poll_task_outstanding_; - bool poll_task_queued_; + bool have_initialized_origin_runner_ = false; + bool has_config_ = false; + bool poll_task_outstanding_ = false; + bool poll_task_queued_ = false; }; void PollingProxyConfigService::AddObserver(Observer* observer) {
diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_config.cc index cf92c2c..5908492 100644 --- a/net/proxy_resolution/proxy_config.cc +++ b/net/proxy_resolution/proxy_config.cc
@@ -41,10 +41,7 @@ } // namespace -ProxyConfig::ProxyRules::ProxyRules() - : reverse_bypass(false), - type(Type::EMPTY) { -} +ProxyConfig::ProxyRules::ProxyRules() = default; ProxyConfig::ProxyRules::ProxyRules(const ProxyRules& other) = default; @@ -210,7 +207,7 @@ return nullptr; } -ProxyConfig::ProxyConfig() : auto_detect_(false), pac_mandatory_(false) {} +ProxyConfig::ProxyConfig() = default; ProxyConfig::ProxyConfig(const ProxyConfig& config) = default;
diff --git a/net/proxy_resolution/proxy_config.h b/net/proxy_resolution/proxy_config.h index dac5572..17e364c 100644 --- a/net/proxy_resolution/proxy_config.h +++ b/net/proxy_resolution/proxy_config.h
@@ -117,9 +117,9 @@ ProxyBypassRules bypass_rules; // Reverse the meaning of |bypass_rules|. - bool reverse_bypass; + bool reverse_bypass = false; - Type type; + Type type = Type::EMPTY; // Set if |type| is Type::PROXY_LIST. ProxyList single_proxies; @@ -225,7 +225,7 @@ private: // True if the proxy configuration should be auto-detected. - bool auto_detect_; + bool auto_detect_ = false; // True if the proxy configuration was created from system settings. bool from_system_ = false; @@ -235,7 +235,7 @@ // If true, blocks all traffic in case fetching the PAC script from |pac_url_| // fails. Only valid if |pac_url_| is non-empty. - bool pac_mandatory_; + bool pac_mandatory_ = false; // Manual proxy settings. ProxyRules proxy_rules_;
diff --git a/net/proxy_resolution/proxy_config_service_linux.cc b/net/proxy_resolution/proxy_config_service_linux.cc index 1a3b7d4..e2448a7 100644 --- a/net/proxy_resolution/proxy_config_service_linux.cc +++ b/net/proxy_resolution/proxy_config_service_linux.cc
@@ -237,14 +237,7 @@ class SettingGetterImplGSettings : public ProxyConfigServiceLinux::SettingGetter { public: - SettingGetterImplGSettings() - : client_(nullptr), - http_client_(nullptr), - https_client_(nullptr), - ftp_client_(nullptr), - socks_client_(nullptr), - notify_delegate_(nullptr), - debounce_timer_(new base::OneShotTimer()) {} + SettingGetterImplGSettings() : debounce_timer_(new base::OneShotTimer()) {} SettingGetterImplGSettings(const SettingGetterImplGSettings&) = delete; SettingGetterImplGSettings& operator=(const SettingGetterImplGSettings&) = @@ -472,12 +465,12 @@ setting_getter->OnChangeNotification(); } - GSettings* client_; - GSettings* http_client_; - GSettings* https_client_; - GSettings* ftp_client_; - GSettings* socks_client_; - ProxyConfigServiceLinux::Delegate* notify_delegate_; + GSettings* client_ = nullptr; + GSettings* http_client_ = nullptr; + GSettings* https_client_ = nullptr; + GSettings* ftp_client_ = nullptr; + GSettings* socks_client_ = nullptr; + ProxyConfigServiceLinux::Delegate* notify_delegate_ = nullptr; std::unique_ptr<base::OneShotTimer> debounce_timer_; // Task runner for the thread that we make gsettings calls on. It should @@ -522,12 +515,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter { public: explicit SettingGetterImplKDE(base::Environment* env_var_getter) - : inotify_fd_(-1), - notify_delegate_(nullptr), - debounce_timer_(new base::OneShotTimer()), - indirect_manual_(false), - auto_no_pac_(false), - reversed_bypass_list_(false), + : debounce_timer_(new base::OneShotTimer()), env_var_getter_(env_var_getter), file_task_runner_(nullptr) { // This has to be called on the UI thread (http://crbug.com/69057). @@ -1020,14 +1008,14 @@ typedef std::map<StringListSetting, std::vector<std::string> > strings_map_type; - int inotify_fd_; + int inotify_fd_ = -1; std::unique_ptr<base::FileDescriptorWatcher::Controller> inotify_watcher_; - ProxyConfigServiceLinux::Delegate* notify_delegate_; + ProxyConfigServiceLinux::Delegate* notify_delegate_ = nullptr; std::unique_ptr<base::OneShotTimer> debounce_timer_; std::vector<base::FilePath> kde_config_dirs_; - bool indirect_manual_; - bool auto_no_pac_; - bool reversed_bypass_list_; + bool indirect_manual_ = false; + bool auto_no_pac_ = false; + bool reversed_bypass_list_ = false; // We don't own |env_var_getter_|. It's safe to hold a pointer to it, since // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the // same lifetime.
diff --git a/net/proxy_resolution/proxy_info.cc b/net/proxy_resolution/proxy_info.cc index 2396fefa..f1e2f909 100644 --- a/net/proxy_resolution/proxy_info.cc +++ b/net/proxy_resolution/proxy_info.cc
@@ -8,7 +8,7 @@ namespace net { -ProxyInfo::ProxyInfo() : did_bypass_proxy_(false) {} +ProxyInfo::ProxyInfo() = default; ProxyInfo::ProxyInfo(const ProxyInfo& other) = default;
diff --git a/net/proxy_resolution/proxy_info.h b/net/proxy_resolution/proxy_info.h index 69cae35..e2d926e 100644 --- a/net/proxy_resolution/proxy_info.h +++ b/net/proxy_resolution/proxy_info.h
@@ -203,7 +203,7 @@ MutableNetworkTrafficAnnotationTag traffic_annotation_; // Whether the proxy result represent a proxy bypass. - bool did_bypass_proxy_; + bool did_bypass_proxy_ = false; // How long it took to resolve the proxy. Times are both null if proxy was // determined synchronously without running a PAC.
diff --git a/net/quic/bidirectional_stream_quic_impl.cc b/net/quic/bidirectional_stream_quic_impl.cc index 2c70a2bd..befaf5538 100644 --- a/net/quic/bidirectional_stream_quic_impl.cc +++ b/net/quic/bidirectional_stream_quic_impl.cc
@@ -43,18 +43,7 @@ : session_(std::move(session)), stream_(nullptr), request_info_(nullptr), - delegate_(nullptr), - response_status_(OK), - negotiated_protocol_(kProtoUnknown), - read_buffer_len_(0), - headers_bytes_received_(0), - headers_bytes_sent_(0), - closed_stream_received_bytes_(0), - closed_stream_sent_bytes_(0), - closed_is_first_stream_(false), - has_sent_headers_(false), - send_request_headers_automatically_(true), - may_invoke_callbacks_(true) {} + delegate_(nullptr) {} BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() { if (stream_) {
diff --git a/net/quic/bidirectional_stream_quic_impl.h b/net/quic/bidirectional_stream_quic_impl.h index 834babd..eb54b1f6 100644 --- a/net/quic/bidirectional_stream_quic_impl.h +++ b/net/quic/bidirectional_stream_quic_impl.h
@@ -91,10 +91,10 @@ // Saves the response status if the stream is explicitly closed via OnError // or OnClose with an error. Once all buffered data has been returned, this // will be used as the final response. - int response_status_; + int response_status_ = OK; // The protocol that is negotiated. - NextProto negotiated_protocol_; + NextProto negotiated_protocol_ = kProtoUnknown; // Connect timing information for this stream. Populated when headers are // received. LoadTimingInfo::ConnectTiming connect_timing_; @@ -104,33 +104,33 @@ // User provided read buffer for ReadData() response. scoped_refptr<IOBuffer> read_buffer_; - int read_buffer_len_; + int read_buffer_len_ = 0; // Number of bytes received by the headers stream on behalf of this stream. - int64_t headers_bytes_received_; + int64_t headers_bytes_received_ = 0; // Number of bytes sent by the headers stream on behalf of this stream. - int64_t headers_bytes_sent_; + int64_t headers_bytes_sent_ = 0; // After |stream_| has been closed, this keeps track of the total number of // bytes received over the network for |stream_| while it was open. - int64_t closed_stream_received_bytes_; + int64_t closed_stream_received_bytes_ = 0; // After |stream_| has been closed, this keeps track of the total number of // bytes sent over the network for |stream_| while it was open. - int64_t closed_stream_sent_bytes_; + int64_t closed_stream_sent_bytes_ = 0; // True if the stream is the first stream negotiated on the session. Set when // the stream was closed. If |stream_| is failed to be created, this takes on // the default value of false. - bool closed_is_first_stream_; + bool closed_is_first_stream_ = false; // Indicates whether initial headers have been sent. - bool has_sent_headers_; + bool has_sent_headers_ = false; // Whether to automatically send request headers when stream is negotiated. // If false, headers will not be sent until SendRequestHeaders() is called or // until next SendData/SendvData, during which QUIC will try to combine header // frame with data frame in the same packet if possible. - bool send_request_headers_automatically_; + bool send_request_headers_automatically_ = true; // True when callbacks to the delegate may be invoked synchronously. - bool may_invoke_callbacks_; + bool may_invoke_callbacks_ = true; base::WeakPtrFactory<BidirectionalStreamQuicImpl> weak_factory_{this}; };
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc index 3525e3d5..e7132c61 100644 --- a/net/quic/bidirectional_stream_quic_impl_unittest.cc +++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -460,7 +460,6 @@ kDefaultServerHostName, quic::Perspective::IS_CLIENT, client_headers_include_h2_stream_dependency_), - packet_number_(0), server_maker_(version_, connection_id_, &clock_, @@ -852,7 +851,7 @@ const quic::QuicConnectionId connection_id_; const quic::QuicStreamId stream_id_; QuicTestPacketMaker client_maker_; - uint64_t packet_number_; + uint64_t packet_number_ = 0; QuicTestPacketMaker server_maker_; IPEndPoint self_addr_; IPEndPoint peer_addr_;
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index 0b7c958..f6fdcc5 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -34,8 +34,7 @@ namespace net { -ProofVerifyDetailsChromium::ProofVerifyDetailsChromium() - : pkp_bypassed(false), is_fatal_cert_error(false) {} +ProofVerifyDetailsChromium::ProofVerifyDetailsChromium() = default; ProofVerifyDetailsChromium::~ProofVerifyDetailsChromium() {} @@ -165,7 +164,7 @@ // passed to CertVerifier::Verify. int cert_verify_flags_; - State next_state_; + State next_state_ = STATE_NONE; base::TimeTicks start_time_; @@ -186,7 +185,6 @@ transport_security_state_(transport_security_state), sct_auditing_delegate_(sct_auditing_delegate), cert_verify_flags_(cert_verify_flags), - next_state_(STATE_NONE), start_time_(base::TimeTicks::Now()), net_log_(net_log) { CHECK(proof_verifier_);
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h index fb14c67..57a6ae7 100644 --- a/net/quic/crypto/proof_verifier_chromium.h +++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -47,11 +47,11 @@ std::string pinning_failure_log; // True if PKP was bypassed due to a local trust anchor. - bool pkp_bypassed; + bool pkp_bypassed = false; // True if there was a certificate error which should be treated as fatal, // and false otherwise. - bool is_fatal_cert_error; + bool is_fatal_cert_error = false; }; // ProofVerifyContextChromium is the implementation-specific information that a
diff --git a/net/quic/mock_crypto_client_stream.cc b/net/quic/mock_crypto_client_stream.cc index f4c3d8f..8183255 100644 --- a/net/quic/mock_crypto_client_stream.cc +++ b/net/quic/mock_crypto_client_stream.cc
@@ -71,8 +71,6 @@ /*has_application_state = */ true), QuicCryptoHandshaker(this, session), handshake_mode_(handshake_mode), - encryption_established_(false), - handshake_confirmed_(false), crypto_negotiated_params_(new QuicCryptoNegotiatedParameters), use_mock_crypter_(use_mock_crypter), server_id_(server_id),
diff --git a/net/quic/mock_crypto_client_stream.h b/net/quic/mock_crypto_client_stream.h index eef99bd..d6bf54b 100644 --- a/net/quic/mock_crypto_client_stream.h +++ b/net/quic/mock_crypto_client_stream.h
@@ -101,8 +101,8 @@ void FillCryptoParams(); HandshakeMode handshake_mode_; - bool encryption_established_; - bool handshake_confirmed_; + bool encryption_established_ = false; + bool handshake_confirmed_ = false; quiche::QuicheReferenceCountedPointer<quic::QuicCryptoNegotiatedParameters> crypto_negotiated_params_; quic::CryptoFramer crypto_framer_;
diff --git a/net/quic/mock_crypto_client_stream_factory.cc b/net/quic/mock_crypto_client_stream_factory.cc index 9ff68c6..3b50b76 100644 --- a/net/quic/mock_crypto_client_stream_factory.cc +++ b/net/quic/mock_crypto_client_stream_factory.cc
@@ -15,10 +15,7 @@ MockCryptoClientStreamFactory::~MockCryptoClientStreamFactory() {} MockCryptoClientStreamFactory::MockCryptoClientStreamFactory() - : handshake_mode_(MockCryptoClientStream::CONFIRM_HANDSHAKE), - last_stream_(nullptr), - config_(new quic::QuicConfig()), - use_mock_crypter_(false) {} + : last_stream_(nullptr), config_(new quic::QuicConfig()) {} void MockCryptoClientStreamFactory::SetConfig(const quic::QuicConfig& config) { config_ = std::make_unique<quic::QuicConfig>(config);
diff --git a/net/quic/mock_crypto_client_stream_factory.h b/net/quic/mock_crypto_client_stream_factory.h index e27d9b1..540660cc 100644 --- a/net/quic/mock_crypto_client_stream_factory.h +++ b/net/quic/mock_crypto_client_stream_factory.h
@@ -56,11 +56,12 @@ void SetConfig(const quic::QuicConfig& config); private: - MockCryptoClientStream::HandshakeMode handshake_mode_; + MockCryptoClientStream::HandshakeMode handshake_mode_ = + MockCryptoClientStream::CONFIRM_HANDSHAKE; raw_ptr<MockCryptoClientStream> last_stream_; base::queue<const ProofVerifyDetailsChromium*> proof_verify_details_queue_; std::unique_ptr<quic::QuicConfig> config_; - bool use_mock_crypter_; + bool use_mock_crypter_ = false; }; } // namespace net
diff --git a/net/quic/mock_quic_data.cc b/net/quic/mock_quic_data.cc index c6f3af3..0ba04e7bc 100644 --- a/net/quic/mock_quic_data.cc +++ b/net/quic/mock_quic_data.cc
@@ -9,7 +9,7 @@ namespace test { MockQuicData::MockQuicData(quic::ParsedQuicVersion version) - : sequence_number_(0), printer_(version) {} + : printer_(version) {} MockQuicData::~MockQuicData() {}
diff --git a/net/quic/mock_quic_data.h b/net/quic/mock_quic_data.h index b887388..6c87c68 100644 --- a/net/quic/mock_quic_data.h +++ b/net/quic/mock_quic_data.h
@@ -68,7 +68,7 @@ std::unique_ptr<MockConnect> connect_; std::vector<MockWrite> writes_; std::vector<MockRead> reads_; - size_t sequence_number_; + size_t sequence_number_ = 0; std::unique_ptr<SequencedSocketData> socket_data_; QuicPacketPrinter printer_; };
diff --git a/net/quic/network_connection.cc b/net/quic/network_connection.cc index b545829..970a5cc 100644 --- a/net/quic/network_connection.cc +++ b/net/quic/network_connection.cc
@@ -9,9 +9,7 @@ namespace net { -NetworkConnection::NetworkConnection() - : connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN), - connection_description_(nullptr) { +NetworkConnection::NetworkConnection() { NetworkChangeNotifier::AddIPAddressObserver(this); NetworkChangeNotifier::AddConnectionTypeObserver(this); OnIPAddressChanged();
diff --git a/net/quic/network_connection.h b/net/quic/network_connection.h index 589a88b6..e2ea747 100644 --- a/net/quic/network_connection.h +++ b/net/quic/network_connection.h
@@ -49,10 +49,11 @@ private: // Cache the connection type to avoid calling the potentially expensive // NetworkChangeNotifier::GetConnectionType() function. - NetworkChangeNotifier::ConnectionType connection_type_; + NetworkChangeNotifier::ConnectionType connection_type_ = + NetworkChangeNotifier::CONNECTION_UNKNOWN; // Cache the connection description string to avoid calling the expensive // GetWifiPHYLayerProtocol() function. - const char* connection_description_; + const char* connection_description_ = nullptr; }; } // namespace net
diff --git a/net/quic/quic_chromium_alarm_factory_test.cc b/net/quic/quic_chromium_alarm_factory_test.cc index 729b814..1f74a825 100644 --- a/net/quic/quic_chromium_alarm_factory_test.cc +++ b/net/quic/quic_chromium_alarm_factory_test.cc
@@ -14,7 +14,7 @@ class TestDelegate : public quic::QuicAlarm::DelegateWithoutContext { public: - TestDelegate() : fired_(false) {} + TestDelegate() = default; void OnAlarm() override { fired_ = true; } @@ -22,7 +22,7 @@ void Clear() { fired_ = false; } private: - bool fired_; + bool fired_ = false; }; class QuicChromiumAlarmFactoryTest : public ::testing::Test {
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 36b8f36..918f5e05 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -367,13 +367,8 @@ destination_(std::move(destination)), net_log_(session_->net_log()), was_handshake_confirmed_(session->OneRttKeysAvailable()), - net_error_(OK), - quic_error_(quic::QUIC_NO_ERROR), - port_migration_detected_(false), server_id_(session_->server_id()), - quic_version_(session->connection()->version()), - push_handle_(nullptr), - was_ever_used_(false) { + quic_version_(session->connection()->version()) { DCHECK(session_); session_->AddHandle(this); } @@ -957,10 +952,8 @@ max_time_on_non_default_network_(max_time_on_non_default_network), max_migrations_to_non_default_network_on_write_error_( max_migrations_to_non_default_network_on_write_error), - current_migrations_to_non_default_network_on_write_error_(0), max_migrations_to_non_default_network_on_path_degrading_( max_migrations_to_non_default_network_on_path_degrading), - current_migrations_to_non_default_network_on_path_degrading_(0), clock_(clock), yield_after_packets_(yield_after_packets), yield_after_duration_(yield_after_duration), @@ -968,16 +961,12 @@ most_recent_network_disconnected_timestamp_(base::TimeTicks()), tick_clock_(tick_clock), most_recent_stream_close_time_(tick_clock_->NowTicks()), - most_recent_write_error_(0), most_recent_write_error_timestamp_(base::TimeTicks()), crypto_config_(std::move(crypto_config)), stream_factory_(stream_factory), transport_security_state_(transport_security_state), ssl_config_service_(ssl_config_service), server_info_(std::move(server_info)), - pkp_bypassed_(false), - is_fatal_cert_error_(false), - num_total_streams_(0), task_runner_(task_runner), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::QUIC_SESSION)), logger_(new QuicConnectionLogger(this, @@ -987,23 +976,9 @@ http3_logger_(VersionUsesHttp3(connection->transport_version()) ? new QuicHttp3Logger(net_log_) : nullptr), - going_away_(false), - port_migration_detected_(false), push_delegate_(push_delegate), - streams_pushed_count_(0), - streams_pushed_and_claimed_count_(0), - bytes_pushed_count_(0), - bytes_pushed_and_unclaimed_count_(0), - retry_migrate_back_count_(0), - current_migration_cause_(UNKNOWN_CAUSE), - send_packet_after_migration_(false), - wait_for_new_network_(false), - ignore_read_error_(false), headers_include_h2_stream_dependency_( headers_include_h2_stream_dependency), - attempted_zero_rtt_(false), - num_migrations_(0), - last_key_update_reason_(quic::KeyUpdateReason::kInvalid), push_promise_index_(std::move(push_promise_index)), path_validation_writer_delegate_(this, task_runner_) { default_network_ = default_network;
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index 58c70a036..f1a38c3 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -333,9 +333,9 @@ // session is destroyed. NetLogWithSource net_log_; bool was_handshake_confirmed_; - int net_error_; - quic::QuicErrorCode quic_error_; - bool port_migration_detected_; + int net_error_ = OK; + quic::QuicErrorCode quic_error_ = quic::QUIC_NO_ERROR; + bool port_migration_detected_ = false; quic::QuicServerId server_id_; quic::ParsedQuicVersion quic_version_; LoadTimingInfo::ConnectTiming connect_timing_; @@ -345,11 +345,11 @@ // is asynchronous, i.e. it returned quic::QUIC_PENDING, and remains valid // until |OnRendezvouResult()| fires or |push_handle_->Cancel()| is // invoked. - quic::QuicClientPushPromiseIndex::TryHandle* push_handle_; + quic::QuicClientPushPromiseIndex::TryHandle* push_handle_ = nullptr; CompletionOnceCallback push_callback_; std::unique_ptr<QuicChromiumClientStream::Handle> push_stream_; - bool was_ever_used_; + bool was_ever_used_ = false; }; // A helper class used to manage a request to create a stream. @@ -971,11 +971,11 @@ // Maximum allowed number of migrations to non-default network triggered by // packet write error per default network. int max_migrations_to_non_default_network_on_write_error_; - int current_migrations_to_non_default_network_on_write_error_; + int current_migrations_to_non_default_network_on_write_error_ = 0; // Maximum allowed number of migrations to non-default network triggered by // path degrading per default network. int max_migrations_to_non_default_network_on_path_degrading_; - int current_migrations_to_non_default_network_on_path_degrading_; + int current_migrations_to_non_default_network_on_path_degrading_ = 0; raw_ptr<const quic::QuicClock> clock_; // Unowned. int yield_after_packets_; quic::QuicTime::Delta yield_after_duration_; @@ -985,7 +985,7 @@ raw_ptr<const base::TickClock> tick_clock_; base::TimeTicks most_recent_stream_close_time_; - int most_recent_write_error_; + int most_recent_write_error_ = 0; base::TimeTicks most_recent_write_error_timestamp_; std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_; @@ -999,13 +999,13 @@ std::unique_ptr<QuicServerInfo> server_info_; std::unique_ptr<CertVerifyResult> cert_verify_result_; std::string pinning_failure_log_; - bool pkp_bypassed_; - bool is_fatal_cert_error_; + bool pkp_bypassed_ = false; + bool is_fatal_cert_error_ = false; HandleSet handles_; StreamRequestQueue stream_requests_; std::vector<CompletionOnceCallback> waiting_for_confirmation_callbacks_; CompletionOnceCallback callback_; - size_t num_total_streams_; + size_t num_total_streams_ = 0; raw_ptr<base::SequencedTaskRunner> task_runner_; NetLogWithSource net_log_; std::vector<std::unique_ptr<QuicChromiumPacketReader>> packet_readers_; @@ -1014,17 +1014,17 @@ std::unique_ptr<QuicHttp3Logger> http3_logger_; // True when the session is going away, and streams may no longer be created // on this session. Existing stream will continue to be processed. - bool going_away_; + bool going_away_ = false; // True when the session receives a go away from server due to port migration. - bool port_migration_detected_; + bool port_migration_detected_ = false; // Not owned. |push_delegate_| outlives the session and handles server pushes // received by session. raw_ptr<ServerPushDelegate> push_delegate_; // UMA histogram counters for streams pushed to this session. - int streams_pushed_count_; - int streams_pushed_and_claimed_count_; - uint64_t bytes_pushed_count_; - uint64_t bytes_pushed_and_unclaimed_count_; + int streams_pushed_count_ = 0; + int streams_pushed_and_claimed_count_ = 0; + uint64_t bytes_pushed_count_ = 0; + uint64_t bytes_pushed_and_unclaimed_count_ = 0; // Stores the packet that witnesses socket write error. This packet will be // written to an alternate socket when the migration completes and the // alternate socket is unblocked. @@ -1032,32 +1032,33 @@ // Stores the latest default network platform marks if migration is enabled. // Otherwise, stores the network interface that is used by the connection. NetworkChangeNotifier::NetworkHandle default_network_; - int retry_migrate_back_count_; + int retry_migrate_back_count_ = 0; base::OneShotTimer migrate_back_to_default_timer_; - MigrationCause current_migration_cause_; + MigrationCause current_migration_cause_ = UNKNOWN_CAUSE; // True if a packet needs to be sent when packet writer is unblocked to // complete connection migration. The packet can be a cached packet if // |packet_| is set, a queued packet, or a PING packet. - bool send_packet_after_migration_; + bool send_packet_after_migration_ = false; // True if migration is triggered, and there is no alternate network to // migrate to. - bool wait_for_new_network_; + bool wait_for_new_network_ = false; // True if read errors should be ignored. Set when migration on write error is // posted and unset until the first packet is written after migration. - bool ignore_read_error_; + bool ignore_read_error_ = false; // If true, client headers will include HTTP/2 stream dependency info derived // from spdy::SpdyStreamPrecedence. bool headers_include_h2_stream_dependency_; Http2PriorityDependencies priority_dependency_state_; - bool attempted_zero_rtt_; + bool attempted_zero_rtt_ = false; - size_t num_migrations_; + size_t num_migrations_ = 0; // The reason for the last 1-RTT key update on the connection. Will be // kInvalid if no key updates have occurred. - quic::KeyUpdateReason last_key_update_reason_; + quic::KeyUpdateReason last_key_update_reason_ = + quic::KeyUpdateReason::kInvalid; std::unique_ptr<quic::QuicClientPushPromiseIndex> push_promise_index_;
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index 4439774..ffba0e1 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc
@@ -161,8 +161,7 @@ &clock_, kServerHostname, quic::Perspective::IS_SERVER, - false), - migrate_session_early_v2_(false) { + false) { FLAGS_quic_enable_http3_grease_randomness = false; quic::QuicEnableVersion(version_); // Advance the time, because timers do not like uninitialized times. @@ -314,7 +313,7 @@ QuicTestPacketMaker client_maker_; QuicTestPacketMaker server_maker_; ProofVerifyDetailsChromium verify_details_; - bool migrate_session_early_v2_; + bool migrate_session_early_v2_ = false; quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_; };
diff --git a/net/quic/quic_chromium_client_stream.cc b/net/quic/quic_chromium_client_stream.cc index e4fb1556..9767668 100644 --- a/net/quic/quic_chromium_client_stream.cc +++ b/net/quic/quic_chromium_client_stream.cc
@@ -46,10 +46,7 @@ QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream) : stream_(stream), - may_invoke_callbacks_(true), read_headers_buffer_(nullptr), - read_body_buffer_len_(0), - net_error_(ERR_UNEXPECTED), net_log_(stream->net_log()) { SaveState(); }
diff --git a/net/quic/quic_chromium_client_stream.h b/net/quic/quic_chromium_client_stream.h index c1ff6d3f..fbf9299 100644 --- a/net/quic/quic_chromium_client_stream.h +++ b/net/quic/quic_chromium_client_stream.h
@@ -178,7 +178,7 @@ raw_ptr<QuicChromiumClientStream> stream_; // Unowned. - bool may_invoke_callbacks_; // True when callbacks may be invoked. + bool may_invoke_callbacks_ = true; // True when callbacks may be invoked. // Callback to be invoked when ReadInitialHeaders completes asynchronously. CompletionOnceCallback read_headers_callback_; @@ -188,7 +188,7 @@ // Callback to be invoked when ReadBody completes asynchronously. CompletionOnceCallback read_body_callback_; raw_ptr<IOBuffer> read_body_buffer_; - int read_body_buffer_len_; + int read_body_buffer_len_ = 0; // Callback to be invoked when WriteStreamData or WritevStreamData completes // asynchronously. @@ -206,7 +206,7 @@ size_t num_bytes_consumed_; Idempotency idempotency_ = DEFAULT_IDEMPOTENCY; - int net_error_; + int net_error_ = ERR_UNEXPECTED; NetLogWithSource net_log_;
diff --git a/net/quic/quic_chromium_packet_reader.cc b/net/quic/quic_chromium_packet_reader.cc index 0f1a9987..b2756f9 100644 --- a/net/quic/quic_chromium_packet_reader.cc +++ b/net/quic/quic_chromium_packet_reader.cc
@@ -31,8 +31,6 @@ const NetLogWithSource& net_log) : socket_(socket), visitor_(visitor), - read_pending_(false), - num_packets_read_(0), clock_(clock), yield_after_packets_(yield_after_packets), yield_after_duration_(yield_after_duration),
diff --git a/net/quic/quic_chromium_packet_reader.h b/net/quic/quic_chromium_packet_reader.h index 701d2f7..bdb54b2 100644 --- a/net/quic/quic_chromium_packet_reader.h +++ b/net/quic/quic_chromium_packet_reader.h
@@ -65,8 +65,8 @@ raw_ptr<DatagramClientSocket> socket_; raw_ptr<Visitor> visitor_; - bool read_pending_; - int num_packets_read_; + bool read_pending_ = false; + int num_packets_read_ = 0; raw_ptr<const quic::QuicClock> clock_; // Not owned. int yield_after_packets_; quic::QuicTime::Delta yield_after_duration_;
diff --git a/net/quic/quic_chromium_packet_writer.cc b/net/quic/quic_chromium_packet_writer.cc index e575096..a9c070cd 100644 --- a/net/quic/quic_chromium_packet_writer.cc +++ b/net/quic/quic_chromium_packet_writer.cc
@@ -69,7 +69,7 @@ } // namespace QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity) - : IOBuffer(capacity), capacity_(capacity), size_(0) {} + : IOBuffer(capacity), capacity_(capacity) {} QuicChromiumPacketWriter::ReusableIOBuffer::~ReusableIOBuffer() {}
diff --git a/net/quic/quic_chromium_packet_writer.h b/net/quic/quic_chromium_packet_writer.h index 80e5a9e..1781d34 100644 --- a/net/quic/quic_chromium_packet_writer.h +++ b/net/quic/quic_chromium_packet_writer.h
@@ -44,7 +44,7 @@ private: ~ReusableIOBuffer() override; size_t capacity_; - size_t size_; + size_t size_ = 0; }; // Delegate interface which receives notifications on socket write events. class NET_EXPORT_PRIVATE Delegate {
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index ccf6585..2bddbdf9 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc
@@ -62,19 +62,6 @@ std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, const NetLogWithSource& net_log) : session_(session), - last_received_packet_size_(0), - no_packet_received_after_ping_(false), - previous_received_packet_size_(0), - num_out_of_order_received_packets_(0), - num_out_of_order_large_received_packets_(0), - num_packets_received_(0), - num_frames_received_(0), - num_duplicate_frames_received_(0), - num_incorrect_connection_ids_(0), - num_undecryptable_packets_(0), - num_duplicate_packets_(0), - num_blocked_frames_received_(0), - num_blocked_frames_sent_(0), connection_description_(connection_description), socket_performance_watcher_(std::move(socket_performance_watcher)), event_logger_(session, net_log) {}
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h index ea58d8fe..f070213 100644 --- a/net/quic/quic_connection_logger.h +++ b/net/quic/quic_connection_logger.h
@@ -154,11 +154,11 @@ // The last packet number received. quic::QuicPacketNumber last_received_packet_number_; // The size of the most recently received packet. - size_t last_received_packet_size_; + size_t last_received_packet_size_ = 0; // True if a PING frame has been sent and no packet has been received. - bool no_packet_received_after_ping_; + bool no_packet_received_after_ping_ = false; // The size of the previously received packet. - size_t previous_received_packet_size_; + size_t previous_received_packet_size_ = 0; // The first received packet number. Used as the left edge of // received_packets_ and received_acks_. In the case where packets are // received out of order, packets with numbers smaller than @@ -169,35 +169,35 @@ quic::QuicPacketNumber largest_received_packet_number_; // Number of times that the current received packet number is // smaller than the last received packet number. - size_t num_out_of_order_received_packets_; + size_t num_out_of_order_received_packets_ = 0; // Number of times that the current received packet number is // smaller than the last received packet number and where the // size of the current packet is larger than the size of the previous // packet. - size_t num_out_of_order_large_received_packets_; + size_t num_out_of_order_large_received_packets_ = 0; // The number of times that OnPacketHeader was called. // If the network replicates packets, then this number may be slightly // different from the real number of distinct packets received. - quic::QuicPacketCount num_packets_received_; + quic::QuicPacketCount num_packets_received_ = 0; // The quic::kCADR value provided by the server in ServerHello. IPEndPoint local_address_from_shlo_; // The first local address from which a packet was received. IPEndPoint local_address_from_self_; // Count of the number of frames received. - int num_frames_received_; + int num_frames_received_ = 0; // Count of the number of duplicate frames received. - int num_duplicate_frames_received_; + int num_duplicate_frames_received_ = 0; // Count of the number of packets received with incorrect connection IDs. - int num_incorrect_connection_ids_; + int num_incorrect_connection_ids_ = 0; // Count of the number of undecryptable packets received. - int num_undecryptable_packets_; + int num_undecryptable_packets_ = 0; // Count of the number of duplicate packets received. - int num_duplicate_packets_; + int num_duplicate_packets_ = 0; // Count of the number of BLOCKED frames received. - int num_blocked_frames_received_; + int num_blocked_frames_received_ = 0; // Count of the number of BLOCKED frames sent. - int num_blocked_frames_sent_; - // Vector of inital packets status' indexed by packet numbers, where + int num_blocked_frames_sent_ = 0; + // Vector of initial packets status' indexed by packet numbers, where // false means never received. We track 150 packets starting from // first_received_packet_number_. std::bitset<150> received_packets_;
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc index 27170337..c8c982d6 100644 --- a/net/quic/quic_end_to_end_unittest.cc +++ b/net/quic/quic_end_to_end_unittest.cc
@@ -93,8 +93,7 @@ ssl_config_service_(new SSLConfigServiceDefaults), proxy_resolution_service_( ConfiguredProxyResolutionService::CreateDirect()), - auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()), - strike_register_no_startup_period_(false) { + auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()) { request_.method = "GET"; request_.url = GURL("https://test.example.com/"); request_.load_flags = 0; @@ -237,7 +236,7 @@ quic::QuicConfig server_config_; quic::QuicCryptoServerConfig::ConfigOptions server_config_options_; bool server_started_; - bool strike_register_no_startup_period_; + bool strike_register_no_startup_period_ = false; }; TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 3964b05d..f3ba9a4 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -62,26 +62,10 @@ std::unique_ptr<QuicChromiumClientSession::Handle> session, std::set<std::string> dns_aliases) : MultiplexedHttpStream(std::move(session)), - next_state_(STATE_NONE), stream_(nullptr), request_info_(nullptr), - can_send_early_(false), request_body_stream_(nullptr), - priority_(MINIMUM_PRIORITY), response_info_(nullptr), - has_response_status_(false), - response_status_(ERR_UNEXPECTED), - response_headers_received_(false), - trailing_headers_received_(false), - headers_bytes_received_(0), - headers_bytes_sent_(0), - closed_stream_received_bytes_(0), - closed_stream_sent_bytes_(0), - closed_is_first_stream_(false), - user_buffer_len_(0), - session_error_(ERR_UNEXPECTED), - found_promise_(false), - in_loop_(false), dns_aliases_(std::move(dns_aliases)) {} QuicHttpStream::~QuicHttpStream() {
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h index e6ceaf7..e4dfa0d0 100644 --- a/net/quic/quic_http_stream.h +++ b/net/quic/quic_http_stream.h
@@ -151,7 +151,7 @@ return static_cast<const QuicChromiumClientSession::Handle*>(session()); } - State next_state_; + State next_state_ = STATE_NONE; std::unique_ptr<QuicChromiumClientStream::Handle> stream_; @@ -163,53 +163,53 @@ raw_ptr<const HttpRequestInfo> request_info_; // Whether this request can be sent without confirmation. - bool can_send_early_; + bool can_send_early_ = false; // The request body to send, if any, owned by the caller. raw_ptr<UploadDataStream> request_body_stream_; // Time the request was issued. base::Time request_time_; // The priority of the request. - RequestPriority priority_; + RequestPriority priority_ = MINIMUM_PRIORITY; // |response_info_| is the HTTP response data object which is filled in // when a the response headers are read. It is not owned by this stream. raw_ptr<HttpResponseInfo> response_info_; - bool has_response_status_; // true if response_status_ as been set. + bool has_response_status_ = false; // true if response_status_ as been set. // Because response data is buffered, also buffer the response status if the // stream is explicitly closed via OnError or OnClose with an error. // Once all buffered data has been returned, this will be used as the final // response. - int response_status_; + int response_status_ = ERR_UNEXPECTED; // Serialized request headers. spdy::Http2HeaderBlock request_headers_; spdy::Http2HeaderBlock response_header_block_; - bool response_headers_received_; + bool response_headers_received_ = false; spdy::Http2HeaderBlock trailing_header_block_; - bool trailing_headers_received_; + bool trailing_headers_received_ = false; // Number of bytes received by the headers stream on behalf of this stream. - int64_t headers_bytes_received_; + int64_t headers_bytes_received_ = 0; // Number of bytes sent by the headers stream on behalf of this stream. - int64_t headers_bytes_sent_; + int64_t headers_bytes_sent_ = 0; // Number of bytes received when the stream was closed. - int64_t closed_stream_received_bytes_; + int64_t closed_stream_received_bytes_ = 0; // Number of bytes sent when the stream was closed. - int64_t closed_stream_sent_bytes_; + int64_t closed_stream_sent_bytes_ = 0; // True if the stream is the first stream negotiated on the session. Set when // the stream was closed. If |stream_| is failed to be created, this takes on // the default value of false. - bool closed_is_first_stream_; + bool closed_is_first_stream_ = false; // The caller's callback to be used for asynchronous operations. CompletionOnceCallback callback_; // Caller provided buffer for the ReadResponseBody() response. scoped_refptr<IOBuffer> user_buffer_; - int user_buffer_len_; + int user_buffer_len_ = 0; // Temporary buffer used to read the request body from UploadDataStream. scoped_refptr<IOBufferWithSize> raw_request_body_buf_; @@ -218,12 +218,13 @@ NetLogWithSource stream_net_log_; - int session_error_; // Error code from the connection shutdown. + int session_error_ = + ERR_UNEXPECTED; // Error code from the connection shutdown. - bool found_promise_; + bool found_promise_ = false; // Set to true when DoLoop() is being executed, false otherwise. - bool in_loop_; + bool in_loop_ = false; // Session connect timing info. LoadTimingInfo::ConnectTiming connect_timing_;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 4313961..a24eb00 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -253,10 +253,7 @@ class TestSocketPerformanceWatcherFactory : public SocketPerformanceWatcherFactory { public: - TestSocketPerformanceWatcherFactory() - : watcher_count_(0u), - should_notify_updated_rtt_(true), - rtt_notification_received_(false) {} + TestSocketPerformanceWatcherFactory() = default; TestSocketPerformanceWatcherFactory( const TestSocketPerformanceWatcherFactory&) = delete; @@ -287,9 +284,9 @@ } private: - size_t watcher_count_; - bool should_notify_updated_rtt_; - bool rtt_notification_received_; + size_t watcher_count_ = 0u; + bool should_notify_updated_rtt_ = true; + bool rtt_notification_received_ = false; }; class QuicNetworkTransactionTest
diff --git a/net/quic/quic_proxy_client_socket.cc b/net/quic/quic_proxy_client_socket.cc index b9c5b0e..512e987 100644 --- a/net/quic/quic_proxy_client_socket.cc +++ b/net/quic/quic_proxy_client_socket.cc
@@ -31,11 +31,9 @@ const NetLogWithSource& net_log, HttpAuthController* auth_controller, ProxyDelegate* proxy_delegate) - : next_state_(STATE_DISCONNECTED), - stream_(std::move(stream)), + : stream_(std::move(stream)), session_(std::move(session)), read_buf_(nullptr), - write_buf_len_(0), endpoint_(endpoint), auth_(auth_controller), proxy_server_(proxy_server),
diff --git a/net/quic/quic_proxy_client_socket.h b/net/quic/quic_proxy_client_socket.h index 00996b19..4a31834f 100644 --- a/net/quic/quic_proxy_client_socket.h +++ b/net/quic/quic_proxy_client_socket.h
@@ -107,7 +107,7 @@ int DoReadReply(); int DoReadReplyComplete(int result); - State next_state_; + State next_state_ = STATE_DISCONNECTED; // Handle to the QUIC Stream that this sits on top of. std::unique_ptr<QuicChromiumClientStream::Handle> stream_; @@ -124,7 +124,7 @@ // Stores the callback for Write(). CompletionOnceCallback write_callback_; // Stores the write buffer length for Write(). - int write_buf_len_; + int write_buf_len_ = 0; // CONNECT request and response. HttpRequestInfo request_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 22108d7..2ed3c62 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -509,7 +509,7 @@ UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StaleAndFreshHostMatched", matched); } - IoState io_state_; + IoState io_state_ = STATE_RESOLVE_HOST; raw_ptr<QuicStreamFactory> factory_; quic::ParsedQuicVersion quic_version_; raw_ptr<HostResolver> host_resolver_; @@ -523,9 +523,9 @@ const bool retry_on_alternate_network_before_handshake_; const bool race_stale_dns_on_connection_; const NetLogWithSource net_log_; - bool host_resolution_finished_; - bool connection_retried_; - QuicChromiumClientSession* session_; + bool host_resolution_finished_ = false; + bool connection_retried_ = false; + QuicChromiumClientSession* session_ = nullptr; // If connection migraiton is supported, |network_| denotes the network on // which |session_| is created. NetworkChangeNotifier::NetworkHandle network_; @@ -556,8 +556,7 @@ bool require_dns_https_alpn, int cert_verify_flags, const NetLogWithSource& net_log) - : io_state_(STATE_RESOLVE_HOST), - factory_(factory), + : factory_(factory), quic_version_(quic_version), host_resolver_(host_resolver), key_(key), @@ -574,9 +573,6 @@ net_log_( NetLogWithSource::Make(net_log.net_log(), NetLogSourceType::QUIC_STREAM_FACTORY_JOB)), - host_resolution_finished_(false), - connection_retried_(false), - session_(nullptr), network_(NetworkChangeNotifier::kInvalidNetworkHandle) { DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn); net_log_.BeginEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB, @@ -1033,7 +1029,7 @@ } QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory) - : factory_(factory), expect_on_host_resolution_(false) {} + : factory_(factory) {} QuicStreamRequest::~QuicStreamRequest() { if (factory_ && !callback_.is_null()) @@ -1171,8 +1167,7 @@ SocketPerformanceWatcherFactory* socket_performance_watcher_factory, QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory, QuicContext* quic_context) - : is_quic_known_to_work_on_current_network_(false), - net_log_(net_log), + : net_log_(net_log), host_resolver_(host_resolver), client_socket_factory_(client_socket_factory), http_server_properties_(http_server_properties), @@ -1201,9 +1196,6 @@ yield_after_duration_(quic::QuicTime::Delta::FromMilliseconds( kQuicYieldAfterDurationMilliseconds)), default_network_(NetworkChangeNotifier::kInvalidNetworkHandle), - need_to_check_persisted_supports_quic_(true), - prefer_aes_gcm_recorded_(false), - num_push_streams_created_(0), connectivity_monitor_(default_network_), tick_clock_(nullptr), task_runner_(nullptr),
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index 0dad149..7151d302 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -194,7 +194,7 @@ // Set in Request(). If true, then OnHostResolutionComplete() is expected to // be called in the future. - bool expect_on_host_resolution_; + bool expect_on_host_resolution_ = false; // Callback passed to WaitForHostResolution(). CompletionOnceCallback host_resolution_callback_; }; @@ -515,7 +515,7 @@ // expected to work in general, rather than whether QUIC was broken / recently // broken when used with a particular server. That information is stored in // the broken alternative service map in HttpServerProperties. - bool is_quic_known_to_work_on_current_network_; + bool is_quic_known_to_work_on_current_network_ = false; raw_ptr<NetLog> net_log_; raw_ptr<HostResolver> host_resolver_; @@ -599,12 +599,12 @@ IPEndPoint local_address_; // True if we need to check HttpServerProperties if QUIC was supported last // time. - bool need_to_check_persisted_supports_quic_; - bool prefer_aes_gcm_recorded_; + bool need_to_check_persisted_supports_quic_ = true; + bool prefer_aes_gcm_recorded_ = false; NetworkConnection network_connection_; - int num_push_streams_created_; + int num_push_streams_created_ = 0; QuicConnectivityMonitor connectivity_monitor_;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 529b572..32370cf 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -150,7 +150,7 @@ // IPV4 address. class TestConnectionMigrationSocketFactory : public MockClientSocketFactory { public: - TestConnectionMigrationSocketFactory() : next_source_host_num_(1u) {} + TestConnectionMigrationSocketFactory() = default; TestConnectionMigrationSocketFactory( const TestConnectionMigrationSocketFactory&) = delete; @@ -171,14 +171,14 @@ } private: - uint8_t next_source_host_num_; + uint8_t next_source_host_num_ = 1u; }; // TestPortMigrationSocketFactory will vend sockets with incremental port // number. class TestPortMigrationSocketFactory : public MockClientSocketFactory { public: - TestPortMigrationSocketFactory() : next_source_port_num_(1u) {} + TestPortMigrationSocketFactory() = default; TestPortMigrationSocketFactory(const TestPortMigrationSocketFactory&) = delete; @@ -199,7 +199,7 @@ } private: - uint16_t next_source_port_num_; + uint16_t next_source_port_num_ = 1u; }; class QuicStreamFactoryTestBase : public WithTaskEnvironment { @@ -238,11 +238,9 @@ url2_(kServer2Url), url3_(kServer3Url), url4_(kServer4Url), - privacy_mode_(PRIVACY_MODE_DISABLED), failed_on_default_network_callback_(base::BindRepeating( &QuicStreamFactoryTestBase::OnFailedOnDefaultNetwork, base::Unretained(this))), - failed_on_default_network_(false), quic_params_(context_.params()) { FLAGS_quic_enable_http3_grease_randomness = false; FLAGS_quic_enable_chaos_protection = false; @@ -966,11 +964,11 @@ GURL url3_; GURL url4_; - PrivacyMode privacy_mode_; + PrivacyMode privacy_mode_ = PRIVACY_MODE_DISABLED; NetLogWithSource net_log_; TestCompletionCallback callback_; const CompletionRepeatingCallback failed_on_default_network_callback_; - bool failed_on_default_network_; + bool failed_on_default_network_ = false; NetErrorDetails net_error_details_; raw_ptr<QuicParams> quic_params_;
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc index 9db4722..374f14b4 100644 --- a/net/quic/quic_test_packet_maker.cc +++ b/net/quic/quic_test_packet_maker.cc
@@ -108,11 +108,8 @@ spdy_response_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION), qpack_encoder_(&decoder_stream_error_delegate_), perspective_(perspective), - encryption_level_(quic::ENCRYPTION_FORWARD_SECURE), - long_header_type_(quic::INVALID_PACKET_TYPE), client_headers_include_h2_stream_dependency_( - client_headers_include_h2_stream_dependency), - save_packet_frames_(false) { + client_headers_include_h2_stream_dependency) { DCHECK(!(perspective_ == quic::Perspective::IS_SERVER && client_headers_include_h2_stream_dependency_));
diff --git a/net/quic/quic_test_packet_maker.h b/net/quic/quic_test_packet_maker.h index bcb5223..f015f9ee 100644 --- a/net/quic/quic_test_packet_maker.h +++ b/net/quic/quic_test_packet_maker.h
@@ -604,8 +604,8 @@ quic::test::MockRandom random_generator_; std::map<quic::QuicStreamId, quic::QuicStreamOffset> stream_offsets_; quic::Perspective perspective_; - quic::EncryptionLevel encryption_level_; - quic::QuicLongHeaderType long_header_type_; + quic::EncryptionLevel encryption_level_ = quic::ENCRYPTION_FORWARD_SECURE; + quic::QuicLongHeaderType long_header_type_ = quic::INVALID_PACKET_TYPE; // If true, generated request headers will include non-default HTTP2 stream // dependency info. bool client_headers_include_h2_stream_dependency_; @@ -614,7 +614,7 @@ std::vector<std::unique_ptr<std::string>> saved_stream_data_; // If |save_packet_frames_| is true, save generated packets in // |saved_frames_|, allowing retransmission packets to be built. - bool save_packet_frames_; + bool save_packet_frames_ = false; std::map<quic::QuicPacketNumber, quic::QuicFrames> saved_frames_; // State necessary for building the current packet.
diff --git a/net/reporting/mock_persistent_reporting_store.cc b/net/reporting/mock_persistent_reporting_store.cc index 1cb84d0..eed7ef3 100644 --- a/net/reporting/mock_persistent_reporting_store.cc +++ b/net/reporting/mock_persistent_reporting_store.cc
@@ -153,13 +153,7 @@ } } -MockPersistentReportingStore::MockPersistentReportingStore() - : load_started_(false), - endpoint_count_(0), - endpoint_group_count_(0), - queued_endpoint_count_delta_(0), - queued_endpoint_group_count_delta_(0) {} - +MockPersistentReportingStore::MockPersistentReportingStore() = default; MockPersistentReportingStore::~MockPersistentReportingStore() = default; void MockPersistentReportingStore::LoadReportingClients(
diff --git a/net/reporting/mock_persistent_reporting_store.h b/net/reporting/mock_persistent_reporting_store.h index a630528..41e06ab 100644 --- a/net/reporting/mock_persistent_reporting_store.h +++ b/net/reporting/mock_persistent_reporting_store.h
@@ -142,18 +142,18 @@ std::vector<CachedReportingEndpointGroup> prestored_endpoint_groups_; // Set when LoadReportingClients() is called. - bool load_started_; + bool load_started_ = false; // Simulates the total number of endpoints/groups that would be stored in the // store. Updated when pre-stored policies are added, and when Flush() is // called. - int endpoint_count_; - int endpoint_group_count_; + int endpoint_count_ = 0; + int endpoint_group_count_ = 0; // Simulates the delta to be added to to the counts the next time Flush() is // called. Reset to 0 when Flush() is called. - int queued_endpoint_count_delta_; - int queued_endpoint_group_count_delta_; + int queued_endpoint_count_delta_ = 0; + int queued_endpoint_group_count_delta_ = 0; }; bool operator==(const MockPersistentReportingStore::Command& lhs,
diff --git a/net/reporting/reporting_cache_unittest.cc b/net/reporting/reporting_cache_unittest.cc index fd382e6d..d7669ca 100644 --- a/net/reporting/reporting_cache_unittest.cc +++ b/net/reporting/reporting_cache_unittest.cc
@@ -37,8 +37,7 @@ class TestReportingCacheObserver : public ReportingCacheObserver { public: - TestReportingCacheObserver() - : cached_reports_update_count_(0), cached_clients_update_count_(0) {} + TestReportingCacheObserver() = default; void OnReportsUpdated() override { ++cached_reports_update_count_; } void OnClientsUpdated() override { ++cached_clients_update_count_; } @@ -51,8 +50,8 @@ } private: - int cached_reports_update_count_; - int cached_clients_update_count_; + int cached_reports_update_count_ = 0; + int cached_clients_update_count_ = 0; }; // The tests are parametrized on a boolean value which represents whether or not
diff --git a/net/reporting/reporting_policy.cc b/net/reporting/reporting_policy.cc index 9756443..956db4137 100644 --- a/net/reporting/reporting_policy.cc +++ b/net/reporting/reporting_policy.cc
@@ -31,19 +31,11 @@ } ReportingPolicy::ReportingPolicy() - : max_report_count(100u), - max_endpoint_count(1000u), - max_endpoints_per_origin(40u), - delivery_interval(base::Minutes(1)), + : delivery_interval(base::Minutes(1)), persistence_interval(base::Minutes(1)), - persist_reports_across_restarts(false), - persist_clients_across_restarts(true), garbage_collection_interval(base::Minutes(5)), max_report_age(base::Minutes(15)), - max_group_staleness(base::Days(7)), - max_report_attempts(5), - persist_reports_across_network_changes(false), - persist_clients_across_network_changes(true) { + max_group_staleness(base::Days(7)) { endpoint_backoff_policy.num_errors_to_ignore = 0; endpoint_backoff_policy.initial_delay_ms = 60 * 1000; // 1 minute endpoint_backoff_policy.multiply_factor = 2.0;
diff --git a/net/reporting/reporting_policy.h b/net/reporting/reporting_policy.h index 7dda903..edecae7 100644 --- a/net/reporting/reporting_policy.h +++ b/net/reporting/reporting_policy.h
@@ -28,15 +28,15 @@ ~ReportingPolicy(); // Maximum number of reports to queue before evicting the oldest. - size_t max_report_count; + size_t max_report_count = 100u; // Maximum number of endpoints to remember before evicting - size_t max_endpoint_count; + size_t max_endpoint_count = 1000u; // Maximum number of endpoints for a given origin before evicting // TODO(chlily): This is actually a limit on the endpoints for a given client // (for a NIK, origin pair), so rename this. - size_t max_endpoints_per_origin; + size_t max_endpoints_per_origin = 40u; // Minimum interval at which to attempt delivery of queued reports. base::TimeDelta delivery_interval; @@ -49,11 +49,11 @@ base::TimeDelta persistence_interval; // Whether to persist undelivered reports across embedder restarts. - bool persist_reports_across_restarts; + bool persist_reports_across_restarts = false; // Whether to persist clients (per-origin endpoint configurations) across // embedder restarts. - bool persist_clients_across_restarts; + bool persist_clients_across_restarts = true; // Minimum interval at which to garbage-collect the cache. base::TimeDelta garbage_collection_interval; @@ -66,15 +66,15 @@ // Maximum number of delivery attempts a report can have before being // discarded as failed. - int max_report_attempts; + int max_report_attempts = 5; // Whether to persist (versus clear) reports when the network changes to avoid // leaking browsing data between networks. - bool persist_reports_across_network_changes; + bool persist_reports_across_network_changes = false; // Whether to persist (versus clear) clients when the network changes to avoid // leaking browsing data between networks. - bool persist_clients_across_network_changes; + bool persist_clients_across_network_changes = true; }; } // namespace net
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc index cab6067..02ed98a 100644 --- a/net/reporting/reporting_service.cc +++ b/net/reporting/reporting_service.cc
@@ -41,11 +41,8 @@ // Tasks are queued pending completion of loading from the store. class ReportingServiceImpl : public ReportingService { public: - ReportingServiceImpl(std::unique_ptr<ReportingContext> context) - : context_(std::move(context)), - shut_down_(false), - started_loading_from_store_(false), - initialized_(false) { + explicit ReportingServiceImpl(std::unique_ptr<ReportingContext> context) + : context_(std::move(context)) { if (!context_->IsClientDataPersisted()) initialized_ = true; } @@ -301,9 +298,9 @@ } std::unique_ptr<ReportingContext> context_; - bool shut_down_; - bool started_loading_from_store_; - bool initialized_; + bool shut_down_ = false; + bool started_loading_from_store_ = false; + bool initialized_ = false; std::vector<base::OnceClosure> task_backlog_; bool respect_network_isolation_key_ = base::FeatureList::IsEnabled(
diff --git a/net/reporting/reporting_uploader.cc b/net/reporting/reporting_uploader.cc index 75d4bde9..0f978de 100644 --- a/net/reporting/reporting_uploader.cc +++ b/net/reporting/reporting_uploader.cc
@@ -86,8 +86,7 @@ const std::string& json, int max_depth, ReportingUploader::UploadCallback callback) - : state(CREATED), - report_origin(report_origin), + : report_origin(report_origin), url(url), isolation_info(isolation_info), payload_reader(UploadOwnedBytesElementReader::CreateWithString(json)), @@ -98,7 +97,7 @@ std::move(callback).Run(outcome); } - State state; + State state = CREATED; const url::Origin report_origin; const GURL url; const IsolationInfo isolation_info;
diff --git a/net/reporting/reporting_uploader_unittest.cc b/net/reporting/reporting_uploader_unittest.cc index add3a94..c414700 100644 --- a/net/reporting/reporting_uploader_unittest.cc +++ b/net/reporting/reporting_uploader_unittest.cc
@@ -96,7 +96,7 @@ class TestUploadCallback { public: - TestUploadCallback() : called_(false), waiting_(false) {} + TestUploadCallback() = default; ReportingUploader::UploadCallback callback() { return base::BindOnce(&TestUploadCallback::OnUploadComplete, @@ -129,10 +129,10 @@ } } - bool called_; + bool called_ = false; ReportingUploader::Outcome outcome_; - bool waiting_; + bool waiting_ = false; base::OnceClosure closure_; };
diff --git a/net/server/http_connection.cc b/net/server/http_connection.cc index 0cf5d1a1..73f4fe1bd 100644 --- a/net/server/http_connection.cc +++ b/net/server/http_connection.cc
@@ -92,9 +92,7 @@ } HttpConnection::QueuedWriteIOBuffer::QueuedWriteIOBuffer() - : total_size_(0), - max_buffer_size_(kDefaultMaxBufferSize) { -} + : max_buffer_size_(kDefaultMaxBufferSize) {} HttpConnection::QueuedWriteIOBuffer::~QueuedWriteIOBuffer() { data_ = nullptr; // pending_data_ owns data_.
diff --git a/net/server/http_connection.h b/net/server/http_connection.h index 8f3eaa0d..b59d1b8 100644 --- a/net/server/http_connection.h +++ b/net/server/http_connection.h
@@ -109,7 +109,7 @@ // This needs to indirect since we need pointer stability for the payload // chunks, as they may be handed out via net::IOBuffer::data(). base::queue<std::unique_ptr<std::string>> pending_data_; - int total_size_; + int total_size_ = 0; int max_buffer_size_; };
diff --git a/net/server/http_server.cc b/net/server/http_server.cc index 909ed5c..b9a556e 100644 --- a/net/server/http_server.cc +++ b/net/server/http_server.cc
@@ -54,9 +54,7 @@ HttpServer::HttpServer(std::unique_ptr<ServerSocket> server_socket, HttpServer::Delegate* delegate) - : server_socket_(std::move(server_socket)), - delegate_(delegate), - last_id_(0) { + : server_socket_(std::move(server_socket)), delegate_(delegate) { DCHECK(server_socket_); // Start accepting connections in next run loop in case when delegate is not // ready to get callbacks.
diff --git a/net/server/http_server.h b/net/server/http_server.h index 7ca9406..30f1735 100644 --- a/net/server/http_server.h +++ b/net/server/http_server.h
@@ -132,7 +132,7 @@ std::unique_ptr<StreamSocket> accepted_socket_; const raw_ptr<HttpServer::Delegate> delegate_; - int last_id_; + int last_id_ = 0; std::map<int, std::unique_ptr<HttpConnection>> id_to_connection_; base::WeakPtrFactory<HttpServer> weak_ptr_factory_{this};
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc index 72fccea1..ea67618e 100644 --- a/net/server/http_server_unittest.cc +++ b/net/server/http_server_unittest.cc
@@ -178,7 +178,7 @@ class HttpServerTest : public TestWithTaskEnvironment, public HttpServer::Delegate { public: - HttpServerTest() : quit_on_close_connection_(-1) {} + HttpServerTest() = default; void SetUp() override { std::unique_ptr<ServerSocket> server_socket( @@ -276,7 +276,7 @@ private: base::test::RepeatingTestFuture<ReceivedRequest> received_requests_; std::unique_ptr<base::RunLoop> quit_on_create_loop_; - int quit_on_close_connection_; + int quit_on_close_connection_ = -1; }; namespace { @@ -943,7 +943,7 @@ class MockStreamSocket : public StreamSocket { public: - MockStreamSocket() : connected_(true), read_buf_(nullptr), read_buf_len_(0) {} + MockStreamSocket() : read_buf_(nullptr) {} MockStreamSocket(const MockStreamSocket&) = delete; MockStreamSocket& operator=(const MockStreamSocket&) = delete; @@ -1027,9 +1027,9 @@ private: ~MockStreamSocket() override = default; - bool connected_; + bool connected_ = true; scoped_refptr<IOBuffer> read_buf_; - int read_buf_len_; + int read_buf_len_ = 0; CompletionOnceCallback read_callback_; std::string pending_read_data_; NetLogWithSource net_log_;
diff --git a/net/server/web_socket.cc b/net/server/web_socket.cc index 6046222..c4155cb7 100644 --- a/net/server/web_socket.cc +++ b/net/server/web_socket.cc
@@ -52,7 +52,7 @@ } // namespace WebSocket::WebSocket(HttpServer* server, HttpConnection* connection) - : server_(server), connection_(connection), closed_(false) {} + : server_(server), connection_(connection) {} WebSocket::~WebSocket() = default;
diff --git a/net/server/web_socket.h b/net/server/web_socket.h index af27eb6..ce53804e6 100644 --- a/net/server/web_socket.h +++ b/net/server/web_socket.h
@@ -56,7 +56,7 @@ const raw_ptr<HttpServer> server_; const raw_ptr<HttpConnection> connection_; std::unique_ptr<WebSocketEncoder> encoder_; - bool closed_; + bool closed_ = false; std::unique_ptr<NetworkTrafficAnnotationTag> traffic_annotation_ = nullptr; };
diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc index 8de84106..a51fea51 100644 --- a/net/socket/client_socket_handle.cc +++ b/net/socket/client_socket_handle.cc
@@ -21,13 +21,9 @@ namespace net { ClientSocketHandle::ClientSocketHandle() - : is_initialized_(false), - pool_(nullptr), + : pool_(nullptr), higher_pool_(nullptr), - reuse_type_(ClientSocketHandle::UNUSED), - group_generation_(-1), - resolve_error_info_(ResolveErrorInfo(OK)), - is_ssl_error_(false) {} + resolve_error_info_(ResolveErrorInfo(OK)) {} ClientSocketHandle::~ClientSocketHandle() { Reset();
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h index 48dd94f..6f68a98 100644 --- a/net/socket/client_socket_handle.h +++ b/net/socket/client_socket_handle.h
@@ -228,18 +228,18 @@ // Resets the supplemental error state. void ResetErrorState(); - bool is_initialized_; + bool is_initialized_ = false; raw_ptr<ClientSocketPool> pool_; raw_ptr<HigherLayeredPool> higher_pool_; std::unique_ptr<StreamSocket> socket_; ClientSocketPool::GroupId group_id_; - SocketReuseType reuse_type_; + SocketReuseType reuse_type_ = ClientSocketHandle::UNUSED; CompletionOnceCallback callback_; base::TimeDelta idle_time_; // See ClientSocketPool::ReleaseSocket() for an explanation. - int64_t group_generation_; + int64_t group_generation_ = -1; ResolveErrorInfo resolve_error_info_; - bool is_ssl_error_; + bool is_ssl_error_ = false; scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_; std::vector<ConnectionAttempt> connection_attempts_;
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index ae102ac..c5dded33 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -148,10 +148,7 @@ class MockClientSocket : public StreamSocket { public: explicit MockClientSocket(net::NetLog* net_log) - : connected_(false), - has_unread_data_(false), - net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)), - was_used_to_convey_data_(false) {} + : net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {} MockClientSocket(const MockClientSocket&) = delete; MockClientSocket& operator=(const MockClientSocket&) = delete; @@ -218,17 +215,17 @@ void ApplySocketTag(const SocketTag& tag) override {} private: - bool connected_; - bool has_unread_data_; + bool connected_ = false; + bool has_unread_data_ = false; NetLogWithSource net_log_; - bool was_used_to_convey_data_; + bool was_used_to_convey_data_ = false; }; class TestConnectJob; class MockClientSocketFactory : public ClientSocketFactory { public: - MockClientSocketFactory() : allocation_count_(0) {} + MockClientSocketFactory() = default; std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket( DatagramSocket::BindType bind_type, @@ -273,7 +270,7 @@ int allocation_count() const { return allocation_count_; } private: - int allocation_count_; + int allocation_count_ = 0; std::vector<TestConnectJob*> waiting_jobs_; }; @@ -320,10 +317,7 @@ NetLogSourceType::TRANSPORT_CONNECT_JOB, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT), job_type_(job_type), - client_socket_factory_(client_socket_factory), - load_state_(LOAD_STATE_IDLE), - has_established_connection_(false), - store_additional_error_state_(false) {} + client_socket_factory_(client_socket_factory) {} TestConnectJob(const TestConnectJob&) = delete; TestConnectJob& operator=(const TestConnectJob&) = delete; @@ -517,9 +511,9 @@ bool waiting_success_; const JobType job_type_; const raw_ptr<MockClientSocketFactory> client_socket_factory_; - LoadState load_state_; - bool has_established_connection_; - bool store_additional_error_state_; + LoadState load_state_ = LOAD_STATE_IDLE; + bool has_established_connection_ = false; + bool store_additional_error_state_ = false; base::WeakPtrFactory<TestConnectJob> weak_factory_{this}; }; @@ -4860,7 +4854,7 @@ public: MockLayeredPool(TransportClientSocketPool* pool, const ClientSocketPool::GroupId& group_id) - : pool_(pool), group_id_(group_id), can_release_connection_(true) { + : pool_(pool), group_id_(group_id) { pool_->AddHigherLayeredPool(this); } @@ -4902,7 +4896,7 @@ ClientSocketHandle handle_; TestCompletionCallback callback_; const ClientSocketPool::GroupId group_id_; - bool can_release_connection_; + bool can_release_connection_ = true; }; // Tests the basic case of closing an idle socket in a higher layered pool when
diff --git a/net/socket/connect_job_unittest.cc b/net/socket/connect_job_unittest.cc index 39a1329..8e8918b 100644 --- a/net/socket/connect_job_unittest.cc +++ b/net/socket/connect_job_unittest.cc
@@ -43,8 +43,7 @@ nullptr /* net_log */, NetLogSourceType::TRANSPORT_CONNECT_JOB, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT), - job_type_(job_type), - last_seen_priority_(DEFAULT_PRIORITY) { + job_type_(job_type) { switch (job_type_) { case JobType::kSyncSuccess: socket_data_provider_.set_connect_data(MockConnect(SYNCHRONOUS, OK)); @@ -87,7 +86,7 @@ protected: const JobType job_type_; StaticSocketDataProvider socket_data_provider_; - RequestPriority last_seen_priority_; + RequestPriority last_seen_priority_ = DEFAULT_PRIORITY; }; class ConnectJobTest : public testing::Test {
diff --git a/net/socket/sequenced_socket_data_unittest.cc b/net/socket/sequenced_socket_data_unittest.cc index b8905f3..41843e8 100644 --- a/net/socket/sequenced_socket_data_unittest.cc +++ b/net/socket/sequenced_socket_data_unittest.cc
@@ -47,14 +47,7 @@ // a read or write operation specified by SetInvokeRead or SetInvokeWrite. class ReentrantHelper { public: - ReentrantHelper(StreamSocket* socket) - : socket_(socket), - verify_read_(false), - first_read_data_(nullptr), - first_len_(-1), - second_read_(false), - second_write_data_(nullptr), - second_len_(-1) {} + explicit ReentrantHelper(StreamSocket* socket) : socket_(socket) {} ReentrantHelper(const ReentrantHelper&) = delete; ReentrantHelper& operator=(const ReentrantHelper&) = delete; @@ -135,17 +128,17 @@ raw_ptr<StreamSocket> socket_; - bool verify_read_; + bool verify_read_ = false; scoped_refptr<IOBuffer> first_read_buf_; - const char* first_read_data_; - int first_len_; + const char* first_read_data_ = nullptr; + int first_len_ = -1; CompletionOnceCallback second_callback_; - bool second_read_; + bool second_read_ = false; int second_rv_; scoped_refptr<IOBuffer> second_read_buf_; - const char* second_write_data_; - int second_len_; + const char* second_write_data_ = nullptr; + int second_len_ = -1; }; class SequencedSocketDataTest : public TestWithTaskEnvironment { @@ -227,12 +220,12 @@ std::unique_ptr<SequencedSocketData> data_; MockClientSocketFactory socket_factory_; - bool expect_eof_; + bool expect_eof_ = true; std::unique_ptr<StreamSocket> sock_; }; -SequencedSocketDataTest::SequencedSocketDataTest() : expect_eof_(true) {} +SequencedSocketDataTest::SequencedSocketDataTest() = default; SequencedSocketDataTest::~SequencedSocketDataTest() { // Make sure no unexpected pending tasks will cause a failure.
diff --git a/net/socket/socket_bio_adapter.cc b/net/socket/socket_bio_adapter.cc index 8ff8c58..38423545 100644 --- a/net/socket/socket_bio_adapter.cc +++ b/net/socket/socket_bio_adapter.cc
@@ -62,11 +62,7 @@ Delegate* delegate) : socket_(socket), read_buffer_capacity_(read_buffer_capacity), - read_offset_(0), - read_result_(0), write_buffer_capacity_(write_buffer_capacity), - write_buffer_used_(0), - write_error_(OK), delegate_(delegate) { bio_.reset(BIO_new(&kBIOMethod)); bio_->ptr = this;
diff --git a/net/socket/socket_bio_adapter.h b/net/socket/socket_bio_adapter.h index f5fed240..487e9b7e 100644 --- a/net/socket/socket_bio_adapter.h +++ b/net/socket/socket_bio_adapter.h
@@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "net/base/completion_repeating_callback.h" +#include "net/base/net_errors.h" #include "net/base/net_export.h" #include "third_party/boringssl/src/include/openssl/base.h" @@ -120,11 +121,11 @@ // deallocated when unused. scoped_refptr<IOBuffer> read_buffer_; // The number of bytes of read_buffer_ consumed. - int read_offset_; + int read_offset_ = 0; // The result of the most recent socket Read(). If ERR_IO_PENDING, there is a // socket Read() in progress. If another error, Read() has failed. Otherwise, // it is the number of bytes in the buffer (zero if empty). - int read_result_; + int read_result_ = 0; // The capacity of the write buffer. int write_buffer_capacity_; @@ -133,11 +134,11 @@ // Write(). The buffer is deallocated when unused. scoped_refptr<GrowableIOBuffer> write_buffer_; // The number of bytes of data in write_buffer_. - int write_buffer_used_; + int write_buffer_used_ = 0; // The most recent socket Write() error. If ERR_IO_PENDING, there is a socket // Write() in progress. If OK, there is no socket Write() in progress and none // have failed. - int write_error_; + int write_error_ = OK; raw_ptr<Delegate> delegate_;
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc index c3b6eb06..1e054bd7 100644 --- a/net/socket/socket_posix.cc +++ b/net/socket/socket_posix.cc
@@ -72,10 +72,7 @@ : socket_fd_(kInvalidSocket), accept_socket_watcher_(FROM_HERE), read_socket_watcher_(FROM_HERE), - read_buf_len_(0), - write_socket_watcher_(FROM_HERE), - write_buf_len_(0), - waiting_connect_(false) {} + write_socket_watcher_(FROM_HERE) {} SocketPosix::~SocketPosix() { Close();
diff --git a/net/socket/socket_posix.h b/net/socket/socket_posix.h index 29b0209..02d1600 100644 --- a/net/socket/socket_posix.h +++ b/net/socket/socket_posix.h
@@ -137,7 +137,7 @@ // Non-null when a Read() is in progress. scoped_refptr<IOBuffer> read_buf_; - int read_buf_len_; + int read_buf_len_ = 0; CompletionOnceCallback read_callback_; // Non-null when a ReadIfReady() is in progress. @@ -145,13 +145,13 @@ base::MessagePumpForIO::FdWatchController write_socket_watcher_; scoped_refptr<IOBuffer> write_buf_; - int write_buf_len_; + int write_buf_len_ = 0; // External callback; called when write or connect is complete. CompletionOnceCallback write_callback_; // A connect operation is pending. In this case, |write_callback_| needs to be // called when connect is complete. - bool waiting_connect_; + bool waiting_connect_ = false; std::unique_ptr<SockaddrStorage> peer_address_;
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 028a6a7b..f9f41402 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -187,7 +187,7 @@ StaticSocketDataHelper::StaticSocketDataHelper( base::span<const MockRead> reads, base::span<const MockWrite> writes) - : reads_(reads), read_index_(0), writes_(writes), write_index_(0) {} + : reads_(reads), writes_(writes) {} StaticSocketDataHelper::~StaticSocketDataHelper() = default; @@ -334,8 +334,6 @@ SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result) : connect(mode, result), - next_proto(kProtoUnknown), - cert_request_info(nullptr), expected_ssl_version_min(kDefaultSSLVersionMin), expected_ssl_version_max(kDefaultSSLVersionMax) { SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_3, @@ -743,8 +741,7 @@ SequencedSocketData::~SequencedSocketData() = default; -MockClientSocketFactory::MockClientSocketFactory() - : enable_read_if_ready_(false) {} +MockClientSocketFactory::MockClientSocketFactory() = default; MockClientSocketFactory::~MockClientSocketFactory() = default; @@ -859,7 +856,7 @@ } MockClientSocket::MockClientSocket(const NetLogWithSource& net_log) - : connected_(false), net_log_(net_log) { + : net_log_(net_log) { local_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 123); peer_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 0); } @@ -942,14 +939,8 @@ : MockClientSocket(NetLogWithSource::Make(net_log, NetLogSourceType::NONE)), addresses_(addresses), data_(data), - read_offset_(0), read_data_(SYNCHRONOUS, ERR_UNEXPECTED), - need_read_data_(true), - peer_closed_connection_(false), - pending_read_buf_(nullptr), - pending_read_buf_len_(0), - was_used_to_convey_data_(false), - enable_read_if_ready_(false) { + pending_read_buf_(nullptr) { DCHECK(data_); peer_addr_ = data->connect_data().peer_addr; data_->Initialize(this); @@ -1510,16 +1501,11 @@ MockUDPClientSocket::MockUDPClientSocket(SocketDataProvider* data, net::NetLog* net_log) - : connected_(false), - data_(data), - read_offset_(0), + : data_(data), read_data_(SYNCHRONOUS, ERR_UNEXPECTED), - need_read_data_(true), source_host_(IPAddress(192, 0, 2, 33)), - source_port_(123), network_(NetworkChangeNotifier::kInvalidNetworkHandle), pending_read_buf_(nullptr), - pending_read_buf_len_(0), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::NONE)) { if (data_) { data_->Initialize(this); @@ -1868,7 +1854,7 @@ // static const int ClientSocketPoolTest::kRequestNotFound = -2; -ClientSocketPoolTest::ClientSocketPoolTest() : completion_count_(0) {} +ClientSocketPoolTest::ClientSocketPoolTest() = default; ClientSocketPoolTest::~ClientSocketPoolTest() = default; int ClientSocketPoolTest::GetOrderOfRequest(size_t index) const { @@ -1980,10 +1966,8 @@ ProxyServer::Direct(), false /* is_for_websockets */, common_connect_job_params), - client_socket_factory_(common_connect_job_params->client_socket_factory), - last_request_priority_(DEFAULT_PRIORITY), - release_count_(0), - cancel_count_(0) {} + client_socket_factory_(common_connect_job_params->client_socket_factory) { +} MockTransportClientSocketPool::~MockTransportClientSocketPool() = default;
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 147b03a..788df9d 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -409,9 +409,9 @@ const MockWrite& PeekRealWrite() const; const base::span<const MockRead> reads_; - size_t read_index_; + size_t read_index_ = 0; const base::span<const MockWrite> writes_; - size_t write_index_; + size_t write_index_ = 0; }; // SocketDataProvider which responds based on static tables of mock reads and @@ -483,7 +483,7 @@ base::RepeatingClosure confirm_callback; // Result for GetNegotiatedProtocol(). - NextProto next_proto; + NextProto next_proto = kProtoUnknown; // Result for GetPeerApplicationSettings(). absl::optional<std::string> peer_application_settings; @@ -492,7 +492,7 @@ SSLInfo ssl_info; // Result for GetSSLCertRequestInfo(). - SSLCertRequestInfo* cert_request_info; + SSLCertRequestInfo* cert_request_info = nullptr; // Result for GetECHRetryConfigs(). std::vector<uint8_t> ech_retry_configs; @@ -713,7 +713,7 @@ // If true, ReadIfReady() is enabled; otherwise ReadIfReady() returns // ERR_READ_IF_READY_NOT_IMPLEMENTED. - bool enable_read_if_ready_; + bool enable_read_if_ready_ = false; }; class MockClientSocket : public TransportClientSocket { @@ -761,7 +761,7 @@ void RunCallback(CompletionOnceCallback callback, int result); // True if Connect completed successfully and Disconnect hasn't been called. - bool connected_; + bool connected_ = false; IPEndPoint local_addr_; IPEndPoint peer_addr_; @@ -837,18 +837,18 @@ AddressList addresses_; raw_ptr<SocketDataProvider> data_; - int read_offset_; + int read_offset_ = 0; MockRead read_data_; - bool need_read_data_; + bool need_read_data_ = true; // True if the peer has closed the connection. This allows us to simulate // the recv(..., MSG_PEEK) call in the IsConnectedAndIdle method of the real // TCPClientSocket. - bool peer_closed_connection_; + bool peer_closed_connection_ = false; // While an asynchronous read is pending, we save our user-buffer state. scoped_refptr<IOBuffer> pending_read_buf_; - int pending_read_buf_len_; + int pending_read_buf_len_ = 0; CompletionOnceCallback pending_read_callback_; // Non-null when a ReadIfReady() is pending. @@ -856,11 +856,11 @@ CompletionOnceCallback pending_connect_callback_; CompletionOnceCallback pending_write_callback_; - bool was_used_to_convey_data_; + bool was_used_to_convey_data_ = false; // If true, ReadIfReady() is enabled; otherwise ReadIfReady() returns // ERR_READ_IF_READY_NOT_IMPLEMENTED. - bool enable_read_if_ready_; + bool enable_read_if_ready_ = false; BeforeConnectCallback before_connect_callback_; }; @@ -1033,13 +1033,13 @@ void RunCallbackAsync(CompletionOnceCallback callback, int result); void RunCallback(CompletionOnceCallback callback, int result); - bool connected_; + bool connected_ = false; raw_ptr<SocketDataProvider> data_; - int read_offset_; + int read_offset_ = 0; MockRead read_data_; - bool need_read_data_; + bool need_read_data_ = true; IPAddress source_host_; - uint16_t source_port_; // Ephemeral source port. + uint16_t source_port_ = 123; // Ephemeral source port. // Address of the "remote" peer we're connected to. IPEndPoint peer_addr_; @@ -1049,7 +1049,7 @@ // While an asynchronous IO is pending, we save our user-buffer state. scoped_refptr<IOBuffer> pending_read_buf_; - int pending_read_buf_len_; + int pending_read_buf_len_ = 0; CompletionOnceCallback pending_read_callback_; CompletionOnceCallback pending_write_callback_; @@ -1154,7 +1154,7 @@ private: std::vector<std::unique_ptr<TestSocketRequest>> requests_; std::vector<TestSocketRequest*> request_order_; - size_t completion_count_; + size_t completion_count_ = 0; }; class MockTransportSocketParams @@ -1249,9 +1249,9 @@ private: raw_ptr<ClientSocketFactory> client_socket_factory_; std::vector<std::unique_ptr<MockConnectJob>> job_list_; - RequestPriority last_request_priority_; - int release_count_; - int cancel_count_; + RequestPriority last_request_priority_ = DEFAULT_PRIORITY; + int release_count_ = 0; + int cancel_count_ = 0; }; // WrappedStreamSocket is a base class that wraps an existing StreamSocket,
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc index dce65101..cc8dd8a0 100644 --- a/net/socket/socks5_client_socket.cc +++ b/net/socket/socks5_client_socket.cc
@@ -38,12 +38,7 @@ : io_callback_(base::BindRepeating(&SOCKS5ClientSocket::OnIOComplete, base::Unretained(this))), transport_socket_(std::move(transport_socket)), - next_state_(STATE_NONE), - completed_handshake_(false), - bytes_sent_(0), - bytes_received_(0), read_header_size(kReadHeaderSize), - was_ever_used_(false), destination_(destination), net_log_(transport_socket_->NetLog()), traffic_annotation_(traffic_annotation) {}
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h index 41b58b6..5612be0 100644 --- a/net/socket/socks5_client_socket.h +++ b/net/socket/socks5_client_socket.h
@@ -125,7 +125,7 @@ // Stores the underlying socket. std::unique_ptr<StreamSocket> transport_socket_; - State next_state_; + State next_state_ = STATE_NONE; // Stores the callback to the layer above, called on completing Connect(). CompletionOnceCallback user_callback_; @@ -141,15 +141,15 @@ // This becomes true when the SOCKS handshake has completed and the // overlying connection is free to communicate. - bool completed_handshake_; + bool completed_handshake_ = false; // These contain the bytes sent / received by the SOCKS handshake. - size_t bytes_sent_; - size_t bytes_received_; + size_t bytes_sent_ = 0; + size_t bytes_received_ = 0; size_t read_header_size; - bool was_ever_used_; + bool was_ever_used_ = false; const HostPortPair destination_;
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc index 782e4822..a6887260 100644 --- a/net/socket/socks_client_socket.cc +++ b/net/socket/socks_client_socket.cc
@@ -68,11 +68,6 @@ SecureDnsPolicy secure_dns_policy, const NetworkTrafficAnnotationTag& traffic_annotation) : transport_socket_(std::move(transport_socket)), - next_state_(STATE_NONE), - completed_handshake_(false), - bytes_sent_(0), - bytes_received_(0), - was_ever_used_(false), host_resolver_(host_resolver), secure_dns_policy_(secure_dns_policy), destination_(destination),
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h index d053827b..1f30a219 100644 --- a/net/socket/socks_client_socket.h +++ b/net/socket/socks_client_socket.h
@@ -117,7 +117,7 @@ // Stores the underlying socket. std::unique_ptr<StreamSocket> transport_socket_; - State next_state_; + State next_state_ = STATE_NONE; // Stores the callbacks to the layer above, called on completing Connect(). CompletionOnceCallback user_callback_; @@ -133,14 +133,14 @@ // This becomes true when the SOCKS handshake has completed and the // overlying connection is free to communicate. - bool completed_handshake_; + bool completed_handshake_ = false; // These contain the bytes sent / received by the SOCKS handshake. - size_t bytes_sent_; - size_t bytes_received_; + size_t bytes_sent_ = 0; + size_t bytes_received_ = 0; // This becomes true when the socket is used to send or receive data. - bool was_ever_used_; + bool was_ever_used_ = false; // Used to resolve the hostname to which the SOCKS proxy will connect. raw_ptr<HostResolver> host_resolver_;
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc index 0e86859..08bfe951 100644 --- a/net/socket/ssl_client_socket.cc +++ b/net/socket/ssl_client_socket.cc
@@ -15,9 +15,7 @@ namespace net { -SSLClientSocket::SSLClientSocket() - : signed_cert_timestamps_received_(false), - stapled_ocsp_response_received_(false) {} +SSLClientSocket::SSLClientSocket() = default; // static void SSLClientSocket::SetSSLKeyLogger(std::unique_ptr<SSLKeyLogger> logger) {
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index a49095c..35ca217 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h
@@ -80,9 +80,9 @@ ConnectSignedCertTimestampsEnablesOCSP); // True if SCTs were received via a TLS extension. - bool signed_cert_timestamps_received_; + bool signed_cert_timestamps_received_ = false; // True if a stapled OCSP response was received. - bool stapled_ocsp_response_received_; + bool stapled_ocsp_response_received_ = false; }; // Shared state and configuration across multiple SSLClientSockets.
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 9943a21e..fd2171c 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -382,23 +382,12 @@ const HostPortPair& host_and_port, const SSLConfig& ssl_config) : pending_read_error_(kSSLClientSocketNoPendingResult), - pending_read_ssl_error_(SSL_ERROR_NONE), - completed_connect_(false), - was_ever_used_(false), context_(context), cert_verification_result_(kCertVerifyPending), stream_socket_(std::move(stream_socket)), host_and_port_(host_and_port), ssl_config_(ssl_config), - next_handshake_state_(STATE_NONE), - in_confirm_handshake_(false), - peek_complete_(false), - disconnected_(false), - negotiated_protocol_(kProtoUnknown), - certificate_requested_(false), signature_result_(kSSLClientSocketNoPendingResult), - pkp_bypassed_(false), - is_fatal_cert_error_(false), net_log_(stream_socket_->NetLog()) { CHECK(context_); }
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h index deed27f..e8c93487 100644 --- a/net/socket/ssl_client_socket_impl.h +++ b/net/socket/ssl_client_socket_impl.h
@@ -239,7 +239,7 @@ // If there is a pending read result, the OpenSSL result code (output of // SSL_get_error) associated with it. - int pending_read_ssl_error_; + int pending_read_ssl_error_ = SSL_ERROR_NONE; // If there is a pending read result, the OpenSSLErrorInfo associated with it. OpenSSLErrorInfo pending_read_error_info_; @@ -247,11 +247,11 @@ // Set when Connect finishes. scoped_refptr<X509Certificate> server_cert_; CertVerifyResult server_cert_verify_result_; - bool completed_connect_; + bool completed_connect_ = false; // Set when Read() or Write() successfully reads or writes data to or from the // network. - bool was_ever_used_; + bool was_ever_used_ = false; const raw_ptr<SSLClientContext> context_; @@ -274,24 +274,24 @@ STATE_HANDSHAKE, STATE_HANDSHAKE_COMPLETE, }; - State next_handshake_state_; + State next_handshake_state_ = STATE_NONE; // True if we are currently confirming the handshake. - bool in_confirm_handshake_; + bool in_confirm_handshake_ = false; // True if the post-handshake SSL_peek has completed. - bool peek_complete_; + bool peek_complete_ = false; // True if the socket has been disconnected. - bool disconnected_; + bool disconnected_ = false; // True if certificate verification used an ECH name override. bool used_ech_name_override_ = false; - NextProto negotiated_protocol_; + NextProto negotiated_protocol_ = kProtoUnknown; // Set to true if a CertificateRequest was received. - bool certificate_requested_; + bool certificate_requested_ = false; int signature_result_; std::vector<uint8_t> signature_; @@ -302,11 +302,11 @@ std::string pinning_failure_log_; // True if PKP is bypassed due to a local trust anchor. - bool pkp_bypassed_; + bool pkp_bypassed_ = false; // True if there was a certificate error which should be treated as fatal, // and false otherwise. - bool is_fatal_cert_error_; + bool is_fatal_cert_error_ = false; // True if the socket should respond to client certificate requests with // |client_cert_| and |client_private_key_|, which may be null to continue
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index ffbb0cc1..a01a153 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -531,9 +531,7 @@ class CountingStreamSocket : public WrappedStreamSocket { public: explicit CountingStreamSocket(std::unique_ptr<StreamSocket> transport) - : WrappedStreamSocket(std::move(transport)), - read_count_(0), - write_count_(0) {} + : WrappedStreamSocket(std::move(transport)) {} ~CountingStreamSocket() override = default; // Socket implementation: @@ -556,8 +554,8 @@ int write_count() const { return write_count_; } private: - int read_count_; - int write_count_; + int read_count_ = 0; + int write_count_ = 0; }; // A helper class that will delete |socket| when the callback is invoked. @@ -593,7 +591,7 @@ // reported and the number of violations reported. class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { public: - MockExpectCTReporter() : num_failures_(0) {} + MockExpectCTReporter() = default; ~MockExpectCTReporter() override = default; void OnExpectCTFailed( @@ -634,7 +632,7 @@ private: HostPortPair host_port_pair_; GURL report_uri_; - uint32_t num_failures_; + uint32_t num_failures_ = 0; raw_ptr<const X509Certificate> served_certificate_chain_; raw_ptr<const X509Certificate> validated_certificate_chain_; SignedCertificateTimestampAndStatusList signed_certificate_timestamps_;
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc index af1a435..6646027 100644 --- a/net/socket/ssl_connect_job.cc +++ b/net/socket/ssl_connect_job.cc
@@ -134,9 +134,7 @@ NetLogEventType::SSL_CONNECT_JOB_CONNECT), params_(std::move(params)), callback_(base::BindRepeating(&SSLConnectJob::OnIOComplete, - base::Unretained(this))), - ssl_negotiation_started_(false), - disable_legacy_crypto_with_fallback_(true) {} + base::Unretained(this))) {} SSLConnectJob::~SSLConnectJob() { // In the case the job was canceled, need to delete nested job first to
diff --git a/net/socket/ssl_connect_job.h b/net/socket/ssl_connect_job.h index 66b9d0f..7d4c3c21 100644 --- a/net/socket/ssl_connect_job.h +++ b/net/socket/ssl_connect_job.h
@@ -188,12 +188,12 @@ std::unique_ptr<SSLClientSocket> ssl_socket_; // True once SSL negotiation has started. - bool ssl_negotiation_started_; + bool ssl_negotiation_started_ = false; // True if legacy crypto should be disabled for the job's current connection // attempt. On error, the connection will be retried with legacy crypto // enabled. - bool disable_legacy_crypto_with_fallback_; + bool disable_legacy_crypto_with_fallback_ = true; scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_;
diff --git a/net/socket/ssl_server_socket_impl.cc b/net/socket/ssl_server_socket_impl.cc index 1e2a9f4..5b6598c 100644 --- a/net/socket/ssl_server_socket_impl.cc +++ b/net/socket/ssl_server_socket_impl.cc
@@ -180,17 +180,17 @@ // Used by Read function. scoped_refptr<IOBuffer> user_read_buf_; - int user_read_buf_len_; + int user_read_buf_len_ = 0; // Used by Write function. scoped_refptr<IOBuffer> user_write_buf_; - int user_write_buf_len_; + int user_write_buf_len_ = 0; // OpenSSL stuff bssl::UniquePtr<SSL> ssl_; // Whether we received any data in early data. - bool early_data_received_; + bool early_data_received_ = false; // StreamSocket for sending and receiving data. std::unique_ptr<StreamSocket> transport_socket_; @@ -199,10 +199,10 @@ // Certificate for the client. scoped_refptr<X509Certificate> client_cert_; - State next_handshake_state_; - bool completed_handshake_; + State next_handshake_state_ = STATE_NONE; + bool completed_handshake_ = false; - NextProto negotiated_protocol_; + NextProto negotiated_protocol_ = kProtoUnknown; base::WeakPtrFactory<SocketImpl> weak_factory_{this}; }; @@ -212,13 +212,7 @@ std::unique_ptr<StreamSocket> transport_socket) : context_(context), signature_result_(kSSLServerSocketNoPendingResult), - user_read_buf_len_(0), - user_write_buf_len_(0), - early_data_received_(false), - transport_socket_(std::move(transport_socket)), - next_handshake_state_(STATE_NONE), - completed_handshake_(false), - negotiated_protocol_(kProtoUnknown) {} + transport_socket_(std::move(transport_socket)) {} SSLServerContextImpl::SocketImpl::~SocketImpl() { if (ssl_) {
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index e59ce1da..1225c7aa 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -106,8 +106,7 @@ class FakeDataChannel { public: - FakeDataChannel() - : read_buf_len_(0), closed_(false), write_called_after_close_(false) {} + FakeDataChannel() = default; FakeDataChannel(const FakeDataChannel&) = delete; FakeDataChannel& operator=(const FakeDataChannel&) = delete; @@ -203,19 +202,19 @@ CompletionOnceCallback read_callback_; scoped_refptr<IOBuffer> read_buf_; - int read_buf_len_; + int read_buf_len_ = 0; CompletionOnceCallback write_callback_; base::queue<scoped_refptr<DrainableIOBuffer>> data_; // True if Close() has been called. - bool closed_; + bool closed_ = false; // Controls the completion of Write() after the FakeDataChannel is closed. // After the FakeDataChannel is closed, the first Write() call completes // asynchronously. - bool write_called_after_close_; + bool write_called_after_close_ = false; base::WeakPtrFactory<FakeDataChannel> weak_factory_{this}; };
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc index 879ae08a..4d5d3f1b 100644 --- a/net/socket/tcp_client_socket_unittest.cc +++ b/net/socket/tcp_client_socket_unittest.cc
@@ -295,7 +295,7 @@ class TestSocketPerformanceWatcher : public SocketPerformanceWatcher { public: - TestSocketPerformanceWatcher() : connection_changed_count_(0u) {} + TestSocketPerformanceWatcher() = default; TestSocketPerformanceWatcher(const TestSocketPerformanceWatcher&) = delete; TestSocketPerformanceWatcher& operator=(const TestSocketPerformanceWatcher&) = @@ -312,7 +312,7 @@ size_t connection_changed_count() const { return connection_changed_count_; } private: - size_t connection_changed_count_; + size_t connection_changed_count_ = 0u; }; // TestSocketPerformanceWatcher requires kernel support for tcp_info struct, and
diff --git a/net/socket/tcp_socket_posix.cc b/net/socket/tcp_socket_posix.cc index 850ad7e..8d9f5bc 100644 --- a/net/socket/tcp_socket_posix.cc +++ b/net/socket/tcp_socket_posix.cc
@@ -162,7 +162,6 @@ NetLog* net_log, const NetLogSource& source) : socket_performance_watcher_(std::move(socket_performance_watcher)), - logging_multiple_connect_attempts_(false), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) { net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source); }
diff --git a/net/socket/tcp_socket_posix.h b/net/socket/tcp_socket_posix.h index c77ea723..7d5feff 100644 --- a/net/socket/tcp_socket_posix.h +++ b/net/socket/tcp_socket_posix.h
@@ -218,7 +218,7 @@ // |socket_performance_watcher_|. May be nullptr. std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher_; - bool logging_multiple_connect_attempts_; + bool logging_multiple_connect_attempts_ = false; NetLogWithSource net_log_;
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc index 51f20a1..28264b4 100644 --- a/net/socket/tcp_socket_unittest.cc +++ b/net/socket/tcp_socket_unittest.cc
@@ -82,9 +82,7 @@ class TestSocketPerformanceWatcher : public SocketPerformanceWatcher { public: explicit TestSocketPerformanceWatcher(bool should_notify_updated_rtt) - : should_notify_updated_rtt_(should_notify_updated_rtt), - connection_changed_count_(0u), - rtt_notification_count_(0u) {} + : should_notify_updated_rtt_(should_notify_updated_rtt) {} TestSocketPerformanceWatcher(const TestSocketPerformanceWatcher&) = delete; TestSocketPerformanceWatcher& operator=(const TestSocketPerformanceWatcher&) = @@ -108,8 +106,8 @@ private: const bool should_notify_updated_rtt_; - size_t connection_changed_count_; - size_t rtt_notification_count_; + size_t connection_changed_count_ = 0u; + size_t rtt_notification_count_ = 0u; }; const int kListenBacklog = 5;
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc index 640f19d9..0d57f2cb 100644 --- a/net/socket/transport_client_socket_pool.cc +++ b/net/socket/transport_client_socket_pool.cc
@@ -1440,10 +1440,7 @@ TransportClientSocketPool* client_socket_pool) : group_id_(group_id), client_socket_pool_(client_socket_pool), - never_assigned_job_count_(0), - unbound_requests_(NUM_PRIORITIES), - active_socket_count_(0), - generation_(0) {} + unbound_requests_(NUM_PRIORITIES) {} TransportClientSocketPool::Group::~Group() { DCHECK_EQ(0u, never_assigned_job_count());
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h index 92cec633..60de4755 100644 --- a/net/socket/transport_client_socket_pool.h +++ b/net/socket/transport_client_socket_pool.h
@@ -529,7 +529,7 @@ // preconnect and decremented when a preconnect is assigned, or when there // are fewer than |never_assigned_job_count_| ConnectJobs. Not incremented // when a request is cancelled. - size_t never_assigned_job_count_; + size_t never_assigned_job_count_ = 0; std::list<IdleSocket> idle_sockets_; JobList jobs_; // For bookkeeping purposes, there is a copy of the raw @@ -538,7 +538,7 @@ // element of |unbound_requests_|. std::list<ConnectJob*> unassigned_jobs_; RequestQueue unbound_requests_; - int active_socket_count_; // number of active sockets used by clients + int active_socket_count_ = 0; // number of active sockets used by clients // A timer for when to start the backup job. base::OneShotTimer backup_job_timer_; @@ -553,7 +553,7 @@ // rather than reused. Destroying a group will reset the generation number, // but as that only happens once there are no outstanding sockets or // requests associated with the group, that's harmless. - int64_t generation_; + int64_t generation_ = 0; }; using GroupMap = std::map<GroupId, Group*>;
diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc index ac4cc87..184f21a 100644 --- a/net/socket/transport_client_socket_pool_test_util.cc +++ b/net/socket/transport_client_socket_pool_test_util.cc
@@ -44,8 +44,7 @@ class MockConnectClientSocket : public TransportClientSocket { public: MockConnectClientSocket(const AddressList& addrlist, net::NetLog* net_log) - : connected_(false), - addrlist_(addrlist), + : addrlist_(addrlist), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {} MockConnectClientSocket(const MockConnectClientSocket&) = delete; @@ -106,7 +105,7 @@ int SetSendBufferSize(int32_t size) override { return OK; } private: - bool connected_; + bool connected_ = false; const AddressList addrlist_; NetLogWithSource net_log_; }; @@ -186,7 +185,6 @@ Error connect_error, net::NetLog* net_log) : connect_error_(connect_error), - is_connected_(false), addrlist_(addrlist), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {} @@ -299,7 +297,7 @@ } Error connect_error_; - bool is_connected_; + bool is_connected_ = false; const AddressList addrlist_; NetLogWithSource net_log_; CompletionOnceCallback callback_; @@ -364,8 +362,6 @@ MockTransportClientSocketFactory::MockTransportClientSocketFactory( NetLog* net_log) : net_log_(net_log), - allocation_count_(0), - client_socket_type_(Type::kSynchronous), delay_(base::Milliseconds(ClientSocketPool::kMaxConnectRetryIntervalMs)) { }
diff --git a/net/socket/transport_client_socket_pool_test_util.h b/net/socket/transport_client_socket_pool_test_util.h index b619bf2..01b73b7b 100644 --- a/net/socket/transport_client_socket_pool_test_util.h +++ b/net/socket/transport_client_socket_pool_test_util.h
@@ -145,8 +145,8 @@ private: raw_ptr<NetLog> net_log_; - int allocation_count_; - Type client_socket_type_; + int allocation_count_ = 0; + Type client_socket_type_ = Type::kSynchronous; base::span<const Rule> rules_; base::TimeDelta delay_; base::queue<base::OnceClosure> triggerable_sockets_;
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 9d6af2d..3a6e3e1 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -862,8 +862,7 @@ : group_id_(group_id), socket_params_(socket_params), handle_(handle), - pool_(pool), - within_callback_(false) {} + pool_(pool) {} RequestSocketCallback(const RequestSocketCallback&) = delete; RequestSocketCallback& operator=(const RequestSocketCallback&) = delete; @@ -900,7 +899,7 @@ scoped_refptr<ClientSocketPool::SocketParams> socket_params_; const raw_ptr<ClientSocketHandle> handle_; const raw_ptr<TransportClientSocketPool> pool_; - bool within_callback_; + bool within_callback_ = false; }; TEST_F(TransportClientSocketPoolTest, RequestTwice) {
diff --git a/net/socket/transport_client_socket_unittest.cc b/net/socket/transport_client_socket_unittest.cc index cd21ee5401..10ee954 100644 --- a/net/socket/transport_client_socket_unittest.cc +++ b/net/socket/transport_client_socket_unittest.cc
@@ -45,8 +45,7 @@ public WithTaskEnvironment { public: TransportClientSocketTest() - : listen_port_(0), - socket_factory_(ClientSocketFactory::GetDefaultFactory()) {} + : socket_factory_(ClientSocketFactory::GetDefaultFactory()) {} ~TransportClientSocketTest() override = default; @@ -68,7 +67,7 @@ protected: base::RunLoop connect_loop_; - uint16_t listen_port_; + uint16_t listen_port_ = 0; RecordingNetLogObserver net_log_observer_; const raw_ptr<ClientSocketFactory> socket_factory_; std::unique_ptr<StreamSocket> sock_;
diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc index 8024299..8361b39 100644 --- a/net/socket/transport_connect_job.cc +++ b/net/socket/transport_connect_job.cc
@@ -132,8 +132,7 @@ net_log, NetLogSourceType::TRANSPORT_CONNECT_JOB, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT), - params_(params), - next_state_(STATE_NONE) { + params_(params) { if (endpoint_result_override) { has_dns_override_ = true; endpoint_results_ = {std::move(endpoint_result_override->result)};
diff --git a/net/socket/transport_connect_job.h b/net/socket/transport_connect_job.h index cb97bcb..029320656 100644 --- a/net/socket/transport_connect_job.h +++ b/net/socket/transport_connect_job.h
@@ -217,7 +217,7 @@ std::set<std::string> dns_aliases_; bool has_dns_override_ = false; - State next_state_; + State next_state_ = STATE_NONE; // The addresses are divided into IPv4 and IPv6, which are performed partially // in parallel. If the list of IPv6 addresses is non-empty, then the IPv6 jobs
diff --git a/net/socket/transport_connect_sub_job.cc b/net/socket/transport_connect_sub_job.cc index 28c9834d..0de0bba 100644 --- a/net/socket/transport_connect_sub_job.cc +++ b/net/socket/transport_connect_sub_job.cc
@@ -120,11 +120,7 @@ std::vector<IPEndPoint> addresses, TransportConnectJob* parent_job, SubJobType type) - : parent_job_(parent_job), - addresses_(std::move(addresses)), - current_address_index_(0), - next_state_(STATE_NONE), - type_(type) {} + : parent_job_(parent_job), addresses_(std::move(addresses)), type_(type) {} TransportConnectSubJob::~TransportConnectSubJob() = default;
diff --git a/net/socket/transport_connect_sub_job.h b/net/socket/transport_connect_sub_job.h index 09682264..807635a 100644 --- a/net/socket/transport_connect_sub_job.h +++ b/net/socket/transport_connect_sub_job.h
@@ -75,9 +75,9 @@ const raw_ptr<TransportConnectJob> parent_job_; std::vector<IPEndPoint> addresses_; - size_t current_address_index_; + size_t current_address_index_ = 0; - State next_state_; + State next_state_ = STATE_NONE; const SubJobType type_; std::unique_ptr<StreamSocket> transport_socket_;
diff --git a/net/socket/udp_server_socket.cc b/net/socket/udp_server_socket.cc index 58129d58..e16084b6 100644 --- a/net/socket/udp_server_socket.cc +++ b/net/socket/udp_server_socket.cc
@@ -13,10 +13,7 @@ UDPServerSocket::UDPServerSocket(net::NetLog* net_log, const net::NetLogSource& source) - : socket_(DatagramSocket::DEFAULT_BIND, net_log, source), - allow_address_reuse_(false), - allow_broadcast_(false), - allow_address_sharing_for_multicast_(false) {} + : socket_(DatagramSocket::DEFAULT_BIND, net_log, source) {} UDPServerSocket::~UDPServerSocket() = default;
diff --git a/net/socket/udp_server_socket.h b/net/socket/udp_server_socket.h index 9006f4e..1e51ccdd 100644 --- a/net/socket/udp_server_socket.h +++ b/net/socket/udp_server_socket.h
@@ -61,9 +61,9 @@ private: UDPSocket socket_; - bool allow_address_reuse_; - bool allow_broadcast_; - bool allow_address_sharing_for_multicast_; + bool allow_address_reuse_ = false; + bool allow_broadcast_ = false; + bool allow_address_sharing_for_multicast_ = false; }; } // namespace net
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc index c4b33de..8dfabde 100644 --- a/net/socket/udp_socket_posix.cc +++ b/net/socket/udp_socket_posix.cc
@@ -133,29 +133,16 @@ : write_async_watcher_(std::make_unique<WriteAsyncWatcher>(this)), sender_(new UDPSocketPosixSender()), socket_(kInvalidSocket), - socket_hash_(0), - addr_family_(0), - is_connected_(false), - socket_options_(SOCKET_OPTION_MULTICAST_LOOP), - sendto_flags_(0), - multicast_interface_(0), - multicast_time_to_live_(1), bind_type_(bind_type), read_socket_watcher_(FROM_HERE), write_socket_watcher_(FROM_HERE), read_watcher_(this), write_watcher_(this), - last_async_result_(0), - write_async_timer_running_(false), - write_async_outstanding_(0), - read_buf_len_(0), recv_from_address_(nullptr), - write_buf_len_(0), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)), bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle), always_update_bytes_received_(base::FeatureList::IsEnabled( - features::kUdpSocketPosixAlwaysUpdateBytesReceived)), - experimental_recv_optimization_enabled_(false) { + features::kUdpSocketPosixAlwaysUpdateBytesReceived)) { net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source); } @@ -1077,11 +1064,11 @@ tag_ = tag; } -UDPSocketPosixSender::UDPSocketPosixSender() : sendmmsg_enabled_(false) {} -UDPSocketPosixSender::~UDPSocketPosixSender() {} +UDPSocketPosixSender::UDPSocketPosixSender() = default; +UDPSocketPosixSender::~UDPSocketPosixSender() = default; SendResult::SendResult() : rv(0), write_count(0) {} -SendResult::~SendResult() {} +SendResult::~SendResult() = default; SendResult::SendResult(int _rv, int _write_count, DatagramBuffers _buffers) : rv(_rv), write_count(_write_count), buffers(std::move(_buffers)) {} SendResult::SendResult(SendResult&& other) = default;
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h index 9bd2e6d0..351c305 100644 --- a/net/socket/udp_socket_posix.h +++ b/net/socket/udp_socket_posix.h
@@ -84,6 +84,9 @@ public: UDPSocketPosixSender(); + UDPSocketPosixSender(const UDPSocketPosixSender&) = delete; + UDPSocketPosixSender& operator=(const UDPSocketPosixSender&) = delete; + SendResult SendBuffers(int fd, DatagramBuffers buffers); void SetSendmmsgEnabled(bool enabled) { @@ -113,9 +116,7 @@ #endif private: - UDPSocketPosixSender(const UDPSocketPosixSender&) = delete; - UDPSocketPosixSender& operator=(const UDPSocketPosixSender&) = delete; - bool sendmmsg_enabled_; + bool sendmmsg_enabled_ = false; }; class NET_EXPORT UDPSocketPosix { @@ -127,7 +128,7 @@ // throughput estimate. class ReceivedActivityMonitor { public: - ReceivedActivityMonitor() : bytes_(0), increments_(0) {} + ReceivedActivityMonitor() = default; ReceivedActivityMonitor(const ReceivedActivityMonitor&) = delete; ReceivedActivityMonitor& operator=(const ReceivedActivityMonitor&) = delete; @@ -143,8 +144,8 @@ void Update(); void OnTimerFired(); - uint32_t bytes_; - uint32_t increments_; + uint32_t bytes_ = 0; + uint32_t increments_ = 0; base::RepeatingTimer timer_; }; @@ -391,8 +392,7 @@ // Watcher for WriteAsync paths. class WriteAsyncWatcher : public base::MessagePumpForIO::FdWatcher { public: - explicit WriteAsyncWatcher(UDPSocketPosix* socket) - : socket_(socket), watching_(false) {} + explicit WriteAsyncWatcher(UDPSocketPosix* socket) : socket_(socket) {} WriteAsyncWatcher(const WriteAsyncWatcher&) = delete; WriteAsyncWatcher& operator=(const WriteAsyncWatcher&) = delete; @@ -409,7 +409,7 @@ private: const raw_ptr<UDPSocketPosix> socket_; - bool watching_; + bool watching_ = false; }; void IncreaseWriteAsyncOutstanding(int increment) { @@ -544,24 +544,24 @@ // Hash of |socket_| to verify that it is not corrupted when calling close(). // Used to debug https://crbug.com/906005. // TODO(crbug.com/906005): Remove this once the bug is fixed. - int socket_hash_; + int socket_hash_ = 0; - int addr_family_; - bool is_connected_; + int addr_family_ = 0; + bool is_connected_ = false; // Bitwise-or'd combination of SocketOptions. Specifies the set of // options that should be applied to |socket_| before Bind(). - int socket_options_; + int socket_options_ = SOCKET_OPTION_MULTICAST_LOOP; // Flags passed to sendto(). - int sendto_flags_; + int sendto_flags_ = 0; // Multicast interface. - uint32_t multicast_interface_; + uint32_t multicast_interface_ = 0; // Multicast socket options cached for SetMulticastOption. // Cannot be used after Bind(). - int multicast_time_to_live_; + int multicast_time_to_live_ = 1; // How to do source port binding, used only when UDPSocket is part of // UDPClientSocket, since UDPServerSocket provides Bind. @@ -587,22 +587,22 @@ int write_async_max_buffers_ = 16; int written_bytes_ = 0; - int last_async_result_; + int last_async_result_ = 0; base::RepeatingTimer write_async_timer_; - bool write_async_timer_running_; + bool write_async_timer_running_ = false; // Total writes in flight, including those |PostTask*|'d. - int write_async_outstanding_; + int write_async_outstanding_ = 0; scoped_refptr<base::SequencedTaskRunner> task_runner_; // The buffer used by InternalRead() to retry Read requests scoped_refptr<IOBuffer> read_buf_; - int read_buf_len_; + int read_buf_len_ = 0; raw_ptr<IPEndPoint> recv_from_address_; // The buffer used by InternalWrite() to retry Write requests scoped_refptr<IOBuffer> write_buf_; - int write_buf_len_; + int write_buf_len_ = 0; std::unique_ptr<IPEndPoint> send_to_address_; // External callback; called when read is complete. @@ -634,7 +634,7 @@ // By default, the value is set to false. To use the optimization, the // client of the socket has to opt-in by calling the // enable_experimental_recv_optimization() method. - bool experimental_recv_optimization_enabled_; + bool experimental_recv_optimization_enabled_ = false; // Manages decrementing the global open UDP socket counter when this // UDPSocket is destroyed.
diff --git a/net/socket/udp_socket_posix_unittest.cc b/net/socket/udp_socket_posix_unittest.cc index 3fa290a..fc30635 100644 --- a/net/socket/udp_socket_posix_unittest.cc +++ b/net/socket/udp_socket_posix_unittest.cc
@@ -133,8 +133,7 @@ UDPSocketPosixTest() : TestWithTaskEnvironment( base::test::TaskEnvironment::TimeSource::MOCK_TIME), - socket_(DatagramSocket::DEFAULT_BIND, NetLog::Get(), NetLogSource()), - callback_fired_(false) { + socket_(DatagramSocket::DEFAULT_BIND, NetLog::Get(), NetLogSource()) { write_callback_ = base::BindRepeating(&UDPSocketPosixTest::OnWriteComplete, weak_factory_.GetWeakPtr()); } @@ -223,7 +222,7 @@ RecordingNetLogObserver net_log_observer_; MockUDPSocketPosix socket_; DatagramBuffers buffers_; - bool callback_fired_; + bool callback_fired_ = false; int rv_; std::string msgs_[kNumMsgs] = {kHelloMsg, kSecondMsg, kThirdMsg}; int lengths_[kNumMsgs] = {static_cast<int>(kHelloMsg.length()),
diff --git a/net/socket/websocket_endpoint_lock_manager.cc b/net/socket/websocket_endpoint_lock_manager.cc index 16573d6..172bf9e 100644 --- a/net/socket/websocket_endpoint_lock_manager.cc +++ b/net/socket/websocket_endpoint_lock_manager.cc
@@ -47,8 +47,7 @@ } WebSocketEndpointLockManager::WebSocketEndpointLockManager() - : unlock_delay_(base::Milliseconds(kUnlockDelayInMs)), - pending_unlock_count_(0) {} + : unlock_delay_(base::Milliseconds(kUnlockDelayInMs)) {} WebSocketEndpointLockManager::~WebSocketEndpointLockManager() { DCHECK_EQ(lock_info_map_.size(), pending_unlock_count_);
diff --git a/net/socket/websocket_endpoint_lock_manager.h b/net/socket/websocket_endpoint_lock_manager.h index b8fcc83..1d9719ba 100644 --- a/net/socket/websocket_endpoint_lock_manager.h +++ b/net/socket/websocket_endpoint_lock_manager.h
@@ -134,7 +134,7 @@ base::TimeDelta unlock_delay_; // Number of sockets currently pending unlock. - size_t pending_unlock_count_; + size_t pending_unlock_count_ = 0; base::WeakPtrFactory<WebSocketEndpointLockManager> weak_factory_{this}; };
diff --git a/net/socket/websocket_endpoint_lock_manager_unittest.cc b/net/socket/websocket_endpoint_lock_manager_unittest.cc index c6ca3bd..ccfe1a09 100644 --- a/net/socket/websocket_endpoint_lock_manager_unittest.cc +++ b/net/socket/websocket_endpoint_lock_manager_unittest.cc
@@ -26,7 +26,7 @@ class FakeWaiter : public WebSocketEndpointLockManager::Waiter { public: - FakeWaiter() : called_(false) {} + FakeWaiter() = default; void GotEndpointLock() override { CHECK(!called_); @@ -36,7 +36,7 @@ bool called() const { return called_; } private: - bool called_; + bool called_ = false; }; class BlockingWaiter : public FakeWaiter {
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc index e0be94d..b1f7cd2 100644 --- a/net/socket/websocket_transport_client_socket_pool.cc +++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -37,9 +37,7 @@ common_connect_job_params, std::make_unique<ConnectJobFactory>()), proxy_server_(proxy_server), - max_sockets_(max_sockets), - handed_out_socket_count_(0), - flushing_(false) { + max_sockets_(max_sockets) { DCHECK(common_connect_job_params->websocket_endpoint_lock_manager); }
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h index 97a1716..2f88e43f 100644 --- a/net/socket/websocket_transport_client_socket_pool.h +++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -203,8 +203,8 @@ StalledRequestQueue stalled_request_queue_; StalledRequestMap stalled_request_map_; const int max_sockets_; - int handed_out_socket_count_; - bool flushing_; + int handed_out_socket_count_ = 0; + bool flushing_ = false; base::WeakPtrFactory<WebSocketTransportClientSocketPool> weak_factory_{this}; };
diff --git a/net/spdy/bidirectional_stream_spdy_impl.cc b/net/spdy/bidirectional_stream_spdy_impl.cc index 7f05167..4b443a4b 100644 --- a/net/spdy/bidirectional_stream_spdy_impl.cc +++ b/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -35,17 +35,7 @@ : spdy_session_(spdy_session), request_info_(nullptr), delegate_(nullptr), - source_dependency_(source_dependency), - negotiated_protocol_(kProtoUnknown), - more_read_data_pending_(false), - read_buffer_len_(0), - written_end_of_stream_(false), - write_pending_(false), - stream_closed_(false), - closed_stream_status_(ERR_FAILED), - closed_stream_received_bytes_(0), - closed_stream_sent_bytes_(0), - closed_has_load_timing_info_(false) {} + source_dependency_(source_dependency) {} BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() { // Sends a RST to the remote if the stream is destroyed before it completes.
diff --git a/net/spdy/bidirectional_stream_spdy_impl.h b/net/spdy/bidirectional_stream_spdy_impl.h index 4f434eb..41ef997 100644 --- a/net/spdy/bidirectional_stream_spdy_impl.h +++ b/net/spdy/bidirectional_stream_spdy_impl.h
@@ -98,34 +98,34 @@ base::WeakPtr<SpdyStream> stream_; const NetLogSource source_dependency_; - NextProto negotiated_protocol_; + NextProto negotiated_protocol_ = kProtoUnknown; // Buffers the data as it arrives asynchronously from the stream. SpdyReadQueue read_data_queue_; // Whether received more data has arrived since started waiting. - bool more_read_data_pending_; + bool more_read_data_pending_ = false; // User provided read buffer for ReadData() response. scoped_refptr<IOBuffer> read_buffer_; - int read_buffer_len_; + int read_buffer_len_ = 0; // Whether client has written the end of stream flag in request headers or // in SendData()/SendvData(). - bool written_end_of_stream_; + bool written_end_of_stream_ = false; // Whether a SendData() or SendvData() is pending. - bool write_pending_; + bool write_pending_ = false; // Whether OnClose has been invoked. - bool stream_closed_; + bool stream_closed_ = false; // Status reported in OnClose. - int closed_stream_status_; + int closed_stream_status_ = ERR_FAILED; // After |stream_| has been closed, this keeps track of the total number of // bytes received over the network for |stream_| while it was open. - int64_t closed_stream_received_bytes_; + int64_t closed_stream_received_bytes_ = 0; // After |stream_| has been closed, this keeps track of the total number of // bytes sent over the network for |stream_| while it was open. - int64_t closed_stream_sent_bytes_; + int64_t closed_stream_sent_bytes_ = 0; // True if |stream_| has LoadTimingInfo when it is closed. - bool closed_has_load_timing_info_; + bool closed_has_load_timing_info_ = false; // LoadTimingInfo populated when |stream_| is closed. LoadTimingInfo closed_load_timing_info_;
diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc index 36bd3af..94d6338 100644 --- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc +++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -76,15 +76,7 @@ NetLogSource())), read_buf_(read_buf), read_buf_len_(read_buf_len), - loop_(nullptr), - error_(OK), - bytes_read_(0), - on_data_read_count_(0), - on_data_sent_count_(0), - do_not_start_read_(false), - run_until_completion_(false), - not_expect_callback_(false), - on_failed_called_(false) {} + loop_(nullptr) {} TestDelegateBase(const TestDelegateBase&) = delete; TestDelegateBase& operator=(const TestDelegateBase&) = delete; @@ -228,14 +220,14 @@ std::unique_ptr<base::RunLoop> loop_; spdy::Http2HeaderBlock response_headers_; spdy::Http2HeaderBlock trailers_; - int error_; - int bytes_read_; - int on_data_read_count_; - int on_data_sent_count_; - bool do_not_start_read_; - bool run_until_completion_; - bool not_expect_callback_; - bool on_failed_called_; + int error_ = OK; + int bytes_read_ = 0; + int on_data_read_count_ = 0; + int on_data_sent_count_ = 0; + bool do_not_start_read_ = false; + bool run_until_completion_ = false; + bool not_expect_callback_ = false; + bool on_failed_called_ = false; }; } // namespace
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc index 93ffc6f6..913efea 100644 --- a/net/spdy/buffered_spdy_framer.cc +++ b/net/spdy/buffered_spdy_framer.cc
@@ -26,7 +26,6 @@ TimeFunc time_func) : spdy_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION), visitor_(nullptr), - frames_received_(0), max_header_list_size_(max_header_list_size), net_log_(net_log), time_func_(time_func) {
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc index 4f4efb8..1e0d4f6e 100644 --- a/net/spdy/buffered_spdy_framer_unittest.cc +++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -20,12 +20,6 @@ public: TestBufferedSpdyVisitor() : buffered_spdy_framer_(kMaxHeaderListSizeForTest, NetLogWithSource()), - error_count_(0), - setting_count_(0), - headers_frame_count_(0), - push_promise_frame_count_(0), - goaway_count_(0), - altsvc_count_(0), header_stream_id_(static_cast<spdy::SpdyStreamId>(-1)), promised_stream_id_(static_cast<spdy::SpdyStreamId>(-1)) {} @@ -157,12 +151,12 @@ BufferedSpdyFramer buffered_spdy_framer_; // Counters from the visitor callbacks. - int error_count_; - int setting_count_; - int headers_frame_count_; - int push_promise_frame_count_; - int goaway_count_; - int altsvc_count_; + int error_count_ = 0; + int setting_count_ = 0; + int headers_frame_count_ = 0; + int push_promise_frame_count_ = 0; + int goaway_count_ = 0; + int altsvc_count_ = 0; // Header block streaming state: spdy::SpdyStreamId header_stream_id_;
diff --git a/net/spdy/fuzzing/hpack_fuzz_util.cc b/net/spdy/fuzzing/hpack_fuzz_util.cc index d0f1c61..b30544c 100644 --- a/net/spdy/fuzzing/hpack_fuzz_util.cc +++ b/net/spdy/fuzzing/hpack_fuzz_util.cc
@@ -38,7 +38,7 @@ HpackFuzzUtil::GeneratorContext::GeneratorContext() = default; HpackFuzzUtil::GeneratorContext::~GeneratorContext() = default; -HpackFuzzUtil::Input::Input() : offset(0) {} +HpackFuzzUtil::Input::Input() = default; HpackFuzzUtil::Input::~Input() = default; HpackFuzzUtil::FuzzerContext::FuzzerContext() = default;
diff --git a/net/spdy/fuzzing/hpack_fuzz_util.h b/net/spdy/fuzzing/hpack_fuzz_util.h index e629f18..c23602c0 100644 --- a/net/spdy/fuzzing/hpack_fuzz_util.h +++ b/net/spdy/fuzzing/hpack_fuzz_util.h
@@ -46,7 +46,7 @@ const char* ptr() { return input.data() + offset; } std::string input; - size_t offset; + size_t offset = 0; }; // Returns true if the next header block was set at |out|. Returns
diff --git a/net/spdy/http2_priority_dependencies_unittest.cc b/net/spdy/http2_priority_dependencies_unittest.cc index eb8ee47..5f511a7f 100644 --- a/net/spdy/http2_priority_dependencies_unittest.cc +++ b/net/spdy/http2_priority_dependencies_unittest.cc
@@ -31,7 +31,7 @@ class HttpPriorityDependencyTest : public PlatformTest { public: - HttpPriorityDependencyTest() : next_id_(0u) {} + HttpPriorityDependencyTest() = default; // Fixed priority values to use for testing. enum { @@ -92,7 +92,7 @@ } private: - spdy::SpdyStreamId next_id_; + spdy::SpdyStreamId next_id_ = 0u; Http2PriorityDependencies dependency_state_; };
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index f4db5b6..dd9588c 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc
@@ -110,19 +110,8 @@ pushed_stream_id_(pushed_stream_id), is_reused_(spdy_session_->IsReused()), source_dependency_(source_dependency), - stream_(nullptr), - stream_closed_(false), - closed_stream_status_(ERR_FAILED), - closed_stream_id_(0), - closed_stream_received_bytes_(0), - closed_stream_sent_bytes_(0), request_info_(nullptr), response_info_(nullptr), - response_headers_complete_(false), - upload_stream_in_progress_(false), - user_buffer_len_(0), - request_body_buf_size_(0), - was_alpn_negotiated_(false), dns_aliases_(std::move(dns_aliases)) { DCHECK(spdy_session_.get()); }
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h index 7dfc6e8..513b3d6 100644 --- a/net/spdy/spdy_http_stream.h +++ b/net/spdy/spdy_http_stream.h
@@ -167,22 +167,22 @@ // After InitializeStream() is called but before OnClose() is called, // |*stream_| is guaranteed to be valid. // After OnClose() is called, stream_ == nullptr. - SpdyStream* stream_; + SpdyStream* stream_ = nullptr; // False before OnClose() is called, true after. - bool stream_closed_; + bool stream_closed_ = false; // Set only when |stream_closed_| is true. - int closed_stream_status_; - spdy::SpdyStreamId closed_stream_id_; + int closed_stream_status_ = ERR_FAILED; + spdy::SpdyStreamId closed_stream_id_ = 0; bool closed_stream_has_load_timing_info_; LoadTimingInfo closed_stream_load_timing_info_; // After |stream_| has been closed, this keeps track of the total number of // bytes received over the network for |stream_| while it was open. - int64_t closed_stream_received_bytes_; + int64_t closed_stream_received_bytes_ = 0; // After |stream_| has been closed, this keeps track of the total number of // bytes sent over the network for |stream_| while it was open. - int64_t closed_stream_sent_bytes_; + int64_t closed_stream_sent_bytes_ = 0; // The request to send. // Set to null before response body is starting to be read. This is to allow @@ -198,9 +198,9 @@ std::unique_ptr<HttpResponseInfo> push_response_info_; - bool response_headers_complete_; + bool response_headers_complete_ = false; - bool upload_stream_in_progress_; + bool upload_stream_in_progress_ = false; // We buffer the response body as it arrives asynchronously from the stream. SpdyReadQueue response_body_queue_; @@ -210,16 +210,16 @@ // User provided buffer for the ReadResponseBody() response. scoped_refptr<IOBuffer> user_buffer_; - int user_buffer_len_; + int user_buffer_len_ = 0; // Temporary buffer used to read the request body from UploadDataStream. scoped_refptr<IOBufferWithSize> request_body_buf_; - int request_body_buf_size_; + int request_body_buf_size_ = 0; // Timer to execute DoBufferedReadCallback() with a delay. base::OneShotTimer buffered_read_timer_; - bool was_alpn_negotiated_; + bool was_alpn_negotiated_ = false; // Stores any DNS aliases for the remote endpoint. Includes all known aliases, // e.g. from A, AAAA, or HTTPS, not just from the address used for the
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc index 693b1b1..273b456 100644 --- a/net/spdy/spdy_proxy_client_socket.cc +++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -46,9 +46,6 @@ proxy_server_(proxy_server), proxy_delegate_(proxy_delegate), user_agent_(user_agent), - user_buffer_len_(0), - write_buffer_len_(0), - was_ever_used_(false), net_log_(NetLogWithSource::Make(spdy_stream->net_log().net_log(), NetLogSourceType::PROXY_CLIENT_SOCKET)), source_dependency_(source_net_log.source()) {
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h index c0aef4d8..b2a2e4a 100644 --- a/net/spdy/spdy_proxy_client_socket.h +++ b/net/spdy/spdy_proxy_client_socket.h
@@ -173,13 +173,13 @@ // User provided buffer for the Read() response. scoped_refptr<IOBuffer> user_buffer_; - size_t user_buffer_len_; + size_t user_buffer_len_ = 0; // User specified number of bytes to be written. - int write_buffer_len_; + int write_buffer_len_ = 0; // True if the transport socket has ever sent data. - bool was_ever_used_; + bool was_ever_used_ = false; const NetLogWithSource net_log_; const NetLogSource source_dependency_;
diff --git a/net/spdy/spdy_read_queue.cc b/net/spdy/spdy_read_queue.cc index 48ace9b..81d93ba 100644 --- a/net/spdy/spdy_read_queue.cc +++ b/net/spdy/spdy_read_queue.cc
@@ -12,7 +12,7 @@ namespace net { -SpdyReadQueue::SpdyReadQueue() : total_size_(0) {} +SpdyReadQueue::SpdyReadQueue() = default; SpdyReadQueue::~SpdyReadQueue() { Clear();
diff --git a/net/spdy/spdy_read_queue.h b/net/spdy/spdy_read_queue.h index 205e85c..41d73fc 100644 --- a/net/spdy/spdy_read_queue.h +++ b/net/spdy/spdy_read_queue.h
@@ -46,7 +46,7 @@ // Class invariant: // |total_size_| is the sum of GetRemainingSize() of |queue_|'s elements. base::circular_deque<std::unique_ptr<SpdyBuffer>> queue_; - size_t total_size_; + size_t total_size_ = 0; }; } // namespace net
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 148ac4f..fe41ff9 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -935,53 +935,25 @@ ServerPushDelegate* push_delegate, NetworkQualityEstimator* network_quality_estimator, NetLog* net_log) - : in_io_loop_(false), - spdy_session_key_(spdy_session_key), + : spdy_session_key_(spdy_session_key), pool_(nullptr), http_server_properties_(http_server_properties), transport_security_state_(transport_security_state), ssl_config_service_(ssl_config_service), socket_(nullptr), stream_hi_water_mark_(kFirstStreamId), - last_accepted_push_stream_id_(0), push_delegate_(push_delegate), - num_pushed_streams_(0u), - num_active_pushed_streams_(0u), - bytes_pushed_count_(0u), - bytes_pushed_and_unclaimed_count_(0u), - in_flight_write_frame_type_(spdy::SpdyFrameType::DATA), - in_flight_write_frame_size_(0), - availability_state_(STATE_AVAILABLE), - read_state_(READ_STATE_DO_READ), - write_state_(WRITE_STATE_IDLE), - error_on_close_(OK), initial_settings_(initial_settings), enable_http2_settings_grease_(enable_http2_settings_grease), greased_http2_frame_(greased_http2_frame), http2_end_stream_with_data_frame_(http2_end_stream_with_data_frame), enable_priority_update_(enable_priority_update), - deprecate_http2_priorities_(false), - settings_frame_received_(false), - in_confirm_handshake_(false), max_concurrent_streams_(kInitialMaxConcurrentStreams), max_concurrent_pushed_streams_( initial_settings.at(spdy::SETTINGS_MAX_CONCURRENT_STREAMS)), - streams_initiated_count_(0), - streams_pushed_count_(0), - streams_pushed_and_claimed_count_(0), - streams_abandoned_count_(0), - ping_in_flight_(false), - check_connection_on_radio_wakeup_(false), - next_ping_id_(1), last_read_time_(time_func()), - last_compressed_frame_len_(0), - check_ping_status_pending_(false), - session_send_window_size_(0), session_max_recv_window_size_(session_max_recv_window_size), session_max_queued_capped_frames_(session_max_queued_capped_frames), - broken_connection_detection_requests_(0), - session_recv_window_size_(0), - session_unacked_recv_window_bytes_(0), last_recv_window_update_(base::TimeTicks::Now()), time_to_buffer_small_window_updates_( kDefaultTimeToBufferSmallWindowUpdates), @@ -999,7 +971,6 @@ is_http2_enabled_(is_http2_enabled), is_quic_enabled_(is_quic_enabled), enable_push_(IsPushEnabled(initial_settings)), - support_websocket_(false), connection_at_risk_of_loss_time_( base::Seconds(kDefaultConnectionAtRiskOfLossSeconds)), hung_interval_(base::Seconds(kHungIntervalSeconds)),
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 4566fbe..e3437454 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -1076,7 +1076,7 @@ // Whether Do{Read,Write}Loop() is in the call stack. Useful for // making sure we don't destroy ourselves prematurely in that case. - bool in_io_loop_; + bool in_io_loop_ = false; // The key used to identify this session. SpdySessionKey spdy_session_key_; @@ -1112,7 +1112,7 @@ spdy::SpdyStreamId stream_hi_water_mark_; // The next stream id to use. // Used to ensure the server increments push stream ids correctly. - spdy::SpdyStreamId last_accepted_push_stream_id_; + spdy::SpdyStreamId last_accepted_push_stream_id_ = 0; // Queue, for each priority, of pending stream requests that have // not yet been satisfied. @@ -1143,18 +1143,18 @@ // Number of pushed streams. All active streams are stored in // |active_streams_|, but it's better to know the number of push streams // without traversing the whole collection. - size_t num_pushed_streams_; + size_t num_pushed_streams_ = 0u; // Number of active pushed streams in |active_streams_|, i.e. not in reserved // remote state. Streams in reserved state are not counted towards any // concurrency limits. - size_t num_active_pushed_streams_; + size_t num_active_pushed_streams_ = 0u; // Number of bytes that has been pushed by the server. - uint64_t bytes_pushed_count_; + uint64_t bytes_pushed_count_ = 0u; // Number of bytes that has been pushed by the server but never claimed. - uint64_t bytes_pushed_and_unclaimed_count_; + uint64_t bytes_pushed_and_unclaimed_count_ = 0u; // The write queue. SpdyWriteQueue write_queue_; @@ -1164,9 +1164,9 @@ // The buffer we're currently writing. std::unique_ptr<SpdyBuffer> in_flight_write_; // The type of the frame in |in_flight_write_|. - spdy::SpdyFrameType in_flight_write_frame_type_; + spdy::SpdyFrameType in_flight_write_frame_type_ = spdy::SpdyFrameType::DATA; // The size of the frame in |in_flight_write_|. - size_t in_flight_write_frame_size_; + size_t in_flight_write_frame_size_ = 0; // The stream to notify when |in_flight_write_| has been written to // the socket completely. base::WeakPtr<SpdyStream> in_flight_write_stream_; @@ -1178,15 +1178,15 @@ std::unique_ptr<BufferedSpdyFramer> buffered_spdy_framer_; // The state variables. - AvailabilityState availability_state_; - ReadState read_state_; - WriteState write_state_; + AvailabilityState availability_state_ = STATE_AVAILABLE; + ReadState read_state_ = READ_STATE_DO_READ; + WriteState write_state_ = WRITE_STATE_IDLE; // If the session is closing (i.e., |availability_state_| is STATE_DRAINING), // then |error_on_close_| holds the error with which it was closed, which // may be OK (upon a polite GOAWAY) or an error < ERR_IO_PENDING otherwise. // Initialized to OK. - Error error_on_close_; + Error error_on_close_ = OK; // Settings that are sent in the initial SETTINGS frame // (if |enable_sending_initial_data_| is true), @@ -1223,31 +1223,31 @@ // The value of the last received SETTINGS_DEPRECATE_HTTP2_PRIORITIES, with 0 // mapping to false and 1 to true. Initial value is false. - bool deprecate_http2_priorities_; + bool deprecate_http2_priorities_ = false; // True if at least one SETTINGS frame has been received. - bool settings_frame_received_; + bool settings_frame_received_ = false; // The callbacks to notify a request that the handshake has been confirmed. std::vector<CompletionOnceCallback> waiting_for_confirmation_callbacks_; // True if there is an ongoing handshake confirmation with outstanding // requests. - bool in_confirm_handshake_; + bool in_confirm_handshake_ = false; // Limits size_t max_concurrent_streams_; size_t max_concurrent_pushed_streams_; // Some statistics counters for the session. - int streams_initiated_count_; - int streams_pushed_count_; - int streams_pushed_and_claimed_count_; - int streams_abandoned_count_; + int streams_initiated_count_ = 0; + int streams_pushed_count_ = 0; + int streams_pushed_and_claimed_count_ = 0; + int streams_abandoned_count_ = 0; // True if there has been a ping sent for which we have not received a // response yet. There is always at most one ping in flight. - bool ping_in_flight_; + bool ping_in_flight_ = false; // Triggers periodic connection status checks. base::OneShotTimer heartbeat_timer_; @@ -1256,10 +1256,10 @@ base::TimeDelta heartbeat_interval_; // True if the connection status should be checked once the radio wakes up. - bool check_connection_on_radio_wakeup_; + bool check_connection_on_radio_wakeup_ = false; // This is the next ping_id (unique_id) to be sent in PING frame. - spdy::SpdyPingId next_ping_id_; + spdy::SpdyPingId next_ping_id_ = 1; // This is the last time we have sent a PING. base::TimeTicks last_ping_sent_time_; @@ -1268,13 +1268,13 @@ base::TimeTicks last_read_time_; // This is the length of the last compressed frame. - size_t last_compressed_frame_len_; + size_t last_compressed_frame_len_ = 0; // True if there is a CheckPingStatus() task posted on the message loop. - bool check_ping_status_pending_; + bool check_ping_status_pending_ = false; // Current send window size. Zero unless session flow control is turned on. - int32_t session_send_window_size_; + int32_t session_send_window_size_ = 0; // Maximum receive window size. Each time a WINDOW_UPDATE is sent, it // restores the receive window size to this value. Zero unless session flow @@ -1287,18 +1287,18 @@ int session_max_queued_capped_frames_; // Number of active requests which asked for connection status monitoring. - int broken_connection_detection_requests_; + int broken_connection_detection_requests_ = 0; // Sum of |session_unacked_recv_window_bytes_| and current receive window // size. Zero unless session flow control is turned on. // TODO(bnc): Rename or change semantics so that |window_size_| is actual // window size. - int32_t session_recv_window_size_; + int32_t session_recv_window_size_ = 0; // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession, // and this member keeps count of them until the corresponding WINDOW_UPDATEs // are sent. Zero unless session flow control is turned on. - int32_t session_unacked_recv_window_bytes_; + int32_t session_unacked_recv_window_bytes_ = 0; // Time of the last WINDOW_UPDATE for the receive window. base::TimeTicks last_recv_window_update_; @@ -1345,7 +1345,7 @@ // True if the server has advertised WebSocket support via // spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL, see // https://tools.ietf.org/html/draft-ietf-httpbis-h2-websockets-00. - bool support_websocket_; + bool support_websocket_ = false; // |connection_at_risk_of_loss_time_| is an optimization to avoid sending // wasteful preface pings (when we just got some data).
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index da633e2..46766de 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc
@@ -99,7 +99,6 @@ ssl_client_context_(ssl_client_context), resolver_(resolver), quic_supported_versions_(quic_supported_versions), - enable_sending_initial_data_(true), enable_ping_based_connection_checking_( enable_ping_based_connection_checking), is_http2_enabled_(is_http2_enabled),
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 3acf8a1..2ba3a0f 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h
@@ -442,7 +442,7 @@ const quic::ParsedQuicVersionVector quic_supported_versions_; // Defaults to true. May be controlled via SpdySessionPoolPeer for tests. - bool enable_sending_initial_data_; + bool enable_sending_initial_data_ = true; bool enable_ping_based_connection_checking_; const bool is_http2_enabled_;
diff --git a/net/spdy/spdy_session_test_util.cc b/net/spdy/spdy_session_test_util.cc index 29e1c40..7bd5813 100644 --- a/net/spdy/spdy_session_test_util.cc +++ b/net/spdy/spdy_session_test_util.cc
@@ -13,7 +13,7 @@ SpdySessionTestTaskObserver::SpdySessionTestTaskObserver( const std::string& file_name, const std::string& function_name) - : executed_count_(0), file_name_(file_name), function_name_(function_name) { + : file_name_(file_name), function_name_(function_name) { base::CurrentThread::Get()->AddTaskObserver(this); }
diff --git a/net/spdy/spdy_session_test_util.h b/net/spdy/spdy_session_test_util.h index 4b24e29d..fe80eddc 100644 --- a/net/spdy/spdy_session_test_util.h +++ b/net/spdy/spdy_session_test_util.h
@@ -38,7 +38,7 @@ uint16_t executed_count() const { return executed_count_; } private: - uint16_t executed_count_; + uint16_t executed_count_ = 0; std::string file_name_; std::string function_name_; };
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index b0471f2..160439cc 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc
@@ -100,27 +100,16 @@ const NetworkTrafficAnnotationTag& traffic_annotation, bool detect_broken_connection) : type_(type), - stream_id_(0), url_(url), priority_(priority), - send_stalled_by_flow_control_(false), send_window_size_(initial_send_window_size), max_recv_window_size_(max_recv_window_size), recv_window_size_(max_recv_window_size), - unacked_recv_window_bytes_(0), last_recv_window_update_(base::TimeTicks::Now()), session_(session), delegate_(nullptr), - request_headers_valid_(false), - pending_send_status_(MORE_DATA_TO_SEND), request_time_(base::Time::Now()), - response_state_(READY_FOR_HEADERS), - io_state_(STATE_IDLE), net_log_(net_log), - raw_received_bytes_(0), - raw_sent_bytes_(0), - recv_bytes_(0), - write_handler_guard_(false), traffic_annotation_(traffic_annotation), detect_broken_connection_(detect_broken_connection) { CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 4961b13..4cc771a 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h
@@ -474,11 +474,11 @@ const SpdyStreamType type_; - spdy::SpdyStreamId stream_id_; + spdy::SpdyStreamId stream_id_ = 0; const GURL url_; RequestPriority priority_; - bool send_stalled_by_flow_control_; + bool send_stalled_by_flow_control_ = false; // Current send window size. int32_t send_window_size_; @@ -496,7 +496,7 @@ // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession, // and this member keeps count of them until the corresponding WINDOW_UPDATEs // are sent. - int32_t unacked_recv_window_bytes_; + int32_t unacked_recv_window_bytes_ = 0; // Time of the last WINDOW_UPDATE for the receive window base::TimeTicks last_recv_window_update_; @@ -507,13 +507,13 @@ raw_ptr<SpdyStream::Delegate> delegate_; // The headers for the request to send. - bool request_headers_valid_; + bool request_headers_valid_ = false; spdy::Http2HeaderBlock request_headers_; // Data waiting to be sent, and the close state of the local endpoint // after the data is fully written. scoped_refptr<DrainableIOBuffer> pending_send_data_; - SpdySendStatus pending_send_status_; + SpdySendStatus pending_send_status_ = MORE_DATA_TO_SEND; // Data waiting to be received, and the close state of the remote endpoint // after the data is fully read. Specifically, data received before the @@ -526,10 +526,10 @@ base::Time request_time_; spdy::Http2HeaderBlock response_headers_; - ResponseState response_state_; + ResponseState response_state_ = READY_FOR_HEADERS; base::Time response_time_; - State io_state_; + State io_state_ = STATE_IDLE; NetLogWithSource net_log_; @@ -553,19 +553,19 @@ // Number of bytes that have been received on this stream, including frame // overhead and headers. - int64_t raw_received_bytes_; + int64_t raw_received_bytes_ = 0; // Number of bytes that have been sent on this stream, including frame // overhead and headers. - int64_t raw_sent_bytes_; + int64_t raw_sent_bytes_ = 0; // Number of data bytes that have been received on this stream, not including // frame overhead. Note that this does not count headers. - int recv_bytes_; + int recv_bytes_ = 0; // Guards calls of delegate write handlers ensuring |this| is not destroyed. // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked // down. - bool write_handler_guard_; + bool write_handler_guard_ = false; const NetworkTrafficAnnotationTag traffic_annotation_;
diff --git a/net/spdy/spdy_stream_test_util.cc b/net/spdy/spdy_stream_test_util.cc index 50bd5e7..160f385 100644 --- a/net/spdy/spdy_stream_test_util.cc +++ b/net/spdy/spdy_stream_test_util.cc
@@ -51,12 +51,8 @@ return NetLogSource(); } -StreamDelegateBase::StreamDelegateBase( - const base::WeakPtr<SpdyStream>& stream) - : stream_(stream), - stream_id_(0), - send_headers_completed_(false) { -} +StreamDelegateBase::StreamDelegateBase(const base::WeakPtr<SpdyStream>& stream) + : stream_(stream) {} StreamDelegateBase::~StreamDelegateBase() = default;
diff --git a/net/spdy/spdy_stream_test_util.h b/net/spdy/spdy_stream_test_util.h index 711b85f..c560c3d 100644 --- a/net/spdy/spdy_stream_test_util.h +++ b/net/spdy/spdy_stream_test_util.h
@@ -100,9 +100,9 @@ private: base::WeakPtr<SpdyStream> stream_; - spdy::SpdyStreamId stream_id_; + spdy::SpdyStreamId stream_id_ = 0; TestCompletionCallback callback_; - bool send_headers_completed_; + bool send_headers_completed_ = false; std::vector<spdy::Http2HeaderBlock> early_hints_; spdy::Http2HeaderBlock response_headers_; SpdyReadQueue received_data_queue_;
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index fc3b988..59f4da8 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc
@@ -87,7 +87,6 @@ : WithTaskEnvironment(time_source), url_(kDefaultUrl), session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)), - offset_(0), ssl_(SYNCHRONOUS, OK) {} ~SpdyStreamTest() override = default; @@ -176,7 +175,7 @@ // Used by Add{Read,Write}() above. std::vector<MockWrite> writes_; std::vector<MockRead> reads_; - int offset_; + int offset_ = 0; SSLSocketDataProvider ssl_; };
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 8716214..f7f3305 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -182,7 +182,7 @@ class PriorityGetter : public BufferedSpdyFramerVisitorInterface { public: - PriorityGetter() : priority_(0) {} + PriorityGetter() = default; ~PriorityGetter() override = default; spdy::SpdyPriority priority() const { return priority_; } @@ -236,7 +236,7 @@ } private: - spdy::SpdyPriority priority_; + spdy::SpdyPriority priority_ = 0; }; } // namespace
diff --git a/net/spdy/spdy_write_queue.cc b/net/spdy/spdy_write_queue.cc index 3dba92ff..cc9517d5 100644 --- a/net/spdy/spdy_write_queue.cc +++ b/net/spdy/spdy_write_queue.cc
@@ -44,7 +44,7 @@ SpdyWriteQueue::PendingWrite& SpdyWriteQueue::PendingWrite::operator=( PendingWrite&& other) = default; -SpdyWriteQueue::SpdyWriteQueue() : removing_writes_(false) {} +SpdyWriteQueue::SpdyWriteQueue() = default; SpdyWriteQueue::~SpdyWriteQueue() { DCHECK_GE(num_queued_capped_frames_, 0);
diff --git a/net/spdy/spdy_write_queue.h b/net/spdy/spdy_write_queue.h index e3987b7..b353f175 100644 --- a/net/spdy/spdy_write_queue.h +++ b/net/spdy/spdy_write_queue.h
@@ -106,7 +106,7 @@ ~PendingWrite(); }; - bool removing_writes_; + bool removing_writes_ = false; // Number of currently queued capped frames including all priorities. int num_queued_capped_frames_ = 0;
diff --git a/net/ssl/openssl_ssl_util.cc b/net/ssl/openssl_ssl_util.cc index c5b7bfb..2e8e2cd 100644 --- a/net/ssl/openssl_ssl_util.cc +++ b/net/ssl/openssl_ssl_util.cc
@@ -24,10 +24,7 @@ namespace net { -SslSetClearMask::SslSetClearMask() - : set_mask(0), - clear_mask(0) { -} +SslSetClearMask::SslSetClearMask() = default; void SslSetClearMask::ConfigureFlag(long flag, bool state) { (state ? set_mask : clear_mask) |= flag;
diff --git a/net/ssl/openssl_ssl_util.h b/net/ssl/openssl_ssl_util.h index 18c7040..5cce274 100644 --- a/net/ssl/openssl_ssl_util.h +++ b/net/ssl/openssl_ssl_util.h
@@ -34,8 +34,8 @@ SslSetClearMask(); void ConfigureFlag(long flag, bool state); - long set_mask; - long clear_mask; + long set_mask = 0; + long clear_mask = 0; }; // Converts an OpenSSL error code into a net error code, walking the OpenSSL @@ -50,11 +50,11 @@ // Helper struct to store information about an OpenSSL error stack entry. struct OpenSSLErrorInfo { - OpenSSLErrorInfo() : error_code(0), file(nullptr), line(0) {} + OpenSSLErrorInfo() = default; - uint32_t error_code; - const char* file; - int line; + uint32_t error_code = 0; + const char* file = nullptr; + int line = 0; }; // Converts an OpenSSL error code into a net error code, walking the OpenSSL
diff --git a/net/ssl/ssl_cert_request_info.cc b/net/ssl/ssl_cert_request_info.cc index 2ad30cdc..39f6d8f 100644 --- a/net/ssl/ssl_cert_request_info.cc +++ b/net/ssl/ssl_cert_request_info.cc
@@ -8,8 +8,7 @@ namespace net { -SSLCertRequestInfo::SSLCertRequestInfo() : is_proxy(false) { -} +SSLCertRequestInfo::SSLCertRequestInfo() = default; void SSLCertRequestInfo::Reset() { host_and_port = HostPortPair();
diff --git a/net/ssl/ssl_cert_request_info.h b/net/ssl/ssl_cert_request_info.h index 3f0443e..9eaffe6 100644 --- a/net/ssl/ssl_cert_request_info.h +++ b/net/ssl/ssl_cert_request_info.h
@@ -44,7 +44,7 @@ // True if the server that issues this request was the HTTPS proxy used in // the request. False, if the server was the origin server. - bool is_proxy; + bool is_proxy = false; // List of DER-encoded X.509 DistinguishedName of certificate authorities // allowed by the server.
diff --git a/net/ssl/ssl_client_session_cache.cc b/net/ssl/ssl_client_session_cache.cc index 0fecc48..dab00af 100644 --- a/net/ssl/ssl_client_session_cache.cc +++ b/net/ssl/ssl_client_session_cache.cc
@@ -44,8 +44,7 @@ SSLClientSessionCache::SSLClientSessionCache(const Config& config) : clock_(base::DefaultClock::GetInstance()), config_(config), - cache_(config.max_entries), - lookups_since_flush_(0) { + cache_(config.max_entries) { memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( FROM_HERE, base::BindRepeating(&SSLClientSessionCache::OnMemoryPressure, base::Unretained(this)));
diff --git a/net/ssl/ssl_client_session_cache.h b/net/ssl/ssl_client_session_cache.h index 24655c13..271427e 100644 --- a/net/ssl/ssl_client_session_cache.h +++ b/net/ssl/ssl_client_session_cache.h
@@ -121,7 +121,7 @@ raw_ptr<base::Clock> clock_; Config config_; base::LRUCache<Key, Entry> cache_; - size_t lookups_since_flush_; + size_t lookups_since_flush_ = 0; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; };
diff --git a/net/ssl/ssl_server_config.cc b/net/ssl/ssl_server_config.cc index 1002210..425d326b 100644 --- a/net/ssl/ssl_server_config.cc +++ b/net/ssl/ssl_server_config.cc
@@ -13,9 +13,6 @@ SSLServerConfig::SSLServerConfig() : version_min(kDefaultSSLVersionMin), version_max(kDefaultSSLVersionMax), - early_data_enabled(false), - require_ecdhe(false), - client_cert_type(NO_CLIENT_CERT), client_cert_verifier(nullptr) {} SSLServerConfig::SSLServerConfig(const SSLServerConfig& other) = default;
diff --git a/net/ssl/ssl_server_config.h b/net/ssl/ssl_server_config.h index 43d0368..520a8642 100644 --- a/net/ssl/ssl_server_config.h +++ b/net/ssl/ssl_server_config.h
@@ -45,7 +45,7 @@ // Whether early data is enabled on this connection. The caller is obligated // to reject early data that is non-safe to be replayed. - bool early_data_enabled; + bool early_data_enabled = false; // Presorted list of cipher suites which should be explicitly prevented from // being used in addition to those disabled by the net built-in policy. @@ -71,7 +71,7 @@ std::vector<uint16_t> disabled_cipher_suites; // If true, causes only ECDHE cipher suites to be enabled. - bool require_ecdhe; + bool require_ecdhe = false; // cipher_suite_for_testing, if set, causes the server to only support the // specified cipher suite in TLS 1.2 and below. This should only be used in @@ -88,7 +88,7 @@ std::vector<int> curves_for_testing; // Sets the requirement for client certificates during handshake. - ClientCertType client_cert_type; + ClientCertType client_cert_type = NO_CLIENT_CERT; // List of DER-encoded X.509 DistinguishedName of certificate authorities // to be included in the CertificateRequest handshake message,
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc index b37e23bd..bd61f6a 100644 --- a/net/test/embedded_test_server/embedded_test_server_unittest.cc +++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -50,10 +50,7 @@ : public net::test_server::EmbeddedTestServerConnectionListener { public: TestConnectionListener() - : socket_accepted_count_(0), - did_read_from_socket_(false), - did_get_socket_on_complete_(false), - task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + : task_runner_(base::ThreadTaskRunnerHandle::Get()) {} TestConnectionListener(const TestConnectionListener&) = delete; TestConnectionListener& operator=(const TestConnectionListener&) = delete; @@ -104,9 +101,9 @@ } private: - size_t socket_accepted_count_; - bool did_read_from_socket_; - bool did_get_socket_on_complete_; + size_t socket_accepted_count_ = 0; + bool did_read_from_socket_ = false; + bool did_get_socket_on_complete_ = false; base::RunLoop accept_loop_; base::RunLoop complete_loop_;
diff --git a/net/test/embedded_test_server/http_request.cc b/net/test/embedded_test_server/http_request.cc index efb8a7e..691a4b4 100644 --- a/net/test/embedded_test_server/http_request.cc +++ b/net/test/embedded_test_server/http_request.cc
@@ -30,9 +30,7 @@ } // namespace -HttpRequest::HttpRequest() : method(METHOD_UNKNOWN), - has_content(false) { -} +HttpRequest::HttpRequest() = default; HttpRequest::HttpRequest(const HttpRequest& other) = default; @@ -45,10 +43,7 @@ } HttpRequestParser::HttpRequestParser() - : http_request_(std::make_unique<HttpRequest>()), - buffer_position_(0), - state_(STATE_HEADERS), - declared_content_length_(0) {} + : http_request_(std::make_unique<HttpRequest>()) {} HttpRequestParser::~HttpRequestParser() = default;
diff --git a/net/test/embedded_test_server/http_request.h b/net/test/embedded_test_server/http_request.h index 8ddde91..91cdaed 100644 --- a/net/test/embedded_test_server/http_request.h +++ b/net/test/embedded_test_server/http_request.h
@@ -61,12 +61,12 @@ std::string relative_url; // Starts with '/'. Example: "/test?query=foo" GURL base_url; - HttpMethod method; + HttpMethod method = METHOD_UNKNOWN; std::string method_string; std::string all_headers; HeaderMap headers; std::string content; - bool has_content; + bool has_content = false; absl::optional<SSLInfo> ssl_info; }; @@ -135,10 +135,10 @@ std::unique_ptr<HttpRequest> http_request_; std::string buffer_; - size_t buffer_position_; // Current position in the internal buffer. - State state_; + size_t buffer_position_ = 0; // Current position in the internal buffer. + State state_ = STATE_HEADERS; // Content length of the request currently being parsed. - size_t declared_content_length_; + size_t declared_content_length_ = 0; std::unique_ptr<HttpChunkedDecoder> chunked_decoder_; };
diff --git a/net/test/embedded_test_server/http_response.cc b/net/test/embedded_test_server/http_response.cc index 1aafb2be1..cc38408 100644 --- a/net/test/embedded_test_server/http_response.cc +++ b/net/test/embedded_test_server/http_response.cc
@@ -58,7 +58,7 @@ headers_.append(base::StringPrintf("%s\r\n", key_value_pair.c_str())); } -BasicHttpResponse::BasicHttpResponse() : code_(HTTP_OK) {} +BasicHttpResponse::BasicHttpResponse() = default; BasicHttpResponse::~BasicHttpResponse() = default;
diff --git a/net/test/embedded_test_server/http_response.h b/net/test/embedded_test_server/http_response.h index f352100..de2ffe0 100644 --- a/net/test/embedded_test_server/http_response.h +++ b/net/test/embedded_test_server/http_response.h
@@ -126,7 +126,7 @@ void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; private: - HttpStatusCode code_; + HttpStatusCode code_ = HTTP_OK; absl::optional<std::string> reason_; std::string content_; std::string content_type_;
diff --git a/net/test/url_request/url_request_hanging_read_job.cc b/net/test/url_request/url_request_hanging_read_job.cc index 60008a0d..b03430a 100644 --- a/net/test/url_request/url_request_hanging_read_job.cc +++ b/net/test/url_request/url_request_hanging_read_job.cc
@@ -44,9 +44,7 @@ } // namespace URLRequestHangingReadJob::URLRequestHangingReadJob(URLRequest* request) - : URLRequestJob(request), - // non-zero content-length - content_length_(10) {} + : URLRequestJob(request) {} URLRequestHangingReadJob::~URLRequestHangingReadJob() = default;
diff --git a/net/test/url_request/url_request_hanging_read_job.h b/net/test/url_request/url_request_hanging_read_job.h index 938e31b..3350e55 100644 --- a/net/test/url_request/url_request_hanging_read_job.h +++ b/net/test/url_request/url_request_hanging_read_job.h
@@ -37,7 +37,7 @@ void StartAsync(); - const int content_length_; + const int content_length_ = 10; // non-zero content-length base::WeakPtrFactory<URLRequestHangingReadJob> weak_factory_{this}; };
diff --git a/net/test/url_request/url_request_mock_data_job.cc b/net/test/url_request/url_request_mock_data_job.cc index 9e2d8c3c4..72cbaeb 100644 --- a/net/test/url_request/url_request_mock_data_job.cc +++ b/net/test/url_request/url_request_mock_data_job.cc
@@ -100,7 +100,6 @@ int data_repeat_count, bool request_client_certificate) : URLRequestJob(request), - data_offset_(0), request_client_certificate_(request_client_certificate) { DCHECK_GT(data_repeat_count, 0); for (int i = 0; i < data_repeat_count; ++i) {
diff --git a/net/test/url_request/url_request_mock_data_job.h b/net/test/url_request/url_request_mock_data_job.h index f2789e1..1d207bc3 100644 --- a/net/test/url_request/url_request_mock_data_job.h +++ b/net/test/url_request/url_request_mock_data_job.h
@@ -68,7 +68,7 @@ absl::optional<std::string> headers_; std::string data_; - size_t data_offset_; + size_t data_offset_ = 0; bool request_client_certificate_; base::WeakPtrFactory<URLRequestMockDataJob> weak_factory_{this}; };
diff --git a/net/test/url_request/url_request_test_job_backed_by_file.cc b/net/test/url_request/url_request_test_job_backed_by_file.cc index fac551a..8e906a1 100644 --- a/net/test/url_request/url_request_test_job_backed_by_file.cc +++ b/net/test/url_request/url_request_test_job_backed_by_file.cc
@@ -45,11 +45,7 @@ namespace net { -URLRequestTestJobBackedByFile::FileMetaInfo::FileMetaInfo() - : file_size(0), - mime_type_result(false), - file_exists(false), - is_directory(false) {} +URLRequestTestJobBackedByFile::FileMetaInfo::FileMetaInfo() = default; URLRequestTestJobBackedByFile::URLRequestTestJobBackedByFile( URLRequest* request, @@ -58,9 +54,7 @@ : URLRequestJob(request), file_path_(file_path), stream_(new FileStream(file_task_runner)), - file_task_runner_(file_task_runner), - remaining_bytes_(0), - range_parse_result_(OK) {} + file_task_runner_(file_task_runner) {} void URLRequestTestJobBackedByFile::Start() { FileMetaInfo* meta_info = new FileMetaInfo();
diff --git a/net/test/url_request/url_request_test_job_backed_by_file.h b/net/test/url_request/url_request_test_job_backed_by_file.h index 668120c9..a850f88 100644 --- a/net/test/url_request/url_request_test_job_backed_by_file.h +++ b/net/test/url_request/url_request_test_job_backed_by_file.h
@@ -89,16 +89,16 @@ FileMetaInfo(); // Size of the file. - int64_t file_size; + int64_t file_size = 0; // Mime type associated with the file. std::string mime_type; // Result returned from GetMimeTypeFromFile(), i.e. flag showing whether // obtaining of the mime type was successful. - bool mime_type_result; + bool mime_type_result = false; // Flag showing whether the file exists. - bool file_exists; + bool file_exists = false; // Flag showing whether the file name actually refers to a directory. - bool is_directory; + bool is_directory = false; // Absolute path of the file (i.e. symbolic link is resolved). base::FilePath absolute_path; }; @@ -126,10 +126,10 @@ std::vector<HttpByteRange> byte_ranges_; HttpByteRange byte_range_; - int64_t remaining_bytes_; + int64_t remaining_bytes_ = 0; bool serve_mime_type_as_content_type_ = false; - Error range_parse_result_; + Error range_parse_result_ = OK; base::WeakPtrFactory<URLRequestTestJobBackedByFile> weak_ptr_factory_{this}; };
diff --git a/net/tools/cachetool/cachetool.cc b/net/tools/cachetool/cachetool.cc index d6f0f455..6b7634e 100644 --- a/net/tools/cachetool/cachetool.cc +++ b/net/tools/cachetool/cachetool.cc
@@ -85,7 +85,7 @@ class CommandMarshal { public: explicit CommandMarshal(Backend* cache_backend) - : command_failed_(false), cache_backend_(cache_backend) {} + : cache_backend_(cache_backend) {} virtual ~CommandMarshal() = default; // Reads the next command's name to execute. @@ -137,7 +137,7 @@ Backend* cache_backend() { return cache_backend_; } protected: - bool command_failed_; + bool command_failed_ = false; Backend* const cache_backend_; }; @@ -146,7 +146,7 @@ public: ProgramArgumentCommandMarshal(Backend* cache_backend, base::CommandLine::StringVector args) - : CommandMarshal(cache_backend), command_line_args_(args), args_id_(0) {} + : CommandMarshal(cache_backend), command_line_args_(args) {} // Implements CommandMarshal. std::string ReadCommandName() override { @@ -220,7 +220,7 @@ private: const base::CommandLine::StringVector command_line_args_; - size_t args_id_; + size_t args_id_ = 0; }; // Online command input/output that receives pickled commands from stdin and
diff --git a/net/tools/dump_cache/dump_files.cc b/net/tools/dump_cache/dump_files.cc index 009b0e8..34253344 100644 --- a/net/tools/dump_cache/dump_files.cc +++ b/net/tools/dump_cache/dump_files.cc
@@ -160,11 +160,7 @@ class CacheDumper { public: explicit CacheDumper(const base::FilePath& path) - : path_(path), - block_files_(path), - index_(nullptr), - current_hash_(0), - next_addr_(0) {} + : path_(path), block_files_(path) {} CacheDumper(const CacheDumper&) = delete; CacheDumper& operator=(const CacheDumper&) = delete; @@ -187,9 +183,9 @@ base::FilePath path_; disk_cache::BlockFiles block_files_; scoped_refptr<disk_cache::MappedFile> index_file_; - disk_cache::Index* index_; - int current_hash_; - disk_cache::CacheAddr next_addr_; + disk_cache::Index* index_ = nullptr; + int current_hash_ = 0; + disk_cache::CacheAddr next_addr_ = 0; std::set<disk_cache::CacheAddr> dumped_entries_; };
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.cc b/net/tools/quic/quic_client_message_loop_network_helper.cc index 61842efb..4bd223f8 100644 --- a/net/tools/quic/quic_client_message_loop_network_helper.cc +++ b/net/tools/quic/quic_client_message_loop_network_helper.cc
@@ -37,7 +37,7 @@ QuicClientMessageLooplNetworkHelper::QuicClientMessageLooplNetworkHelper( quic::QuicChromiumClock* clock, quic::QuicClientBase* client) - : packet_reader_started_(false), clock_(clock), client_(client) {} + : clock_(clock), client_(client) {} QuicClientMessageLooplNetworkHelper::~QuicClientMessageLooplNetworkHelper() = default;
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.h b/net/tools/quic/quic_client_message_loop_network_helper.h index 23309bc..e11e4c5 100644 --- a/net/tools/quic/quic_client_message_loop_network_helper.h +++ b/net/tools/quic/quic_client_message_loop_network_helper.h
@@ -70,7 +70,7 @@ std::unique_ptr<QuicChromiumPacketReader> packet_reader_; - bool packet_reader_started_; + bool packet_reader_started_ = false; quic::QuicChromiumClock* clock_; quic::QuicClientBase* client_;
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc index b10c9e8a..e355be1 100644 --- a/net/tools/quic/quic_simple_client.cc +++ b/net/tools/quic/quic_simple_client.cc
@@ -48,8 +48,7 @@ base::WrapUnique( new QuicClientMessageLooplNetworkHelper(&clock_, this)), std::move(proof_verifier), - nullptr), - initialized_(false) { + nullptr) { set_server_address(server_address); }
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h index 092c70d..01f8f4cc 100644 --- a/net/tools/quic/quic_simple_client.h +++ b/net/tools/quic/quic_simple_client.h
@@ -61,7 +61,7 @@ quic::QuicChromiumClock clock_; // Tracks if the client is initialized to connect. - bool initialized_; + bool initialized_ = false; base::WeakPtrFactory<QuicSimpleClient> weak_factory_{this}; };
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc index 512fd4d..7d993f9 100644 --- a/net/tools/quic/quic_simple_server.cc +++ b/net/tools/quic/quic_simple_server.cc
@@ -60,8 +60,6 @@ quic::QuicRandom::GetInstance(), std::move(proof_source), quic::KeyExchangeSource::Default()), - read_pending_(false), - synchronous_read_count_(0), read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize)), quic_simple_server_backend_(quic_simple_server_backend) { DCHECK(quic_simple_server_backend);
diff --git a/net/tools/quic/quic_simple_server.h b/net/tools/quic/quic_simple_server.h index 4a31038f..c6f6f48 100644 --- a/net/tools/quic/quic_simple_server.h +++ b/net/tools/quic/quic_simple_server.h
@@ -109,11 +109,11 @@ // Keeps track of whether a read is currently in flight, after which // OnReadComplete will be called. - bool read_pending_; + bool read_pending_ = false; // The number of iterations of the read loop that have completed synchronously // and without posting a new task to the message loop. - int synchronous_read_count_; + int synchronous_read_count_ = 0; // The target buffer of the current read. scoped_refptr<IOBufferWithSize> read_buffer_;
diff --git a/net/tools/quic/quic_simple_server_packet_writer.cc b/net/tools/quic/quic_simple_server_packet_writer.cc index cee2342..8d1349804 100644 --- a/net/tools/quic/quic_simple_server_packet_writer.cc +++ b/net/tools/quic/quic_simple_server_packet_writer.cc
@@ -21,7 +21,7 @@ QuicSimpleServerPacketWriter::QuicSimpleServerPacketWriter( UDPServerSocket* socket, quic::QuicDispatcher* dispatcher) - : socket_(socket), dispatcher_(dispatcher), write_blocked_(false) {} + : socket_(socket), dispatcher_(dispatcher) {} QuicSimpleServerPacketWriter::~QuicSimpleServerPacketWriter() = default;
diff --git a/net/tools/quic/quic_simple_server_packet_writer.h b/net/tools/quic/quic_simple_server_packet_writer.h index f5130586..667980a 100644 --- a/net/tools/quic/quic_simple_server_packet_writer.h +++ b/net/tools/quic/quic_simple_server_packet_writer.h
@@ -65,7 +65,7 @@ quic::QuicDispatcher* dispatcher_; // Whether a write is currently in flight. - bool write_blocked_; + bool write_blocked_ = false; base::WeakPtrFactory<QuicSimpleServerPacketWriter> weak_factory_{this}; };
diff --git a/net/tools/stress_cache/stress_cache.cc b/net/tools/stress_cache/stress_cache.cc index c6eb68a..64187c80 100644 --- a/net/tools/stress_cache/stress_cache.cc +++ b/net/tools/stress_cache/stress_cache.cc
@@ -124,7 +124,7 @@ // closed or deleted. class EntryWrapper { public: - EntryWrapper() : entry_(nullptr), state_(NONE) { + EntryWrapper() { buffer_ = base::MakeRefCounted<net::IOBuffer>(kBufferSize); memset(buffer_->data(), 'k', kBufferSize); } @@ -143,19 +143,19 @@ void OnDeleteDone(int result); void DoIdle(); - disk_cache::Entry* entry_; - Operation state_; + disk_cache::Entry* entry_ = nullptr; + Operation state_ = NONE; scoped_refptr<net::IOBuffer> buffer_; }; // The data that the main thread is working on. struct Data { - Data() : pendig_operations(0), writes(0), iteration(0), cache(nullptr) {} + Data() = default; - int pendig_operations; // Counter of simultaneous operations. - int writes; // How many writes since this iteration started. - int iteration; // The iteration (number of crashes). - disk_cache::BackendImpl* cache; + int pendig_operations = 0; // Counter of simultaneous operations. + int writes = 0; // How many writes since this iteration started. + int iteration = 0; // The iteration (number of crashes). + disk_cache::BackendImpl* cache = nullptr; std::string keys[kNumKeys]; EntryWrapper entries[kNumEntries]; };
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc index 0f8c20c6..43c94da 100644 --- a/net/url_request/http_with_dns_over_https_unittest.cc +++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -64,8 +64,7 @@ class TestHostResolverProc : public HostResolverProc { public: - TestHostResolverProc() - : HostResolverProc(nullptr), insecure_queries_served_(0) {} + TestHostResolverProc() : HostResolverProc(nullptr) {} int Resolve(const std::string& hostname, AddressFamily address_family, @@ -80,8 +79,8 @@ uint32_t insecure_queries_served() { return insecure_queries_served_; } private: - ~TestHostResolverProc() override {} - uint32_t insecure_queries_served_; + ~TestHostResolverProc() override = default; + uint32_t insecure_queries_served_ = 0; }; // Runs and waits for the DoH probe to complete in automatic mode. The resolver @@ -223,7 +222,7 @@ class TestHttpDelegate : public HttpStreamRequest::Delegate { public: explicit TestHttpDelegate(base::RunLoop* loop) : loop_(loop) {} - ~TestHttpDelegate() override {} + ~TestHttpDelegate() override = default; void OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<HttpStream> stream) override {
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc index 940027e5..7cb82bb 100644 --- a/net/url_request/redirect_info.cc +++ b/net/url_request/redirect_info.cc
@@ -99,12 +99,7 @@ } // namespace -RedirectInfo::RedirectInfo() - : status_code(-1), - insecure_scheme_was_upgraded(false), - is_signed_exchange_fallback_redirect(false), - new_referrer_policy( - ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE) {} +RedirectInfo::RedirectInfo() = default; RedirectInfo::RedirectInfo(const RedirectInfo& other) = default;
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h index 7685caa..14a2672 100644 --- a/net/url_request/redirect_info.h +++ b/net/url_request/redirect_info.h
@@ -60,7 +60,7 @@ // The status code for the redirect response. This is almost redundant with // the response headers, but some URLRequestJobs emit redirects without // headers. - int status_code; + int status_code = -1; // The new request method. Depending on the response code, the request method // may change. @@ -77,14 +77,15 @@ // True if this redirect was upgraded to HTTPS due to the // upgrade-insecure-requests policy. - bool insecure_scheme_was_upgraded; + bool insecure_scheme_was_upgraded = false; // True if this is a redirect from Signed Exchange to its fallback URL. - bool is_signed_exchange_fallback_redirect; + bool is_signed_exchange_fallback_redirect = false; // The new referrer policy that should be obeyed if there are // subsequent redirects. - ReferrerPolicy new_referrer_policy; + ReferrerPolicy new_referrer_policy = + ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; }; } // namespace net
diff --git a/net/url_request/report_sender_unittest.cc b/net/url_request/report_sender_unittest.cc index 49d2695..e1f5d81 100644 --- a/net/url_request/report_sender_unittest.cc +++ b/net/url_request/report_sender_unittest.cc
@@ -123,8 +123,7 @@ public: TestReportSenderNetworkDelegate() : url_request_destroyed_callback_(base::DoNothing()), - all_url_requests_destroyed_callback_(base::DoNothing()), - num_requests_(0) {} + all_url_requests_destroyed_callback_(base::DoNothing()) {} TestReportSenderNetworkDelegate(const TestReportSenderNetworkDelegate&) = delete; @@ -195,7 +194,7 @@ private: base::RepeatingClosure url_request_destroyed_callback_; base::RepeatingClosure all_url_requests_destroyed_callback_; - size_t num_requests_; + size_t num_requests_ = 0; GURL expect_url_; std::set<std::string> expect_reports_; std::string expected_content_type_;
diff --git a/net/url_request/test_url_fetcher_factory.cc b/net/url_request/test_url_fetcher_factory.cc index 8e03d6c..321e1013 100644 --- a/net/url_request/test_url_fetcher_factory.cc +++ b/net/url_request/test_url_fetcher_factory.cc
@@ -42,18 +42,7 @@ } TestURLFetcher::TestURLFetcher(int id, const GURL& url, URLFetcherDelegate* d) - : id_(id), - original_url_(url), - delegate_(d), - delegate_for_tests_(nullptr), - did_receive_last_chunk_(false), - fake_load_flags_(0), - fake_response_code_(-1), - fake_response_destination_(STRING), - write_response_file_(false), - fake_was_cached_(false), - fake_response_bytes_(0), - fake_max_retries_(0) { + : id_(id), original_url_(url), delegate_(d), delegate_for_tests_(nullptr) { CHECK(original_url_.is_valid()); }
diff --git a/net/url_request/test_url_fetcher_factory.h b/net/url_request/test_url_fetcher_factory.h index 7a3877f..c75f208 100644 --- a/net/url_request/test_url_fetcher_factory.h +++ b/net/url_request/test_url_fetcher_factory.h
@@ -218,26 +218,26 @@ std::string upload_data_; base::FilePath upload_file_path_; std::list<std::string> chunks_; - bool did_receive_last_chunk_; + bool did_receive_last_chunk_ = false; // User can use set_* methods to provide values returned by getters. // Setting the real values is not possible, because the real class // has no setters. The data is a private member of a class defined // in a .cc file, so we can't get at it with friendship. - int fake_load_flags_; + int fake_load_flags_ = 0; GURL fake_url_; Error fake_error_; - int fake_response_code_; - ResponseDestinationType fake_response_destination_; + int fake_response_code_ = -1; + ResponseDestinationType fake_response_destination_ = STRING; std::string fake_response_string_; base::FilePath fake_response_file_path_; - bool write_response_file_; + bool write_response_file_ = false; ProxyServer fake_proxy_server_; - bool fake_was_cached_; - int64_t fake_response_bytes_; + bool fake_was_cached_ = false; + int64_t fake_response_bytes_ = 0; scoped_refptr<HttpResponseHeaders> fake_response_headers_; HttpRequestHeaders fake_extra_request_headers_; - int fake_max_retries_; + int fake_max_retries_ = 0; std::unique_ptr<URLFetcherResponseWriter> response_writer_; };
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index b9991d11..22b58be 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc
@@ -83,30 +83,8 @@ request_type_(request_type), delegate_(d), delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()), - load_flags_(LOAD_NORMAL), allow_credentials_(absl::nullopt), - response_code_(URLFetcher::RESPONSE_CODE_INVALID), url_request_data_key_(nullptr), - was_cached_(false), - received_response_content_length_(0), - total_received_bytes_(0), - upload_content_set_(false), - upload_range_offset_(0), - upload_range_length_(0), - referrer_policy_( - ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE), - is_chunked_upload_(false), - was_cancelled_(false), - stop_on_redirect_(false), - stopped_on_redirect_(false), - automatically_retry_on_5xx_(true), - num_retries_on_5xx_(0), - max_retries_on_5xx_(0), - num_retries_on_network_changes_(0), - max_retries_on_network_changes_(0), - current_upload_bytes_(-1), - current_response_bytes_(0), - total_response_bytes_(-1), traffic_annotation_(traffic_annotation) { CHECK(original_url_.is_valid()); }
diff --git a/net/url_request/url_fetcher_core.h b/net/url_request/url_fetcher_core.h index 656537e..3d37e01 100644 --- a/net/url_request/url_fetcher_core.h +++ b/net/url_request/url_fetcher_core.h
@@ -254,10 +254,11 @@ // Task runner for upload file access. scoped_refptr<base::TaskRunner> upload_file_task_runner_; std::unique_ptr<URLRequest> request_; // The actual request this wraps - int load_flags_; // Flags for the load operation + int load_flags_ = LOAD_NORMAL; // Flags for the load operation // Whether credentials are sent along with the request. absl::optional<bool> allow_credentials_; - int response_code_; // HTTP status code for the request + int response_code_ = + URLFetcher::RESPONSE_CODE_INVALID; // HTTP status code for the request scoped_refptr<IOBuffer> buffer_; // Read buffer scoped_refptr<URLRequestContextGetter> request_context_getter_; @@ -269,24 +270,25 @@ HttpRequestHeaders extra_request_headers_; scoped_refptr<HttpResponseHeaders> response_headers_; ProxyServer proxy_server_; - bool was_cached_; - int64_t received_response_content_length_; - int64_t total_received_bytes_; + bool was_cached_ = false; + int64_t received_response_content_length_ = 0; + int64_t total_received_bytes_ = 0; IPEndPoint remote_endpoint_; - bool upload_content_set_; // SetUploadData has been called + bool upload_content_set_ = false; // SetUploadData has been called std::string upload_content_; // HTTP POST payload base::FilePath upload_file_path_; // Path to file containing POST payload - uint64_t upload_range_offset_; // Offset from the beginning of the file - // to be uploaded. - uint64_t upload_range_length_; // The length of the part of file to be - // uploaded. + uint64_t upload_range_offset_ = 0; // Offset from the beginning of the file + // to be uploaded. + uint64_t upload_range_length_ = 0; // The length of the part of file to be + // uploaded. URLFetcher::CreateUploadStreamCallback upload_stream_factory_; // Callback to create HTTP POST payload. std::string upload_content_type_; // MIME type of POST payload std::string referrer_; // HTTP Referer header value and policy - ReferrerPolicy referrer_policy_; - bool is_chunked_upload_; // True if using chunked transfer encoding + ReferrerPolicy referrer_policy_ = + ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; + bool is_chunked_upload_ = false; // True if using chunked transfer encoding // Used to write to |chunked_stream|, even after ownership has been passed to // the URLRequest. Continues to be valid even after the request deletes its @@ -316,7 +318,7 @@ scoped_refptr<URLRequestThrottlerEntryInterface> url_throttler_entry_; // True if the URLFetcher has been cancelled. - bool was_cancelled_; + bool was_cancelled_ = false; // Writer object to write response to the destination like file and string. std::unique_ptr<URLFetcherResponseWriter> response_writer_; @@ -324,42 +326,42 @@ // By default any server-initiated redirects are automatically followed. If // this flag is set to true, however, a redirect will halt the fetch and call // back to to the delegate immediately. - bool stop_on_redirect_; + bool stop_on_redirect_ = false; // True when we're actually stopped due to a redirect halted by the above. We // use this to ensure that |url_| is set to the redirect destination rather // than the originally-fetched URL. - bool stopped_on_redirect_; + bool stopped_on_redirect_ = false; // If |automatically_retry_on_5xx_| is false, 5xx responses will be // propagated to the observer, if it is true URLFetcher will automatically // re-execute the request, after the back-off delay has expired. // true by default. - bool automatically_retry_on_5xx_; + bool automatically_retry_on_5xx_ = true; // |num_retries_on_5xx_| indicates how many times we've failed to successfully // fetch this URL due to 5xx responses. Once this value exceeds the maximum // number of retries specified by the owner URLFetcher instance, // we'll give up. - int num_retries_on_5xx_; + int num_retries_on_5xx_ = 0; // Maximum retries allowed when 5xx responses are received. - int max_retries_on_5xx_; + int max_retries_on_5xx_ = 0; // Back-off time delay. 0 by default. base::TimeDelta backoff_delay_; // The number of retries that have been attempted due to ERR_NETWORK_CHANGED. - int num_retries_on_network_changes_; + int num_retries_on_network_changes_ = 0; // Maximum retries allowed when the request fails with ERR_NETWORK_CHANGED. // 0 by default. - int max_retries_on_network_changes_; + int max_retries_on_network_changes_ = 0; // Timer to poll the progress of uploading for POST and PUT requests. // When crbug.com/119629 is fixed, scoped_ptr is not necessary here. std::unique_ptr<base::RepeatingTimer> upload_progress_checker_timer_; // Number of bytes sent so far. - int64_t current_upload_bytes_; + int64_t current_upload_bytes_ = -1; // Number of bytes received so far. - int64_t current_response_bytes_; + int64_t current_response_bytes_ = 0; // Total expected bytes to receive (-1 if it cannot be determined). - int64_t total_response_bytes_; + int64_t total_response_bytes_ = -1; const net::NetworkTrafficAnnotationTag traffic_annotation_;
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc index e9c1cba..dad7794 100644 --- a/net/url_request/url_fetcher_impl_unittest.cc +++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -66,7 +66,7 @@ // Can only be used once. class WaitingURLFetcherDelegate : public URLFetcherDelegate { public: - WaitingURLFetcherDelegate() : did_complete_(false) {} + WaitingURLFetcherDelegate() = default; WaitingURLFetcherDelegate(const WaitingURLFetcherDelegate&) = delete; WaitingURLFetcherDelegate& operator=(const WaitingURLFetcherDelegate&) = @@ -154,7 +154,7 @@ } private: - bool did_complete_; + bool did_complete_ = false; std::unique_ptr<URLFetcherImpl> fetcher_; const scoped_refptr<base::SequencedTaskRunner> task_runner_ = @@ -335,7 +335,7 @@ class URLFetcherTest : public TestWithTaskEnvironment { public: - URLFetcherTest() : num_upload_streams_created_(0) {} + URLFetcherTest() = default; static int GetNumFetcherCores() { return URLFetcherImpl::GetNumFetcherCores(); @@ -470,7 +470,7 @@ std::unique_ptr<EmbeddedTestServer> test_server_; GURL hanging_url_; - size_t num_upload_streams_created_; + size_t num_upload_streams_created_ = 0; }; namespace { @@ -939,8 +939,7 @@ // been uploaded. class CheckUploadProgressDelegate : public WaitingURLFetcherDelegate { public: - CheckUploadProgressDelegate() - : chunk_(1 << 16, 'a'), num_chunks_appended_(0), last_seen_progress_(0) {} + CheckUploadProgressDelegate() : chunk_(1 << 16, 'a') {} CheckUploadProgressDelegate(const CheckUploadProgressDelegate&) = delete; CheckUploadProgressDelegate& operator=(const CheckUploadProgressDelegate&) = @@ -978,8 +977,8 @@ const std::string chunk_; - int64_t num_chunks_appended_; - int64_t last_seen_progress_; + int64_t num_chunks_appended_ = 0; + int64_t last_seen_progress_ = 0; }; TEST_F(URLFetcherTest, UploadProgress) { @@ -1009,8 +1008,8 @@ // that file size is correctly reported. class CheckDownloadProgressDelegate : public WaitingURLFetcherDelegate { public: - CheckDownloadProgressDelegate(int64_t file_size) - : file_size_(file_size), last_seen_progress_(0) {} + explicit CheckDownloadProgressDelegate(int64_t file_size) + : file_size_(file_size) {} CheckDownloadProgressDelegate(const CheckDownloadProgressDelegate&) = delete; CheckDownloadProgressDelegate& operator=( @@ -1033,7 +1032,7 @@ private: int64_t file_size_; - int64_t last_seen_progress_; + int64_t last_seen_progress_ = 0; }; TEST_F(URLFetcherTest, DownloadProgress) { @@ -1422,8 +1421,7 @@ // request. Can't reuse the old one because fetchers release it on completion. ReuseFetcherDelegate( scoped_refptr<URLRequestContextGetter> second_request_context_getter) - : first_request_complete_(false), - second_request_context_getter_(second_request_context_getter) {} + : second_request_context_getter_(second_request_context_getter) {} ReuseFetcherDelegate(const ReuseFetcherDelegate&) = delete; ReuseFetcherDelegate& operator=(const ReuseFetcherDelegate&) = delete; @@ -1450,7 +1448,7 @@ } private: - bool first_request_complete_; + bool first_request_complete_ = false; scoped_refptr<URLRequestContextGetter> second_request_context_getter_; };
diff --git a/net/url_request/url_fetcher_response_writer.cc b/net/url_request/url_fetcher_response_writer.cc index caf260e0..b3064d9 100644 --- a/net/url_request/url_fetcher_response_writer.cc +++ b/net/url_request/url_fetcher_response_writer.cc
@@ -55,9 +55,7 @@ URLFetcherFileWriter::URLFetcherFileWriter( scoped_refptr<base::SequencedTaskRunner> file_task_runner, const base::FilePath& file_path) - : file_task_runner_(file_task_runner), - file_path_(file_path), - owns_file_(false) { + : file_task_runner_(file_task_runner), file_path_(file_path) { DCHECK(file_task_runner_.get()); }
diff --git a/net/url_request/url_fetcher_response_writer.h b/net/url_request/url_fetcher_response_writer.h index 533ad20..474087c 100644 --- a/net/url_request/url_fetcher_response_writer.h +++ b/net/url_request/url_fetcher_response_writer.h
@@ -140,7 +140,7 @@ base::FilePath file_path_; // True when this instance is responsible to delete the file at |file_path_|. - bool owns_file_; + bool owns_file_ = false; std::unique_ptr<FileStream> file_stream_;
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index fcea2dd..59c2435a 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -577,35 +577,13 @@ : context_(context), net_log_(CreateNetLogWithSource(context->net_log(), net_log_source)), url_chain_(1, url), - force_ignore_site_for_cookies_(false), - force_ignore_top_frame_party_for_cookies_(false), - force_main_frame_for_same_site_cookies_(false), method_("GET"), - referrer_policy_( - ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE), - first_party_url_policy_( - RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL), - load_flags_(LOAD_NORMAL), - allow_credentials_(true), - secure_dns_policy_(SecureDnsPolicy::kAllow), -#if BUILDFLAG(ENABLE_REPORTING) - reporting_upload_depth_(0), -#endif delegate_(delegate), is_for_websockets_(is_for_websockets), - status_(OK), - is_pending_(false), - is_redirecting_(false), redirect_limit_(kMaxRedirects), priority_(priority), - delegate_event_type_(NetLogEventType::FAILED), - calling_delegate_(false), - use_blocked_by_as_load_param_(false), - has_notified_completion_(false), - received_response_content_length_(0), creation_time_(base::TimeTicks::Now()), - traffic_annotation_(traffic_annotation), - upgrade_if_insecure_(false) { + traffic_annotation_(traffic_annotation) { // Sanity check out environment. DCHECK(base::ThreadTaskRunnerHandle::IsSet());
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 3b18dd178..10840b0 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -22,6 +22,7 @@ #include "net/base/idempotency.h" #include "net/base/ip_endpoint.h" #include "net/base/isolation_info.h" +#include "net/base/load_flags.h" #include "net/base/load_states.h" #include "net/base/load_timing_info.h" #include "net/base/net_error_details.h" @@ -938,29 +939,31 @@ IsolationInfo isolation_info_; - bool force_ignore_site_for_cookies_; - bool force_ignore_top_frame_party_for_cookies_; - bool force_main_frame_for_same_site_cookies_; + bool force_ignore_site_for_cookies_ = false; + bool force_ignore_top_frame_party_for_cookies_ = false; + bool force_main_frame_for_same_site_cookies_ = false; absl::optional<url::Origin> initiator_; GURL delegate_redirect_url_; std::string method_; // "GET", "POST", etc. Should be all uppercase. std::string referrer_; - ReferrerPolicy referrer_policy_; - RedirectInfo::FirstPartyURLPolicy first_party_url_policy_; + ReferrerPolicy referrer_policy_ = + ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; + RedirectInfo::FirstPartyURLPolicy first_party_url_policy_ = + RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL; HttpRequestHeaders extra_request_headers_; // Flags indicating the request type for the load. Expected values are LOAD_* // enums above. - int load_flags_; + int load_flags_ = LOAD_NORMAL; // Whether the request is allowed to send credentials in general. Set by // caller. - bool allow_credentials_; - SecureDnsPolicy secure_dns_policy_; + bool allow_credentials_ = true; + SecureDnsPolicy secure_dns_policy_ = SecureDnsPolicy::kAllow; CookieAccessResultList maybe_sent_cookies_; CookieAndLineAccessResultList maybe_stored_cookies_; #if BUILDFLAG(ENABLE_REPORTING) - int reporting_upload_depth_; + int reporting_upload_depth_ = 0; #endif // Never access methods of the |delegate_| directly. Always use the @@ -980,7 +983,7 @@ // but once an error is encountered or the request is canceled, it will take // the appropriate error code and never change again. If multiple failures // have been encountered, this will be the first error encountered. - int status_; + int status_ = OK; // The HTTP response info, lazily initialized. HttpResponseInfo response_info_; @@ -988,12 +991,12 @@ // Tells us whether the job is outstanding. This is true from the time // Start() is called to the time we dispatch RequestComplete and indicates // whether the job is active. - bool is_pending_; + bool is_pending_ = false; // Indicates if the request is in the process of redirecting to a new // location. It is true from the time the headers complete until a // new request begins. - bool is_redirecting_; + bool is_redirecting_ = false; // Number of times we're willing to redirect. Used to guard against // infinite redirects. @@ -1010,23 +1013,23 @@ // If |calling_delegate_| is true, the event type of the delegate being // called. - NetLogEventType delegate_event_type_; + NetLogEventType delegate_event_type_ = NetLogEventType::FAILED; // True if this request is currently calling a delegate, or is blocked waiting // for the URL request or network delegate to resume it. - bool calling_delegate_; + bool calling_delegate_ = false; // An optional parameter that provides additional information about what // |this| is currently being blocked by. std::string blocked_by_; - bool use_blocked_by_as_load_param_; + bool use_blocked_by_as_load_param_ = false; // Safe-guard to ensure that we do not send multiple "I am completed" // messages to network delegate. // TODO(battre): Remove this. http://crbug.com/89049 - bool has_notified_completion_; + bool has_notified_completion_ = false; - int64_t received_response_content_length_; + int64_t received_response_content_length_ = 0; base::TimeTicks creation_time_; @@ -1063,7 +1066,7 @@ // entry will be marked as unusable and will not be re-used. std::string expected_response_checksum_; - bool upgrade_if_insecure_; + bool upgrade_if_insecure_ = false; bool send_client_certs_ = true;
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index 49a4284..0c0847c 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc
@@ -55,9 +55,6 @@ network_error_logging_service_(nullptr), #endif // BUILDFLAG(ENABLE_REPORTING) url_requests_(std::make_unique<std::set<const URLRequest*>>()), - enable_brotli_(false), - check_cleartext_permitted_(false), - require_network_isolation_key_(false), bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle) { }
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index 27df35f..9da6d7e 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h
@@ -352,14 +352,14 @@ std::unique_ptr<std::set<const URLRequest*>> url_requests_; // Enables Brotli Content-Encoding support. - bool enable_brotli_; + bool enable_brotli_ = false; // Enables checking system policy before allowing a cleartext http or ws // request. Only used on Android. - bool check_cleartext_permitted_; + bool check_cleartext_permitted_ = false; // Triggers a DCHECK if a NetworkIsolationKey/IsolationInfo is not provided to // a request when true. - bool require_network_isolation_key_; + bool require_network_isolation_key_ = false; NetworkChangeNotifier::NetworkHandle bound_network_;
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index f011342..d8a383a6 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -125,8 +125,7 @@ } // namespace -URLRequestContextBuilder::HttpCacheParams::HttpCacheParams() - : type(IN_MEMORY), max_size(0), reset_cache(false) {} +URLRequestContextBuilder::HttpCacheParams::HttpCacheParams() = default; URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() = default; URLRequestContextBuilder::URLRequestContextBuilder() = default;
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index 0a8de9e9..572a764 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -110,14 +110,14 @@ ~HttpCacheParams(); // The type of HTTP cache. Default is IN_MEMORY. - Type type; + Type type = IN_MEMORY; // The max size of the cache in bytes. Default is algorithmically determined // based off available disk space. - int max_size; + int max_size = 0; // Whether or not we need to reset the cache due to an experiment change. - bool reset_cache; + bool reset_cache = false; // The cache path (when type is DISK). base::FilePath path;
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc index 7ac17525..9a19dde 100644 --- a/net/url_request/url_request_filter.cc +++ b/net/url_request/url_request_filter.cc
@@ -140,7 +140,7 @@ return job; } -URLRequestFilter::URLRequestFilter() : hit_count_(0) { +URLRequestFilter::URLRequestFilter() { DCHECK(OnMessageLoopForInterceptorAddition()); URLRequestJobFactory::SetInterceptorForTesting(this); }
diff --git a/net/url_request/url_request_filter.h b/net/url_request/url_request_filter.h index 44943f3..134f029 100644 --- a/net/url_request/url_request_filter.h +++ b/net/url_request/url_request_filter.h
@@ -88,7 +88,7 @@ // Maps URLs to interceptors. URLInterceptorMap url_interceptor_map_; - mutable int hit_count_; + mutable int hit_count_ = 0; // Singleton instance. static URLRequestFilter* shared_instance_;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 619573f..d170e20 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -229,18 +229,9 @@ URLRequest* request, const HttpUserAgentSettings* http_user_agent_settings) : URLRequestJob(request), - num_cookie_lines_left_(0), - priority_(DEFAULT_PRIORITY), response_info_(nullptr), - proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH), - server_auth_state_(AUTH_STATE_DONT_NEED_AUTH), - read_in_progress_(false), throttling_entry_(nullptr), - done_(false), - awaiting_callback_(false), - http_user_agent_settings_(http_user_agent_settings), - total_received_bytes_from_previous_transactions_(0), - total_sent_bytes_from_previous_transactions_(0) { + http_user_agent_settings_(http_user_agent_settings) { URLRequestThrottlerManager* manager = request->context()->throttler_manager(); if (manager) throttling_entry_ = manager->RegisterRequestUrl(request->url());
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index f2fcb73..7bc5cf5 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -201,7 +201,7 @@ absl::optional<CanonicalCookie> cookie, std::string cookie_string, CookieAccessResult access_result); - int num_cookie_lines_left_; + int num_cookie_lines_left_ = 0; CookieAndLineAccessResultList set_cookie_access_result_list_; // Some servers send the body compressed, but specify the content length as @@ -229,7 +229,7 @@ // set. bool IsPartitionedCookiesEnabled() const; - RequestPriority priority_; + RequestPriority priority_ = DEFAULT_PRIORITY; HttpRequestInfo request_info_; raw_ptr<const HttpResponseInfo> response_info_; @@ -240,11 +240,11 @@ std::unique_ptr<HttpResponseInfo> override_response_info_; // Auth states for proxy and origin server. - AuthState proxy_auth_state_; - AuthState server_auth_state_; + AuthState proxy_auth_state_ = AUTH_STATE_DONT_NEED_AUTH; + AuthState server_auth_state_ = AUTH_STATE_DONT_NEED_AUTH; AuthCredentials auth_credentials_; - bool read_in_progress_; + bool read_in_progress_ = false; std::unique_ptr<HttpTransaction> transaction_; @@ -255,7 +255,7 @@ base::Time request_creation_time_; // True when we are done doing work. - bool done_; + bool done_ = false; // The start time for the job, ignoring re-starts. base::TimeTicks start_time_; @@ -283,16 +283,16 @@ // True if we are waiting a callback and // NetworkDelegate::NotifyURLRequestDestroyed has not been called, yet, // to inform the NetworkDelegate that it may not call back. - bool awaiting_callback_; + bool awaiting_callback_ = false; raw_ptr<const HttpUserAgentSettings> http_user_agent_settings_; // Keeps track of total received bytes over the network from transactions used // by this job that have already been destroyed. - int64_t total_received_bytes_from_previous_transactions_; + int64_t total_received_bytes_from_previous_transactions_ = 0; // Keeps track of total sent bytes over the network from transactions used by // this job that have already been destroyed. - int64_t total_sent_bytes_from_previous_transactions_; + int64_t total_sent_bytes_from_previous_transactions_ = 0; RequestHeadersCallback request_headers_callback_; ResponseHeadersCallback early_response_headers_callback_;
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index a53909f..6cfcbd5 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc
@@ -103,8 +103,7 @@ public: explicit TestURLRequestHttpJob(URLRequest* request) : URLRequestHttpJob(request, - request->context()->http_user_agent_settings()), - use_null_source_stream_(false) {} + request->context()->http_user_agent_settings()) {} TestURLRequestHttpJob(const TestURLRequestHttpJob&) = delete; TestURLRequestHttpJob& operator=(const TestURLRequestHttpJob&) = delete; @@ -128,7 +127,7 @@ using URLRequestHttpJob::priority; private: - bool use_null_source_stream_; + bool use_null_source_stream_ = false; }; class URLRequestHttpJobSetUpSourceTest : public TestWithTaskEnvironment {
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 9b7a9832..9262d5b 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -84,13 +84,7 @@ const raw_ptr<URLRequestJob> job_; }; -URLRequestJob::URLRequestJob(URLRequest* request) - : request_(request), - done_(false), - prefilter_bytes_read_(0), - postfilter_bytes_read_(0), - has_handled_response_(false), - expected_content_size_(-1) {} +URLRequestJob::URLRequestJob(URLRequest* request) : request_(request) {} URLRequestJob::~URLRequestJob() { }
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index 39496e38..0f55a00b 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h
@@ -408,13 +408,13 @@ // Indicates that the job is done producing data, either it has completed // all the data or an error has been encountered. Set exclusively by // NotifyDone so that it is kept in sync with the request. - bool done_; + bool done_ = false; // Number of raw network bytes read from job subclass. - int64_t prefilter_bytes_read_; + int64_t prefilter_bytes_read_ = 0; // Number of bytes after applying |source_stream_| filters. - int64_t postfilter_bytes_read_; + int64_t postfilter_bytes_read_ = 0; // The first SourceStream of the SourceStream chain used. std::unique_ptr<SourceStream> source_stream_; @@ -429,10 +429,10 @@ // Used by HandleResponseIfNecessary to track whether we've sent the // OnResponseStarted callback and potentially redirect callbacks as well. - bool has_handled_response_; + bool has_handled_response_ = false; // Expected content size - int64_t expected_content_size_; + int64_t expected_content_size_ = -1; // Set when a redirect is deferred. Redirects are deferred after validity // checks are performed, so this field must not be modified.
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 194b0871..e186610 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -304,24 +304,7 @@ std::move(on_complete_).Run(); } -TestNetworkDelegate::TestNetworkDelegate() - : last_error_(0), - error_count_(0), - created_requests_(0), - destroyed_requests_(0), - completed_requests_(0), - canceled_requests_(0), - cookie_options_bit_mask_(0), - blocked_annotate_cookies_count_(0), - blocked_set_cookie_count_(0), - set_cookie_count_(0), - before_start_transaction_count_(0), - headers_received_count_(0), - has_load_timing_info_before_redirect_(false), - cancel_request_with_policy_violating_referrer_(false), - before_start_transaction_fails_(false), - add_header_to_first_response_(false), - next_request_id_(0) {} +TestNetworkDelegate::TestNetworkDelegate() = default; TestNetworkDelegate::~TestNetworkDelegate() { for (auto i = next_states_.begin(); i != next_states_.end(); ++i) {
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 33794203..05e5399f 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h
@@ -338,18 +338,18 @@ // OnHeadersReceived() stage. absl::optional<GURL> preserve_fragment_on_redirect_url_; - int last_error_; - int error_count_; - int created_requests_; - int destroyed_requests_; - int completed_requests_; - int canceled_requests_; - int cookie_options_bit_mask_; - int blocked_annotate_cookies_count_; - int blocked_set_cookie_count_; - int set_cookie_count_; - int before_start_transaction_count_; - int headers_received_count_; + int last_error_ = 0; + int error_count_ = 0; + int created_requests_ = 0; + int destroyed_requests_ = 0; + int completed_requests_ = 0; + int canceled_requests_ = 0; + int cookie_options_bit_mask_ = 0; + int blocked_annotate_cookies_count_ = 0; + int blocked_set_cookie_count_ = 0; + int set_cookie_count_ = 0; + int before_start_transaction_count_ = 0; + int headers_received_count_ = 0; // NetworkDelegate callbacks happen in a particular order (e.g. // OnBeforeURLRequest is always called before OnBeforeStartTransaction). @@ -362,12 +362,13 @@ std::map<int, std::string> event_order_; LoadTimingInfo load_timing_info_before_redirect_; - bool has_load_timing_info_before_redirect_; + bool has_load_timing_info_before_redirect_ = false; - bool cancel_request_with_policy_violating_referrer_; // false by default - bool before_start_transaction_fails_; - bool add_header_to_first_response_; - int next_request_id_; + bool cancel_request_with_policy_violating_referrer_ = + false; // false by default + bool before_start_transaction_fails_ = false; + bool add_header_to_first_response_ = false; + int next_request_id_ = 0; }; // ----------------------------------------------------------------------------
diff --git a/net/url_request/url_request_throttler_manager.cc b/net/url_request/url_request_throttler_manager.cc index 1aff5e8..9fb5ca1 100644 --- a/net/url_request/url_request_throttler_manager.cc +++ b/net/url_request/url_request_throttler_manager.cc
@@ -17,9 +17,7 @@ const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200; URLRequestThrottlerManager::URLRequestThrottlerManager() - : requests_since_last_gc_(0), - logged_for_localhost_disabled_(false), - registered_from_thread_(base::kInvalidThreadId) { + : registered_from_thread_(base::kInvalidThreadId) { url_id_replacements_.ClearPassword(); url_id_replacements_.ClearUsername(); url_id_replacements_.ClearQuery();
diff --git a/net/url_request/url_request_throttler_manager.h b/net/url_request/url_request_throttler_manager.h index 3f533f5..5b6a98a6 100644 --- a/net/url_request/url_request_throttler_manager.h +++ b/net/url_request/url_request_throttler_manager.h
@@ -120,7 +120,7 @@ // This keeps track of how many requests have been made. Used with // GarbageCollectEntries. - unsigned int requests_since_last_gc_; + unsigned int requests_since_last_gc_ = 0; // Valid after construction. GURL::Replacements url_id_replacements_; @@ -135,7 +135,7 @@ // Initially false, switches to true once we have logged because of back-off // being disabled for localhost. - bool logged_for_localhost_disabled_; + bool logged_for_localhost_disabled_ = false; // NetLog to use, if configured. NetLogWithSource net_log_;
diff --git a/net/url_request/url_request_throttler_simulation_unittest.cc b/net/url_request/url_request_throttler_simulation_unittest.cc index e55ed330..f7c2bac 100644 --- a/net/url_request/url_request_throttler_simulation_unittest.cc +++ b/net/url_request/url_request_throttler_simulation_unittest.cc
@@ -122,10 +122,6 @@ Server(int max_queries_per_tick, double request_drop_ratio) : max_queries_per_tick_(max_queries_per_tick), request_drop_ratio_(request_drop_ratio), - num_overloaded_ticks_remaining_(0), - num_current_tick_queries_(0), - num_overloaded_ticks_(0), - max_experienced_queries_per_tick_(0), context_(CreateTestURLRequestContextBuilder()->Build()), mock_request_(context_->CreateRequest(GURL(), DEFAULT_PRIORITY, @@ -293,10 +289,10 @@ TimeTicks end_downtime_; const int max_queries_per_tick_; const double request_drop_ratio_; // Ratio of requests to 503 when failing. - int num_overloaded_ticks_remaining_; - int num_current_tick_queries_; - int num_overloaded_ticks_; - int max_experienced_queries_per_tick_; + int num_overloaded_ticks_remaining_ = 0; + int num_current_tick_queries_ = 0; + int num_overloaded_ticks_ = 0; + int max_experienced_queries_per_tick_ = 0; std::vector<int> requests_per_tick_; std::unique_ptr<URLRequestContext> context_; @@ -334,9 +330,7 @@ // regular clients). class RequesterResults { public: - RequesterResults() - : num_attempts_(0), num_successful_(0), num_failed_(0), num_blocked_(0) { - } + RequesterResults() = default; void AddSuccess() { ++num_attempts_; @@ -387,10 +381,10 @@ } private: - int num_attempts_; - int num_successful_; - int num_failed_; - int num_blocked_; + int num_attempts_ = 0; + int num_successful_ = 0; + int num_failed_ = 0; + int num_blocked_ = 0; }; // Represents an Requester in a simulated DDoS situation, that periodically @@ -403,7 +397,6 @@ RequesterResults* results) : throttler_entry_(throttler_entry), time_between_requests_(time_between_requests), - last_attempt_was_failure_(false), server_(server), results_(results) { DCHECK(server_); @@ -477,7 +470,7 @@ base::TimeDelta request_jitter_; TimeTicks time_of_last_attempt_; TimeTicks time_of_last_success_; - bool last_attempt_was_failure_; + bool last_attempt_was_failure_ = false; base::TimeDelta last_downtime_duration_; const raw_ptr<Server> server_; const raw_ptr<RequesterResults> results_; // May be NULL.
diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc index 2f748210..98c2aea 100644 --- a/net/url_request/url_request_throttler_unittest.cc +++ b/net/url_request/url_request_throttler_unittest.cc
@@ -101,7 +101,7 @@ class MockURLRequestThrottlerManager : public URLRequestThrottlerManager { public: - MockURLRequestThrottlerManager() : create_entry_index_(0) {} + MockURLRequestThrottlerManager() = default; // Method to process the URL using URLRequestThrottlerManager protected // method. @@ -129,7 +129,7 @@ } private: - int create_entry_index_; + int create_entry_index_ = 0; }; struct TimeAndBool {
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 62a007b1..66b18c5 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -445,15 +445,15 @@ // Values returned on blocking stages when mode is SYNCHRONOUS or // AUTO_CALLBACK. For USER_CALLBACK these are set automatically to IO_PENDING. - int retval_; + int retval_ = OK; GURL redirect_url_; // Used if non-empty during OnBeforeURLRequest. - int block_on_; // Bit mask: in which stages to block. + int block_on_ = 0; // Bit mask: in which stages to block. // Internal variables, not set by not the user: // Last blocked stage waiting for user callback (unused if |block_mode_| != // USER_CALLBACK). - Stage stage_blocked_for_callback_; + Stage stage_blocked_for_callback_ = NOT_BLOCKED; // Callback objects stored during blocking stages. CompletionOnceCallback callback_; @@ -465,10 +465,7 @@ }; BlockingNetworkDelegate::BlockingNetworkDelegate(BlockMode block_mode) - : block_mode_(block_mode), - retval_(OK), - block_on_(0), - stage_blocked_for_callback_(NOT_BLOCKED) {} + : block_mode_(block_mode) {} void BlockingNetworkDelegate::RunUntilBlocked() { base::RunLoop run_loop; @@ -6399,7 +6396,7 @@ // called. class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { public: - MockExpectCTReporter() : num_failures_(0) {} + MockExpectCTReporter() = default; ~MockExpectCTReporter() override = default; void OnExpectCTFailed( @@ -6417,15 +6414,14 @@ uint32_t num_failures() { return num_failures_; } private: - uint32_t num_failures_; + uint32_t num_failures_ = 0; }; // A CTPolicyEnforcer that returns a default CTPolicyCompliance value // for every certificate. class MockCTPolicyEnforcer : public CTPolicyEnforcer { public: - MockCTPolicyEnforcer() - : default_result_(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS) {} + MockCTPolicyEnforcer() = default; ~MockCTPolicyEnforcer() override = default; ct::CTPolicyCompliance CheckCompliance( @@ -6440,7 +6436,8 @@ } private: - ct::CTPolicyCompliance default_result_; + ct::CTPolicyCompliance default_result_ = + ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS; }; // Tests that Expect CT headers for the preload list are processed correctly. @@ -9977,9 +9974,7 @@ class SSLClientAuthTestDelegate : public TestDelegate { public: - SSLClientAuthTestDelegate() : on_certificate_requested_count_(0) { - set_on_complete(base::DoNothing()); - } + SSLClientAuthTestDelegate() { set_on_complete(base::DoNothing()); } void OnCertificateRequested(URLRequest* request, SSLCertRequestInfo* cert_request_info) override { on_certificate_requested_count_++; @@ -9995,7 +9990,7 @@ } private: - int on_certificate_requested_count_; + int on_certificate_requested_count_ = 0; base::OnceClosure on_certificate_requested_; };
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc index 79f1a63..d66b4b9 100644 --- a/net/websockets/websocket_basic_handshake_stream.cc +++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -177,8 +177,7 @@ std::vector<std::string> requested_extensions, WebSocketStreamRequestAPI* request, WebSocketEndpointLockManager* websocket_endpoint_lock_manager) - : result_(HandshakeResult::INCOMPLETE), - state_(std::move(connection), using_proxy), + : state_(std::move(connection), using_proxy), connect_delegate_(connect_delegate), http_response_info_(nullptr), requested_sub_protocols_(std::move(requested_sub_protocols)),
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h index 8496184..8b84684 100644 --- a/net/websockets/websocket_basic_handshake_stream.h +++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -115,7 +115,7 @@ HttpStreamParser* parser() const { return state_.parser(); } - HandshakeResult result_; + HandshakeResult result_ = HandshakeResult::INCOMPLETE; // The request URL. GURL url_;
diff --git a/net/websockets/websocket_basic_stream_adapters.cc b/net/websockets/websocket_basic_stream_adapters.cc index 0855172..88144bd2 100644 --- a/net/websockets/websocket_basic_stream_adapters.cc +++ b/net/websockets/websocket_basic_stream_adapters.cc
@@ -52,12 +52,7 @@ base::WeakPtr<SpdyStream> stream, Delegate* delegate, NetLogWithSource net_log) - : headers_sent_(false), - stream_(stream), - stream_error_(ERR_CONNECTION_CLOSED), - delegate_(delegate), - write_length_(0), - net_log_(net_log) { + : stream_(stream), delegate_(delegate), net_log_(net_log) { stream_->SetDelegate(this); }
diff --git a/net/websockets/websocket_basic_stream_adapters.h b/net/websockets/websocket_basic_stream_adapters.h index 0052524..e522abac 100644 --- a/net/websockets/websocket_basic_stream_adapters.h +++ b/net/websockets/websocket_basic_stream_adapters.h
@@ -115,13 +115,13 @@ // True if SpdyStream::Delegate::OnHeadersSent() has been called. // SpdyStream::SendData() must not be called before that. - bool headers_sent_; + bool headers_sent_ = false; // The underlying SpdyStream. base::WeakPtr<SpdyStream> stream_; // The error code with which SpdyStream was closed. - int stream_error_; + int stream_error_ = ERR_CONNECTION_CLOSED; raw_ptr<Delegate> delegate_; @@ -140,7 +140,7 @@ // Write length saved to be passed to |write_callback_|. This is necessary // because SpdyStream::Delegate::OnDataSent() does not pass number of bytes // written. - int write_length_; + int write_length_ = 0; // Write callback saved for asynchronous writes (all writes are asynchronous). CompletionOnceCallback write_callback_;
diff --git a/net/websockets/websocket_basic_stream_test.cc b/net/websockets/websocket_basic_stream_test.cc index 440da1d..1d5ab38 100644 --- a/net/websockets/websocket_basic_stream_test.cc +++ b/net/websockets/websocket_basic_stream_test.cc
@@ -128,8 +128,7 @@ nullptr /* net_log */, nullptr /* websocket_endpoint_lock_manager */), pool_(1, 1, &common_connect_job_params_), - generator_(&GenerateNulMaskingKey), - expect_all_io_to_complete_(true) {} + generator_(&GenerateNulMaskingKey) {} ~WebSocketBasicStreamSocketTest() override { // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so @@ -184,7 +183,7 @@ std::string extensions_; NetLogWithSource net_log_; WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_; - bool expect_all_io_to_complete_; + bool expect_all_io_to_complete_ = true; std::unique_ptr<WebSocketBasicStream> stream_; };
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc index 84d37a7..8360beff 100644 --- a/net/websockets/websocket_channel.cc +++ b/net/websockets/websocket_channel.cc
@@ -150,7 +150,7 @@ // those frames. class WebSocketChannel::SendBuffer { public: - SendBuffer() : total_bytes_(0) {} + SendBuffer() = default; // Add a WebSocketFrame to the buffer and increase total_bytes_. void AddFrame(std::unique_ptr<WebSocketFrame> chunk, @@ -168,7 +168,7 @@ // The total size of the payload data in |frames_|. This will be used to // measure the throughput of the link. // TODO(ricea): Measure the throughput of the link. - uint64_t total_bytes_; + uint64_t total_bytes_ = 0; }; void WebSocketChannel::SendBuffer::AddFrame( @@ -248,14 +248,7 @@ closing_handshake_timeout_( base::Seconds(kClosingHandshakeTimeoutSeconds)), underlying_connection_close_timeout_( - base::Seconds(kUnderlyingConnectionCloseTimeoutSeconds)), - has_received_close_frame_(false), - received_close_code_(0), - state_(FRESHLY_CONSTRUCTED), - sending_text_message_(false), - receiving_text_message_(false), - expecting_to_handle_continuation_(false), - initial_frame_forwarded_(false) {} + base::Seconds(kUnderlyingConnectionCloseTimeoutSeconds)) {} WebSocketChannel::~WebSocketChannel() { // The stream may hold a pointer to read_frames_, and so it needs to be
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h index 52c00d9a..c8d9690 100644 --- a/net/websockets/websocket_channel.h +++ b/net/websockets/websocket_channel.h
@@ -366,28 +366,28 @@ // Storage for the status code and reason from the time the Close frame // arrives until the connection is closed and they are passed to // OnDropChannel(). - bool has_received_close_frame_; - uint16_t received_close_code_; + bool has_received_close_frame_ = false; + uint16_t received_close_code_ = 0; std::string received_close_reason_; // The current state of the channel. Mainly used for sanity checking, but also // used to track the close state. - State state_; + State state_ = FRESHLY_CONSTRUCTED; // UTF-8 validator for outgoing Text messages. base::StreamingUtf8Validator outgoing_utf8_validator_; - bool sending_text_message_; + bool sending_text_message_ = false; // UTF-8 validator for incoming Text messages. base::StreamingUtf8Validator incoming_utf8_validator_; - bool receiving_text_message_; + bool receiving_text_message_ = false; // True if we are in the middle of receiving a message. - bool expecting_to_handle_continuation_; + bool expecting_to_handle_continuation_ = false; // True if we have already sent the type (Text or Binary) of the current // message to the renderer. This can be false if the message is empty so far. - bool initial_frame_forwarded_; + bool initial_frame_forwarded_ = false; // True if we're waiting for OnReadDone() callback. bool is_reading_ = false;
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc index f797576..7ac0456 100644 --- a/net/websockets/websocket_channel_test.cc +++ b/net/websockets/websocket_channel_test.cc
@@ -468,7 +468,7 @@ // After constructing the object, call PrepareReadFrames() once for each // time you wish it to return from the test. - ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {} + ReadableFakeWebSocketStream() = default; // Check that all the prepared responses have been consumed. ~ReadableFakeWebSocketStream() override { @@ -555,13 +555,13 @@ std::vector<std::unique_ptr<Response>> responses_; // The index into the responses_ array of the next response to be returned. - size_t index_; + size_t index_ = 0; // True when an async response from ReadFrames() is pending. This only applies // to "real" async responses. Once all the prepared responses have been // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is // not set to true. - bool read_frames_pending_; + bool read_frames_pending_ = false; std::vector<scoped_refptr<IOBuffer>> result_frame_data_; }; @@ -593,7 +593,7 @@ // otherwise the ReadFrames() callback will never be called. class EchoeyFakeWebSocketStream : public FakeWebSocketStream { public: - EchoeyFakeWebSocketStream() : read_frames_(nullptr), done_(false) {} + EchoeyFakeWebSocketStream() : read_frames_(nullptr) {} int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, CompletionOnceCallback callback) override { @@ -661,7 +661,7 @@ raw_ptr<std::vector<std::unique_ptr<WebSocketFrame>>> read_frames_; std::vector<scoped_refptr<IOBuffer>> buffers_; // True if we should close the connection. - bool done_; + bool done_ = false; }; // A FakeWebSocketStream where writes trigger a connection reset. @@ -673,7 +673,7 @@ // 2. Calling either callback may delete the stream altogether. class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream { public: - ResetOnWriteFakeWebSocketStream() : closed_(false) {} + ResetOnWriteFakeWebSocketStream() = default; int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames, CompletionOnceCallback callback) override { @@ -707,7 +707,7 @@ } CompletionOnceCallback read_callback_; - bool closed_; + bool closed_ = false; // An IO error can result in the socket being deleted, so we use weak pointers // to ensure correct behaviour in that case. base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_{this};
diff --git a/net/websockets/websocket_deflate_stream.cc b/net/websockets/websocket_deflate_stream.cc index 229cdd0..709d9a14 100644 --- a/net/websockets/websocket_deflate_stream.cc +++ b/net/websockets/websocket_deflate_stream.cc
@@ -42,10 +42,6 @@ : stream_(std::move(stream)), deflater_(params.client_context_take_over_mode()), inflater_(kChunkSize, kChunkSize), - reading_state_(NOT_READING), - writing_state_(NOT_WRITING), - current_reading_opcode_(WebSocketFrameHeader::kOpCodeText), - current_writing_opcode_(WebSocketFrameHeader::kOpCodeText), predictor_(std::move(predictor)) { DCHECK(stream_); DCHECK(params.IsValidAsResponse());
diff --git a/net/websockets/websocket_deflate_stream.h b/net/websockets/websocket_deflate_stream.h index fecd09569..ad5f0872 100644 --- a/net/websockets/websocket_deflate_stream.h +++ b/net/websockets/websocket_deflate_stream.h
@@ -98,10 +98,12 @@ const std::unique_ptr<WebSocketStream> stream_; WebSocketDeflater deflater_; WebSocketInflater inflater_; - ReadingState reading_state_; - WritingState writing_state_; - WebSocketFrameHeader::OpCode current_reading_opcode_; - WebSocketFrameHeader::OpCode current_writing_opcode_; + ReadingState reading_state_ = NOT_READING; + WritingState writing_state_ = NOT_WRITING; + WebSocketFrameHeader::OpCode current_reading_opcode_ = + WebSocketFrameHeader::kOpCodeText; + WebSocketFrameHeader::OpCode current_writing_opcode_ = + WebSocketFrameHeader::kOpCodeText; std::unique_ptr<WebSocketDeflatePredictor> predictor_; // User callback saved for asynchronous reads.
diff --git a/net/websockets/websocket_deflate_stream_test.cc b/net/websockets/websocket_deflate_stream_test.cc index 2e828cd..45736233 100644 --- a/net/websockets/websocket_deflate_stream_test.cc +++ b/net/websockets/websocket_deflate_stream_test.cc
@@ -94,7 +94,7 @@ // - RecordWrittenDataFrame is called before writing the frame. class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor { public: - WebSocketDeflatePredictorMock() : result_(DEFLATE) {} + WebSocketDeflatePredictorMock() = default; WebSocketDeflatePredictorMock(const WebSocketDeflatePredictorMock&) = delete; WebSocketDeflatePredictorMock& operator=( @@ -185,7 +185,7 @@ } private: - Result result_; + Result result_ = DEFLATE; // Data frames which will be recorded by |RecordInputFrames|. // Pushed by |AddFrameToBeInput| and popped and verified by // |RecordInputFrames|.
diff --git a/net/websockets/websocket_deflater.cc b/net/websockets/websocket_deflater.cc index 8f93a014..983398dd6 100644 --- a/net/websockets/websocket_deflater.cc +++ b/net/websockets/websocket_deflater.cc
@@ -15,8 +15,7 @@ namespace net { -WebSocketDeflater::WebSocketDeflater(ContextTakeOverMode mode) - : mode_(mode), are_bytes_added_(false) {} +WebSocketDeflater::WebSocketDeflater(ContextTakeOverMode mode) : mode_(mode) {} WebSocketDeflater::~WebSocketDeflater() { if (stream_) {
diff --git a/net/websockets/websocket_deflater.h b/net/websockets/websocket_deflater.h index 1b899fe..ab99aef 100644 --- a/net/websockets/websocket_deflater.h +++ b/net/websockets/websocket_deflater.h
@@ -71,7 +71,7 @@ base::circular_deque<char> buffer_; std::vector<char> fixed_buffer_; // true if bytes were added after last Finish(). - bool are_bytes_added_; + bool are_bytes_added_ = false; }; } // namespace net
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc index 2871ba0..2eb011c 100644 --- a/net/websockets/websocket_end_to_end_test.cc +++ b/net/websockets/websocket_end_to_end_test.cc
@@ -159,7 +159,7 @@ void QuitNestedEventLoop(); // failed_ is true if the handshake failed (ie. OnFailChannel was called). - bool failed_; + bool failed_ = false; std::unique_ptr<WebSocketHandshakeResponseInfo> response_; std::string selected_subprotocol_; std::string extensions_; @@ -167,8 +167,7 @@ base::RunLoop run_loop_; }; -ConnectTestingEventInterface::ConnectTestingEventInterface() : failed_(false) { -} +ConnectTestingEventInterface::ConnectTestingEventInterface() = default; void ConnectTestingEventInterface::WaitForResponse() { run_loop_.Run();
diff --git a/net/websockets/websocket_frame.cc b/net/websockets/websocket_frame.cc index 6995fae05..1f931e6c 100644 --- a/net/websockets/websocket_frame.cc +++ b/net/websockets/websocket_frame.cc
@@ -79,7 +79,7 @@ WebSocketFrame::~WebSocketFrame() = default; -WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) {} +WebSocketFrameChunk::WebSocketFrameChunk() = default; WebSocketFrameChunk::~WebSocketFrameChunk() = default;
diff --git a/net/websockets/websocket_frame.h b/net/websockets/websocket_frame.h index e158b94..a6ca5ab4 100644 --- a/net/websockets/websocket_frame.h +++ b/net/websockets/websocket_frame.h
@@ -142,7 +142,7 @@ std::unique_ptr<WebSocketFrameHeader> header; // Indicates this part is the last chunk of a frame. - bool final_chunk; + bool final_chunk = false; // |payload| is always unmasked even if the frame is masked. |payload| might // be empty in the first chunk.
diff --git a/net/websockets/websocket_frame_parser.cc b/net/websockets/websocket_frame_parser.cc index fe5f619..52c89b95 100644 --- a/net/websockets/websocket_frame_parser.cc +++ b/net/websockets/websocket_frame_parser.cc
@@ -36,8 +36,7 @@ namespace net { -WebSocketFrameParser::WebSocketFrameParser() - : frame_offset_(0), websocket_error_(kWebSocketNormalClosure) {} +WebSocketFrameParser::WebSocketFrameParser() = default; WebSocketFrameParser::~WebSocketFrameParser() = default;
diff --git a/net/websockets/websocket_frame_parser.h b/net/websockets/websocket_frame_parser.h index d1a60968..bcffd1b9 100644 --- a/net/websockets/websocket_frame_parser.h +++ b/net/websockets/websocket_frame_parser.h
@@ -81,9 +81,9 @@ std::unique_ptr<WebSocketFrameHeader> current_frame_header_; // Amount of payload data read so far for the current frame. - uint64_t frame_offset_; + uint64_t frame_offset_ = 0; - WebSocketError websocket_error_; + WebSocketError websocket_error_ = kWebSocketNormalClosure; }; } // namespace net
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc index c0d9c83..0f3e465 100644 --- a/net/websockets/websocket_http2_handshake_stream.cc +++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -46,17 +46,13 @@ std::vector<std::string> requested_extensions, WebSocketStreamRequestAPI* request, std::set<std::string> dns_aliases) - : result_(HandshakeResult::HTTP2_INCOMPLETE), - session_(session), + : session_(session), connect_delegate_(connect_delegate), http_response_info_(nullptr), requested_sub_protocols_(requested_sub_protocols), requested_extensions_(requested_extensions), stream_request_(request), request_info_(nullptr), - stream_closed_(false), - stream_error_(OK), - response_headers_complete_(false), dns_aliases_(std::move(dns_aliases)) { DCHECK(connect_delegate); DCHECK(request);
diff --git a/net/websockets/websocket_http2_handshake_stream.h b/net/websockets/websocket_http2_handshake_stream.h index d0a425a..d9ed31cf 100644 --- a/net/websockets/websocket_http2_handshake_stream.h +++ b/net/websockets/websocket_http2_handshake_stream.h
@@ -127,7 +127,7 @@ int net_error, absl::optional<int> response_code); - HandshakeResult result_; + HandshakeResult result_ = HandshakeResult::HTTP2_INCOMPLETE; // The connection to open the Websocket stream on. base::WeakPtr<SpdySession> session_; @@ -165,14 +165,14 @@ std::unique_ptr<WebSocketSpdyStreamAdapter> stream_adapter_; // True if |stream_| has been created then closed. - bool stream_closed_; + bool stream_closed_ = false; // The error code corresponding to the reason for closing the stream. // Only meaningful if |stream_closed_| is true. - int stream_error_; + int stream_error_ = OK; // True if complete response headers have been received. - bool response_headers_complete_; + bool response_headers_complete_ = false; // Save callback provided in asynchronous HttpStream methods. CompletionOnceCallback callback_;
diff --git a/net/websockets/websocket_inflater.cc b/net/websockets/websocket_inflater.cc index c150b5f..9244754 100644 --- a/net/websockets/websocket_inflater.cc +++ b/net/websockets/websocket_inflater.cc
@@ -166,9 +166,8 @@ WebSocketInflater::OutputBuffer::OutputBuffer(size_t capacity) : capacity_(capacity), - buffer_(capacity_ + 1), // 1 for sentinel - head_(0), - tail_(0) {} + buffer_(capacity_ + 1) // 1 for sentinel +{} WebSocketInflater::OutputBuffer::~OutputBuffer() = default; @@ -218,7 +217,7 @@ } WebSocketInflater::InputQueue::InputQueue(size_t capacity) - : capacity_(capacity), head_of_first_buffer_(0), tail_of_last_buffer_(0) {} + : capacity_(capacity) {} WebSocketInflater::InputQueue::~InputQueue() = default;
diff --git a/net/websockets/websocket_inflater.h b/net/websockets/websocket_inflater.h index 7737440..540aeac 100644 --- a/net/websockets/websocket_inflater.h +++ b/net/websockets/websocket_inflater.h
@@ -89,8 +89,8 @@ const size_t capacity_; std::vector<char> buffer_; - size_t head_; - size_t tail_; + size_t head_ = 0; + size_t tail_ = 0; }; class InputQueue { @@ -114,8 +114,8 @@ size_t PushToLastBuffer(const char* data, size_t size); const size_t capacity_; - size_t head_of_first_buffer_; - size_t tail_of_last_buffer_; + size_t head_of_first_buffer_ = 0; + size_t tail_of_last_buffer_ = 0; base::circular_deque<scoped_refptr<IOBufferWithSize>> buffers_; };
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc index 26d2ede4..ee54346 100644 --- a/net/websockets/websocket_stream_create_test_base.cc +++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -93,7 +93,7 @@ }; WebSocketStreamCreateTestBase::WebSocketStreamCreateTestBase() - : has_failed_(false), ssl_fatal_(false), url_request_(nullptr) {} + : url_request_(nullptr) {} WebSocketStreamCreateTestBase::~WebSocketStreamCreateTestBase() = default;
diff --git a/net/websockets/websocket_stream_create_test_base.h b/net/websockets/websocket_stream_create_test_base.h index 380cad7..a57c6f26 100644 --- a/net/websockets/websocket_stream_create_test_base.h +++ b/net/websockets/websocket_stream_create_test_base.h
@@ -83,13 +83,13 @@ // Only set if the connection failed. std::string failure_message_; int failure_response_code_ = -1; - bool has_failed_; + bool has_failed_ = false; std::unique_ptr<WebSocketHandshakeRequestInfo> request_info_; std::unique_ptr<WebSocketHandshakeResponseInfo> response_info_; std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks> ssl_error_callbacks_; SSLInfo ssl_info_; - bool ssl_fatal_; + bool ssl_fatal_ = false; raw_ptr<URLRequest> url_request_; AuthChallengeInfo auth_challenge_info_; base::OnceCallback<void(const AuthCredentials*)> on_auth_required_callback_;
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc index be0a840..a7b9fe87 100644 --- a/net/websockets/websocket_stream_test.cc +++ b/net/websockets/websocket_stream_test.cc
@@ -101,11 +101,7 @@ class WebSocketStreamCreateTest : public TestWithParam<HandshakeStreamType>, public WebSocketStreamCreateTestBase { protected: - WebSocketStreamCreateTest() - : stream_type_(GetParam()), - http2_response_status_("200"), - reset_websocket_http2_stream_(false), - sequence_number_(0) { + WebSocketStreamCreateTest() : stream_type_(GetParam()) { // Make sure these tests all pass with connection partitioning enabled. The // disabled case is less interesting, and is tested more directly at lower // layers. @@ -398,12 +394,12 @@ std::unique_ptr<base::OneShotTimer> timer_; std::string additional_data_; - const char* http2_response_status_; - bool reset_websocket_http2_stream_; + const char* http2_response_status_ = "200"; + bool reset_websocket_http2_stream_ = false; SpdyTestUtil spdy_util_; NetLogWithSource log_; - int sequence_number_; + int sequence_number_ = 0; // Store mock HTTP/2 data. std::vector<spdy::SpdySerializedFrame> frames_;
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc index 6858676..90185ae 100644 --- a/pdf/pdf_view_plugin_base_unittest.cc +++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -15,7 +15,6 @@ #include "base/time/time.h" #include "base/values.h" #include "pdf/accessibility_structs.h" -#include "pdf/content_restriction.h" #include "pdf/document_attachment_info.h" #include "pdf/document_layout.h" #include "pdf/document_metadata.h" @@ -39,14 +38,9 @@ namespace { -using blink::WebPrintParams; using ::testing::ByMove; using ::testing::ElementsAre; -using ::testing::Field; -using ::testing::InSequence; using ::testing::IsEmpty; -using ::testing::IsFalse; -using ::testing::IsTrue; using ::testing::NiceMock; using ::testing::Return; using ::testing::SaveArg; @@ -571,159 +565,4 @@ EXPECT_EQ(gfx::Point(-300, -56), viewport_info.scroll); } -TEST_F(PdfViewPluginBaseWithEngineTest, NormalPrinting) { - WebPrintParams params; - const std::vector<int> kPageNumbers = {0}; - - auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine()); - engine->SetPermissions({DocumentPermission::kPrintHighQuality, - DocumentPermission::kPrintLowQuality}); - - InSequence sequence; - EXPECT_CALL(*engine, - PrintPages(kPageNumbers, - Field(&WebPrintParams::rasterize_pdf, IsFalse()))) - .Times(1); - EXPECT_CALL( - *engine, - PrintPages(kPageNumbers, Field(&WebPrintParams::rasterize_pdf, IsTrue()))) - .Times(1); - - ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), - fake_plugin_.PrintBegin(params)); - fake_plugin_.PrintPages(kPageNumbers); - fake_plugin_.PrintEnd(); - - params.rasterize_pdf = true; - ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), - fake_plugin_.PrintBegin(params)); - fake_plugin_.PrintPages(kPageNumbers); - fake_plugin_.PrintEnd(); -} - -// Regression test for crbug.com/1307219. -TEST_F(PdfViewPluginBaseWithEngineTest, LowQualityPrinting) { - WebPrintParams params; - const std::vector<int> kPageNumbers = {0}; - - auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine()); - engine->SetPermissions({DocumentPermission::kPrintLowQuality}); - - EXPECT_CALL( - *engine, - PrintPages(kPageNumbers, Field(&WebPrintParams::rasterize_pdf, IsTrue()))) - .Times(2); - - ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), - fake_plugin_.PrintBegin(params)); - fake_plugin_.PrintPages(kPageNumbers); - fake_plugin_.PrintEnd(); - - params.rasterize_pdf = true; - ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), - fake_plugin_.PrintBegin(params)); - fake_plugin_.PrintPages(kPageNumbers); - fake_plugin_.PrintEnd(); -} - -TEST_F(PdfViewPluginBaseWithEngineTest, NoPrinting) { - WebPrintParams params; - - auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine()); - engine->SetPermissions({}); - - EXPECT_EQ(0, fake_plugin_.PrintBegin(params)); - - params.rasterize_pdf = true; - EXPECT_EQ(0, fake_plugin_.PrintBegin(params)); -} - -TEST_F(PdfViewPluginBaseWithEngineTest, GetContentRestrictions) { - auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine()); - static constexpr int kContentRestrictionCutPaste = - kContentRestrictionCut | kContentRestrictionPaste; - - // Test engine without any permissions. - engine->SetPermissions({}); - - int content_restrictions = fake_plugin_.GetContentRestrictions(); - EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionCopy | - kContentRestrictionPrint, - content_restrictions); - - // Test engine with only copy permission. - engine->SetPermissions({DocumentPermission::kCopy}); - - content_restrictions = fake_plugin_.GetContentRestrictions(); - EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionPrint, - content_restrictions); - - // Test engine with only print low quality permission. - engine->SetPermissions({DocumentPermission::kPrintLowQuality}); - - content_restrictions = fake_plugin_.GetContentRestrictions(); - EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionCopy, - content_restrictions); - - // Test engine with both copy and print low quality permissions. - engine->SetPermissions( - {DocumentPermission::kCopy, DocumentPermission::kPrintLowQuality}); - - content_restrictions = fake_plugin_.GetContentRestrictions(); - EXPECT_EQ(kContentRestrictionCutPaste, content_restrictions); - - // Test engine with print high and low quality permissions. - engine->SetPermissions({DocumentPermission::kPrintHighQuality, - DocumentPermission::kPrintLowQuality}); - - content_restrictions = fake_plugin_.GetContentRestrictions(); - EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionCopy, - content_restrictions); - - // Test engine with copy, print high and low quality permissions. - engine->SetPermissions({DocumentPermission::kCopy, - DocumentPermission::kPrintHighQuality, - DocumentPermission::kPrintLowQuality}); - - content_restrictions = fake_plugin_.GetContentRestrictions(); - EXPECT_EQ(kContentRestrictionCutPaste, content_restrictions); -} - -TEST_F(PdfViewPluginBaseWithEngineTest, GetAccessibilityDocInfo) { - auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine()); - - // Test engine without any permissions. - engine->SetPermissions({}); - - AccessibilityDocInfo doc_info = fake_plugin_.GetAccessibilityDocInfo(); - EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); - EXPECT_FALSE(doc_info.text_accessible); - EXPECT_FALSE(doc_info.text_copyable); - - // Test engine with only copy permission. - engine->SetPermissions({DocumentPermission::kCopy}); - - doc_info = fake_plugin_.GetAccessibilityDocInfo(); - EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); - EXPECT_FALSE(doc_info.text_accessible); - EXPECT_TRUE(doc_info.text_copyable); - - // Test engine with only copy accessible permission. - engine->SetPermissions({DocumentPermission::kCopyAccessible}); - - doc_info = fake_plugin_.GetAccessibilityDocInfo(); - EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); - EXPECT_TRUE(doc_info.text_accessible); - EXPECT_FALSE(doc_info.text_copyable); - - // Test engine with both copy and copy accessible permission. - engine->SetPermissions( - {DocumentPermission::kCopy, DocumentPermission::kCopyAccessible}); - - doc_info = fake_plugin_.GetAccessibilityDocInfo(); - EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); - EXPECT_TRUE(doc_info.text_accessible); - EXPECT_TRUE(doc_info.text_copyable); -} - } // namespace chrome_pdf
diff --git a/pdf/pdf_view_web_plugin_unittest.cc b/pdf/pdf_view_web_plugin_unittest.cc index cbd366b7..dbe3a9a 100644 --- a/pdf/pdf_view_web_plugin_unittest.cc +++ b/pdf/pdf_view_web_plugin_unittest.cc
@@ -4,6 +4,8 @@ #include "pdf/pdf_view_web_plugin.h" +#include <stdint.h> + #include <functional> #include <memory> #include <string> @@ -26,6 +28,7 @@ #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "net/cookies/site_for_cookies.h" +#include "pdf/accessibility_structs.h" #include "pdf/buildflags.h" #include "pdf/content_restriction.h" #include "pdf/mojom/pdf.mojom.h" @@ -34,6 +37,7 @@ #include "pdf/pdf_view_plugin_base.h" #include "pdf/test/test_helpers.h" #include "pdf/test/test_pdfium_engine.h" +#include "printing/metafile_skia.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -55,6 +59,7 @@ #include "third_party/blink/public/web/web_associated_url_loader_client.h" #include "third_party/blink/public/web/web_plugin_container.h" #include "third_party/blink/public/web/web_plugin_params.h" +#include "third_party/blink/public/web/web_print_params.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" @@ -80,11 +85,14 @@ namespace { using ::testing::AnyNumber; +using ::testing::ElementsAre; using ::testing::ElementsAreArray; using ::testing::Eq; using ::testing::InSequence; using ::testing::Invoke; using ::testing::IsEmpty; +using ::testing::IsFalse; +using ::testing::IsTrue; using ::testing::MockFunction; using ::testing::NiceMock; using ::testing::Pointwise; @@ -816,6 +824,118 @@ plugin_->EnableAccessibility(); } +TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithNoPermissions) { + EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut | + kContentRestrictionPaste | kContentRestrictionPrint, + plugin_->GetContentRestrictions()); +} + +TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy)) + .WillRepeatedly(Return(true)); + + EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste | + kContentRestrictionPrint, + plugin_->GetContentRestrictions()); +} + +TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintLowQualityAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + + EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut | + kContentRestrictionPaste, + plugin_->GetContentRestrictions()); +} + +TEST_F(PdfViewWebPluginTest, + GetContentRestrictionsWithCopyAndPrintLowQualityAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + + EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste, + plugin_->GetContentRestrictions()); +} + +TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, + HasPermission(DocumentPermission::kPrintHighQuality)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + + EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut | + kContentRestrictionPaste, + plugin_->GetContentRestrictions()); +} + +TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAndPrintAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, + HasPermission(DocumentPermission::kPrintHighQuality)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + + EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste, + plugin_->GetContentRestrictions()); +} + +TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithNoPermissions) { + AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo(); + + EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); + EXPECT_FALSE(doc_info.text_accessible); + EXPECT_FALSE(doc_info.text_copyable); +} + +TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy)) + .WillRepeatedly(Return(true)); + + AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo(); + + EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); + EXPECT_FALSE(doc_info.text_accessible); + EXPECT_TRUE(doc_info.text_copyable); +} + +TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAccessibleAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible)) + .WillRepeatedly(Return(true)); + + AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo(); + + EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); + EXPECT_TRUE(doc_info.text_accessible); + EXPECT_FALSE(doc_info.text_copyable); +} + +TEST_F(PdfViewWebPluginTest, + GetAccessibilityDocInfoWithCopyAndCopyAccessibleAllowed) { + EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible)) + .WillRepeatedly(Return(true)); + + AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo(); + + EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count); + EXPECT_TRUE(doc_info.text_accessible); + EXPECT_TRUE(doc_info.text_copyable); +} + TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRect) { EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f)); TestUpdateGeometrySetsPluginRect( @@ -1729,6 +1849,107 @@ SubmitFailingForm("https://wwww.example.com"); } +class PdfViewWebPluginPrintTest : public PdfViewWebPluginTest { + protected: + void SetUp() override { + PdfViewWebPluginTest::SetUp(); + + // Size must be at least 1 for conversion to `SkMemoryStream`. + ON_CALL(*engine_ptr_, PrintPages) + .WillByDefault(Return(std::vector<uint8_t>(1))); + + canvas_.sk_canvas()->SetPrintingMetafile(&metafile_); + } + + printing::MetafileSkia metafile_; +}; + +TEST_F(PdfViewWebPluginPrintTest, HighQuality) { + EXPECT_CALL(*engine_ptr_, + HasPermission(DocumentPermission::kPrintHighQuality)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), + plugin_->PrintBegin(blink::WebPrintParams())); + + EXPECT_CALL( + *engine_ptr_, + PrintPages(ElementsAre(0), + Field(&blink::WebPrintParams::rasterize_pdf, IsFalse()))); + plugin_->PrintPage(0, canvas_.sk_canvas()); + plugin_->PrintEnd(); +} + +TEST_F(PdfViewWebPluginPrintTest, HighQualityRasterized) { + EXPECT_CALL(*engine_ptr_, + HasPermission(DocumentPermission::kPrintHighQuality)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + + blink::WebPrintParams params; + params.rasterize_pdf = true; + ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), + plugin_->PrintBegin(params)); + + EXPECT_CALL( + *engine_ptr_, + PrintPages(ElementsAre(0), + Field(&blink::WebPrintParams::rasterize_pdf, IsTrue()))); + plugin_->PrintPage(0, canvas_.sk_canvas()); + plugin_->PrintEnd(); +} + +// Regression test for crbug.com/1307219. +TEST_F(PdfViewWebPluginPrintTest, LowQuality) { + EXPECT_CALL(*engine_ptr_, + HasPermission(DocumentPermission::kPrintHighQuality)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), + plugin_->PrintBegin(blink::WebPrintParams())); + + EXPECT_CALL( + *engine_ptr_, + PrintPages(ElementsAre(0), + Field(&blink::WebPrintParams::rasterize_pdf, IsTrue()))); + plugin_->PrintPage(0, canvas_.sk_canvas()); + plugin_->PrintEnd(); +} + +// Regression test for crbug.com/1307219. +TEST_F(PdfViewWebPluginPrintTest, LowQualityRasterized) { + EXPECT_CALL(*engine_ptr_, + HasPermission(DocumentPermission::kPrintHighQuality)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality)) + .WillRepeatedly(Return(true)); + + blink::WebPrintParams params; + params.rasterize_pdf = true; + ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber), + plugin_->PrintBegin(params)); + + EXPECT_CALL( + *engine_ptr_, + PrintPages(ElementsAre(0), + Field(&blink::WebPrintParams::rasterize_pdf, IsTrue()))); + plugin_->PrintPage(0, canvas_.sk_canvas()); + plugin_->PrintEnd(); +} + +TEST_F(PdfViewWebPluginPrintTest, Disabled) { + EXPECT_EQ(0, plugin_->PrintBegin(blink::WebPrintParams())); +} + +TEST_F(PdfViewWebPluginPrintTest, DisabledRasterized) { + blink::WebPrintParams params; + params.rasterize_pdf = true; + EXPECT_EQ(0, plugin_->PrintBegin(params)); +} + class PdfViewWebPluginPrintPreviewTest : public PdfViewWebPluginTest { protected: void SetUpClient() override {
diff --git a/pdf/test/test_pdfium_engine.cc b/pdf/test/test_pdfium_engine.cc index b789fa9e..34fc392 100644 --- a/pdf/test/test_pdfium_engine.cc +++ b/pdf/test/test_pdfium_engine.cc
@@ -11,8 +11,6 @@ #include <vector> #include "base/check_op.h" -#include "base/containers/contains.h" -#include "base/containers/flat_set.h" #include "base/values.h" #include "pdf/document_attachment_info.h" #include "pdf/document_metadata.h" @@ -36,10 +34,6 @@ TestPDFiumEngine::~TestPDFiumEngine() = default; -bool TestPDFiumEngine::HasPermission(DocumentPermission permission) const { - return base::Contains(permissions_, permission); -} - const std::vector<DocumentAttachmentInfo>& TestPDFiumEngine::GetDocumentAttachmentInfoList() const { return doc_attachment_info_list_; @@ -71,12 +65,4 @@ return std::vector<uint8_t>(std::begin(kSaveData), std::end(kSaveData)); } -void TestPDFiumEngine::SetPermissions( - const std::vector<DocumentPermission>& permissions) { - permissions_.clear(); - - for (auto& permission : permissions) - permissions_.insert(permission); -} - } // namespace chrome_pdf
diff --git a/pdf/test/test_pdfium_engine.h b/pdf/test/test_pdfium_engine.h index 705dd36..5aa2569 100644 --- a/pdf/test/test_pdfium_engine.h +++ b/pdf/test/test_pdfium_engine.h
@@ -9,7 +9,6 @@ #include <vector> -#include "base/containers/flat_set.h" #include "base/values.h" #include "pdf/document_attachment_info.h" #include "pdf/document_metadata.h" @@ -60,8 +59,7 @@ MOCK_METHOD(std::vector<uint8_t>, PrintPages, - (const std::vector<int>& page_numbers, - const blink::WebPrintParams& print_params), + (const std::vector<int>&, const blink::WebPrintParams&), (override)); MOCK_METHOD(void, ZoomUpdated, (double), (override)); @@ -71,7 +69,7 @@ (const DocumentLayout::Options&), (override)); - bool HasPermission(DocumentPermission permission) const override; + MOCK_METHOD(bool, HasPermission, (DocumentPermission), (const override)); const std::vector<DocumentAttachmentInfo>& GetDocumentAttachmentInfoList() const override; @@ -95,8 +93,6 @@ MOCK_METHOD(void, SetCaretPosition, (const gfx::Point&), (override)); - void SetPermissions(const std::vector<DocumentPermission>& permissions); - MOCK_METHOD(void, OnDocumentCanceled, (), (override)); protected: @@ -110,8 +106,6 @@ std::vector<DocumentAttachmentInfo> doc_attachment_info_list_; DocumentMetadata metadata_; - - base::flat_set<DocumentPermission> permissions_; }; } // namespace chrome_pdf
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index f711104..3b91be2 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -8274,7 +8274,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -8784,7 +8784,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 0c437d7..2a1f7649 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -46249,7 +46249,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46759,7 +46759,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47273,7 +47273,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47783,7 +47783,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48365,7 +48365,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48875,7 +48875,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49457,7 +49457,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49967,7 +49967,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M102", - "revision": "version:102.0.5005.113" + "revision": "version:102.0.5005.124" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index e736a5c..e4905e4 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -3169,6 +3169,34 @@ "test_id_prefix": "ninja://ash/components:ash_components_unittests/" }, { + "args": [ + "--enable-pixel-output-in-tests", + "--git-revision=${got_revision}" + ], + "experiment_percentage": 100, + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ash_pixeltests", + "test_id_prefix": "ninja://ash:ash_pixeltests/" + }, + { "isolate_profile_data": true, "merge": { "args": [],
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index aee181d..0d293619 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -105575,44 +105575,5 @@ "test_id_prefix": "ninja://:blink_web_tests/" } ] - }, - "win7-blink-rel-dummy": { - "isolated_scripts": [ - { - "args": [ - "--num-retries=3", - "--git-revision=${got_revision}" - ], - "isolate_name": "blink_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}" - ], - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Windows-7-SP1" - } - ], - "hard_timeout": 900, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://:blink_web_tests/" - } - ] } }
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 456fbb2..4879df7 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -10164,35 +10164,6 @@ }, { "args": [ - "--num-retries=3", - "--git-revision=${got_revision}" - ], - "isolate_name": "blink_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}" - ], - "resultdb": { - "enable": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ "--test-type=integration" ], "check_flakiness_for_new_tests": false,
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index c64656f..1af0e5e 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -1604,7 +1604,6 @@ 'mac10.15-blink-rel-dummy', 'mac11.0-blink-rel-dummy', 'mac11.0.arm64-blink-rel-dummy', - 'win7-blink-rel-dummy', 'win10.20h2-blink-rel-dummy', 'win11-blink-rel-dummy', ]
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index d4766bb6..49f33be 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -209,6 +209,10 @@ "label": "//ash:ash_unittests", "type": "windowed_test_launcher", }, + "ash_pixeltests": { + "label": "//ash:ash_pixeltests", + "type": "windowed_test_launcher", + }, "aura_unittests": { "label": "//ui/aura:aura_unittests", "type": "windowed_test_launcher",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 9af486f..24ee6408 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -229,6 +229,7 @@ 'blink_web_tests': { 'remove_from': [ 'Win 7 Tests x64 (1)', # 64-bit win is unsupported by the layout tests. + 'Win7 Tests (1)', 'Win10 Tests x64 (dbg)', ], 'modifications': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 003abd2..dc2e9be 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -320,6 +320,18 @@ }, }, + 'ash_pixel_gtests': { + 'ash_pixeltests': { + 'args': [ + '--enable-pixel-output-in-tests', + ], + 'experiment_percentage': 100, + 'mixins': [ + 'skia_gold_test', + ], + }, + }, + 'aura_gtests': { 'aura_unittests': {}, 'compositor_unittests': {}, @@ -6603,6 +6615,7 @@ 'linux_chromeos_browser_tests_require_lacros', 'linux_flavor_specific_chromium_gtests', 'non_android_chromium_gtests', + 'ash_pixel_gtests', ], 'linux_viz_gtests': [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 2105316..bd0b870 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -515,7 +515,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.113', + 'revision': 'version:102.0.5005.124', } ], }, @@ -659,7 +659,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.113', + 'revision': 'version:102.0.5005.124', } ], }, @@ -803,7 +803,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.113', + 'revision': 'version:102.0.5005.124', } ], },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 1fd98ab3..2ef0ebf2 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3810,19 +3810,6 @@ 'isolated_scripts': 'chromium_webkit_isolated_scripts', }, }, - 'win7-blink-rel-dummy': { - 'swarming': { - 'dimension_sets': [ - { - 'os': 'Windows-7-SP1', - }, - ], - 'hard_timeout': 900, - }, - 'test_suites': { - 'isolated_scripts': 'chromium_webkit_isolated_scripts', - }, - }, }, }, {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 278bb5c..6e5b285 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -7283,7 +7283,7 @@ { "name": "Enabled", "params": { - "segment_ids_allowed_for_reporting": "4,5,6,11,12,16" + "segment_ids_allowed_for_reporting": "4,5,6,10,11,12,16" }, "enable_features": [ "SegmentationStructuredMetrics"
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index a594aeb..d7b25c6 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -2659,6 +2659,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_idbcursor_idbindex_idbobjectstore.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_idbindex_idbobjectstore.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_idbindex_idbobjectstore.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediasourcehandle_mediastream.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediasourcehandle_mediastream.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediastreamtrack_string.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediastreamtrack_string.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_path2d_string.cc",
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h index 716e8cf..70a2a8d 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
@@ -213,11 +213,13 @@ // `callback`. using VideoFrameCopyCompletedCallback = base::OnceCallback<void(scoped_refptr<media::VideoFrame>)>; - virtual void CopyRenderingResultsToVideoFrame( + virtual bool CopyRenderingResultsToVideoFrame( WebGraphicsContext3DVideoFramePool* frame_pool, SourceDrawingBuffer, const gfx::ColorSpace& dst_color_space, - VideoFrameCopyCompletedCallback& callback) {} + VideoFrameCopyCompletedCallback callback) { + return false; + } virtual cc::Layer* CcLayer() const { return nullptr; }
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 1cad129..0e7de0b 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
@@ -730,7 +730,10 @@ if (!listener->NeedsNewFrame()) continue; - auto callback = listener->GetNewFrameCallback(); + // Split the listener's callback so that it can be used with both the one + // copy path and fallback two copy path below. + auto split_callback = + base::SplitOnceCallback(listener->GetNewFrameCallback()); const bool can_discard_alpha = listener->CanDiscardAlpha(); // First attempt to copy directly from the rendering context to a video @@ -738,12 +741,13 @@ // where GetSourceImageForCanvasInternal is zero-copy, this is superfluous). if (context_ && can_discard_alpha && base::FeatureList::IsEnabled(kOneCopyCanvasCapture)) { - context_->CopyRenderingResultsToVideoFrame( - copier_->GetAcceleratedVideoFramePool( - SharedGpuContext::ContextProviderWrapper()), - kBackBuffer, gfx::ColorSpace::CreateREC709(), callback); - if (!callback) + if (context_->CopyRenderingResultsToVideoFrame( + copier_->GetAcceleratedVideoFramePool( + SharedGpuContext::ContextProviderWrapper()), + kBackBuffer, gfx::ColorSpace::CreateREC709(), + std::move(split_callback.first))) { continue; + } } // If that fails, then create a StaticBitmapImage for the contents of @@ -760,7 +764,7 @@ // need a context_provider that has a RasterInterface available. copier_->Convert(source_image, can_discard_alpha, SharedGpuContext::ContextProviderWrapper(), - std::move(callback)); + std::move(split_callback.second)); } }
diff --git a/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js b/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js index f3738dc1..371591d 100644 --- a/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js +++ b/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js
@@ -2244,7 +2244,8 @@ */ onWindowTouchEnd(event) { this._thumbStyleTopAnimator = new TransitionAnimator(); - this._thumbStyleTopAnimator.step = this.onThumbStyleTopAnimationStep; + this._thumbStyleTopAnimator.step = + this.onThumbStyleTopAnimationStep.bind(this); this._thumbStyleTopAnimator.setFrom(this.thumb.offsetTop); this._thumbStyleTopAnimator.setTo((this._height - this._thumbHeight) / 2); this._thumbStyleTopAnimator.timingFunction =
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 3c5d7f4f..fa373a5 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -87,6 +87,7 @@ #include "third_party/blink/renderer/core/html/media/media_error.h" #include "third_party/blink/renderer/core/html/media/media_fragment_uri_parser.h" #include "third_party/blink/renderer/core/html/media/media_source_attachment.h" +#include "third_party/blink/renderer/core/html/media/media_source_handle.h" #include "third_party/blink/renderer/core/html/media/media_source_tracer.h" #include "third_party/blink/renderer/core/html/time_ranges.h" #include "third_party/blink/renderer/core/html/track/audio_track.h" @@ -813,7 +814,8 @@ HTMLElement::InsertedInto(insertion_point); if (insertion_point.isConnected()) { UseCounter::Count(GetDocument(), WebFeature::kHTMLMediaElementInDocument); - if ((!FastGetAttribute(html_names::kSrcAttr).IsEmpty() || src_object_) && + if ((!FastGetAttribute(html_names::kSrcAttr).IsEmpty() || + src_object_stream_descriptor_ || src_object_media_source_handle_) && network_state_ == kNetworkEmpty) { ignore_preload_none_ = false; InvokeLoadAlgorithm(); @@ -898,12 +900,40 @@ setAttribute(html_names::kSrcAttr, url); } -void HTMLMediaElement::SetSrcObject(MediaStreamDescriptor* src_object) { - DVLOG(1) << "setSrcObject(" << *this << ")"; - src_object_ = src_object; +void HTMLMediaElement::SetSrcObjectVariant( + SrcObjectVariant src_object_variant) { + DVLOG(1) << __func__ << "(" << *this << ")"; + src_object_stream_descriptor_ = nullptr; + src_object_media_source_handle_ = nullptr; + if (auto** desc = absl::get_if<MediaStreamDescriptor*>(&src_object_variant)) { + src_object_stream_descriptor_ = *desc; + } else if (auto** handle = + absl::get_if<MediaSourceHandle*>(&src_object_variant)) { + src_object_media_source_handle_ = *handle; + } + + DVLOG(2) << __func__ + << ": stream_descriptor=" << src_object_stream_descriptor_ + << ", media_source_handle=" << src_object_media_source_handle_; + InvokeLoadAlgorithm(); } +HTMLMediaElement::SrcObjectVariant HTMLMediaElement::GetSrcObjectVariant() + const { + DVLOG(1) << __func__ << "(" << *this << ")" + << ": stream_descriptor=" << src_object_stream_descriptor_ + << ", media_source_handle=" << src_object_media_source_handle_; + + // At most one is set. + DCHECK(!(src_object_stream_descriptor_ && src_object_media_source_handle_)); + + if (src_object_media_source_handle_) + return SrcObjectVariant(src_object_media_source_handle_.Get()); + + return SrcObjectVariant(src_object_stream_descriptor_.Get()); +} + HTMLMediaElement::NetworkState HTMLMediaElement::getNetworkState() const { return network_state_; } @@ -1141,7 +1171,7 @@ // 6 - If the media element has an assigned media provider object, then let // mode be object. - if (src_object_) { + if (src_object_stream_descriptor_ || src_object_media_source_handle_) { mode = kObject; } else if (FastHasAttribute(html_names::kSrcAttr)) { // Otherwise, if the media element has no assigned media provider object @@ -1209,12 +1239,40 @@ } void HTMLMediaElement::LoadSourceFromObject() { - DCHECK(src_object_); + DCHECK(src_object_stream_descriptor_ || src_object_media_source_handle_); load_state_ = kLoadingFromSrcObject; + if (src_object_media_source_handle_) { + DCHECK(!src_object_stream_descriptor_); + + // Retrieve the internal blob URL from the handle that was created in the + // context where the referenced MediaSource is owned, for the purposes of + // using existing security and logging logic for loading media from a + // MediaSource with a blob URL. + const String media_source_handle_url_ = + src_object_media_source_handle_->GetInternalBlobURL(); + DCHECK(!media_source_handle_url_.IsEmpty()); + + KURL media_url = GetDocument().CompleteURL(media_source_handle_url_); + if (!IsSafeToLoadURL(media_url, kComplain)) { + MediaLoadingFailed( + WebMediaPlayer::kNetworkStateFormatError, + BuildElementErrorMessage( + "Media load from MediaSourceHandle rejected by safety check")); + return; + } + + // No type is available when loading from a MediaSourceHandle, via + // srcObject, even with an internal MediaSource blob URL. + LoadResource(WebMediaPlayerSource(WebURL(media_url)), String()); + return; + } + // No type is available when the resource comes from the 'srcObject' // attribute. - LoadResource(WebMediaPlayerSource(WebMediaStream(src_object_)), String()); + LoadResource( + WebMediaPlayerSource(WebMediaStream(src_object_stream_descriptor_)), + String()); } void HTMLMediaElement::LoadSourceFromAttribute() { @@ -1280,24 +1338,39 @@ // The resource fetch algorithm SetNetworkState(kNetworkLoading); - // Set current_src_ *before* changing to the cache url, the fact that we are + // Set |current_src_| *before* changing to the cache url, the fact that we are // loading from the app cache is an internal detail not exposed through the - // media element API. - current_src_ = url; + // media element API. If loading from an internal MediaSourceHandle object + // URL, then do not expose that URL to app, but instead hold it for use later + // in StartPlayerLoad and elsewhere (for origin, security etc checks normally + // done on |current_src_|.) + if (src_object_media_source_handle_) { + DCHECK(!url.IsEmpty()); + current_src_.SetSource(url, + SourceMetadata::SourceVisibility::kInvisibleToApp); + } else { + current_src_.SetSource(url, + SourceMetadata::SourceVisibility::kVisibleToApp); + } // Default this to empty, so that we use |current_src_| unless the player // provides one later. current_src_after_redirects_ = KURL(); if (audio_source_node_) - audio_source_node_->OnCurrentSrcChanged(current_src_); + audio_source_node_->OnCurrentSrcChanged(current_src_.GetSourceIfVisible()); // Update remote playback client with the new src and consider it incompatible // until proved otherwise. - RemotePlaybackCompatibilityChanged(current_src_, false); + RemotePlaybackCompatibilityChanged(current_src_.GetSourceIfVisible(), false); - DVLOG(3) << "loadResource(" << *this << ") - current_src_ -> " - << UrlForLoggingMedia(current_src_); + DVLOG(3) << "loadResource(" << *this << ") - current src if visible=" + << UrlForLoggingMedia(current_src_.GetSourceIfVisible()) + << ", current src =" << UrlForLoggingMedia(current_src_.GetSource()) + << ", src_object_media_source_handle_=" + << src_object_media_source_handle_ + << ", src_object_stream_descriptor_=" + << src_object_stream_descriptor_; StartProgressEventTimer(); @@ -1309,8 +1382,13 @@ bool attempt_load = true; - media_source_attachment_ = - MediaSourceAttachment::LookupMediaSource(url.GetString()); + if (src_object_media_source_handle_) { + media_source_attachment_ = src_object_media_source_handle_->GetAttachment(); + DCHECK(media_source_attachment_); + } else { + media_source_attachment_ = + MediaSourceAttachment::LookupMediaSource(url.GetString()); + } if (media_source_attachment_) { bool start_result = false; media_source_tracer_ = @@ -1322,9 +1400,12 @@ // attachment. This can help reduce memory bloat later if the app does not // revoke the object URL explicitly and the object URL was the only // remaining strong reference to an attached HTMLMediaElement+MediaSource - // cycle of objects that could otherwise be garbage-collectable. + // cycle of objects that could otherwise be garbage-collectable. Don't + // auto-revoke the internal, unregistered, object URL used to attach via + // srcObject with a MediaSourceHandle, though. if (base::FeatureList::IsEnabled( - media::kRevokeMediaSourceObjectURLOnAttach)) { + media::kRevokeMediaSourceObjectURLOnAttach) && + !src_object_media_source_handle_) { URLFileAPI::revokeObjectURL(GetExecutionContext(), url.GetString()); } } else { @@ -1370,8 +1451,15 @@ DCHECK(!web_media_player_); WebMediaPlayerSource source; - if (src_object_) { - source = WebMediaPlayerSource(WebMediaStream(src_object_)); + if (src_object_stream_descriptor_) { + source = + WebMediaPlayerSource(WebMediaStream(src_object_stream_descriptor_)); + } else if (src_object_media_source_handle_) { + DCHECK(current_src_.GetSourceIfVisible().IsEmpty()); + const KURL& internal_url = current_src_.GetSource(); + DCHECK(!internal_url.IsEmpty()); + + source = WebMediaPlayerSource(WebURL(internal_url)); } else { // Filter out user:pass as those two URL components aren't // considered for media resource fetches (including for the CORS @@ -1386,7 +1474,7 @@ // 'authentication flag' to control how user:pass embedded in a // media resource URL should be treated, then update the handling // here to match. - KURL request_url = current_src_; + KURL request_url = current_src_.GetSourceIfVisible(); if (!request_url.User().IsEmpty()) request_url.SetUser(String()); if (!request_url.Pass().IsEmpty()) @@ -1545,9 +1633,9 @@ WebMediaPlayer::LoadType HTMLMediaElement::GetLoadType() const { if (media_source_attachment_) - return WebMediaPlayer::kLoadTypeMediaSource; + return WebMediaPlayer::kLoadTypeMediaSource; // Either via src or srcObject - if (src_object_) + if (src_object_stream_descriptor_) return WebMediaPlayer::kLoadTypeMediaStream; return WebMediaPlayer::kLoadTypeURL; @@ -1845,7 +1933,9 @@ MakeGarbageCollected<MediaError>(MediaError::kMediaErrDecode, message)); } else if ((error == WebMediaPlayer::kNetworkStateFormatError || error == WebMediaPlayer::kNetworkStateNetworkError) && - load_state_ == kLoadingFromSrcAttr) { + (load_state_ == kLoadingFromSrcAttr || + (load_state_ == kLoadingFromSrcObject && + src_object_media_source_handle_))) { if (message.IsEmpty()) { // Generate a more meaningful error message to differentiate the two types // of MEDIA_SRC_ERR_NOT_SUPPORTED. @@ -1959,6 +2049,7 @@ // skips notification of insecure content. Ensure we always notify the // MixedContentChecker of what happened, even if the load was skipped. if (LocalFrame* frame = GetDocument().GetFrame()) { + const KURL& current_src_for_check = current_src_.GetSource(); // We don't care about the return value here. The MixedContentChecker will // internally notify for insecure content if it needs to regardless of // what the return value ends up being for this call. @@ -1966,13 +2057,13 @@ frame, HasVideo() ? mojom::blink::RequestContextType::VIDEO : mojom::blink::RequestContextType::AUDIO, - current_src_, + current_src_for_check, // Strictly speaking, this check is an approximation; a request could // have have redirected back to its original URL, for example. // However, the redirect status is only used to prevent leaking // information cross-origin via CSP reports, so comparing URLs is // sufficient for that purpose. - current_src_after_redirects_ == current_src_ + current_src_after_redirects_ == current_src_for_check ? ResourceRequest::RedirectStatus::kNoRedirect : ResourceRequest::RedirectStatus::kFollowedRedirect, current_src_after_redirects_, /* devtools_id= */ absl::nullopt, @@ -2022,7 +2113,7 @@ if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) { CreatePlaceholderTracksIfNecessary(); - MediaFragmentURIParser fragment_parser(current_src_); + MediaFragmentURIParser fragment_parser(current_src_.GetSource()); fragment_end_time_ = fragment_parser.EndTime(); // Set the current playback position and the official playback position to @@ -4304,7 +4395,8 @@ visitor->Trace(play_promise_resolve_list_); visitor->Trace(play_promise_reject_list_); visitor->Trace(audio_source_provider_); - visitor->Trace(src_object_); + visitor->Trace(src_object_stream_descriptor_); + visitor->Trace(src_object_media_source_handle_); visitor->Trace(autoplay_policy_); visitor->Trace(media_controls_); visitor->Trace(controls_list_);
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index 6becfb8..d78ca7c 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -33,6 +33,7 @@ #include "base/timer/elapsed_timer.h" #include "media/mojo/mojom/media_player.mojom-blink.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/common/media/display_type.h" #include "third_party/blink/public/platform/web_media_player_client.h" #include "third_party/blink/public/platform/webaudiosourceprovider_impl.h" @@ -85,6 +86,7 @@ class HTMLTrackElement; class MediaError; class MediaSourceAttachment; +class MediaSourceHandle; class MediaSourceTracer; class MediaStreamDescriptor; class ScriptPromiseResolver; @@ -177,7 +179,7 @@ // network state void SetSrc(const AtomicString&); - const KURL& currentSrc() const { return current_src_; } + const KURL& currentSrc() const { return current_src_.GetSourceIfVisible(); } // Return the URL to be used for downloading the media. const KURL& downloadURL() const { @@ -189,8 +191,10 @@ return current_src_after_redirects_; } - void SetSrcObject(MediaStreamDescriptor*); - MediaStreamDescriptor* GetSrcObject() const { return src_object_.Get(); } + using SrcObjectVariant = + absl::variant<MediaStreamDescriptor*, MediaSourceHandle*>; + void SetSrcObjectVariant(SrcObjectVariant src_object_variant); + SrcObjectVariant GetSrcObjectVariant() const; enum NetworkState { kNetworkEmpty, @@ -452,6 +456,30 @@ friend class PictureInPictureControllerTest; friend class VideoWakeLockTest; + class SourceMetadata { + DISALLOW_NEW(); + + public: + enum class SourceVisibility { kVisibleToApp, kInvisibleToApp }; + SourceMetadata() = default; + void SetSource(const KURL& src, SourceVisibility visibility) { + src_ = src; + invisible_to_app_ = visibility == SourceVisibility::kInvisibleToApp; + } + const KURL& GetSourceIfVisible() const { + return invisible_to_app_ ? NullURL() : src_; + } + const KURL& GetSource() const { return src_; } + + private: + KURL src_; + + // If true, then |current_src| is used only for internal loading and safety + // checks, and for logging that is not visible to apps, either. For example, + // when loading from a MediaSourceHandle as srcObject, this would be true. + bool invisible_to_app_ = false; + }; + bool HasPendingActivityInternal() const; void ResetMediaPlayerAndMediaSource(); @@ -700,9 +728,12 @@ NetworkState network_state_; ReadyState ready_state_; ReadyState ready_state_maximum_; - KURL current_src_; + + SourceMetadata current_src_; KURL current_src_after_redirects_; - Member<MediaStreamDescriptor> src_object_; + + Member<MediaStreamDescriptor> src_object_stream_descriptor_; + Member<MediaSourceHandle> src_object_media_source_handle_; // To prevent potential regression when extended by the MSE API, do not set // |error_| outside of constructor and SetError().
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc index 57c395de..782bc21 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -296,7 +296,8 @@ HTMLMediaElement* Media() const { return media_.Get(); } void SetCurrentSrc(const AtomicString& src) { KURL url(src); - Media()->current_src_ = url; + Media()->current_src_.SetSource( + url, HTMLMediaElement::SourceMetadata::SourceVisibility::kVisibleToApp); } MockWebMediaPlayer* MockMediaPlayer() { return media_player_; }
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc index c08f010a..958be189 100644 --- a/third_party/blink/renderer/core/layout/hit_test_result.cc +++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/core/layout/hit_test_result.h" #include "cc/base/region.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" #include "third_party/blink/renderer/core/dom/pseudo_element.h" @@ -39,6 +40,7 @@ #include "third_party/blink/renderer/core/html/html_image_element.h" #include "third_party/blink/renderer/core/html/html_map_element.h" #include "third_party/blink/renderer/core/html/media/html_media_element.h" +#include "third_party/blink/renderer/core/html/media/media_source_handle.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/input_type_names.h" @@ -440,8 +442,26 @@ } MediaStreamDescriptor* HitTestResult::GetMediaStreamDescriptor() const { - if (HTMLMediaElement* media_elt = MediaElement()) - return media_elt->GetSrcObject(); + if (HTMLMediaElement* media_elt = MediaElement()) { + auto variant = media_elt->GetSrcObjectVariant(); + if (absl::holds_alternative<MediaStreamDescriptor*>(variant)) { + // It might be nullptr-valued variant, too, here, but we return nullptr + // for that, regardless. + return absl::get<MediaStreamDescriptor*>(variant); + } + } + return nullptr; +} + +MediaSourceHandle* HitTestResult::GetMediaSourceHandle() const { + if (HTMLMediaElement* media_elt = MediaElement()) { + auto variant = media_elt->GetSrcObjectVariant(); + if (absl::holds_alternative<MediaSourceHandle*>(variant)) { + // It might be a nullptr-valued MediaStreamDescriptor* variant, here, but + // we return nullptr for that, regardless. + return absl::get<MediaSourceHandle*>(variant); + } + } return nullptr; }
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.h b/third_party/blink/renderer/core/layout/hit_test_result.h index 5105121..37e272f 100644 --- a/third_party/blink/renderer/core/layout/hit_test_result.h +++ b/third_party/blink/renderer/core/layout/hit_test_result.h
@@ -51,6 +51,7 @@ class HTMLMediaElement; class Image; class KURL; +class MediaSourceHandle; class MediaStreamDescriptor; class NGPhysicalBoxFragment; class Node; @@ -161,6 +162,7 @@ KURL AbsoluteImageURL() const; KURL AbsoluteMediaURL() const; MediaStreamDescriptor* GetMediaStreamDescriptor() const; + MediaSourceHandle* GetMediaSourceHandle() const; KURL AbsoluteLinkURL() const; String TextContent() const; bool IsLiveLink() const;
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 612d9ede..e8022633 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -484,12 +484,13 @@ data.alt_text = html_element->AltText().Utf8(); } if (!result.AbsoluteMediaURL().IsEmpty() || - result.GetMediaStreamDescriptor()) { + result.GetMediaStreamDescriptor() || result.GetMediaSourceHandle()) { if (!result.AbsoluteMediaURL().IsEmpty()) data.src_url = GURL(result.AbsoluteMediaURL()); // We know that if absoluteMediaURL() is not empty or element has a media - // stream descriptor, then this is a media element. + // stream descriptor or element has a media source handle, then this is a + // media element. auto* media_element = To<HTMLMediaElement>(result.InnerNode()); if (IsA<HTMLVideoElement>(*media_element)) { // A video element should be presented as an audio element when it has an
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 b8d1e74..2929d090 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
@@ -413,7 +413,7 @@ MediaStreamComponentVector dummy_components; auto* media_stream_descriptor = MakeGarbageCollected<MediaStreamDescriptor>( dummy_components, dummy_components); - video->SetSrcObject(media_stream_descriptor); + video->SetSrcObjectVariant(media_stream_descriptor); GetDocument()->body()->AppendChild(video); test::RunPendingTasks(); SetReadyState(video.Get(), HTMLMediaElement::kHaveMetadata);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 36e9e17..e212606 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -3130,8 +3130,15 @@ PaintPropertyTreeBuilderFragmentContext& context) { DCHECK(!IsInNGFragmentTraversal()); InitFragmentPaintProperties(fragment, needs_paint_properties, context); - fragment.SetLegacyPaginationOffset(pagination_offset); - fragment.SetLogicalTopInFlowThread(context.logical_top_in_flow_thread); + if (context.current.fragmentainer_idx == WTF::kNotFound) { + fragment.SetLegacyPaginationOffset(pagination_offset); + fragment.SetLogicalTopInFlowThread(context.logical_top_in_flow_thread); + } else { + // We're inside (monolithic) legacy content, but further out there's an NG + // fragmentation context. Use the fragmentainer index, just like we do for + // NG objects. + fragment.SetFragmentID(context.current.fragmentainer_idx); + } } void PaintPropertyTreeBuilder::InitFragmentPaintPropertiesForNG( @@ -3140,6 +3147,8 @@ context_.fragments.push_back(PaintPropertyTreeBuilderFragmentContext()); else context_.fragments.resize(1); + context_.fragments[0].current.fragmentainer_idx = + pre_paint_info_->fragmentainer_idx; InitFragmentPaintProperties(*pre_paint_info_->fragment_data, needs_paint_properties, context_.fragments[0]); }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h index 0948140..e713267 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -118,6 +118,14 @@ // that are baked in PaintOffsetTranslations since we entered the // fragmentainer. PhysicalOffset paint_offset_for_oof_in_fragmentainer; + + // The fragmentainer index of the nearest ancestor that participates in + // block fragmentation. This is updated as we update properties for an + // object that participates in block fragmentation. If we enter monolithic + // content (legacy or NG), the index will be kept and inherited down the + // tree, so that we eventually set the correct "NG" fragment index in the + // FragmentData object, rather than using a bogus legacy flow-thread offset. + wtf_size_t fragmentainer_idx = WTF::kNotFound; }; ContainingBlockContext current;
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc index 2059ed0..1699485 100644 --- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc +++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc
@@ -225,14 +225,14 @@ &MediaStreamVideoTrackUnderlyingSink::ConvertDone, WrapPersistent(this), resolver, video_frame, estimated_capture_time); const bool success = accelerated_frame_pool_->ConvertVideoFrame( - std::move(video_frame), gfx::ColorSpace::CreateREC709(), + video_frame, gfx::ColorSpace::CreateREC709(), std::move(convert_done_callback)); if (success) { convert_to_nv12_gmb_failure_count_ = 0; } else { + ConvertDone(resolver, video_frame, estimated_capture_time, + /*converted_video_frame=*/nullptr); convert_to_nv12_gmb_failure_count_++; - // Note that `ConvertVideoFrame` will call `convert_done_callback` with - // nullptr even if it returns false, so we still return resolver->Promise() } return resolver->Promise(); }
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc index fc28f85..f119c1f 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
@@ -8,6 +8,7 @@ #include "base/run_loop.h" #include "base/test/gmock_callback_support.h" #include "media/base/limits.h" +#include "media/base/video_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -112,6 +113,21 @@ scoped_refptr<media::VideoFrame> video_frame, std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames, base::TimeTicks estimated_capture_time) { + if (video_frame->format() != media::PIXEL_FORMAT_I420 && + video_frame->format() != media::PIXEL_FORMAT_I420A) { + auto size = video_frame->visible_rect().size(); + auto converted_format = + opaque ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A; + auto i420_frame = media::VideoFrame::CreateFrame( + converted_format, size, gfx::Rect(size), size, + video_frame->timestamp()); + std::vector<uint8_t> tmp_buf; + auto status = + media::ConvertAndScaleFrame(*video_frame, *i420_frame, tmp_buf); + EXPECT_TRUE(status.is_ok()); + video_frame = i420_frame; + } + if (opaque) EXPECT_EQ(media::PIXEL_FORMAT_I420, video_frame->format()); else
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc index aab5622..18166536 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.h" #include "base/memory/ptr_util.h" +#include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" @@ -181,7 +182,11 @@ track->Component(), MediaStreamDescriptorClient::DispatchEventTiming::kScheduled); } - MediaStreamDescriptor* const descriptor = media_element_->GetSrcObject(); + auto variant = media_element_->GetSrcObjectVariant(); + // The load type check above, should prevent this from failing: + DCHECK(absl::holds_alternative<MediaStreamDescriptor*>(variant)); + MediaStreamDescriptor* const descriptor = + absl::get<MediaStreamDescriptor*>(variant); DCHECK(descriptor); for (unsigned i = 0; i < descriptor->NumberOfAudioComponents(); i++) { media_stream_->AddTrackByComponentAndFireEvents( @@ -311,7 +316,11 @@ // If |element| is actually playing a MediaStream, just clone it. if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) { - MediaStreamDescriptor* const element_descriptor = element.GetSrcObject(); + auto variant = element.GetSrcObjectVariant(); + // The load type check above, should prevent this from failing: + DCHECK(absl::holds_alternative<MediaStreamDescriptor*>(variant)); + MediaStreamDescriptor* const element_descriptor = + absl::get<MediaStreamDescriptor*>(variant); DCHECK(element_descriptor); return MediaStream::Create(context, element_descriptor); }
diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc index a0f51b3..54fab7b 100644 --- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
@@ -115,7 +115,8 @@ TRACE_EVENT0("media", "H264Encoder::EncodeOnEncodingTaskRunner"); DCHECK(encoding_task_runner_->RunsTasksInCurrentSequence()); DCHECK(frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_NV12 || - frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420); + frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420 || + frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420A); if (frame->format() == media::PIXEL_FORMAT_NV12) frame = ConvertToI420ForSoftwareEncoder(frame);
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc index d7aa5c58..9dc5103 100644 --- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc +++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
@@ -227,7 +227,7 @@ MediaStreamComponentVector dummy_tracks; auto* descriptor = MakeGarbageCollected<MediaStreamDescriptor>( dummy_tracks, dummy_tracks); - Video()->SetSrcObject(descriptor); + Video()->SetSrcObjectVariant(descriptor); } else { Video()->SetSrc("http://example.com/foo.mp4"); }
diff --git a/third_party/blink/renderer/modules/srcobject/BUILD.gn b/third_party/blink/renderer/modules/srcobject/BUILD.gn index e70b0e5a..13afbba 100644 --- a/third_party/blink/renderer/modules/srcobject/BUILD.gn +++ b/third_party/blink/renderer/modules/srcobject/BUILD.gn
@@ -9,5 +9,8 @@ "html_media_element_src_object.cc", "html_media_element_src_object.h", ] - deps = [ "//third_party/blink/renderer/modules/mediastream" ] + deps = [ + "//third_party/blink/renderer/modules/mediasource", + "//third_party/blink/renderer/modules/mediastream", + ] }
diff --git a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc index 2409a44..adf49d9 100644 --- a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc +++ b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc
@@ -4,18 +4,35 @@ #include "third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h" +#include "third_party/abseil-cpp/absl/types/variant.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_union_mediasourcehandle_mediastream.h" #include "third_party/blink/renderer/core/html/media/html_media_element.h" +#include "third_party/blink/renderer/core/html/media/media_source_handle.h" +#include "third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h" #include "third_party/blink/renderer/modules/mediastream/media_stream.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h" namespace blink { // static -MediaStream* HTMLMediaElementSrcObject::srcObject(HTMLMediaElement& element) { - MediaStreamDescriptor* descriptor = element.GetSrcObject(); +V8MediaProvider* HTMLMediaElementSrcObject::srcObject( + HTMLMediaElement& element) { + HTMLMediaElement::SrcObjectVariant src_object_variant = + element.GetSrcObjectVariant(); + + if (absl::holds_alternative<blink::MediaSourceHandle*>(src_object_variant)) { + auto* handle = absl::get<MediaSourceHandle*>(src_object_variant); + DCHECK(handle); // A nullptr is seen as a MediaStreamDescriptor*. + return MakeGarbageCollected<V8MediaProvider>( + static_cast<MediaSourceHandleImpl*>(handle)); + } + + // Otherwise, it is either null or a non-nullptr MediaStreamDescriptor*. + auto* descriptor = absl::get<MediaStreamDescriptor*>(src_object_variant); if (descriptor) { MediaStream* stream = ToMediaStream(descriptor); - return stream; + return MakeGarbageCollected<V8MediaProvider>(stream); } return nullptr; @@ -23,12 +40,36 @@ // static void HTMLMediaElementSrcObject::setSrcObject(HTMLMediaElement& element, - MediaStream* media_stream) { - if (!media_stream) { - element.SetSrcObject(nullptr); + V8MediaProvider* media_provider) { + if (!media_provider) { + // Default-constructed variant is a nullptr-valued MediaStreamDescriptor* + // since that type is the 0'th index of an + // HTMLMediaElement::SrcObjectVariant. + element.SetSrcObjectVariant(HTMLMediaElement::SrcObjectVariant()); return; } - element.SetSrcObject(media_stream->Descriptor()); + + switch (media_provider->GetContentType()) { + case V8MediaProvider::ContentType::kMediaSourceHandle: { + MediaSourceHandle* handle = media_provider->GetAsMediaSourceHandle(); + + // JS null MediaProvider is a nullptr in |media_provider|, handled above. + DCHECK(handle); + + handle->mark_used(); + element.SetSrcObjectVariant(handle); + break; + } + case V8MediaProvider::ContentType::kMediaStream: { + MediaStream* media_stream = media_provider->GetAsMediaStream(); + + // JS null MediaProvider is a nullptr in |media_provider|, handled above. + DCHECK(media_stream); + + element.SetSrcObjectVariant(media_stream->Descriptor()); + break; + } + } } } // namespace blink
diff --git a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h index f3ca4f9..d48a7cd 100644 --- a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h +++ b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h
@@ -5,20 +5,20 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SRCOBJECT_HTML_MEDIA_ELEMENT_SRC_OBJECT_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SRCOBJECT_HTML_MEDIA_ELEMENT_SRC_OBJECT_H_ +#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" namespace blink { -class MediaStream; class HTMLMediaElement; class MODULES_EXPORT HTMLMediaElementSrcObject { STATIC_ONLY(HTMLMediaElementSrcObject); public: - static MediaStream* srcObject(HTMLMediaElement&); - static void setSrcObject(HTMLMediaElement&, MediaStream*); + static V8MediaProvider* srcObject(HTMLMediaElement&); + static void setSrcObject(HTMLMediaElement&, V8MediaProvider*); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl index 0481d3b3..f6f2b88c 100644 --- a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl +++ b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl
@@ -5,7 +5,7 @@ // https://html.spec.whatwg.org/C/#dom-media-srcobject // TODO(guidou): Add support for MediaSource and Blob, as defined in the spec. -typedef MediaStream MediaProvider; +typedef (MediaSourceHandle or MediaStream) MediaProvider; [ ImplementedAs=HTMLMediaElementSrcObject
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 585419a..96905ade 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1771,24 +1771,25 @@ return true; } -void WebGLRenderingContextBase::CopyRenderingResultsToVideoFrame( +bool WebGLRenderingContextBase::CopyRenderingResultsToVideoFrame( WebGraphicsContext3DVideoFramePool* frame_pool, SourceDrawingBuffer src_buffer, const gfx::ColorSpace& dst_color_space, - VideoFrameCopyCompletedCallback& callback) { + VideoFrameCopyCompletedCallback callback) { if (!frame_pool) - return; + return false; auto* drawing_buffer = GetDrawingBuffer(); if (!drawing_buffer) - return; + return false; ScopedFramebufferRestorer fbo_restorer(this); if (!drawing_buffer->ResolveAndBindForReadAndDraw()) - return; + return false; - drawing_buffer->CopyToVideoFrame(frame_pool, src_buffer, is_origin_top_left_, - dst_color_space, callback); + return drawing_buffer->CopyToVideoFrame(frame_pool, src_buffer, + is_origin_top_left_, dst_color_space, + std::move(callback)); } gfx::Size WebGLRenderingContextBase::DrawingBufferSize() const {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index bc1235e..78feed5 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -724,11 +724,11 @@ bool PaintRenderingResultsToCanvas(SourceDrawingBuffer) override; bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*, SourceDrawingBuffer) override; - void CopyRenderingResultsToVideoFrame( + bool CopyRenderingResultsToVideoFrame( WebGraphicsContext3DVideoFramePool*, SourceDrawingBuffer, const gfx::ColorSpace&, - VideoFrameCopyCompletedCallback&) override; + VideoFrameCopyCompletedCallback) override; cc::Layer* CcLayer() const override; void Stop() override;
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 ccc5638..100db37 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -1071,7 +1071,7 @@ // Use an empty sync token for `mailbox_holder` because we have already waited // on the required sync tokens above. gpu::MailboxHolder mailbox_holder(mailbox, gpu::SyncToken(), texture_target_); - copy_function(mailbox_holder, format, size, color_space); + bool succeeded = copy_function(mailbox_holder, format, size, color_space); gpu::SyncToken sync_token; dst_interface->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); @@ -1081,7 +1081,7 @@ texture_id_to_restore_access, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM); } - return true; + return succeeded; } bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl, @@ -1105,7 +1105,7 @@ auto copy_function = [&](const gpu::MailboxHolder& src_mailbox, viz::ResourceFormat, const gfx::Size&, - const gfx::ColorSpace&) { + const gfx::ColorSpace&) -> bool { GLuint src_texture = dst_gl->CreateAndTexStorage2DSharedImageCHROMIUM( src_mailbox.mailbox.name); dst_gl->BeginSharedImageAccessDirectCHROMIUM( @@ -1118,6 +1118,7 @@ unpack_unpremultiply_alpha_needed); dst_gl->EndSharedImageAccessDirectCHROMIUM(src_texture); dst_gl->DeleteTextures(1, &src_texture); + return true; }; return CopyToPlatformInternal(dst_gl, src_buffer, copy_function); } @@ -1136,61 +1137,41 @@ auto copy_function = [&](const gpu::MailboxHolder& src_mailbox, viz::ResourceFormat, const gfx::Size&, - const gfx::ColorSpace&) { + const gfx::ColorSpace&) -> bool { dst_raster_interface->CopySubTexture( src_mailbox.mailbox, dst_mailbox, dst_texture_target, dst_texture_offset.x(), dst_texture_offset.y(), src_sub_rectangle.x(), src_sub_rectangle.y(), src_sub_rectangle.width(), src_sub_rectangle.height(), flip_y, unpack_premultiply_alpha_needed); + return true; }; return CopyToPlatformInternal(dst_raster_interface, src_buffer, copy_function); } -void DrawingBuffer::CopyToVideoFrame( +bool DrawingBuffer::CopyToVideoFrame( WebGraphicsContext3DVideoFramePool* frame_pool, SourceDrawingBuffer src_buffer, bool src_origin_is_top_left, const gfx::ColorSpace& dst_color_space, - WebGraphicsContext3DVideoFramePool::FrameReadyCallback& callback) { - const GrSurfaceOrigin src_surface_origin = src_origin_is_top_left - ? kTopLeft_GrSurfaceOrigin - : kBottomLeft_GrSurfaceOrigin; - // Split the callback so that one can be consumed by the copy if it succeeds, - // and the other can be used to restore the original callback reference. - auto split_callback = base::SplitOnceCallback(std::move(callback)); - // Restore the original callback; we will reset it below if the copy succeeds. - callback = std::move(split_callback.first); - - // Frame pool copy callback that wraps the original (split) callback. - auto frame_pool_callback = base::BindOnce( - [](WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback, - scoped_refptr<media::VideoFrame> video_frame) { - // Only run callback if copy succeeds, otherwise caller will handle - // failure e.g. HTMLCanvasElement fallback to static bitmap image copy. - if (video_frame) - std::move(callback).Run(std::move(video_frame)); - }, - std::move(split_callback.second)); - - auto copy_function = - [&](const gpu::MailboxHolder& src_mailbox, viz::ResourceFormat src_format, - const gfx::Size& src_size, const gfx::ColorSpace& src_color_space) { - if (frame_pool->CopyRGBATextureToVideoFrame( - src_format, src_size, src_color_space, src_surface_origin, - src_mailbox, dst_color_space, std::move(frame_pool_callback))) { - // This method indicates success by consuming the callback argument - // so do that if the copy has consumed the wrapped split callback. - callback.Reset(); - } - }; + WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback) { // Ensure that `frame_pool` has not experienced a context loss. // https://crbug.com/1269230 auto* raster_interface = frame_pool->GetRasterInterface(); if (!raster_interface) - return; - CopyToPlatformInternal(raster_interface, src_buffer, copy_function); + return false; + const GrSurfaceOrigin src_surface_origin = src_origin_is_top_left + ? kTopLeft_GrSurfaceOrigin + : kBottomLeft_GrSurfaceOrigin; + auto copy_function = + [&](const gpu::MailboxHolder& src_mailbox, viz::ResourceFormat src_format, + const gfx::Size& src_size, const gfx::ColorSpace& src_color_space) { + return frame_pool->CopyRGBATextureToVideoFrame( + src_format, src_size, src_color_space, src_surface_origin, + src_mailbox, dst_color_space, std::move(callback)); + }; + return CopyToPlatformInternal(raster_interface, src_buffer, copy_function); } cc::Layer* DrawingBuffer::CcLayer() {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h index 25773d4..2648412 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -284,12 +284,12 @@ const gfx::Rect& src_sub_rectangle, SourceDrawingBuffer src_buffer); - void CopyToVideoFrame( + bool CopyToVideoFrame( WebGraphicsContext3DVideoFramePool* frame_pool, SourceDrawingBuffer src_buffer, bool src_origin_is_top_left, const gfx::ColorSpace& dst_color_space, - WebGraphicsContext3DVideoFramePool::FrameReadyCallback& callback); + WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback); sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer); @@ -459,8 +459,8 @@ gpu::SyncToken receive_sync_token; }; - // CopyFunction(const gpu::MailboxHolder&, viz::ResourceFormat, - // const gfx::Size&, const gfx::ColorSpace&) + // bool CopyFunction(const gpu::MailboxHolder&, viz::ResourceFormat, + // const gfx::Size&, const gfx::ColorSpace&) template <typename CopyFunction> bool CopyToPlatformInternal(gpu::InterfaceBase* dst_interface, SourceDrawingBuffer src_buffer,
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc index 2355f36..0592eea 100644 --- a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc +++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc
@@ -66,9 +66,7 @@ std::move(sk_image), gfx::Rect(sk_image_size), sk_image_size, base::TimeDelta()); if (sk_image_video_frame) { - std::move(callback).Run( - ConvertToYUVFrame(std::move(sk_image_video_frame), - /* flip = */ false)); + std::move(callback).Run(std::move(sk_image_video_frame)); return; } } @@ -86,6 +84,8 @@ // Try async reading if image is texture backed. if (image->CurrentFrameKnownToBeOpaque() || can_discard_alpha_) { + // Split the callback so it can be used for both the GMB frame pool copy and + // ReadYUVPixelsAsync fallback paths. auto split_callback = base::SplitOnceCallback(std::move(callback)); if (accelerated_frame_pool_enabled_) { if (!accelerated_frame_pool_) { @@ -93,44 +93,21 @@ std::make_unique<WebGraphicsContext3DVideoFramePool>( context_provider); } - auto blit_done_lambda = - [](base::WeakPtr<StaticBitmapImageToVideoFrameCopier> converter, - base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper> - context_provider, - scoped_refptr<StaticBitmapImage> image, - FrameReadyCallback callback, - scoped_refptr<media::VideoFrame> video_frame) { - if (!converter) - return; - if (video_frame) { - converter->OnYUVPixelsReadAsync(video_frame, std::move(callback), - true); - } else if (context_provider) { - converter->ReadYUVPixelsAsync(image, - context_provider->ContextProvider(), - std::move(callback)); - } - }; - auto blit_done_callback = - WTF::Bind(blit_done_lambda, weak_ptr_factory_.GetWeakPtr(), - context_provider, image, std::move(split_callback.first)); - // TODO(https://crbug.com/1224279): This assumes that all // StaticBitmapImages are 8-bit sRGB. Expose the color space and pixel // format that is backing `image->GetMailboxHolder()`, or, alternatively, // expose an accelerated SkImage. - accelerated_frame_pool_->CopyRGBATextureToVideoFrame( - viz::SkColorTypeToResourceFormat(kRGBA_8888_SkColorType), - gfx::Size(image->width(), image->height()), - gfx::ColorSpace::CreateSRGB(), - image->IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin - : kBottomLeft_GrSurfaceOrigin, - image->GetMailboxHolder(), gfx::ColorSpace::CreateREC709(), - std::move(blit_done_callback)); - // Early out even if the above fails since it would've already invoked the - // FrameReadyCallback with a null VideoFrame to indicate failure, and that - // will cause us to the take the fallback path in |blit_done_lambda|. - return; + if (accelerated_frame_pool_->CopyRGBATextureToVideoFrame( + viz::SkColorTypeToResourceFormat(kRGBA_8888_SkColorType), + gfx::Size(image->width(), image->height()), + gfx::ColorSpace::CreateSRGB(), + image->IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin + : kBottomLeft_GrSurfaceOrigin, + image->GetMailboxHolder(), gfx::ColorSpace::CreateREC709(), + std::move(split_callback.first))) { + // Early out on success, otherwise fallback to ReadYUVPixelsAsync path. + return; + } } ReadYUVPixelsAsync(image, context_provider->ContextProvider(), std::move(split_callback.second)); @@ -168,8 +145,7 @@ DLOG(ERROR) << "Couldn't read pixels from PaintImage"; return; } - std::move(callback).Run( - ConvertToYUVFrame(std::move(temp_argb_frame), /* flip = */ false)); + std::move(callback).Run(std::move(temp_argb_frame)); } void StaticBitmapImageToVideoFrameCopier::ReadARGBPixelsAsync( @@ -272,8 +248,51 @@ return; } - bool flip = result_origin == kBottomLeft_GrSurfaceOrigin; - std::move(callback).Run(ConvertToYUVFrame(std::move(temp_argb_frame), flip)); + // If a frame comes with BottomLeft origin it's effectively upside down. + // Frame consumers are not ready to deal with it. We can swap rows to fix it, + // but it would add an extra copy. Instead we set up a wrapper frame that + // references the same data but has color planes with negative strides, + // it forces all the code that handles frames to process rows bottom-up. + auto& coded_size = temp_argb_frame->coded_size(); + if (result_origin == kBottomLeft_GrSurfaceOrigin && coded_size.height() > 1) { + auto pixel_format = temp_argb_frame->format(); + auto rgb_plane = temp_argb_frame->layout().planes()[0]; + size_t last_row_offset = + rgb_plane.offset + rgb_plane.stride * (coded_size.height() - 1); + media::ColorPlaneLayout reverse_rgb_plane(-rgb_plane.stride, + last_row_offset, rgb_plane.size); + + std::vector<media::ColorPlaneLayout> planes{reverse_rgb_plane}; + if (temp_argb_frame->layout().planes().size() > 1 && !can_discard_alpha_) { + auto alpha_plane = temp_argb_frame->layout().planes()[1]; + last_row_offset = + alpha_plane.offset + alpha_plane.stride * (coded_size.height() - 1); + media::ColorPlaneLayout reverse_alpha_plane( + -alpha_plane.stride, last_row_offset, alpha_plane.size); + planes.push_back(reverse_alpha_plane); + } else { + // Dropping alpha from pixel format + if (pixel_format == media::PIXEL_FORMAT_ARGB) + pixel_format = media::PIXEL_FORMAT_XRGB; + else if (pixel_format == media::PIXEL_FORMAT_ABGR) + pixel_format = media::PIXEL_FORMAT_XBGR; + } + auto layout = media::VideoFrameLayout::CreateWithPlanes(pixel_format, + coded_size, planes) + .value(); + + const auto& last_plane = layout.planes()[layout.planes().size() - 1]; + size_t data_size = last_plane.offset + last_plane.size; + auto reverse_stride_frame = media::VideoFrame::WrapExternalDataWithLayout( + layout, gfx::Rect(coded_size), coded_size, + temp_argb_frame->data(media::VideoFrame::kARGBPlane), data_size, + temp_argb_frame->timestamp()); + + reverse_stride_frame->AddDestructionObserver(base::BindOnce( + [](scoped_refptr<media::VideoFrame>) {}, std::move(temp_argb_frame))); + temp_argb_frame = reverse_stride_frame; + } + std::move(callback).Run(std::move(temp_argb_frame)); } void StaticBitmapImageToVideoFrameCopier::OnYUVPixelsReadAsync( @@ -295,70 +314,4 @@ image = nullptr; } -scoped_refptr<media::VideoFrame> -StaticBitmapImageToVideoFrameCopier::ConvertToYUVFrame( - scoped_refptr<media::VideoFrame> temp_argb_frame, - bool flip) { - DVLOG(4) << __func__; - DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_); - TRACE_EVENT0("webrtc", "CanvasCaptureHandler::ConvertToYUVFrame"); - - const bool skip_alpha = - media::IsOpaque(temp_argb_frame->format()) || can_discard_alpha_; - const uint8_t* source_ptr = - temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane); - const gfx::Size image_size = temp_argb_frame->coded_size(); - const int stride = temp_argb_frame->stride(media::VideoFrame::kARGBPlane); - - scoped_refptr<media::VideoFrame> video_frame = frame_pool_.CreateFrame( - skip_alpha ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A, - image_size, gfx::Rect(image_size), image_size, base::TimeDelta()); - if (!video_frame) { - DLOG(ERROR) << "Couldn't allocate video frame"; - return nullptr; - } - - int (*ConvertToI420)(const uint8_t* src_argb, int src_stride_argb, - uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u, - int dst_stride_u, uint8_t* dst_v, int dst_stride_v, - int width, int height) = nullptr; - switch (temp_argb_frame->format()) { - case media::PIXEL_FORMAT_XBGR: - case media::PIXEL_FORMAT_ABGR: - ConvertToI420 = libyuv::ABGRToI420; - break; - case media::PIXEL_FORMAT_XRGB: - case media::PIXEL_FORMAT_ARGB: - ConvertToI420 = libyuv::ARGBToI420; - break; - default: - NOTIMPLEMENTED() << "Unexpected pixel format."; - return nullptr; - } - - if (ConvertToI420(source_ptr, stride, - video_frame->visible_data(media::VideoFrame::kYPlane), - video_frame->stride(media::VideoFrame::kYPlane), - video_frame->visible_data(media::VideoFrame::kUPlane), - video_frame->stride(media::VideoFrame::kUPlane), - video_frame->visible_data(media::VideoFrame::kVPlane), - video_frame->stride(media::VideoFrame::kVPlane), - image_size.width(), - (flip ? -1 : 1) * image_size.height()) != 0) { - DLOG(ERROR) << "Couldn't convert to I420"; - return nullptr; - } - if (!skip_alpha) { - // It is ok to use ARGB function because alpha has the same alignment for - // both ABGR and ARGB. - libyuv::ARGBExtractAlpha( - source_ptr, stride, - video_frame->visible_data(media::VideoFrame::kAPlane), - video_frame->stride(media::VideoFrame::kAPlane), image_size.width(), - (flip ? -1 : 1) * image_size.height()); - } - - return video_frame; -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h index 83fc1f0..a1a11cbc 100644 --- a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h +++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h
@@ -65,10 +65,6 @@ bool success); void OnReleaseMailbox(scoped_refptr<StaticBitmapImage> image); - scoped_refptr<media::VideoFrame> ConvertToYUVFrame( - scoped_refptr<media::VideoFrame> argb_video_frame, - bool flip); - media::VideoFramePool frame_pool_; std::unique_ptr<WebGraphicsContext3DVideoFramePool> accelerated_frame_pool_; bool can_discard_alpha_ = false;
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc index 0a54857..ee2c57b0 100644 --- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc +++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
@@ -120,11 +120,6 @@ const gpu::MailboxHolder& src_mailbox_holder, const gfx::ColorSpace& dst_color_space, FrameReadyCallback callback) { - // Issue `callback` with a nullptr VideoFrame if we return early. - base::ScopedClosureRunner failure_runner(WTF::Bind( - [](FrameReadyCallback* callback) { std::move(*callback).Run(nullptr); }, - base::Unretained(&callback))); - if (!weak_context_provider_) return false; auto* context_provider = weak_context_provider_->ContextProvider(); @@ -154,10 +149,15 @@ const bool copy_succeeded = media::CopyRGBATextureToVideoFrame( raster_context_provider, src_format, src_size, src_color_space, src_surface_origin, src_mailbox_holder, dst_frame.get()); - if (!copy_succeeded) + if (!copy_succeeded) { + ri->DeleteQueriesEXT(1, &query_id); return false; + } - IgnoreResult(failure_runner.Release()); + // QueryEXT functions are used to make sure that CopyRGBATextureToVideoFrame() + // texture copy before we access GMB data. + ri->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); + auto on_query_done_cb = [](scoped_refptr<media::VideoFrame> frame, base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper> ctx_wrapper, @@ -173,9 +173,6 @@ std::move(callback).Run(std::move(frame)); }; - // QueryEXT functions are used to make sure that CopyRGBATextureToVideoFrame() - // texture copy before we access GMB data. - ri->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); auto* context_support = raster_context_provider->ContextSupport(); DCHECK(context_support); context_support->SignalQuery(
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h index 233b201..fbee97c 100644 --- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h +++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h
@@ -53,14 +53,13 @@ base::OnceCallback<void(scoped_refptr<media::VideoFrame>)>; // On success, this function will issue return true and will call the - // specified FrameCallback with the resulting VideoFrame when the frame - // is ready. On failure this will issue `callback` with a nullptr VideoFrame - // and then return false. The resulting VideoFrame will always be NV12. - // Note: In some paths `src_color_space` is ignored in favor of the - // SharedImage color space associated with `src_mailbox_holder`. - // Note: If the YUV to RGB matrix of `dst_color_space` is not Rec601, then - // this function will use the matrix for Rec709 (it supports no other - // values). See https://crbug.com/skia/12545. + // specified FrameCallback with the resulting VideoFrame when the frame is + // ready. On failure this will return false. The resulting VideoFrame will + // always be NV12. Note: In some paths `src_color_space` is ignored in favor + // of the SharedImage color space associated with `src_mailbox_holder`. Note: + // If the YUV to RGB matrix of `dst_color_space` is not Rec601, then this + // function will use the matrix for Rec709 (it supports no other values). See + // https://crbug.com/skia/12545. bool CopyRGBATextureToVideoFrame(viz::ResourceFormat src_format, const gfx::Size& src_size, const gfx::ColorSpace& src_color_space,
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index b830a45a..2bd04cb4 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -13,6 +13,8 @@ # Tests that fail in legacy but pass in NG # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] crbug.com/626703 external/wpt/preload/preload-referrer-policy.html [ Timeout ] crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/floats-aspect-ratio-001.html [ Failure ] crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-move-into-script-disabled-iframe.html [ Timeout ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials index 214a663..e586cbc 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials +++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -44,6 +44,7 @@ crbug.com/1209223 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-security-check-same-origin-domain.sub.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] crbug.com/626703 external/wpt/preload/preload-referrer-policy.html [ Timeout ] crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-move-into-script-disabled-iframe.html [ Timeout ] crbug.com/626703 external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 0ddfcce..c118ddb8 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3343,6 +3343,14 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Linux ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 [ Mac11 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 [ Mac12 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 [ Mac12-arm64 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 [ Win ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] +crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ] crbug.com/626703 [ Linux ] external/wpt/preload/preload-referrer-policy.html [ Skip Timeout ] crbug.com/626703 [ Mac10.15 ] external/wpt/preload/preload-referrer-policy.html [ Skip Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/preload/preload-referrer-policy.html [ Skip Timeout ] @@ -7097,4 +7105,4 @@ # Sheriff 2022-06-08 crbug.com/1229084 [ Linux ] external/wpt/storage-access-api/requestStorageAccess.sub.window.html [ Failure Pass ] -crbug.com/1229084 [ Win ] external/wpt/storage-access-api/requestStorageAccess.sub.window.html [ Failure Pass ] \ No newline at end of file +crbug.com/1229084 [ Win ] external/wpt/storage-access-api/requestStorageAccess.sub.window.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index c085294..0bff7d7 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: a6101f13a28eb78dbef77e276ddee75052a8a2d4 +Version: c801c26f4182f6e2fbf72ac3093a3746d8d50400
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index cd5173a..78bcbf9a 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -4368,6 +4368,19 @@ ] ] }, + "service-workers": { + "cache-storage": { + "crashtests": { + "cache-response-clone.https.html": [ + "ec930a87d934c4b232d42c9d411457a1776e86ca", + [ + null, + {} + ] + ] + } + } + }, "shadow-dom": { "event-on-pseudo-element-crash.html": [ "c03f51a64f439e772ff56702dc132f8cd8c7938c", @@ -86763,6 +86776,125 @@ {} ] ], + "repeated-section": { + "abspos.tentative.html": [ + "a7297f1dd559f5bb38a1143d0371d17d4ee29bba", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-in-inline.tentative.html": [ + "1a94c697f15707efe09767c64b9c71a9103d78dc", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "captions.tentative.html": [ + "1f28d56802cf2aa4f631c509510dd9761243bfc0", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "footer.tentative.html": [ + "8789ef2915fd98bb21e58a4d221f87b8e78f0998", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "header-after-break.tentative.html": [ + "6a5abc011fa20c0df1613055307aec47a26381e1", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "header-footer.tentative.html": [ + "7a1e956a8dacf6b497f9e9d1a87a3f37255b6418", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "header.tentative.html": [ + "6f4ad01097ea0525c7c513ae9f74ede800d7d7cf", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "inline-block.tentative.html": [ + "6dee47e375752e73e63030fd0c27951b966683d8", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "multicol.tentative.html": [ + "6dcd51bfe3e088262b407bd686a1db000771fdf7", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ] + }, "section-with-overflow-000.html": [ "909052765b6cc616389f52cb4e21857caeab38fd", [ @@ -88419,6 +88551,34 @@ {} ] ], + "animation": { + "opacity-animation-ending-correctly-001.html": [ + "1fb36cd366ff260f073c7de6d8062d9fceff5340", + [ + null, + [ + [ + "/css/css-color/animation/opacity-animation-ending-correctly-001-ref.html", + "==" + ] + ], + {} + ] + ], + "opacity-animation-ending-correctly-002.html": [ + "7ba097fb105ab683d6a8a7484007821a13a75a62", + [ + null, + [ + [ + "/css/css-color/animation/opacity-animation-ending-correctly-001-ref.html", + "==" + ] + ], + {} + ] + ] + }, "at-color-profile-001.html": [ "f2a971532c823dfe821a0eed1a9fe0e7a8631a71", [ @@ -150589,6 +150749,19 @@ {} ] ], + "highlight-pseudos-currentcolor-inheritance-computed-002.html": [ + "0d0da9ecec96f7357b1e7a6cd684abb9a1c56a6f", + [ + null, + [ + [ + "/css/css-pseudo/reference/highlight-pseudos-currentcolor-inheritance-computed-002-ref.html", + "==" + ] + ], + {} + ] + ], "highlight-styling-001.html": [ "63d8ee1eda47dec0eeaf30f56316e4203e49f182", [ @@ -179769,6 +179942,19 @@ {} ] ], + "text-decoration-color-recalc-002.html": [ + "ce5c36dd5b6508c6d34ac0de5a5e65aa1c54fcf5", + [ + null, + [ + [ + "/css/css-text-decor/text-decoration-color-recalc-002-ref.html", + "==" + ] + ], + {} + ] + ], "text-decoration-color-recalc.html": [ "c82bdcad73852b10842b7da568ca77b80ebe65a8", [ @@ -184736,6 +184922,34 @@ ] ], "individual-transform": { + "animation": { + "individual-transform-combine.html": [ + "9551a3a726a1c2e5dbee246be7258ba5e6db910f", + [ + null, + [ + [ + "/css/css-transforms/individual-transform/animation/individual-transform-combine-ref.html", + "==" + ] + ], + {} + ] + ], + "individual-transform-ordering.html": [ + "9d127f163bc2b88ba4eedc28bf9eb143846b26c1", + [ + null, + [ + [ + "/css/css-transforms/individual-transform/animation/individual-transform-ordering-ref.html", + "==" + ] + ], + {} + ] + ] + }, "individual-transform-1.html": [ "f21954e01dfc0f8f70c9dd43262d40b3374010b5", [ @@ -193685,6 +193899,19 @@ ] }, "css-transitions": { + "inherit-background-color-transition.html": [ + "2c0e4aed933ec69f145f55dac81f262d93a3cdaa", + [ + null, + [ + [ + "/css/css-transitions/inherit-background-color-transition-ref.html", + "==" + ] + ], + {} + ] + ], "no-transition-from-ua-to-blocking-stylesheet.html": [ "4967eabda86bf42be467b826f8782e91a115748e", [ @@ -244002,7 +244229,7 @@ ] ], "transform-dynamic-change.html": [ - "abd05cce16e7b9cd3b021467420087a648f4e32f", + "57b5551061945931b39f35394e2974b2306e2762", [ null, [ @@ -262173,6 +262400,12 @@ "3b8771a704a5f79e7062f790c04f0bbd24efb05b", [] ], + "animation": { + "opacity-animation-ending-correctly-001-ref.html": [ + "ca55dc66f3007a6104b0298d77a215e1d6f2c123", + [] + ] + }, "background-color-hsl-001-ref.html": [ "f37a73d1707f056962baad29a2198fd3b271e362", [] @@ -281040,6 +281273,10 @@ "b3c89177591ad83476edd3616f135f1cd65700d8", [] ], + "highlight-pseudos-currentcolor-inheritance-computed-002-ref.html": [ + "67ecb8df640f72e1725e42a648f2c6e1f33490e2", + [] + ], "placeholder-excluded-properties-ref.html": [ "0e573cb3d6cbac837c9e10552e360aa713fee60b", [] @@ -287343,6 +287580,10 @@ [] ] }, + "text-decoration-color-recalc-002-ref.html": [ + "440d2f051cae91b62ff33b454646306dcbd05f0f", + [] + ], "text-decoration-line-grammar-error-color-001-ref.html": [ "2592110a1199515b6376d21a963132bfe90400bc", [] @@ -287786,6 +288027,16 @@ [] ], "individual-transform": { + "animation": { + "individual-transform-combine-ref.html": [ + "7c8eb206a9fb7fc9a4cf53f5282cfc1fb251d450", + [] + ], + "individual-transform-ordering-ref.html": [ + "b7dce51e8bab9e5985426d8b8d16966557eef742", + [] + ] + }, "individual-transform-1-ref.html": [ "dbc5f05d8925a8ddd37c8a6499b0563d4fdaf71e", [] @@ -289013,6 +289264,10 @@ "f72f11dccae5e8b63de6148573723f86fbb4c708", [] ], + "inherit-background-color-transition-ref.html": [ + "b7a5824836e157f21649fabe12a701b860e04c9f", + [] + ], "no-transition-from-ua-to-blocking-stylesheet-ref.html": [ "93b4ae982e80d31df4cb0eac448ceb3341c57a81", [] @@ -289121,7 +289376,7 @@ [] ], "properties.js": [ - "3255261f6c604ee2bdfc3b07f6acd917408cd677", + "93c47cd2f0310cbe445ec4bdcce29534275adde6", [] ], "ruler-h-50%.png": [ @@ -295875,7 +296130,7 @@ [] ], "OWNERS": [ - "73c81fa31d15b0276bb6c8e59002a8ab94031899", + "167a625063bc31c6e7d58df13f8561ed28931b29", [] ], "README.md": [ @@ -301718,10 +301973,6 @@ "9885466ebb5540246b80fcf39dbd461ab6cd5721", [] ], - "delegate-request-subframe.html": [ - "9bb9d7816d45289f10589bb5ae8d998b44efd1e9", - [] - ], "echo-fullscreenEnabled.html": [ "ad5edf79866273d0debb2dbc438e6dec6f305cd3", [] @@ -305293,7 +305544,7 @@ [] ], "fill-and-stroke-styles.yaml": [ - "f52a3e24c61e527d620066720f75443e99406236", + "16c8aa52c5ceae08b828ea2cd2fcec6a626edf38", [] ], "line-styles.yaml": [ @@ -305335,7 +305586,7 @@ }, "offscreen": { "fill-and-stroke-styles.yaml": [ - "7a57a4730e096c728010b754c503c753a6972326", + "c70082cf6d2d700ea91080a969dfbffdb5ebf4eb", [] ], "line-styles.yaml": [ @@ -305416,6 +305667,18 @@ } } }, + "capability-delegation": { + "resources": { + "delegate-fullscreen-request-recipient.html": [ + "11daf738d6856d72b6a575639915443659785df3", + [] + ], + "utils.js": [ + "3add3eb6f50eb97c857e561a4cb43bd3c29c31ab", + [] + ] + } + }, "cross-origin-embedder-policy": { "META.yml": [ "dc7010880b61d455c7ecdc43cbc2a4e00081bd19", @@ -305771,7 +306034,15 @@ "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", [] ], - "coep.https.html.headers": [ + "coep-with-cross-origin.https.html.headers": [ + "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", + [] + ], + "coep-with-same-origin.https.html.headers": [ + "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", + [] + ], + "coep-with-same-site.https.html.headers": [ "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", [] ], @@ -305990,7 +306261,7 @@ }, "resources": { "reporting-common.js": [ - "6ed75b2c5715e2466bbd8e946a8edacd74667b73", + "585287d39dd644fc4a76dabff743c46ecfb03102", [] ], "test-access-property.js": [ @@ -306009,7 +306280,7 @@ [] ], "common.js": [ - "34589f40d93496e2b61864af9ae77fb945eca83d", + "ff6be1bbe53545e4ef64b31e7969e640cf59c3b0", [] ], "coop-coep.py": [ @@ -306037,7 +306308,7 @@ [] ], "popup-test.js": [ - "3da5ca11fe5881a6bd228e1c3757bf6523becc62", + "f613a9f770d0de62730d1a023691f01acf5b5162", [] ], "postback.html": [ @@ -309695,7 +309966,7 @@ [] ], "iframe-domain-failure.sub.html": [ - "9fea70380547e12492cb472612cab379d5bbd560", + "0cdb8b5f5955b46aed32099db1aed9b823c09aad", [] ], "iframe-domain-failure.sub.html.headers": [ @@ -311132,6 +311403,14 @@ "c1dd8dddf9eec3ab3fb58df01c549c251f3a3fdf", [] ], + "bfcache": { + "resources": { + "common.js": [ + "9c852bbfb3ed1d607b69de96fb3717cb4725e23e", + [] + ] + } + }, "image-maps": { "image-map-processing-model": { "hash-name-reference-test-data.html": [ @@ -318456,7 +318735,7 @@ ] }, "lint.ignore": [ - "fdba97deda7a6eb41a7209caae79371b2dd10917", + "07ad220e4f7d1bd7949842ad37827cca99b6eb9f", [] ], "loading": { @@ -321403,7 +321682,7 @@ [] ], "navigation-id.helper.js": [ - "fd6e24d5c584f0871a800e6b410e7baea8a1a559", + "53099cadb254df0a4d087bc9dd75340b5ddb40fa", [] ], "performanceobservers.js": [ @@ -321415,6 +321694,18 @@ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", [] ], + "json_resource.json": [ + "68b6ac1d56f7c25d29f01cc020bda162389776bf", + [] + ], + "make_long_task.js": [ + "a52d6d839298ccbd3c984984a3038c7797cccc34", + [] + ], + "navigation-id-detached-frame-page.html": [ + "02aafbb5c78368c69dbf1cdae81b432d988e17d1", + [] + ], "postmessage-entry.html": [ "ef5be73395b49d895a2589be547a7f3950f416ba", [] @@ -322391,6 +322682,10 @@ "e4e3217b8c14ce97c7888000676f7e46e771ac70", [] ], + "modulepreload-iframe.html": [ + "1d3d21f4d953ee1eac4fbc93e91f4a404d5f0c8f", + [] + ], "preload_helper.js": [ "1c7c1a2750e7bc8dbd24ec16f4037183a4a9e91d", [] @@ -324738,7 +325033,7 @@ [] ], "mock-subapps.js": [ - "dd6899a597b154b487fd50304a60a2469dfb7ba5", + "96ddcfd246f28977ded46cbac0bfb73785e5628f", [] ], "mock-textdetection.js": [ @@ -328404,7 +328699,11 @@ "1ab609f11bf2be22696f0b132b88d8fc86546b93", [] ], - "notification.html": [ + "notification-before-activation.html": [ + "16aab488a572506abda901d89384e3798c7670ca", + [] + ], + "notification-on-activation.html": [ "03e36f06c134e1ee0ced6c703d1b8e20f1c7511b", [] ], @@ -329593,7 +329892,7 @@ [] ], "transform-dynamic-change-ref.html": [ - "cdcad92fe1f46bc3f76a1e0ac2c253122d1a2590", + "df8afcebc18e912d3c4a66be7e069f1a827e1e88", [] ], "tspan-opacity-mixed-direction-ref.svg": [ @@ -330529,7 +330828,7 @@ [] ], "viewport_support.js": [ - "5cea91a0155ae5c1de213ef96260d884361d9fba", + "7da5670d9027249e444f05badae048874a702bc7", [] ] }, @@ -358040,7 +358339,7 @@ }, "clipboard-apis": { "async-custom-formats-write-read.tentative.https.html": [ - "b6c368f75bc2f2902b9a5cd09e52871461daa8d0", + "77991ec98aa098e92cd13c01ff54468e6ccf8f1b", [ null, { @@ -358049,7 +358348,7 @@ ] ], "async-html-script-removal.https.html": [ - "90dc44c9db20e31ceae6bead41b956754cfe9d9d", + "44c11add855137ed00634c4435e758fa8c548067", [ null, { @@ -358065,7 +358364,7 @@ ] ], "async-navigator-clipboard-read-resource-load.https.html": [ - "5f74be1a8228273350f8793ce2ac8325c1335130", + "d1e3019e7f939965f6814436752e92a44ecb1b25", [ null, { @@ -358074,7 +358373,7 @@ ] ], "async-navigator-clipboard-read-sanitize.https.html": [ - "9e0ab2ee740f85ea4e9de9d3f1d2ac43bee5a985", + "cc1836753478b79972627b87bb3bca1e75c29459", [ null, { @@ -358083,7 +358382,7 @@ ] ], "async-promise-write-blobs-read-blobs.https.html": [ - "e4b93c7c5ffb7c0fc2fb0fb9d95932788177dda1", + "12184c92e0777f5d10a63ad8e075e8422d5545a5", [ null, { @@ -358092,7 +358391,7 @@ ] ], "async-svg-script-removal.https.html": [ - "cd1a551d9d12852f3ff8233bf535eb29e88c48ef", + "292d100b2fc7d2274a9e1bbf3dec85ed67f4fb32", [ null, { @@ -358101,7 +358400,7 @@ ] ], "async-unsanitized-html-formats-write-read.tentative.https.html": [ - "887ba8a484fd97c0956f70c85138099223be493c", + "ffe6a31c2a7a9382796b1917d724eb4b1ac13fd5", [ null, { @@ -358110,7 +358409,7 @@ ] ], "async-unsanitized-plaintext-formats-write-read.tentative.https.html": [ - "f44ed22618e2fd0c2781f959140d3d4d22cd45e9", + "1c5638ca0a5faf806ed9d003b6c36f20bedcb263", [ null, { @@ -358119,7 +358418,7 @@ ] ], "async-write-blobs-read-blobs.https.html": [ - "50d23a9c3625d5295407a783ad63908571fd55f7", + "8bec558b2b2de8a38c0f9620942a5307c8158665", [ null, { @@ -358128,7 +358427,7 @@ ] ], "async-write-html-read-html.https.html": [ - "7c271b9bd78d1b68b86a911923789c32f02210fe", + "ec1817c027bbc19304cfbd01034b4fbd2b54454c", [ null, { @@ -358137,7 +358436,7 @@ ] ], "async-write-image-read-image.https.html": [ - "281358dfc5f8d68d3d6d436fdd92dbc8fb8b7b5d", + "e10b69d824c20394ab151fc6ce1bd7c6260e76e9", [ null, { @@ -358146,7 +358445,7 @@ ] ], "async-write-svg-read-svg.https.html": [ - "19c91597c111ee267e95f6d4bb0092fa2aafec25", + "42f6c547b2979947c437a9b515f7ade9f1faf138", [ null, { @@ -358195,7 +358494,7 @@ ] ], "write-read-on-detached-iframe.https.html": [ - "c0f11772929eed601c1fc8e921ea3d933ba6444f", + "b21e6b20bc0d9940d35994e2867d415102fe8b76", [ null, { @@ -358204,7 +358503,7 @@ ] ], "writeText-readText-on-detached-iframe.https.html": [ - "9cd8900aab0f9ee9399b5fdb1c175563a06884ea", + "24fa586fc7709b72ef651b22f680ea290018c265", [ null, { @@ -358236,7 +358535,7 @@ ] ], "clipboard-read-enabled-by-feature-policy-attribute-cross-origin-tentative.https.sub.html": [ - "3b1cfd52ad7c9f4166fa9e529c80a227dd93bbb3", + "367d033d0f6afa1c2a9c6a0048444e012118656d", [ null, { @@ -358245,7 +358544,7 @@ ] ], "clipboard-read-enabled-by-feature-policy-attribute-tentative.https.sub.html": [ - "15d268426163727a3dbf2adbb01db40ea7fecd1f", + "e812854b4c75053f7350ba6b8864e5649dac9214", [ null, { @@ -358254,7 +358553,7 @@ ] ], "clipboard-read-enabled-by-feature-policy-cross-origin-tentative.https.sub.html": [ - "1b6f4929a19deaf7779643944fb7f90020235ff4", + "c371ea3b41cb2e648202f1aaf76b542fa0f033f8", [ null, { @@ -358263,7 +358562,7 @@ ] ], "clipboard-read-enabled-by-feature-policy.tentative.https.sub.html": [ - "f8c5bcb129f9324056ad57368dab3a85b982117c", + "552183cc67d461a61541d803ade89ebc729778a4", [ null, { @@ -358272,7 +358571,7 @@ ] ], "clipboard-read-enabled-on-self-origin-by-feature-policy.tentative.https.sub.html": [ - "47aa6511ec599be99f685b5a419511b81ee0baef", + "17dc3628a7722047f07997d0a8544a9599f75bf3", [ null, { @@ -358292,7 +358591,7 @@ ] ], "clipboard-write-enabled-by-feature-policy-attribute-cross-origin-tentative.https.sub.html": [ - "c931bbbb89f32f8035cac150d0eb658e31e8bf8b", + "e669c8fec4910dc8f3f7a038b69f0b17e671c94a", [ null, { @@ -358301,7 +358600,7 @@ ] ], "clipboard-write-enabled-by-feature-policy-attribute-tentative.https.sub.html": [ - "a2858c638e6c05f08ea8d4b71dd8891a21b63b43", + "b57dfe3dd2888dcaace721a10aeda58ee8e03ee9", [ null, { @@ -358310,7 +358609,7 @@ ] ], "clipboard-write-enabled-by-feature-policy-cross-origin-tentative.https.sub.html": [ - "0f3164d9b02a13f8d5296bdbdd65b11041889a13", + "6e7029cc789a63e0603b596739ca6eac36bbdc88", [ null, { @@ -358319,7 +358618,7 @@ ] ], "clipboard-write-enabled-by-feature-policy.tentative.https.sub.html": [ - "1c6fc49a056605a1dfab3fb96cd1155ea72716c7", + "ca97994c617d0ee751672be28eaaf30b59283a66", [ null, { @@ -358328,7 +358627,7 @@ ] ], "clipboard-write-enabled-on-self-origin-by-feature-policy.tentative.https.sub.html": [ - "51db5a427d2b4140786555e07c7f57624a8ae505", + "5615a68ac55af819759d1bbd214ac940289ceb39", [ null, { @@ -358363,7 +358662,7 @@ ], "permissions": { "readText-denied.https.html": [ - "935f520e7de2dd15e0019c798dd0966c454235cd", + "010f4ba21b95332c3fabb59c2861b634e1ea48ee", [ null, { @@ -358372,7 +358671,7 @@ ] ], "readText-granted.https.html": [ - "ab76cd5e1da86e830829c45d876ae3e016a573f3", + "e912bd64a83148baaaaffa1214ccc0ba37fa3e44", [ null, { @@ -358381,7 +358680,7 @@ ] ], "writeText-denied.https.html": [ - "4d0530f0bc221773606b27b119d0b20100444703", + "5fbcab411748e25170c06da87d8ff7930cfa6b7d", [ null, { @@ -358390,7 +358689,7 @@ ] ], "writeText-granted.https.html": [ - "b03ae7ff26b59cbd00ec1a25a6953023b139ee71", + "ff347b7adda0727a07e9e76df9adb482eae746bd", [ null, { @@ -358401,7 +358700,7 @@ }, "text-write-read": { "async-write-read.https.html": [ - "a00c5b27a4d65f148d3cafaf4700a0e3e286cfee", + "c46e5d43171314132ab0be20a93a1f50e9b25b64", [ null, { @@ -358410,7 +358709,7 @@ ] ], "async-write-readText.https.html": [ - "e8156af47f4c34395136c463ecb1dae2cd8c9870", + "66969b1777b251ebc7413e59453c9857a0f7b5b7", [ null, { @@ -358419,7 +358718,7 @@ ] ], "async-writeText-read.https.html": [ - "4a37aa1a5f73d3b9521145637c2bbbaf35dd2e96", + "ddf563269a422a578fc4c7206810790c9f090e30", [ null, { @@ -358428,7 +358727,7 @@ ] ], "async-writeText-readText.https.html": [ - "7e56bfef2c684415eaaa4e62bcde77232fa8531f", + "0defdf7a709535020f24c674796d8a9b9bf0dd4b", [ null, { @@ -369942,6 +370241,13 @@ {} ] ], + "animation-timing-function-linear.tentative.html": [ + "007d7a10aeae233b072ad04ee2725a2b2004088a", + [ + null, + {} + ] + ], "animation-timing-function-valid.html": [ "7ab823ea1da1535606ac4aad30fb21f423ba6703", [ @@ -371130,6 +371436,13 @@ {} ] ], + "offset-top-block-in-inline.html": [ + "72b35087e424cbf13289686dcc9436309320b27e", + [ + null, + {} + ] + ], "overflow-clip-007.html": [ "a90cba2f846442195c18f88f0b0607f48769374d", [ @@ -379601,6 +379914,13 @@ {} ] ], + "object-view-box-interpolation.html": [ + "18ac72db70d63a78f2f61ea358adb3396631042b", + [ + null, + {} + ] + ], "object-view-box-parsing.html": [ "da17b7936fb9a3552ce263369c84282df30a4c23", [ @@ -384058,6 +384378,13 @@ {} ] ], + "snap-on-focus.html": [ + "b8763992055fd700a21a743b562acf4bff858227", + [ + null, + {} + ] + ], "snap-to-transformed-target.html": [ "b8604269b4b9a1d6dbf337cfe867714cbf40fabb", [ @@ -417571,6 +417898,16 @@ } ] ], + "first-input-interactionid-tap.html": [ + "c5c6f5177ebd9882c41385000c9bb3d08f3e8567", + [ + null, + { + "testdriver": true, + "timeout": "long" + } + ] + ], "first-input-shadow-dom.html": [ "5911dabd54e65f34b04eb40f2e99dd0089047e66", [ @@ -432660,15 +432997,6 @@ }, "fullscreen": { "api": { - "delegate-request.https.sub.tentative.html": [ - "37e0099e6a8692ac24a531814cd3324c0b71e8d5", - [ - null, - { - "testdriver": true - } - ] - ], "document-exit-fullscreen-active-document.html": [ "8279fae533774fcf6daced99ffc84413a0a9172d", [ @@ -440056,6 +440384,13 @@ {} ] ], + "2d.fillStyle.get.halftransparent.html": [ + "4101bf4ce9d5ff6501dc38fe14f83d6198b9ce12", + [ + null, + {} + ] + ], "2d.fillStyle.get.semitransparent.html": [ "9f1784730977e29d12122f6e62514afe847de59c", [ @@ -447870,6 +448205,20 @@ {} ] ], + "2d.fillStyle.get.halftransparent.html": [ + "47e555547e839d7fe688fe9bf2cb6695d4c6b67a", + [ + null, + {} + ] + ], + "2d.fillStyle.get.halftransparent.worker.js": [ + "ec66b5868c8e5613d84944c10432fc5276b530dd", + [ + "html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.get.halftransparent.worker.html", + {} + ] + ], "2d.fillStyle.get.semitransparent.html": [ "9f8566809d9024d8e05c9a2a1a192fa169a504b6", [ @@ -457905,6 +458254,53 @@ } } }, + "capability-delegation": { + "delegate-fullscreen-request-popup-cross-origin.https.sub.tentative.html": [ + "2d531a5d983500567119617a05edb773a0232861", + [ + null, + { + "testdriver": true + } + ] + ], + "delegate-fullscreen-request-popup-same-origin.https.tentative.html": [ + "d429095cfcbbdddb5b651b713669770b0cb23863", + [ + null, + { + "testdriver": true + } + ] + ], + "delegate-fullscreen-request-subframe-cross-origin.https.sub.tentative.html": [ + "5f2d2f61c97aab3a168a3baafd120db78505ce61", + [ + null, + { + "testdriver": true + } + ] + ], + "delegate-fullscreen-request-subframe-same-origin.https.tentative.html": [ + "9e5482dc183e42b5f3fd9284fe43d7229bca01e1", + [ + null, + { + "testdriver": true + } + ] + ], + "delegation-consumes-activation.https.tentative.html": [ + "1a8805de486d24cbce75bff0ba0792fd3b3d0712", + [ + null, + { + "testdriver": true + } + ] + ] + }, "cross-origin-embedder-policy": { "about-blank-popup.https.html": [ "2dc73c7561ff297ea2cf50c67d8218fef941a194", @@ -459312,8 +459708,26 @@ } ] ], - "coep.https.html": [ - "f6d975564f4fd0a5d272ea6977b7aa93c64e4794", + "coep-with-cross-origin.https.html": [ + "3f6256bcd283b2e9c16839aede42ec79f7992b2f", + [ + null, + { + "timeout": "long" + } + ] + ], + "coep-with-same-origin.https.html": [ + "66e7aaf88e5279fc3b56beec235bbeb883370b8e", + [ + null, + { + "timeout": "long" + } + ] + ], + "coep-with-same-site.https.html": [ + "abce6597901ad52a92e0aa5f4187acec06cbad26", [ null, { @@ -459403,7 +459817,7 @@ ] ], "header-parsing-failures.https.html": [ - "1973550103225d8843cd52d796e13aa64d228a78", + "55b126ff379b1071cc22b4a1fa706865824550f3", [ "html/cross-origin-opener-policy/header-parsing-failures.https.html?1-4", { @@ -459444,7 +459858,7 @@ ] ], "header-parsing-successes.https.html": [ - "0d3dadb4ce26b6ed0a4f203818bdf450718162dd", + "8e055669ad845bf7437056b111b5f5f9fe925efa", [ null, { @@ -459463,7 +459877,7 @@ ] ], "popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html": [ - "d45d9e4a086aece4531b36ccbf64e4bca12d1c0f", + "21e0875f41b020c454d0ae0efceaa036934f2e89", [ null, { @@ -459472,7 +459886,7 @@ ] ], "popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html": [ - "1a09d5996faf24c650aa22bb4b3b93c053cb10d7", + "89b0b4934ea4bfaf223d8f0929f494df3dea79db", [ null, { @@ -459481,7 +459895,7 @@ ] ], "popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html": [ - "e884d21622bdb851bf09731bc86ef6eb05f7cb25", + "fb3330365fbf4b1c743bdc132084b7f326d352fc", [ null, { @@ -459490,7 +459904,7 @@ ] ], "popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html": [ - "d45d9e4a086aece4531b36ccbf64e4bca12d1c0f", + "21e0875f41b020c454d0ae0efceaa036934f2e89", [ null, { @@ -459499,7 +459913,7 @@ ] ], "popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html": [ - "1a09d5996faf24c650aa22bb4b3b93c053cb10d7", + "89b0b4934ea4bfaf223d8f0929f494df3dea79db", [ null, { @@ -459508,7 +459922,7 @@ ] ], "popup-same-site-unsafe-allow-outgoing-with-same-site.https.html": [ - "e884d21622bdb851bf09731bc86ef6eb05f7cb25", + "fb3330365fbf4b1c743bdc132084b7f326d352fc", [ null, { @@ -459517,7 +459931,7 @@ ] ], "popup-same-site-with-cross-origin.https.html": [ - "d45d9e4a086aece4531b36ccbf64e4bca12d1c0f", + "21e0875f41b020c454d0ae0efceaa036934f2e89", [ null, { @@ -459526,7 +459940,7 @@ ] ], "popup-same-site-with-same-origin.https.html": [ - "1a09d5996faf24c650aa22bb4b3b93c053cb10d7", + "89b0b4934ea4bfaf223d8f0929f494df3dea79db", [ null, { @@ -459535,7 +459949,7 @@ ] ], "popup-same-site-with-same-site.https.html": [ - "e884d21622bdb851bf09731bc86ef6eb05f7cb25", + "fb3330365fbf4b1c743bdc132084b7f326d352fc", [ null, { @@ -459734,7 +460148,7 @@ ] ], "popup-same-origin-allow-popups-with-cross-origin.https.html": [ - "c776f4450ff221ce286af9eeeb3ba9f1edba0db1", + "d025faeb67ee0b2bd2d7616a7c6619d5a6d61dd8", [ null, { @@ -459743,7 +460157,7 @@ ] ], "popup-same-origin-allow-popups-with-same-origin.https.html": [ - "7e14d072774c3a1536449287f92985056bbd249b", + "438e4242848ffb7d383919279dd001d5cfe2c2c6", [ null, { @@ -459752,7 +460166,7 @@ ] ], "popup-same-origin-allow-popups-with-same-site.https.html": [ - "7d734fa27f2603f6c4a1cdeefa1d29623f3d5d24", + "d1b6b60d7c8232ee4fa5d46445e8870727127d5b", [ null, { @@ -459768,7 +460182,7 @@ ] ], "popup-same-origin-with-cross-origin.https.html": [ - "a01ab56d173137aa25abba811ffceddae393c300", + "bd1e6848c4bfe823e4bcdc7b548c667684fd98da", [ null, { @@ -459777,7 +460191,7 @@ ] ], "popup-same-origin-with-same-origin.https.html": [ - "b103bb7308a6ec6c6200ae795b55a7eeaba18927", + "caf4b173c28b348f412c358021a85df0a56964a6", [ null, { @@ -459786,7 +460200,7 @@ ] ], "popup-same-origin-with-same-site.https.html": [ - "3ed8b1cd014344f16d468f65c5500aeb300a95f3", + "93ba9c9888cf1885545c3b0ac57fbee8b8b105f4", [ null, { @@ -459795,7 +460209,7 @@ ] ], "popup-unsafe-none-with-cross-origin.https.html": [ - "c776f4450ff221ce286af9eeeb3ba9f1edba0db1", + "31ac5694913b7957ab7f7f20fcea499ae590ccb9", [ null, { @@ -459804,7 +460218,7 @@ ] ], "popup-unsafe-none-with-same-origin.https.html": [ - "7b3f4d94718e79bf6f748c99aa3075640a57ee67", + "18f87048c30b65155e04dbbf3450f379adb91ddf", [ null, { @@ -459813,7 +460227,7 @@ ] ], "popup-unsafe-none-with-same-site.https.html": [ - "7d734fa27f2603f6c4a1cdeefa1d29623f3d5d24", + "d1b6b60d7c8232ee4fa5d46445e8870727127d5b", [ null, { @@ -459822,7 +460236,7 @@ ] ], "popup-unspecified-with-cross-origin.https.html": [ - "c776f4450ff221ce286af9eeeb3ba9f1edba0db1", + "31ac5694913b7957ab7f7f20fcea499ae590ccb9", [ null, { @@ -459831,7 +460245,7 @@ ] ], "popup-unspecified-with-same-origin.https.html": [ - "7b3f4d94718e79bf6f748c99aa3075640a57ee67", + "18f87048c30b65155e04dbbf3450f379adb91ddf", [ null, { @@ -459840,7 +460254,7 @@ ] ], "popup-unspecified-with-same-site.https.html": [ - "7d734fa27f2603f6c4a1cdeefa1d29623f3d5d24", + "d1b6b60d7c8232ee4fa5d46445e8870727127d5b", [ null, { @@ -459849,7 +460263,7 @@ ] ], "popup-with-structured-header.https.html": [ - "729be3c4aade82c4ede2c52a9b328f70ec2cd181", + "e337e69cc0c67b565af7aceeae87ebe93410f766", [ null, { @@ -461832,7 +462246,7 @@ ] ], "window-domain-failure.https.sub.html": [ - "2deff50d8dd91642f337ae19a3df733837fe8c83", + "6fa196e094e9b5ed6011f46bc1a75b66c1870d01", [ null, {} @@ -465103,6 +465517,50 @@ } }, "embedded-content": { + "bfcache": { + "embeded-html.html": [ + "0808538337710337f9dc8705bf1c951266b027f8", + [ + null, + {} + ] + ], + "embeded-img.html": [ + "7e9d713c0a79cb64d99cb2b27c32c60713453d59", + [ + null, + {} + ] + ], + "embeded-js.html": [ + "c3b027563d32e55ada6d45bfddc43afe0640e87a", + [ + null, + {} + ] + ], + "embeded-mp4.html": [ + "fde560e5be95dfb067cd54aa5bad303e59b32e6e", + [ + null, + {} + ] + ], + "embeded-not-found.html": [ + "0b56b5eadc536b131f386ab2724637d024e8f204", + [ + null, + {} + ] + ], + "embeded-type-only.html": [ + "90c9d3311c3096c646d628c75402106afeb54470", + [ + null, + {} + ] + ] + }, "image-maps": { "image-map-processing-model": { "hash-name-reference.html": [ @@ -471348,15 +471806,6 @@ {} ] ], - "selectmenu-shadow-root-replacement.tentative.html": [ - "b505e58ee2837b922616ee8d594c2c790fc185cd", - [ - null, - { - "testdriver": true - } - ] - ], "selectmenu-validity.tentative.html": [ "a58fe54ff6a28b33574996db863f7cbd20c31b8f", [ @@ -472366,11 +472815,12 @@ ] ], "popup-light-dismiss.tentative.html": [ - "a5401cd426b1380fd18e93511335cee21411260c", + "10317a8f35d6555f28305e54d92ff8c5f0bc68bc", [ null, { - "testdriver": true + "testdriver": true, + "timeout": "long" } ] ], @@ -474476,6 +474926,13 @@ {} ] ], + "delay-load-event.html": [ + "5ec6433e65b59c026209964002a8db47f3f97a94", + [ + null, + {} + ] + ], "dynamic-imports-credentials-setTimeout.sub.html": [ "189aa819fa53a5e701969429ff596863e7f0a84c", [ @@ -480422,7 +480879,7 @@ ] ], "document-synthetic-errorevent.html": [ - "8b1b3cfb5b2c33c07da64e02f3c160cce748e2f7", + "a541611909767a58300846613ecbc530b7f68bdd", [ null, {} @@ -485934,14 +486391,14 @@ }, "mrow": { "inferred-mrow-baseline.html": [ - "2b208aa8b026bbb30ecc1e5984853a2a06043fb9", + "cc007cf81ff823890a59ccec5c285f3b23853b4b", [ null, {} ] ], "inferred-mrow-stretchy.html": [ - "35c6d699ccb2dbced9e28e43885d38e778f23041", + "a1e409a248e9075e697a2a31208f40a009e66440", [ null, {} @@ -485983,7 +486440,7 @@ ] ], "spacing.html": [ - "bad3370ca5b8d57ecb102a6e746e08afefd312ec", + "c066f72cde22face93a56946bf6dffe9b2627ae5", [ null, {} @@ -486556,6 +487013,13 @@ {} ] ], + "table-cell-mrow-layout.html": [ + "1e76e3949a5bb1db505fd1c841d69431f5423281", + [ + null, + {} + ] + ], "table-default-styles-001.html": [ "495cdc000af5cecdc0892be59c0313c61c322d7f", [ @@ -486784,7 +487248,7 @@ ] ], "dynamic-childlist-002.html": [ - "e4b4313d6fc0e9138f4c36540537e03800002699", + "099401eaccc0524d514c6203f360d6c682d2b089", [ null, {} @@ -488487,8 +488951,8 @@ } }, "mediacapture-region": { - "MediaDevices-produceCropId.https.html": [ - "af8c659a5ba0d771f9ff46813e4cf50011580975", + "CropTarget-fromElement.https.html": [ + "fb0393bda536a79fdd272b1eb10e5597499defdb", [ null, {} @@ -495294,7 +495758,7 @@ ] ], "same-document-away-and-back-navigation-api.html": [ - "0ece14d4b7d3bc61fa5f6cffff6ea3297ce5edc5", + "220908e4c46cb91ad24408078ef1f7846b45e1b6", [ null, {} @@ -497514,8 +497978,42 @@ {} ] ], - "navigation-id.tentative.html": [ - "08dbd4b01b1359b8af3971e03cb33743e12d58fa", + "navigation-id-detached-frame.tentative.html": [ + "add11255af45c00a596f8e34e909a3304a92881b", + [ + null, + {} + ] + ], + "navigation-id-element-timing.tentative.html": [ + "bc52f208b0726421f1d36cdc6b737030c0760c1d", + [ + null, + { + "timeout": "long" + } + ] + ], + "navigation-id-long-task-task-attribution.tentative.html": [ + "662e17508b26dc671bf4ed25618a3b9ed9b0cac1", + [ + null, + { + "timeout": "long" + } + ] + ], + "navigation-id-mark-measure.tentative.html": [ + "42795f94a98cd07aee3c13dab7d33bbd2743848e", + [ + null, + { + "timeout": "long" + } + ] + ], + "navigation-id-resource-timing.tentative.html": [ + "1ec906ebbbba4a8118f746ac94c52aa399556f05", [ null, { @@ -500463,6 +500961,15 @@ {} ] ], + "link-header-modulepreload.html": [ + "fd759f6251f2073f9c0015f6b4df692951520ded", + [ + null, + { + "timeout": "long" + } + ] + ], "link-header-on-subresource.html": [ "418e8a63a7989794e6774ddca7e987bb594c7396", [ @@ -500694,7 +501201,7 @@ ] ], "subresource-integrity.html": [ - "0d88aba5223f8854022387b0ce867f4e420810f8", + "58f59126edb566e65dd25274b8d713dff449ba85", [ null, {} @@ -522730,7 +523237,7 @@ ] ], "restriction-notification.https.html": [ - "e9d3ba22a5908912302674ba7373a8aa3d1f623b", + "205d020ccb88fa0db498f80275384984e96e8783", [ null, { @@ -528217,14 +528724,14 @@ }, "subapps": { "add-error.tentative.https.html": [ - "b7d339a90c38ef12cf0ef8794a66027a97116448", + "1ae3d0d7affba720bc1546692b8ff7ed59f7d2d5", [ null, {} ] ], "add-success.tentative.https.html": [ - "2463d3c2fdf7b1b67e52a487186a8e8328df12a4", + "1f347fd222f05db55b89a4fa73c8f434ea3749c8", [ null, {} @@ -535718,6 +536225,15 @@ } ] ], + "page-and-offset-in-iframe.html": [ + "086c816956e8f33929e9e0c3249c9d0555a6e565", + [ + null, + { + "testdriver": true + } + ] + ], "resize-event-order.html": [ "41a13728bc3ff61cfc32bb02839eab5a11d1d33b", [ @@ -535728,7 +536244,7 @@ ] ], "scroll-event-order.html": [ - "5ab5e0747a67bbc82e3620da5cafd1813277245c", + "da5b77c0e26a3950dfd1e4d3018dbbbabeb67f9b", [ null, { @@ -566474,6 +566990,13 @@ {} ] ], + "SharedWorker-constructor.html": [ + "7909eb5369531243809ba47a4f4ae79e94032937", + [ + null, + {} + ] + ], "URLMismatchError.htm": [ "683d201ad3a0f7bbf8959d731ec20416c347909c", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative.html new file mode 100644 index 0000000..007d7a1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Animations: getComputedStyle().animationTimingFunction with linear(...)</title> +<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/6533"> +<meta name="assert" content="animation-timing-function: linear(...) parsing tests"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<div id="target"></div> +<script> +test_valid_value("animation-timing-function", "linear()"); +test_valid_value("animation-timing-function", "linear(0)"); +test_valid_value("animation-timing-function", "linear(0, 1)"); +test_valid_value("animation-timing-function", "linear(0 0% 100%)"); +test_valid_value("animation-timing-function", "linear(0% 100% 0)", "linear(0 0% 100%)"); +test_valid_value("animation-timing-function", "linear(0 0% 50%, 1 50% 100%)"); +test_valid_value("animation-timing-function", "linear(0, 0.5 25% 75%, 1 100% 100%)"); +test_valid_value("animation-timing-function", "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)"); + +test_invalid_value("animation-timing-function", "linear(100%)"); +test_invalid_value("animation-timing-function", "linear(0% 1 50%)"); + +test_computed_value("animation-timing-function", "linear()"); +test_computed_value("animation-timing-function", "linear(0)"); +test_computed_value("animation-timing-function", "linear(0, 1)"); +test_computed_value("animation-timing-function", "linear(0 0% 100%)"); +test_computed_value("animation-timing-function", "linear(0% 100% 0)", "linear(0 0% 100%)"); +test_computed_value("animation-timing-function", "linear(0 0% 50%, 1 50% 100%)"); +test_computed_value("animation-timing-function", "linear(0, 0.5 25% 75%, 1 100% 100%)"); +test_computed_value("animation-timing-function", "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/svg-with-transform.html b/third_party/blink/web_tests/external/wpt/css/css-break/svg-with-transform.html new file mode 100644 index 0000000..3aa7facf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/svg-with-transform.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1334213"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:2; gap:0; column-fill:auto; width:100px; height:100px; background:red;"> + <div style="height:100px; background:green;"></div> + <svg style="position:relative;"> + <rect transform="scale(2)" width="25" height="50" fill="green"/> + </svg> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-on-focus.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-on-focus.html new file mode 100644 index 0000000..b876399 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-on-focus.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<title>Scroll snap on Element.focus()</title> +<link rel="help" href="https://drafts.csswg.org/css-scroll-snap/" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +div { + position: absolute; + margin: 0; +} + +#scroller { + height: 500px; + width: 500px; + overflow-y: scroll; + scroll-snap-type: y mandatory; +} + +.snap { + width: 100%; + height: 300px; + top: 100px; + left: 0; + background-color: green; + scroll-snap-align: start none; +} + +.no-snap { + width: 100%; + height: 300px; + top: 100px; + left: 0; + background-color: red; +} + +.area { + width: 100%; + height: 2000px; +} +</style> + +<div id="scroller"> + <div class="area"></div> + <div class="snap" style="top: 0px;"></div> + <div class="no-snap" style="top: 1000px;" tabindex=-1></div> + <div class="snap" style="top: 1200px;"></div> +</div> + +<script> +test(t => { + document.querySelector(".no-snap").focus(); + assert_equals(scroller.scrollTop, 1200); +}, "scroll snap should happens on Element.focus()"); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html index 8b1b3cf..a5416119 100644 --- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html +++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html
@@ -21,10 +21,24 @@ const eventWatcher = new EventWatcher(t, document, "error"); const promise = eventWatcher.wait_for("error").then(e => { assert_equals(e.defaultPrevented, false); + assert_equals(e.message, ""); + assert_equals(e.filename, ""); + assert_equals(e.lineno, 0); + assert_equals(e.colno, 0); + assert_equals(e.error, undefined); }); document.dispatchEvent(new ErrorEvent("error", { cancelable: true })); return promise; }, "error event is normal (return true does not cancel; one arg) on Document, with a synthetic ErrorEvent"); + +test(() => { + const e = new ErrorEvent("error"); + assert_equals(e.message, ""); + assert_equals(e.filename, ""); + assert_equals(e.lineno, 0); + assert_equals(e.colno, 0); + assert_equals(e.error, undefined); +}, "Initial values of ErrorEvent members") </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-modulepreload.html b/third_party/blink/web_tests/external/wpt/preload/link-header-modulepreload.html new file mode 100644 index 0000000..fd759f6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/preload/link-header-modulepreload.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Makes sure that Link headers support modulepreload</title> +<meta name="timeout" content="long"> +<script src="/common/utils.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/preload/resources/preload_helper.js"></script> +<body> +<script> + promise_test(async t => { + const id = token(); + const moduleLink = getAbsoluteURL('./resources/module1.js'); + const params = new URLSearchParams(); + params.set('link', `<${moduleLink}>;rel=modulepreload`); + params.set('type', 'text/html'); + params.set('file', 'modulepreload-iframe.html') + const docURL = getAbsoluteURL(`./resources/echo-preload-header.py?${params.toString()}`); + const iframe = document.createElement('iframe'); + t.add_cleanup(() => iframe.remove()); + iframe.src = docURL; + const messageReceived = new Promise(resolve => window.addEventListener('message', m => { + resolve(m.data); + })) + document.body.appendChild(iframe); + const result = await messageReceived; + assert_equals(result, 1); + }, 'test that a header-preloaded module is loaded and consumed'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/resources/modulepreload-iframe.html b/third_party/blink/web_tests/external/wpt/preload/resources/modulepreload-iframe.html new file mode 100644 index 0000000..1d3d21f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/preload/resources/modulepreload-iframe.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<body> + <script> + const m = new URL('module1.js', location.href).toString(); + const observer = new PerformanceObserver(l => { + const entries = l.getEntriesByName(m); + if (entries.length === 1) { + import(m).then(() => { + observer.disconnect(); + const all = performance.getEntriesByName(m); + window.parent.postMessage(all.length, '*'); + }); + } + }); + + observer.observe({type: 'resource', buffered: true}); + + + </script> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html new file mode 100644 index 0000000..ec930a8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html class="test-wait"> +<meta charset="utf-8"> +<script type="module"> + const cache = await window.caches.open('cache_name_0') + await cache.add("") + const resp1 = await cache.match("") + const readStream = resp1.body + // Cloning will open the stream via NS_AsyncCopy in Gecko + resp1.clone() + // Give a little bit of time + await new Promise(setTimeout) + // At this point the previous open operation is about to finish but not yet. + // It will finish after the second open operation is made, potentially causing incorrect state. + await readStream.getReader().read(); + document.documentElement.classList.remove('test-wait') +</script>
diff --git a/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/SharedWorker-constructor.html b/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/SharedWorker-constructor.html new file mode 100644 index 0000000..7909eb5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/SharedWorker-constructor.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Test SharedWorker constructor functionality.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(() => { + assert_throws_js(Error, + function() { + new SharedWorker({toString:function(){throw new Error()}})}, + 'toString exception should be propagated'); +}, 'Test toString propagation exception.'); + +test(() => { + assert_throws_js(TypeError, + function() { new SharedWorker(); }, + 'invoking SharedWorker constructor without arguments should result ' + + 'in an exception.') +}, 'Test Sharedworker creation with no arguments'); + + +test(() => { + assert_throws_dom("SyntaxError", + function() { var Sharedworker = new SharedWorker('http://invalid:123$'); }, + 'Invoking SharedWorker constructor with invalid script URL should ' + + 'result in an exception.'); +}, 'Test invalid script URL.'); + +</script>
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html index c7ca3ac..7f4765d2 100644 --- a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html +++ b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html
@@ -12,24 +12,40 @@ <input type=month id=picker> <script> -promise_test(async () => { +const openPickerAndGetThumb = async () => { await openPicker(picker); - - async function rAF() { - return new Promise(resolve => internals.pagePopupWindow.requestAnimationFrame(resolve)); - } - const scrubby = internals.pagePopupWindow.global.picker.yearListView_.scrubbyScrollBar; const thumb = scrubby.element.querySelector('.scrubby-scroll-thumb'); const originalTop = thumb.style.top; const thumbOffset = cumulativeOffset(thumb); + return { thumb, thumbX: thumbOffset[0] + 1, thumbY: thumbOffset[1] + 1, originalTop }; +} - eventSender.mouseMoveTo(thumbOffset[0] + 1, thumbOffset[1] + 1); +promise_test(async () => { + const {thumb, thumbX, thumbY, originalTop} = await openPickerAndGetThumb(); + + eventSender.mouseMoveTo(thumbX, thumbY); eventSender.mouseDown(); - eventSender.mouseMoveTo(thumbOffset[0] + 1, thumbOffset[1] - 15); + eventSender.mouseMoveTo(thumbX, thumbY - 15); skipAnimation(); eventSender.mouseUp(); skipAnimation(); assert_equals(thumb.style.top, originalTop); }, `Verifies that the date picker's scrubby scrollbar returns to its initial state after being clicked and dragged.`); + +promise_test(async () => { + const {thumb, thumbX, thumbY, originalTop} = await openPickerAndGetThumb(); + + eventSender.clearTouchPoints(); + eventSender.addTouchPoint(thumbX, thumbY); + eventSender.touchStart(); + eventSender.updateTouchPoint(0, thumbX, thumbY - 15); + eventSender.touchMove(); + skipAnimation(); + eventSender.releaseTouchPoint(0); + eventSender.touchEnd(); + skipAnimation(); + assert_equals(thumb.style.top, originalTop); +}, `Verifies that the date picker's scrubby scrollbar returns to its initial state after being touched and dragged.`); + </script>
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative-expected.txt new file mode 100644 index 0000000..a3d961ad --- /dev/null +++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +FAIL e.style['animation-timing-function'] = "linear()" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0, 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0 0% 100%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0% 100% 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0 0% 50%, 1 50% 100%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0, 0.5 25% 75%, 1 100% 100%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['animation-timing-function'] = "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['animation-timing-function'] = "linear(100%)" should not set the property value +PASS e.style['animation-timing-function'] = "linear(0% 1 50%)" should not set the property value +FAIL Property animation-timing-function value 'linear()' assert_true: 'linear()' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0)' assert_true: 'linear(0)' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0, 1)' assert_true: 'linear(0, 1)' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0 0% 100%)' assert_true: 'linear(0 0% 100%)' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0% 100% 0)' assert_true: 'linear(0% 100% 0)' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0 0% 50%, 1 50% 100%)' assert_true: 'linear(0 0% 50%, 1 50% 100%)' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0, 0.5 25% 75%, 1 100% 100%)' assert_true: 'linear(0, 0.5 25% 75%, 1 100% 100%)' is a supported value for animation-timing-function. expected true got false +FAIL Property animation-timing-function value 'linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)' assert_true: 'linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)' is a supported value for animation-timing-function. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt index d50cca6b..093acf8 100644 --- a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt +++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL HTMLMediaElement.srcObject blob assert_unreached: TypeError: Failed to set the 'srcObject' property on 'HTMLMediaElement': Failed to convert value to 'MediaStream'. Reached unreachable code +FAIL HTMLMediaElement.srcObject blob assert_unreached: TypeError: Failed to set the 'srcObject' property on 'HTMLMediaElement': The provided value is not of type '(MediaSourceHandle or MediaStream)'. Reached unreachable code Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent-expected.txt new file mode 100644 index 0000000..5bfc1594 --- /dev/null +++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL error event is normal (return true does not cancel; one arg) on Document, with a synthetic ErrorEvent assert_equals: expected (undefined) undefined but got (object) null +FAIL Initial values of ErrorEvent members assert_equals: expected (undefined) undefined but got (object) null +Harness: the test ran to completion. +
diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn index 87ef3e6..2df7b35 100644 --- a/third_party/breakpad/BUILD.gn +++ b/third_party/breakpad/BUILD.gn
@@ -608,6 +608,9 @@ "breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.h", "breakpad/src/client/linux/minidump_writer/minidump_writer.cc", "breakpad/src/client/linux/minidump_writer/minidump_writer.h", + "breakpad/src/client/linux/minidump_writer/pe_file.cc", + "breakpad/src/client/linux/minidump_writer/pe_file.h", + "breakpad/src/client/linux/minidump_writer/pe_structs.h", "breakpad/src/client/linux/minidump_writer/proc_cpuinfo_reader.h", "breakpad/src/client/minidump_file_writer-inl.h", "breakpad/src/client/minidump_file_writer.cc", @@ -865,6 +868,8 @@ "breakpad/src/common/windows/pe_util.h", "breakpad/src/common/windows/string_utils-inl.h", "breakpad/src/common/windows/string_utils.cc", + "breakpad/src/common/windows/sym_upload_v2_protocol.cc", + "breakpad/src/common/windows/sym_upload_v2_protocol.h", "breakpad/src/common/windows/symbol_collector_client.cc", "breakpad/src/common/windows/symbol_collector_client.h", ]
diff --git a/third_party/lottie/BUILD.gn b/third_party/lottie/BUILD.gn index 6e2bb195..3a18ad7 100644 --- a/third_party/lottie/BUILD.gn +++ b/third_party/lottie/BUILD.gn
@@ -24,7 +24,7 @@ generate_grd("build_grdp") { grd_prefix = "lottie" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":minify" ] + public_deps = [ ":minify" ] input_files_base_dir = rebase_path(target_gen_dir, root_build_dir) input_files = [ "lottie_worker.min.js" ] resource_path_prefix = "lottie"
diff --git a/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js b/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js index 4f998c4..d8e8613 100644 --- a/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js +++ b/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js
@@ -1 +1 @@ -window.JSCompiler_renameProperty=function(prop,obj){return prop};let microtaskCurrHandle=0;let microtaskLastHandle=0;let microtaskCallbacks=[];let microtaskNodeContent=0;let microtaskNode=document.createTextNode("");new window.MutationObserver(microtaskFlush).observe(microtaskNode,{characterData:true});function microtaskFlush(){const len=microtaskCallbacks.length;for(let i=0;i<len;i++){let cb=microtaskCallbacks[i];if(cb){try{cb()}catch(e){setTimeout((()=>{throw e}))}}}microtaskCallbacks.splice(0,len);microtaskLastHandle+=len}const timeOut={after(delay){return{run(fn){return window.setTimeout(fn,delay)},cancel(handle){window.clearTimeout(handle)}}},run(fn,delay){return window.setTimeout(fn,delay)},cancel(handle){window.clearTimeout(handle)}};const animationFrame={run(fn){return window.requestAnimationFrame(fn)},cancel(handle){window.cancelAnimationFrame(handle)}};const idlePeriod={run(fn){return window.requestIdleCallback?window.requestIdleCallback(fn):window.setTimeout(fn,16)},cancel(handle){window.cancelIdleCallback?window.cancelIdleCallback(handle):window.clearTimeout(handle)}};const microTask={run(callback){microtaskNode.textContent=microtaskNodeContent++;microtaskCallbacks.push(callback);return microtaskCurrHandle++},cancel(handle){const idx=handle-microtaskLastHandle;if(idx>=0){if(!microtaskCallbacks[idx]){throw new Error("invalid async handle: "+handle)}microtaskCallbacks[idx]=null}}};let dedupeId$1=0;const dedupingMixin=function(mixin){let mixinApplications=mixin.__mixinApplications;if(!mixinApplications){mixinApplications=new WeakMap;mixin.__mixinApplications=mixinApplications}let mixinDedupeId=dedupeId$1++;function dedupingMixin(base){let baseSet=base.__mixinSet;if(baseSet&&baseSet[mixinDedupeId]){return base}let map=mixinApplications;let extended=map.get(base);if(!extended){extended=mixin(base);map.set(base,extended)}let mixinSet=Object.create(extended.__mixinSet||baseSet||null);mixinSet[mixinDedupeId]=true;extended.__mixinSet=mixinSet;return extended}return dedupingMixin};class Debouncer{constructor(){this._asyncModule=null;this._callback=null;this._timer=null}setConfig(asyncModule,callback){this._asyncModule=asyncModule;this._callback=callback;this._timer=this._asyncModule.run((()=>{this._timer=null;debouncerQueue.delete(this);this._callback()}))}cancel(){if(this.isActive()){this._cancelAsync();debouncerQueue.delete(this)}}_cancelAsync(){if(this.isActive()){this._asyncModule.cancel(this._timer);this._timer=null}}flush(){if(this.isActive()){this.cancel();this._callback()}}isActive(){return this._timer!=null}static debounce(debouncer,asyncModule,callback){if(debouncer instanceof Debouncer){debouncer._cancelAsync()}else{debouncer=new Debouncer}debouncer.setConfig(asyncModule,callback);return debouncer}}let debouncerQueue=new Set;const enqueueDebouncer=function(debouncer){debouncerQueue.add(debouncer)};const flushDebouncers=function(){const didFlush=Boolean(debouncerQueue.size);debouncerQueue.forEach((debouncer=>{try{debouncer.flush()}catch(e){setTimeout((()=>{throw e}))}}));return didFlush};let CSS_URL_RX=/(url\()([^)]*)(\))/g;let ABS_URL=/(^\/)|(^#)|(^[\w-\d]*:)/;let workingURL;let resolveDoc;function resolveUrl(url,baseURI){if(url&&ABS_URL.test(url)){return url}if(workingURL===undefined){workingURL=false;try{const u=new URL("b","http://a");u.pathname="c%20d";workingURL=u.href==="http://a/c%20d"}catch(e){}}if(!baseURI){baseURI=document.baseURI||window.location.href}if(workingURL){return new URL(url,baseURI).href}if(!resolveDoc){resolveDoc=document.implementation.createHTMLDocument("temp");resolveDoc.base=resolveDoc.createElement("base");resolveDoc.head.appendChild(resolveDoc.base);resolveDoc.anchor=resolveDoc.createElement("a");resolveDoc.body.appendChild(resolveDoc.anchor)}resolveDoc.base.href=baseURI;resolveDoc.anchor.href=url;return resolveDoc.anchor.href||url}function resolveCss(cssText,baseURI){return cssText.replace(CSS_URL_RX,(function(m,pre,url,post){return pre+"'"+resolveUrl(url.replace(/["']/g,""),baseURI)+"'"+post}))}function pathFromUrl(url){return url.substring(0,url.lastIndexOf("/")+1)}const useShadow=!window.ShadyDOM;Boolean(!window.ShadyCSS||window.ShadyCSS.nativeCss);let rootPath=pathFromUrl(document.baseURI||window.location.href);let sanitizeDOMValue=window.Polymer&&window.Polymer.sanitizeDOMValue||undefined;let passiveTouchGestures=false;let strictTemplatePolicy=false;const wrap=window["ShadyDOM"]&&window["ShadyDOM"]["noPatch"]&&window["ShadyDOM"]["wrap"]?window["ShadyDOM"]["wrap"]:n=>n;let HAS_NATIVE_TA=typeof document.head.style.touchAction==="string";let GESTURE_KEY="__polymerGestures";let HANDLED_OBJ="__polymerGesturesHandled";let TOUCH_ACTION="__polymerGesturesTouchAction";let TAP_DISTANCE=25;let TRACK_DISTANCE=5;let TRACK_LENGTH=2;let MOUSE_TIMEOUT=2500;let MOUSE_EVENTS=["mousedown","mousemove","mouseup","click"];let MOUSE_WHICH_TO_BUTTONS=[0,1,4,2];let MOUSE_HAS_BUTTONS=function(){try{return new MouseEvent("test",{buttons:1}).buttons===1}catch(e){return false}}();function isMouseEvent(name){return MOUSE_EVENTS.indexOf(name)>-1}let SUPPORTS_PASSIVE=false;(function(){try{let opts=Object.defineProperty({},"passive",{get(){SUPPORTS_PASSIVE=true}});window.addEventListener("test",null,opts);window.removeEventListener("test",null,opts)}catch(e){}})();function PASSIVE_TOUCH(eventName){if(isMouseEvent(eventName)||eventName==="touchend"){return}if(HAS_NATIVE_TA&&SUPPORTS_PASSIVE&&passiveTouchGestures){return{passive:true}}else{return}}let IS_TOUCH_ONLY=navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);const clickedLabels=[];const labellable={button:true,input:true,keygen:true,meter:true,output:true,textarea:true,progress:true,select:true};const canBeDisabled={button:true,command:true,fieldset:true,input:true,keygen:true,optgroup:true,option:true,select:true,textarea:true};function canBeLabelled(el){return labellable[el.localName]||false}function matchingLabels(el){let labels=Array.prototype.slice.call(el.labels||[]);if(!labels.length){labels=[];let root=el.getRootNode();if(el.id){let matching=root.querySelectorAll(`label[for = ${el.id}]`);for(let i=0;i<matching.length;i++){labels.push(matching[i])}}}return labels}let mouseCanceller=function(mouseEvent){let sc=mouseEvent.sourceCapabilities;if(sc&&!sc.firesTouchEvents){return}mouseEvent[HANDLED_OBJ]={skip:true};if(mouseEvent.type==="click"){let clickFromLabel=false;let path=getComposedPath(mouseEvent);for(let i=0;i<path.length;i++){if(path[i].nodeType===Node.ELEMENT_NODE){if(path[i].localName==="label"){clickedLabels.push(path[i])}else if(canBeLabelled(path[i])){let ownerLabels=matchingLabels(path[i]);for(let j=0;j<ownerLabels.length;j++){clickFromLabel=clickFromLabel||clickedLabels.indexOf(ownerLabels[j])>-1}}}if(path[i]===POINTERSTATE.mouse.target){return}}if(clickFromLabel){return}mouseEvent.preventDefault();mouseEvent.stopPropagation()}};function setupTeardownMouseCanceller(setup){let events=IS_TOUCH_ONLY?["click"]:MOUSE_EVENTS;for(let i=0,en;i<events.length;i++){en=events[i];if(setup){clickedLabels.length=0;document.addEventListener(en,mouseCanceller,true)}else{document.removeEventListener(en,mouseCanceller,true)}}}function ignoreMouse(e){if(!POINTERSTATE.mouse.mouseIgnoreJob){setupTeardownMouseCanceller(true)}let unset=function(){setupTeardownMouseCanceller();POINTERSTATE.mouse.target=null;POINTERSTATE.mouse.mouseIgnoreJob=null};POINTERSTATE.mouse.target=getComposedPath(e)[0];POINTERSTATE.mouse.mouseIgnoreJob=Debouncer.debounce(POINTERSTATE.mouse.mouseIgnoreJob,timeOut.after(MOUSE_TIMEOUT),unset)}function hasLeftMouseButton(ev){let type=ev.type;if(!isMouseEvent(type)){return false}if(type==="mousemove"){let buttons=ev.buttons===undefined?1:ev.buttons;if(ev instanceof window.MouseEvent&&!MOUSE_HAS_BUTTONS){buttons=MOUSE_WHICH_TO_BUTTONS[ev.which]||0}return Boolean(buttons&1)}else{let button=ev.button===undefined?0:ev.button;return button===0}}function isSyntheticClick(ev){if(ev.type==="click"){if(ev.detail===0){return true}let t=_findOriginalTarget(ev);if(!t.nodeType||t.nodeType!==Node.ELEMENT_NODE){return true}let bcr=t.getBoundingClientRect();let x=ev.pageX,y=ev.pageY;return!(x>=bcr.left&&x<=bcr.right&&(y>=bcr.top&&y<=bcr.bottom))}return false}let POINTERSTATE={mouse:{target:null,mouseIgnoreJob:null},touch:{x:0,y:0,id:-1,scrollDecided:false}};function firstTouchAction(ev){let ta="auto";let path=getComposedPath(ev);for(let i=0,n;i<path.length;i++){n=path[i];if(n[TOUCH_ACTION]){ta=n[TOUCH_ACTION];break}}return ta}function trackDocument(stateObj,movefn,upfn){stateObj.movefn=movefn;stateObj.upfn=upfn;document.addEventListener("mousemove",movefn);document.addEventListener("mouseup",upfn)}function untrackDocument(stateObj){document.removeEventListener("mousemove",stateObj.movefn);document.removeEventListener("mouseup",stateObj.upfn);stateObj.movefn=null;stateObj.upfn=null}document.addEventListener("touchend",ignoreMouse,SUPPORTS_PASSIVE?{passive:true}:false);const getComposedPath=window.ShadyDOM&&window.ShadyDOM.noPatch?window.ShadyDOM.composedPath:event=>event.composedPath&&event.composedPath()||[];const gestures={};const recognizers=[];function deepTargetFind(x,y){let node=document.elementFromPoint(x,y);let next=node;while(next&&next.shadowRoot&&!window.ShadyDOM){let oldNext=next;next=next.shadowRoot.elementFromPoint(x,y);if(oldNext===next){break}if(next){node=next}}return node}function _findOriginalTarget(ev){const path=getComposedPath(ev);return path.length>0?path[0]:ev.target}function _handleNative(ev){let handled;let type=ev.type;let node=ev.currentTarget;let gobj=node[GESTURE_KEY];if(!gobj){return}let gs=gobj[type];if(!gs){return}if(!ev[HANDLED_OBJ]){ev[HANDLED_OBJ]={};if(type.slice(0,5)==="touch"){ev=ev;let t=ev.changedTouches[0];if(type==="touchstart"){if(ev.touches.length===1){POINTERSTATE.touch.id=t.identifier}}if(POINTERSTATE.touch.id!==t.identifier){return}if(!HAS_NATIVE_TA){if(type==="touchstart"||type==="touchmove"){_handleTouchAction(ev)}}}}handled=ev[HANDLED_OBJ];if(handled.skip){return}for(let i=0,r;i<recognizers.length;i++){r=recognizers[i];if(gs[r.name]&&!handled[r.name]){if(r.flow&&r.flow.start.indexOf(ev.type)>-1&&r.reset){r.reset()}}}for(let i=0,r;i<recognizers.length;i++){r=recognizers[i];if(gs[r.name]&&!handled[r.name]){handled[r.name]=true;r[type](ev)}}}function _handleTouchAction(ev){let t=ev.changedTouches[0];let type=ev.type;if(type==="touchstart"){POINTERSTATE.touch.x=t.clientX;POINTERSTATE.touch.y=t.clientY;POINTERSTATE.touch.scrollDecided=false}else if(type==="touchmove"){if(POINTERSTATE.touch.scrollDecided){return}POINTERSTATE.touch.scrollDecided=true;let ta=firstTouchAction(ev);let shouldPrevent=false;let dx=Math.abs(POINTERSTATE.touch.x-t.clientX);let dy=Math.abs(POINTERSTATE.touch.y-t.clientY);if(!ev.cancelable);else if(ta==="none"){shouldPrevent=true}else if(ta==="pan-x"){shouldPrevent=dy>dx}else if(ta==="pan-y"){shouldPrevent=dx>dy}if(shouldPrevent){ev.preventDefault()}else{prevent("track")}}}function addListener(node,evType,handler){if(gestures[evType]){_add(node,evType,handler);return true}return false}function removeListener(node,evType,handler){if(gestures[evType]){_remove(node,evType,handler);return true}return false}function _add(node,evType,handler){let recognizer=gestures[evType];let deps=recognizer.deps;let name=recognizer.name;let gobj=node[GESTURE_KEY];if(!gobj){node[GESTURE_KEY]=gobj={}}for(let i=0,dep,gd;i<deps.length;i++){dep=deps[i];if(IS_TOUCH_ONLY&&isMouseEvent(dep)&&dep!=="click"){continue}gd=gobj[dep];if(!gd){gobj[dep]=gd={_count:0}}if(gd._count===0){node.addEventListener(dep,_handleNative,PASSIVE_TOUCH(dep))}gd[name]=(gd[name]||0)+1;gd._count=(gd._count||0)+1}node.addEventListener(evType,handler);if(recognizer.touchAction){setTouchAction(node,recognizer.touchAction)}}function _remove(node,evType,handler){let recognizer=gestures[evType];let deps=recognizer.deps;let name=recognizer.name;let gobj=node[GESTURE_KEY];if(gobj){for(let i=0,dep,gd;i<deps.length;i++){dep=deps[i];gd=gobj[dep];if(gd&&gd[name]){gd[name]=(gd[name]||1)-1;gd._count=(gd._count||1)-1;if(gd._count===0){node.removeEventListener(dep,_handleNative,PASSIVE_TOUCH(dep))}}}}node.removeEventListener(evType,handler)}function register$1(recog){recognizers.push(recog);for(let i=0;i<recog.emits.length;i++){gestures[recog.emits[i]]=recog}}function _findRecognizerByEvent(evName){for(let i=0,r;i<recognizers.length;i++){r=recognizers[i];for(let j=0,n;j<r.emits.length;j++){n=r.emits[j];if(n===evName){return r}}}return null}function setTouchAction(node,value){if(HAS_NATIVE_TA&&node instanceof HTMLElement){microTask.run((()=>{node.style.touchAction=value}))}node[TOUCH_ACTION]=value}function _fire(target,type,detail){let ev=new Event(type,{bubbles:true,cancelable:true,composed:true});ev.detail=detail;wrap(target).dispatchEvent(ev);if(ev.defaultPrevented){let preventer=detail.preventer||detail.sourceEvent;if(preventer&&preventer.preventDefault){preventer.preventDefault()}}}function prevent(evName){let recognizer=_findRecognizerByEvent(evName);if(recognizer.info){recognizer.info.prevent=true}}function resetMouseCanceller(){if(POINTERSTATE.mouse.mouseIgnoreJob){POINTERSTATE.mouse.mouseIgnoreJob.flush()}}register$1({name:"downup",deps:["mousedown","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["down","up"],info:{movefn:null,upfn:null},reset:function(){untrackDocument(this.info)},mousedown:function(e){if(!hasLeftMouseButton(e)){return}let t=_findOriginalTarget(e);let self=this;let movefn=function movefn(e){if(!hasLeftMouseButton(e)){downupFire("up",t,e);untrackDocument(self.info)}};let upfn=function upfn(e){if(hasLeftMouseButton(e)){downupFire("up",t,e)}untrackDocument(self.info)};trackDocument(this.info,movefn,upfn);downupFire("down",t,e)},touchstart:function(e){downupFire("down",_findOriginalTarget(e),e.changedTouches[0],e)},touchend:function(e){downupFire("up",_findOriginalTarget(e),e.changedTouches[0],e)}});function downupFire(type,target,event,preventer){if(!target){return}_fire(target,type,{x:event.clientX,y:event.clientY,sourceEvent:event,preventer:preventer,prevent:function(e){return prevent(e)}})}register$1({name:"track",touchAction:"none",deps:["mousedown","touchstart","touchmove","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["track"],info:{x:0,y:0,state:"start",started:false,moves:[],addMove:function(move){if(this.moves.length>TRACK_LENGTH){this.moves.shift()}this.moves.push(move)},movefn:null,upfn:null,prevent:false},reset:function(){this.info.state="start";this.info.started=false;this.info.moves=[];this.info.x=0;this.info.y=0;this.info.prevent=false;untrackDocument(this.info)},mousedown:function(e){if(!hasLeftMouseButton(e)){return}let t=_findOriginalTarget(e);let self=this;let movefn=function movefn(e){let x=e.clientX,y=e.clientY;if(trackHasMovedEnough(self.info,x,y)){self.info.state=self.info.started?e.type==="mouseup"?"end":"track":"start";if(self.info.state==="start"){prevent("tap")}self.info.addMove({x:x,y:y});if(!hasLeftMouseButton(e)){self.info.state="end";untrackDocument(self.info)}if(t){trackFire(self.info,t,e)}self.info.started=true}};let upfn=function upfn(e){if(self.info.started){movefn(e)}untrackDocument(self.info)};trackDocument(this.info,movefn,upfn);this.info.x=e.clientX;this.info.y=e.clientY},touchstart:function(e){let ct=e.changedTouches[0];this.info.x=ct.clientX;this.info.y=ct.clientY},touchmove:function(e){let t=_findOriginalTarget(e);let ct=e.changedTouches[0];let x=ct.clientX,y=ct.clientY;if(trackHasMovedEnough(this.info,x,y)){if(this.info.state==="start"){prevent("tap")}this.info.addMove({x:x,y:y});trackFire(this.info,t,ct);this.info.state="track";this.info.started=true}},touchend:function(e){let t=_findOriginalTarget(e);let ct=e.changedTouches[0];if(this.info.started){this.info.state="end";this.info.addMove({x:ct.clientX,y:ct.clientY});trackFire(this.info,t,ct)}}});function trackHasMovedEnough(info,x,y){if(info.prevent){return false}if(info.started){return true}let dx=Math.abs(info.x-x);let dy=Math.abs(info.y-y);return dx>=TRACK_DISTANCE||dy>=TRACK_DISTANCE}function trackFire(info,target,touch){if(!target){return}let secondlast=info.moves[info.moves.length-2];let lastmove=info.moves[info.moves.length-1];let dx=lastmove.x-info.x;let dy=lastmove.y-info.y;let ddx,ddy=0;if(secondlast){ddx=lastmove.x-secondlast.x;ddy=lastmove.y-secondlast.y}_fire(target,"track",{state:info.state,x:touch.clientX,y:touch.clientY,dx:dx,dy:dy,ddx:ddx,ddy:ddy,sourceEvent:touch,hover:function(){return deepTargetFind(touch.clientX,touch.clientY)}})}register$1({name:"tap",deps:["mousedown","click","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["click","touchend"]},emits:["tap"],info:{x:NaN,y:NaN,prevent:false},reset:function(){this.info.x=NaN;this.info.y=NaN;this.info.prevent=false},mousedown:function(e){if(hasLeftMouseButton(e)){this.info.x=e.clientX;this.info.y=e.clientY}},click:function(e){if(hasLeftMouseButton(e)){trackForward(this.info,e)}},touchstart:function(e){const touch=e.changedTouches[0];this.info.x=touch.clientX;this.info.y=touch.clientY},touchend:function(e){trackForward(this.info,e.changedTouches[0],e)}});function trackForward(info,e,preventer){let dx=Math.abs(e.clientX-info.x);let dy=Math.abs(e.clientY-info.y);let t=_findOriginalTarget(preventer||e);if(!t||canBeDisabled[t.localName]&&t.hasAttribute("disabled")){return}if(isNaN(dx)||isNaN(dy)||dx<=TAP_DISTANCE&&dy<=TAP_DISTANCE||isSyntheticClick(e)){if(!info.prevent){_fire(t,"tap",{x:e.clientX,y:e.clientY,sourceEvent:e,preventer:preventer})}}}const findOriginalTarget=_findOriginalTarget;const add=addListener;const remove=removeListener;var gestures$1=Object.freeze({__proto__:null,gestures:gestures,recognizers:recognizers,deepTargetFind:deepTargetFind,addListener:addListener,removeListener:removeListener,register:register$1,setTouchAction:setTouchAction,prevent:prevent,resetMouseCanceller:resetMouseCanceller,findOriginalTarget:findOriginalTarget,add:add,remove:remove});let modules={};let lcModules={};function setModule(id,module){modules[id]=lcModules[id.toLowerCase()]=module}function findModule(id){return modules[id]||lcModules[id.toLowerCase()]}function styleOutsideTemplateCheck(inst){if(inst.querySelector("style")){console.warn("dom-module %s has style outside template",inst.id)}}class DomModule extends HTMLElement{static get observedAttributes(){return["id"]}static import(id,selector){if(id){let m=findModule(id);if(m&&selector){return m.querySelector(selector)}return m}return null}attributeChangedCallback(name,old,value,namespace){if(old!==value){this.register()}}get assetpath(){if(!this.__assetpath){const owner=window.HTMLImports&&HTMLImports.importForElement?HTMLImports.importForElement(this)||document:this.ownerDocument;const url=resolveUrl(this.getAttribute("assetpath")||"",owner.baseURI);this.__assetpath=pathFromUrl(url)}return this.__assetpath}register(id){id=id||this.id;if(id){this.id=id;setModule(id,this);styleOutsideTemplateCheck(this)}}}DomModule.prototype["modules"]=modules;customElements.define("dom-module",DomModule);const MODULE_STYLE_LINK_SELECTOR="link[rel=import][type~=css]";const INCLUDE_ATTR="include";const SHADY_UNSCOPED_ATTR="shady-unscoped";function importModule(moduleId){return DomModule.import(moduleId)}function styleForImport(importDoc){let container=importDoc.body?importDoc.body:importDoc;const importCss=resolveCss(container.textContent,importDoc.baseURI);const style=document.createElement("style");style.textContent=importCss;return style}function stylesFromModules(moduleIds){const modules=moduleIds.trim().split(/\s+/);const styles=[];for(let i=0;i<modules.length;i++){styles.push(...stylesFromModule(modules[i]))}return styles}function stylesFromModule(moduleId){const m=importModule(moduleId);if(!m){console.warn("Could not find style data in module named",moduleId);return[]}if(m._styles===undefined){const styles=[];styles.push(..._stylesFromModuleImports(m));const template=m.querySelector("template");if(template){styles.push(...stylesFromTemplate(template,m.assetpath))}m._styles=styles}return m._styles}function stylesFromTemplate(template,baseURI){if(!template._styles){const styles=[];const e$=template.content.querySelectorAll("style");for(let i=0;i<e$.length;i++){let e=e$[i];let include=e.getAttribute(INCLUDE_ATTR);if(include){styles.push(...stylesFromModules(include).filter((function(item,index,self){return self.indexOf(item)===index})))}if(baseURI){e.textContent=resolveCss(e.textContent,baseURI)}styles.push(e)}template._styles=styles}return template._styles}function stylesFromModuleImports(moduleId){let m=importModule(moduleId);return m?_stylesFromModuleImports(m):[]}function _stylesFromModuleImports(module){const styles=[];const p$=module.querySelectorAll(MODULE_STYLE_LINK_SELECTOR);for(let i=0;i<p$.length;i++){let p=p$[i];if(p.import){const importDoc=p.import;const unscoped=p.hasAttribute(SHADY_UNSCOPED_ATTR);if(unscoped&&!importDoc._unscopedStyle){const style=styleForImport(importDoc);style.setAttribute(SHADY_UNSCOPED_ATTR,"");importDoc._unscopedStyle=style}else if(!importDoc._style){importDoc._style=styleForImport(importDoc)}styles.push(unscoped?importDoc._unscopedStyle:importDoc._style)}}return styles}function cssFromModules(moduleIds){let modules=moduleIds.trim().split(/\s+/);let cssText="";for(let i=0;i<modules.length;i++){cssText+=cssFromModule(modules[i])}return cssText}function cssFromModule(moduleId){let m=importModule(moduleId);if(m&&m._cssText===undefined){let cssText=_cssFromModuleImports(m);let t=m.querySelector("template");if(t){cssText+=cssFromTemplate(t,m.assetpath)}m._cssText=cssText||null}if(!m){console.warn("Could not find style data in module named",moduleId)}return m&&m._cssText||""}function cssFromTemplate(template,baseURI){let cssText="";const e$=stylesFromTemplate(template,baseURI);for(let i=0;i<e$.length;i++){let e=e$[i];if(e.parentNode){e.parentNode.removeChild(e)}cssText+=e.textContent}return cssText}function _cssFromModuleImports(module){let cssText="";let styles=_stylesFromModuleImports(module);for(let i=0;i<styles.length;i++){cssText+=styles[i].textContent}return cssText}function isPath(path){return path.indexOf(".")>=0}function root(path){let dotIndex=path.indexOf(".");if(dotIndex===-1){return path}return path.slice(0,dotIndex)}function isAncestor(base,path){return base.indexOf(path+".")===0}function isDescendant(base,path){return path.indexOf(base+".")===0}function translate(base,newBase,path){return newBase+path.slice(base.length)}function matches(base,path){return base===path||isAncestor(base,path)||isDescendant(base,path)}function normalize(path){if(Array.isArray(path)){let parts=[];for(let i=0;i<path.length;i++){let args=path[i].toString().split(".");for(let j=0;j<args.length;j++){parts.push(args[j])}}return parts.join(".")}else{return path}}function split(path){if(Array.isArray(path)){return normalize(path).split(".")}return path.toString().split(".")}function get(root,path,info){let prop=root;let parts=split(path);for(let i=0;i<parts.length;i++){if(!prop){return}let part=parts[i];prop=prop[part]}if(info){info.path=parts.join(".")}return prop}function set(root,path,value){let prop=root;let parts=split(path);let last=parts[parts.length-1];if(parts.length>1){for(let i=0;i<parts.length-1;i++){let part=parts[i];prop=prop[part];if(!prop){return}}prop[last]=value}else{prop[path]=value}return parts.join(".")}const caseMap={};const DASH_TO_CAMEL=/-[a-z]/g;const CAMEL_TO_DASH=/([A-Z])/g;function dashToCamelCase(dash){return caseMap[dash]||(caseMap[dash]=dash.indexOf("-")<0?dash:dash.replace(DASH_TO_CAMEL,(m=>m[1].toUpperCase())))}function camelToDashCase(camel){return caseMap[camel]||(caseMap[camel]=camel.replace(CAMEL_TO_DASH,"-$1").toLowerCase())}const microtask=microTask;const PropertiesChanged=dedupingMixin((superClass=>{class PropertiesChanged extends superClass{static createProperties(props){const proto=this.prototype;for(let prop in props){if(!(prop in proto)){proto._createPropertyAccessor(prop)}}}static attributeNameForProperty(property){return property.toLowerCase()}static typeForProperty(name){}_createPropertyAccessor(property,readOnly){this._addPropertyToAttributeMap(property);if(!this.hasOwnProperty("__dataHasAccessor")){this.__dataHasAccessor=Object.assign({},this.__dataHasAccessor)}if(!this.__dataHasAccessor[property]){this.__dataHasAccessor[property]=true;this._definePropertyAccessor(property,readOnly)}}_addPropertyToAttributeMap(property){if(!this.hasOwnProperty("__dataAttributes")){this.__dataAttributes=Object.assign({},this.__dataAttributes)}if(!this.__dataAttributes[property]){const attr=this.constructor.attributeNameForProperty(property);this.__dataAttributes[attr]=property}}_definePropertyAccessor(property,readOnly){Object.defineProperty(this,property,{get(){return this._getProperty(property)},set:readOnly?function(){}:function(value){this._setProperty(property,value)}})}constructor(){super();this.__dataEnabled=false;this.__dataReady=false;this.__dataInvalid=false;this.__data={};this.__dataPending=null;this.__dataOld=null;this.__dataInstanceProps=null;this.__serializing=false;this._initializeProperties()}ready(){this.__dataReady=true;this._flushProperties()}_initializeProperties(){for(let p in this.__dataHasAccessor){if(this.hasOwnProperty(p)){this.__dataInstanceProps=this.__dataInstanceProps||{};this.__dataInstanceProps[p]=this[p];delete this[p]}}}_initializeInstanceProperties(props){Object.assign(this,props)}_setProperty(property,value){if(this._setPendingProperty(property,value)){this._invalidateProperties()}}_getProperty(property){return this.__data[property]}_setPendingProperty(property,value,ext){let old=this.__data[property];let changed=this._shouldPropertyChange(property,value,old);if(changed){if(!this.__dataPending){this.__dataPending={};this.__dataOld={}}if(this.__dataOld&&!(property in this.__dataOld)){this.__dataOld[property]=old}this.__data[property]=value;this.__dataPending[property]=value}return changed}_invalidateProperties(){if(!this.__dataInvalid&&this.__dataReady){this.__dataInvalid=true;microtask.run((()=>{if(this.__dataInvalid){this.__dataInvalid=false;this._flushProperties()}}))}}_enableProperties(){if(!this.__dataEnabled){this.__dataEnabled=true;if(this.__dataInstanceProps){this._initializeInstanceProperties(this.__dataInstanceProps);this.__dataInstanceProps=null}this.ready()}}_flushProperties(){const props=this.__data;const changedProps=this.__dataPending;const old=this.__dataOld;if(this._shouldPropertiesChange(props,changedProps,old)){this.__dataPending=null;this.__dataOld=null;this._propertiesChanged(props,changedProps,old)}}_shouldPropertiesChange(currentProps,changedProps,oldProps){return Boolean(changedProps)}_propertiesChanged(currentProps,changedProps,oldProps){}_shouldPropertyChange(property,value,old){return old!==value&&(old===old||value===value)}attributeChangedCallback(name,old,value,namespace){if(old!==value){this._attributeToProperty(name,value)}if(super.attributeChangedCallback){super.attributeChangedCallback(name,old,value,namespace)}}_attributeToProperty(attribute,value,type){if(!this.__serializing){const map=this.__dataAttributes;const property=map&&map[attribute]||attribute;this[property]=this._deserializeValue(value,type||this.constructor.typeForProperty(property))}}_propertyToAttribute(property,attribute,value){this.__serializing=true;value=arguments.length<3?this[property]:value;this._valueToNodeAttribute(this,value,attribute||this.constructor.attributeNameForProperty(property));this.__serializing=false}_valueToNodeAttribute(node,value,attribute){const str=this._serializeValue(value);if(str===undefined){node.removeAttribute(attribute)}else{if(attribute==="class"||attribute==="name"||attribute==="slot"){node=wrap(node)}node.setAttribute(attribute,str)}}_serializeValue(value){switch(typeof value){case"boolean":return value?"":undefined;default:return value!=null?value.toString():undefined}}_deserializeValue(value,type){switch(type){case Boolean:return value!==null;case Number:return Number(value);default:return value}}}return PropertiesChanged}));const nativeProperties={};let proto=HTMLElement.prototype;while(proto){let props=Object.getOwnPropertyNames(proto);for(let i=0;i<props.length;i++){nativeProperties[props[i]]=true}proto=Object.getPrototypeOf(proto)}function saveAccessorValue(model,property){if(!nativeProperties[property]){let value=model[property];if(value!==undefined){if(model.__data){model._setPendingProperty(property,value)}else{if(!model.__dataProto){model.__dataProto={}}else if(!model.hasOwnProperty(JSCompiler_renameProperty("__dataProto",model))){model.__dataProto=Object.create(model.__dataProto)}model.__dataProto[property]=value}}}}const PropertyAccessors=dedupingMixin((superClass=>{const base=PropertiesChanged(superClass);class PropertyAccessors extends base{static createPropertiesForAttributes(){let a$=this.observedAttributes;for(let i=0;i<a$.length;i++){this.prototype._createPropertyAccessor(dashToCamelCase(a$[i]))}}static attributeNameForProperty(property){return camelToDashCase(property)}_initializeProperties(){if(this.__dataProto){this._initializeProtoProperties(this.__dataProto);this.__dataProto=null}super._initializeProperties()}_initializeProtoProperties(props){for(let p in props){this._setProperty(p,props[p])}}_ensureAttribute(attribute,value){const el=this;if(!el.hasAttribute(attribute)){this._valueToNodeAttribute(el,value,attribute)}}_serializeValue(value){switch(typeof value){case"object":if(value instanceof Date){return value.toString()}else if(value){try{return JSON.stringify(value)}catch(x){return""}}default:return super._serializeValue(value)}}_deserializeValue(value,type){let outValue;switch(type){case Object:try{outValue=JSON.parse(value)}catch(x){outValue=value}break;case Array:try{outValue=JSON.parse(value)}catch(x){outValue=null;console.warn(`Polymer::Attributes: couldn't decode Array as JSON: ${value}`)}break;case Date:outValue=isNaN(value)?String(value):Number(value);outValue=new Date(outValue);break;default:outValue=super._deserializeValue(value,type);break}return outValue}_definePropertyAccessor(property,readOnly){saveAccessorValue(this,property);super._definePropertyAccessor(property,readOnly)}_hasAccessor(property){return this.__dataHasAccessor&&this.__dataHasAccessor[property]}_isPropertyPending(prop){return Boolean(this.__dataPending&&prop in this.__dataPending)}}return PropertyAccessors}));const walker=document.createTreeWalker(document,NodeFilter.SHOW_ALL,null,false);const templateExtensions={"dom-if":true,"dom-repeat":true};function wrapTemplateExtension(node){let is=node.getAttribute("is");if(is&&templateExtensions[is]){let t=node;t.removeAttribute("is");node=t.ownerDocument.createElement(is);t.parentNode.replaceChild(node,t);node.appendChild(t);while(t.attributes.length){node.setAttribute(t.attributes[0].name,t.attributes[0].value);t.removeAttribute(t.attributes[0].name)}}return node}function findTemplateNode(root,nodeInfo){let parent=nodeInfo.parentInfo&&findTemplateNode(root,nodeInfo.parentInfo);if(parent){walker.currentNode=parent;for(let n=walker.firstChild(),i=0;n;n=walker.nextSibling()){if(nodeInfo.parentIndex===i++){return n}}}else{return root}}function applyIdToMap(inst,map,node,nodeInfo){if(nodeInfo.id){map[nodeInfo.id]=node}}function applyEventListener(inst,node,nodeInfo){if(nodeInfo.events&&nodeInfo.events.length){for(let j=0,e$=nodeInfo.events,e;j<e$.length&&(e=e$[j]);j++){inst._addMethodEventListenerToNode(node,e.name,e.value,inst)}}}function applyTemplateContent(inst,node,nodeInfo){if(nodeInfo.templateInfo){node._templateInfo=nodeInfo.templateInfo}}function createNodeEventHandler(context,eventName,methodName){context=context._methodHost||context;let handler=function(e){if(context[methodName]){context[methodName](e,e.detail)}else{console.warn("listener method `"+methodName+"` not defined")}};return handler}const TemplateStamp=dedupingMixin((superClass=>{class TemplateStamp extends superClass{static _parseTemplate(template,outerTemplateInfo){if(!template._templateInfo){let templateInfo=template._templateInfo={};templateInfo.nodeInfoList=[];templateInfo.stripWhiteSpace=true;this._parseTemplateContent(template,templateInfo,{parent:null})}return template._templateInfo}static _parseTemplateContent(template,templateInfo,nodeInfo){return this._parseTemplateNode(template.content,templateInfo,nodeInfo)}static _parseTemplateNode(node,templateInfo,nodeInfo){let noted;let element=node;if(element.localName=="template"&&!element.hasAttribute("preserve-content")){noted=this._parseTemplateNestedTemplate(element,templateInfo,nodeInfo)||noted}else if(element.localName==="slot"){templateInfo.hasInsertionPoint=true}walker.currentNode=element;if(walker.firstChild()){noted=this._parseTemplateChildNodes(element,templateInfo,nodeInfo)||noted}if(element.hasAttributes&&element.hasAttributes()){noted=this._parseTemplateNodeAttributes(element,templateInfo,nodeInfo)||noted}return noted}static _parseTemplateChildNodes(root,templateInfo,nodeInfo){if(root.localName==="script"||root.localName==="style"){return}walker.currentNode=root;for(let node=walker.firstChild(),parentIndex=0,next;node;node=next){if(node.localName=="template"){node=wrapTemplateExtension(node)}walker.currentNode=node;next=walker.nextSibling();if(node.nodeType===Node.TEXT_NODE){let n=next;while(n&&n.nodeType===Node.TEXT_NODE){node.textContent+=n.textContent;next=walker.nextSibling();root.removeChild(n);n=next}if(templateInfo.stripWhiteSpace&&!node.textContent.trim()){root.removeChild(node);continue}}let childInfo={parentIndex:parentIndex,parentInfo:nodeInfo};if(this._parseTemplateNode(node,templateInfo,childInfo)){childInfo.infoIndex=templateInfo.nodeInfoList.push(childInfo)-1}walker.currentNode=node;if(walker.parentNode()){parentIndex++}}}static _parseTemplateNestedTemplate(node,outerTemplateInfo,nodeInfo){let templateInfo=this._parseTemplate(node,outerTemplateInfo);let content=templateInfo.content=node.content.ownerDocument.createDocumentFragment();content.appendChild(node.content);nodeInfo.templateInfo=templateInfo;return true}static _parseTemplateNodeAttributes(node,templateInfo,nodeInfo){let noted=false;let attrs=Array.from(node.attributes);for(let i=attrs.length-1,a;a=attrs[i];i--){noted=this._parseTemplateNodeAttribute(node,templateInfo,nodeInfo,a.name,a.value)||noted}return noted}static _parseTemplateNodeAttribute(node,templateInfo,nodeInfo,name,value){if(name.slice(0,3)==="on-"){node.removeAttribute(name);nodeInfo.events=nodeInfo.events||[];nodeInfo.events.push({name:name.slice(3),value:value});return true}else if(name==="id"){nodeInfo.id=value;return true}return false}static _contentForTemplate(template){let templateInfo=template._templateInfo;return templateInfo&&templateInfo.content||template.content}_stampTemplate(template){if(template&&!template.content&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate){HTMLTemplateElement.decorate(template)}let templateInfo=this.constructor._parseTemplate(template);let nodeInfo=templateInfo.nodeInfoList;let content=templateInfo.content||template.content;let dom=document.importNode(content,true);dom.__noInsertionPoint=!templateInfo.hasInsertionPoint;let nodes=dom.nodeList=new Array(nodeInfo.length);dom.$={};for(let i=0,l=nodeInfo.length,info;i<l&&(info=nodeInfo[i]);i++){let node=nodes[i]=findTemplateNode(dom,info);applyIdToMap(this,dom.$,node,info);applyTemplateContent(this,node,info);applyEventListener(this,node,info)}dom=dom;return dom}_addMethodEventListenerToNode(node,eventName,methodName,context){context=context||node;let handler=createNodeEventHandler(context,eventName,methodName);this._addEventListenerToNode(node,eventName,handler);return handler}_addEventListenerToNode(node,eventName,handler){node.addEventListener(eventName,handler)}_removeEventListenerFromNode(node,eventName,handler){node.removeEventListener(eventName,handler)}}return TemplateStamp}));let dedupeId=0;const TYPES={COMPUTE:"__computeEffects",REFLECT:"__reflectEffects",NOTIFY:"__notifyEffects",PROPAGATE:"__propagateEffects",OBSERVE:"__observeEffects",READ_ONLY:"__readOnly"};const capitalAttributeRegex=/[A-Z]/;function ensureOwnEffectMap(model,type){let effects=model[type];if(!effects){effects=model[type]={}}else if(!model.hasOwnProperty(type)){effects=model[type]=Object.create(model[type]);for(let p in effects){let protoFx=effects[p];let instFx=effects[p]=Array(protoFx.length);for(let i=0;i<protoFx.length;i++){instFx[i]=protoFx[i]}}}return effects}function runEffects(inst,effects,props,oldProps,hasPaths,extraArgs){if(effects){let ran=false;let id=dedupeId++;for(let prop in props){if(runEffectsForProperty(inst,effects,id,prop,props,oldProps,hasPaths,extraArgs)){ran=true}}return ran}return false}function runEffectsForProperty(inst,effects,dedupeId,prop,props,oldProps,hasPaths,extraArgs){let ran=false;let rootProperty=hasPaths?root(prop):prop;let fxs=effects[rootProperty];if(fxs){for(let i=0,l=fxs.length,fx;i<l&&(fx=fxs[i]);i++){if((!fx.info||fx.info.lastRun!==dedupeId)&&(!hasPaths||pathMatchesTrigger(prop,fx.trigger))){if(fx.info){fx.info.lastRun=dedupeId}fx.fn(inst,prop,props,oldProps,fx.info,hasPaths,extraArgs);ran=true}}}return ran}function pathMatchesTrigger(path,trigger){if(trigger){let triggerPath=trigger.name;return triggerPath==path||!!(trigger.structured&&isAncestor(triggerPath,path))||!!(trigger.wildcard&&isDescendant(triggerPath,path))}else{return true}}function runObserverEffect(inst,property,props,oldProps,info){let fn=typeof info.method==="string"?inst[info.method]:info.method;let changedProp=info.property;if(fn){fn.call(inst,inst.__data[changedProp],oldProps[changedProp])}else if(!info.dynamicFn){console.warn("observer method `"+info.method+"` not defined")}}function runNotifyEffects(inst,notifyProps,props,oldProps,hasPaths){let fxs=inst[TYPES.NOTIFY];let notified;let id=dedupeId++;for(let prop in notifyProps){if(notifyProps[prop]){if(fxs&&runEffectsForProperty(inst,fxs,id,prop,props,oldProps,hasPaths)){notified=true}else if(hasPaths&¬ifyPath(inst,prop,props)){notified=true}}}let host;if(notified&&(host=inst.__dataHost)&&host._invalidateProperties){host._invalidateProperties()}}function notifyPath(inst,path,props){let rootProperty=root(path);if(rootProperty!==path){let eventName=camelToDashCase(rootProperty)+"-changed";dispatchNotifyEvent(inst,eventName,props[path],path);return true}return false}function dispatchNotifyEvent(inst,eventName,value,path){let detail={value:value,queueProperty:true};if(path){detail.path=path}wrap(inst).dispatchEvent(new CustomEvent(eventName,{detail:detail}))}function runNotifyEffect(inst,property,props,oldProps,info,hasPaths){let rootProperty=hasPaths?root(property):property;let path=rootProperty!=property?property:null;let value=path?get(inst,path):inst.__data[property];if(path&&value===undefined){value=props[property]}dispatchNotifyEvent(inst,info.eventName,value,path)}function handleNotification(event,inst,fromProp,toPath,negate){let value;let detail=event.detail;let fromPath=detail&&detail.path;if(fromPath){toPath=translate(fromProp,toPath,fromPath);value=detail&&detail.value}else{value=event.currentTarget[fromProp]}value=negate?!value:value;if(!inst[TYPES.READ_ONLY]||!inst[TYPES.READ_ONLY][toPath]){if(inst._setPendingPropertyOrPath(toPath,value,true,Boolean(fromPath))&&(!detail||!detail.queueProperty)){inst._invalidateProperties()}}}function runReflectEffect(inst,property,props,oldProps,info){let value=inst.__data[property];if(sanitizeDOMValue){value=sanitizeDOMValue(value,info.attrName,"attribute",inst)}inst._propertyToAttribute(property,info.attrName,value)}function runComputedEffects(inst,changedProps,oldProps,hasPaths){let computeEffects=inst[TYPES.COMPUTE];if(computeEffects){let inputProps=changedProps;while(runEffects(inst,computeEffects,inputProps,oldProps,hasPaths)){Object.assign(oldProps,inst.__dataOld);Object.assign(changedProps,inst.__dataPending);inputProps=inst.__dataPending;inst.__dataPending=null}}}function runComputedEffect(inst,property,props,oldProps,info){let result=runMethodEffect(inst,property,props,oldProps,info);let computedProp=info.methodInfo;if(inst.__dataHasAccessor&&inst.__dataHasAccessor[computedProp]){inst._setPendingProperty(computedProp,result,true)}else{inst[computedProp]=result}}function computeLinkedPaths(inst,path,value){let links=inst.__dataLinkedPaths;if(links){let link;for(let a in links){let b=links[a];if(isDescendant(a,path)){link=translate(a,b,path);inst._setPendingPropertyOrPath(link,value,true,true)}else if(isDescendant(b,path)){link=translate(b,a,path);inst._setPendingPropertyOrPath(link,value,true,true)}}}}function addBinding(constructor,templateInfo,nodeInfo,kind,target,parts,literal){nodeInfo.bindings=nodeInfo.bindings||[];let binding={kind:kind,target:target,parts:parts,literal:literal,isCompound:parts.length!==1};nodeInfo.bindings.push(binding);if(shouldAddListener(binding)){let{event:event,negate:negate}=binding.parts[0];binding.listenerEvent=event||camelToDashCase(target)+"-changed";binding.listenerNegate=negate}let index=templateInfo.nodeInfoList.length;for(let i=0;i<binding.parts.length;i++){let part=binding.parts[i];part.compoundIndex=i;addEffectForBindingPart(constructor,templateInfo,binding,part,index)}}function addEffectForBindingPart(constructor,templateInfo,binding,part,index){if(!part.literal){if(binding.kind==="attribute"&&binding.target[0]==="-"){console.warn("Cannot set attribute "+binding.target+' because "-" is not a valid attribute starting character')}else{let dependencies=part.dependencies;let info={index:index,binding:binding,part:part,evaluator:constructor};for(let j=0;j<dependencies.length;j++){let trigger=dependencies[j];if(typeof trigger=="string"){trigger=parseArg(trigger);trigger.wildcard=true}constructor._addTemplatePropertyEffect(templateInfo,trigger.rootProperty,{fn:runBindingEffect,info:info,trigger:trigger})}}}}function runBindingEffect(inst,path,props,oldProps,info,hasPaths,nodeList){let node=nodeList[info.index];let binding=info.binding;let part=info.part;if(hasPaths&&part.source&&path.length>part.source.length&&binding.kind=="property"&&!binding.isCompound&&node.__isPropertyEffectsClient&&node.__dataHasAccessor&&node.__dataHasAccessor[binding.target]){let value=props[path];path=translate(part.source,binding.target,path);if(node._setPendingPropertyOrPath(path,value,false,true)){inst._enqueueClient(node)}}else{let value=info.evaluator._evaluateBinding(inst,part,path,props,oldProps,hasPaths);applyBindingValue(inst,node,binding,part,value)}}function applyBindingValue(inst,node,binding,part,value){value=computeBindingValue(node,value,binding,part);if(sanitizeDOMValue){value=sanitizeDOMValue(value,binding.target,binding.kind,node)}if(binding.kind=="attribute"){inst._valueToNodeAttribute(node,value,binding.target)}else{let prop=binding.target;if(node.__isPropertyEffectsClient&&node.__dataHasAccessor&&node.__dataHasAccessor[prop]){if(!node[TYPES.READ_ONLY]||!node[TYPES.READ_ONLY][prop]){if(node._setPendingProperty(prop,value)){inst._enqueueClient(node)}}}else{inst._setUnmanagedPropertyToNode(node,prop,value)}}}function computeBindingValue(node,value,binding,part){if(binding.isCompound){let storage=node.__dataCompoundStorage[binding.target];storage[part.compoundIndex]=value;value=storage.join("")}if(binding.kind!=="attribute"){if(binding.target==="textContent"||binding.target==="value"&&(node.localName==="input"||node.localName==="textarea")){value=value==undefined?"":value}}return value}function shouldAddListener(binding){return Boolean(binding.target)&&binding.kind!="attribute"&&binding.kind!="text"&&!binding.isCompound&&binding.parts[0].mode==="{"}function setupBindings(inst,templateInfo){let{nodeList:nodeList,nodeInfoList:nodeInfoList}=templateInfo;if(nodeInfoList.length){for(let i=0;i<nodeInfoList.length;i++){let info=nodeInfoList[i];let node=nodeList[i];let bindings=info.bindings;if(bindings){for(let i=0;i<bindings.length;i++){let binding=bindings[i];setupCompoundStorage(node,binding);addNotifyListener(node,inst,binding)}}node.__dataHost=inst}}}function setupCompoundStorage(node,binding){if(binding.isCompound){let storage=node.__dataCompoundStorage||(node.__dataCompoundStorage={});let parts=binding.parts;let literals=new Array(parts.length);for(let j=0;j<parts.length;j++){literals[j]=parts[j].literal}let target=binding.target;storage[target]=literals;if(binding.literal&&binding.kind=="property"){node[target]=binding.literal}}}function addNotifyListener(node,inst,binding){if(binding.listenerEvent){let part=binding.parts[0];node.addEventListener(binding.listenerEvent,(function(e){handleNotification(e,inst,binding.target,part.source,part.negate)}))}}function createMethodEffect(model,sig,type,effectFn,methodInfo,dynamicFn){dynamicFn=sig.static||dynamicFn&&(typeof dynamicFn!=="object"||dynamicFn[sig.methodName]);let info={methodName:sig.methodName,args:sig.args,methodInfo:methodInfo,dynamicFn:dynamicFn};for(let i=0,arg;i<sig.args.length&&(arg=sig.args[i]);i++){if(!arg.literal){model._addPropertyEffect(arg.rootProperty,type,{fn:effectFn,info:info,trigger:arg})}}if(dynamicFn){model._addPropertyEffect(sig.methodName,type,{fn:effectFn,info:info})}}function runMethodEffect(inst,property,props,oldProps,info){let context=inst._methodHost||inst;let fn=context[info.methodName];if(fn){let args=inst._marshalArgs(info.args,property,props);return fn.apply(context,args)}else if(!info.dynamicFn){console.warn("method `"+info.methodName+"` not defined")}}const emptyArray=[];const IDENT="(?:"+"[a-zA-Z_$][\\w.:$\\-*]*"+")";const NUMBER="(?:"+"[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?"+")";const SQUOTE_STRING="(?:"+"'(?:[^'\\\\]|\\\\.)*'"+")";const DQUOTE_STRING="(?:"+'"(?:[^"\\\\]|\\\\.)*"'+")";const STRING="(?:"+SQUOTE_STRING+"|"+DQUOTE_STRING+")";const ARGUMENT="(?:("+IDENT+"|"+NUMBER+"|"+STRING+")\\s*"+")";const ARGUMENTS="(?:"+ARGUMENT+"(?:,\\s*"+ARGUMENT+")*"+")";const ARGUMENT_LIST="(?:"+"\\(\\s*"+"(?:"+ARGUMENTS+"?"+")"+"\\)\\s*"+")";const BINDING="("+IDENT+"\\s*"+ARGUMENT_LIST+"?"+")";const OPEN_BRACKET="(\\[\\[|{{)"+"\\s*";const CLOSE_BRACKET="(?:]]|}})";const NEGATE="(?:(!)\\s*)?";const EXPRESSION=OPEN_BRACKET+NEGATE+BINDING+CLOSE_BRACKET;const bindingRegex=new RegExp(EXPRESSION,"g");function literalFromParts(parts){let s="";for(let i=0;i<parts.length;i++){let literal=parts[i].literal;s+=literal||""}return s}function parseMethod(expression){let m=expression.match(/([^\s]+?)\(([\s\S]*)\)/);if(m){let methodName=m[1];let sig={methodName:methodName,static:true,args:emptyArray};if(m[2].trim()){let args=m[2].replace(/\\,/g,",").split(",");return parseArgs(args,sig)}else{return sig}}return null}function parseArgs(argList,sig){sig.args=argList.map((function(rawArg){let arg=parseArg(rawArg);if(!arg.literal){sig.static=false}return arg}),this);return sig}function parseArg(rawArg){let arg=rawArg.trim().replace(/,/g,",").replace(/\\(.)/g,"$1");let a={name:arg,value:"",literal:false};let fc=arg[0];if(fc==="-"){fc=arg[1]}if(fc>="0"&&fc<="9"){fc="#"}switch(fc){case"'":case'"':a.value=arg.slice(1,-1);a.literal=true;break;case"#":a.value=Number(arg);a.literal=true;break}if(!a.literal){a.rootProperty=root(arg);a.structured=isPath(arg);if(a.structured){a.wildcard=arg.slice(-2)==".*";if(a.wildcard){a.name=arg.slice(0,-2)}}}return a}function getArgValue(data,props,path){let value=get(data,path);if(value===undefined){value=props[path]}return value}function notifySplices(inst,array,path,splices){inst.notifyPath(path+".splices",{indexSplices:splices});inst.notifyPath(path+".length",array.length)}function notifySplice(inst,array,path,index,addedCount,removed){notifySplices(inst,array,path,[{index:index,addedCount:addedCount,removed:removed,object:array,type:"splice"}])}function upper(name){return name[0].toUpperCase()+name.substring(1)}const PropertyEffects=dedupingMixin((superClass=>{const propertyEffectsBase=TemplateStamp(PropertyAccessors(superClass));class PropertyEffects extends propertyEffectsBase{constructor(){super();this.__isPropertyEffectsClient=true;this.__dataCounter=0;this.__dataClientsReady;this.__dataPendingClients;this.__dataToNotify;this.__dataLinkedPaths;this.__dataHasPaths;this.__dataCompoundStorage;this.__dataHost;this.__dataTemp;this.__dataClientsInitialized;this.__data;this.__dataPending;this.__dataOld;this.__computeEffects;this.__reflectEffects;this.__notifyEffects;this.__propagateEffects;this.__observeEffects;this.__readOnly;this.__templateInfo}get PROPERTY_EFFECT_TYPES(){return TYPES}_initializeProperties(){super._initializeProperties();hostStack.registerHost(this);this.__dataClientsReady=false;this.__dataPendingClients=null;this.__dataToNotify=null;this.__dataLinkedPaths=null;this.__dataHasPaths=false;this.__dataCompoundStorage=this.__dataCompoundStorage||null;this.__dataHost=this.__dataHost||null;this.__dataTemp={};this.__dataClientsInitialized=false}_initializeProtoProperties(props){this.__data=Object.create(props);this.__dataPending=Object.create(props);this.__dataOld={}}_initializeInstanceProperties(props){let readOnly=this[TYPES.READ_ONLY];for(let prop in props){if(!readOnly||!readOnly[prop]){this.__dataPending=this.__dataPending||{};this.__dataOld=this.__dataOld||{};this.__data[prop]=this.__dataPending[prop]=props[prop]}}}_addPropertyEffect(property,type,effect){this._createPropertyAccessor(property,type==TYPES.READ_ONLY);let effects=ensureOwnEffectMap(this,type)[property];if(!effects){effects=this[type][property]=[]}effects.push(effect)}_removePropertyEffect(property,type,effect){let effects=ensureOwnEffectMap(this,type)[property];let idx=effects.indexOf(effect);if(idx>=0){effects.splice(idx,1)}}_hasPropertyEffect(property,type){let effects=this[type];return Boolean(effects&&effects[property])}_hasReadOnlyEffect(property){return this._hasPropertyEffect(property,TYPES.READ_ONLY)}_hasNotifyEffect(property){return this._hasPropertyEffect(property,TYPES.NOTIFY)}_hasReflectEffect(property){return this._hasPropertyEffect(property,TYPES.REFLECT)}_hasComputedEffect(property){return this._hasPropertyEffect(property,TYPES.COMPUTE)}_setPendingPropertyOrPath(path,value,shouldNotify,isPathNotification){if(isPathNotification||root(Array.isArray(path)?path[0]:path)!==path){if(!isPathNotification){let old=get(this,path);path=set(this,path,value);if(!path||!super._shouldPropertyChange(path,value,old)){return false}}this.__dataHasPaths=true;if(this._setPendingProperty(path,value,shouldNotify)){computeLinkedPaths(this,path,value);return true}}else{if(this.__dataHasAccessor&&this.__dataHasAccessor[path]){return this._setPendingProperty(path,value,shouldNotify)}else{this[path]=value}}return false}_setUnmanagedPropertyToNode(node,prop,value){if(value!==node[prop]||typeof value=="object"){node[prop]=value}}_setPendingProperty(property,value,shouldNotify){let propIsPath=this.__dataHasPaths&&isPath(property);let prevProps=propIsPath?this.__dataTemp:this.__data;if(this._shouldPropertyChange(property,value,prevProps[property])){if(!this.__dataPending){this.__dataPending={};this.__dataOld={}}if(!(property in this.__dataOld)){this.__dataOld[property]=this.__data[property]}if(propIsPath){this.__dataTemp[property]=value}else{this.__data[property]=value}this.__dataPending[property]=value;if(propIsPath||this[TYPES.NOTIFY]&&this[TYPES.NOTIFY][property]){this.__dataToNotify=this.__dataToNotify||{};this.__dataToNotify[property]=shouldNotify}return true}return false}_setProperty(property,value){if(this._setPendingProperty(property,value,true)){this._invalidateProperties()}}_invalidateProperties(){if(this.__dataReady){this._flushProperties()}}_enqueueClient(client){this.__dataPendingClients=this.__dataPendingClients||[];if(client!==this){this.__dataPendingClients.push(client)}}_flushProperties(){this.__dataCounter++;super._flushProperties();this.__dataCounter--}_flushClients(){if(!this.__dataClientsReady){this.__dataClientsReady=true;this._readyClients();this.__dataReady=true}else{this.__enableOrFlushClients()}}__enableOrFlushClients(){let clients=this.__dataPendingClients;if(clients){this.__dataPendingClients=null;for(let i=0;i<clients.length;i++){let client=clients[i];if(!client.__dataEnabled){client._enableProperties()}else if(client.__dataPending){client._flushProperties()}}}}_readyClients(){this.__enableOrFlushClients()}setProperties(props,setReadOnly){for(let path in props){if(setReadOnly||!this[TYPES.READ_ONLY]||!this[TYPES.READ_ONLY][path]){this._setPendingPropertyOrPath(path,props[path],true)}}this._invalidateProperties()}ready(){this._flushProperties();if(!this.__dataClientsReady){this._flushClients()}if(this.__dataPending){this._flushProperties()}}_propertiesChanged(currentProps,changedProps,oldProps){let hasPaths=this.__dataHasPaths;this.__dataHasPaths=false;runComputedEffects(this,changedProps,oldProps,hasPaths);let notifyProps=this.__dataToNotify;this.__dataToNotify=null;this._propagatePropertyChanges(changedProps,oldProps,hasPaths);this._flushClients();runEffects(this,this[TYPES.REFLECT],changedProps,oldProps,hasPaths);runEffects(this,this[TYPES.OBSERVE],changedProps,oldProps,hasPaths);if(notifyProps){runNotifyEffects(this,notifyProps,changedProps,oldProps,hasPaths)}if(this.__dataCounter==1){this.__dataTemp={}}}_propagatePropertyChanges(changedProps,oldProps,hasPaths){if(this[TYPES.PROPAGATE]){runEffects(this,this[TYPES.PROPAGATE],changedProps,oldProps,hasPaths)}let templateInfo=this.__templateInfo;while(templateInfo){runEffects(this,templateInfo.propertyEffects,changedProps,oldProps,hasPaths,templateInfo.nodeList);templateInfo=templateInfo.nextTemplateInfo}}linkPaths(to,from){to=normalize(to);from=normalize(from);this.__dataLinkedPaths=this.__dataLinkedPaths||{};this.__dataLinkedPaths[to]=from}unlinkPaths(path){path=normalize(path);if(this.__dataLinkedPaths){delete this.__dataLinkedPaths[path]}}notifySplices(path,splices){let info={path:""};let array=get(this,path,info);notifySplices(this,array,info.path,splices)}get(path,root){return get(root||this,path)}set(path,value,root){if(root){set(root,path,value)}else{if(!this[TYPES.READ_ONLY]||!this[TYPES.READ_ONLY][path]){if(this._setPendingPropertyOrPath(path,value,true)){this._invalidateProperties()}}}}push(path,...items){let info={path:""};let array=get(this,path,info);let len=array.length;let ret=array.push(...items);if(items.length){notifySplice(this,array,info.path,len,items.length,[])}return ret}pop(path){let info={path:""};let array=get(this,path,info);let hadLength=Boolean(array.length);let ret=array.pop();if(hadLength){notifySplice(this,array,info.path,array.length,0,[ret])}return ret}splice(path,start,deleteCount,...items){let info={path:""};let array=get(this,path,info);if(start<0){start=array.length-Math.floor(-start)}else if(start){start=Math.floor(start)}let ret;if(arguments.length===2){ret=array.splice(start)}else{ret=array.splice(start,deleteCount,...items)}if(items.length||ret.length){notifySplice(this,array,info.path,start,items.length,ret)}return ret}shift(path){let info={path:""};let array=get(this,path,info);let hadLength=Boolean(array.length);let ret=array.shift();if(hadLength){notifySplice(this,array,info.path,0,0,[ret])}return ret}unshift(path,...items){let info={path:""};let array=get(this,path,info);let ret=array.unshift(...items);if(items.length){notifySplice(this,array,info.path,0,items.length,[])}return ret}notifyPath(path,value){let propPath;if(arguments.length==1){let info={path:""};value=get(this,path,info);propPath=info.path}else if(Array.isArray(path)){propPath=normalize(path)}else{propPath=path}if(this._setPendingPropertyOrPath(propPath,value,true,true)){this._invalidateProperties()}}_createReadOnlyProperty(property,protectedSetter){this._addPropertyEffect(property,TYPES.READ_ONLY);if(protectedSetter){this["_set"+upper(property)]=function(value){this._setProperty(property,value)}}}_createPropertyObserver(property,method,dynamicFn){let info={property:property,method:method,dynamicFn:Boolean(dynamicFn)};this._addPropertyEffect(property,TYPES.OBSERVE,{fn:runObserverEffect,info:info,trigger:{name:property}});if(dynamicFn){this._addPropertyEffect(method,TYPES.OBSERVE,{fn:runObserverEffect,info:info,trigger:{name:method}})}}_createMethodObserver(expression,dynamicFn){let sig=parseMethod(expression);if(!sig){throw new Error("Malformed observer expression '"+expression+"'")}createMethodEffect(this,sig,TYPES.OBSERVE,runMethodEffect,null,dynamicFn)}_createNotifyingProperty(property){this._addPropertyEffect(property,TYPES.NOTIFY,{fn:runNotifyEffect,info:{eventName:camelToDashCase(property)+"-changed",property:property}})}_createReflectedProperty(property){let attr=this.constructor.attributeNameForProperty(property);if(attr[0]==="-"){console.warn("Property "+property+" cannot be reflected to attribute "+attr+' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.')}else{this._addPropertyEffect(property,TYPES.REFLECT,{fn:runReflectEffect,info:{attrName:attr}})}}_createComputedProperty(property,expression,dynamicFn){let sig=parseMethod(expression);if(!sig){throw new Error("Malformed computed expression '"+expression+"'")}createMethodEffect(this,sig,TYPES.COMPUTE,runComputedEffect,property,dynamicFn)}_marshalArgs(args,path,props){const data=this.__data;const values=[];for(let i=0,l=args.length;i<l;i++){let{name:name,structured:structured,wildcard:wildcard,value:value,literal:literal}=args[i];if(!literal){if(wildcard){const matches=isDescendant(name,path);const pathValue=getArgValue(data,props,matches?path:name);value={path:matches?path:name,value:pathValue,base:matches?get(data,name):pathValue}}else{value=structured?getArgValue(data,props,name):data[name]}}values[i]=value}return values}static addPropertyEffect(property,type,effect){this.prototype._addPropertyEffect(property,type,effect)}static createPropertyObserver(property,method,dynamicFn){this.prototype._createPropertyObserver(property,method,dynamicFn)}static createMethodObserver(expression,dynamicFn){this.prototype._createMethodObserver(expression,dynamicFn)}static createNotifyingProperty(property){this.prototype._createNotifyingProperty(property)}static createReadOnlyProperty(property,protectedSetter){this.prototype._createReadOnlyProperty(property,protectedSetter)}static createReflectedProperty(property){this.prototype._createReflectedProperty(property)}static createComputedProperty(property,expression,dynamicFn){this.prototype._createComputedProperty(property,expression,dynamicFn)}static bindTemplate(template){return this.prototype._bindTemplate(template)}_bindTemplate(template,instanceBinding){let templateInfo=this.constructor._parseTemplate(template);let wasPreBound=this.__templateInfo==templateInfo;if(!wasPreBound){for(let prop in templateInfo.propertyEffects){this._createPropertyAccessor(prop)}}if(instanceBinding){templateInfo=Object.create(templateInfo);templateInfo.wasPreBound=wasPreBound;if(!wasPreBound&&this.__templateInfo){let last=this.__templateInfoLast||this.__templateInfo;this.__templateInfoLast=last.nextTemplateInfo=templateInfo;templateInfo.previousTemplateInfo=last;return templateInfo}}return this.__templateInfo=templateInfo}static _addTemplatePropertyEffect(templateInfo,prop,effect){let hostProps=templateInfo.hostProps=templateInfo.hostProps||{};hostProps[prop]=true;let effects=templateInfo.propertyEffects=templateInfo.propertyEffects||{};let propEffects=effects[prop]=effects[prop]||[];propEffects.push(effect)}_stampTemplate(template){hostStack.beginHosting(this);let dom=super._stampTemplate(template);hostStack.endHosting(this);let templateInfo=this._bindTemplate(template,true);templateInfo.nodeList=dom.nodeList;if(!templateInfo.wasPreBound){let nodes=templateInfo.childNodes=[];for(let n=dom.firstChild;n;n=n.nextSibling){nodes.push(n)}}dom.templateInfo=templateInfo;setupBindings(this,templateInfo);if(this.__dataReady){runEffects(this,templateInfo.propertyEffects,this.__data,null,false,templateInfo.nodeList)}return dom}_removeBoundDom(dom){let templateInfo=dom.templateInfo;if(templateInfo.previousTemplateInfo){templateInfo.previousTemplateInfo.nextTemplateInfo=templateInfo.nextTemplateInfo}if(templateInfo.nextTemplateInfo){templateInfo.nextTemplateInfo.previousTemplateInfo=templateInfo.previousTemplateInfo}if(this.__templateInfoLast==templateInfo){this.__templateInfoLast=templateInfo.previousTemplateInfo}templateInfo.previousTemplateInfo=templateInfo.nextTemplateInfo=null;let nodes=templateInfo.childNodes;for(let i=0;i<nodes.length;i++){let node=nodes[i];node.parentNode.removeChild(node)}}static _parseTemplateNode(node,templateInfo,nodeInfo){let noted=super._parseTemplateNode(node,templateInfo,nodeInfo);if(node.nodeType===Node.TEXT_NODE){let parts=this._parseBindings(node.textContent,templateInfo);if(parts){node.textContent=literalFromParts(parts)||" ";addBinding(this,templateInfo,nodeInfo,"text","textContent",parts);noted=true}}return noted}static _parseTemplateNodeAttribute(node,templateInfo,nodeInfo,name,value){let parts=this._parseBindings(value,templateInfo);if(parts){let origName=name;let kind="property";if(capitalAttributeRegex.test(name)){kind="attribute"}else if(name[name.length-1]=="$"){name=name.slice(0,-1);kind="attribute"}let literal=literalFromParts(parts);if(literal&&kind=="attribute"){if(name=="class"&&node.hasAttribute("class")){literal+=" "+node.getAttribute(name)}node.setAttribute(name,literal)}if(node.localName==="input"&&origName==="value"){node.setAttribute(origName,"")}node.removeAttribute(origName);if(kind==="property"){name=dashToCamelCase(name)}addBinding(this,templateInfo,nodeInfo,kind,name,parts,literal);return true}else{return super._parseTemplateNodeAttribute(node,templateInfo,nodeInfo,name,value)}}static _parseTemplateNestedTemplate(node,templateInfo,nodeInfo){let noted=super._parseTemplateNestedTemplate(node,templateInfo,nodeInfo);let hostProps=nodeInfo.templateInfo.hostProps;let mode="{";for(let source in hostProps){let parts=[{mode:mode,source:source,dependencies:[source]}];addBinding(this,templateInfo,nodeInfo,"property","_host_"+source,parts)}return noted}static _parseBindings(text,templateInfo){let parts=[];let lastIndex=0;let m;while((m=bindingRegex.exec(text))!==null){if(m.index>lastIndex){parts.push({literal:text.slice(lastIndex,m.index)})}let mode=m[1][0];let negate=Boolean(m[2]);let source=m[3].trim();let customEvent=false,notifyEvent="",colon=-1;if(mode=="{"&&(colon=source.indexOf("::"))>0){notifyEvent=source.substring(colon+2);source=source.substring(0,colon);customEvent=true}let signature=parseMethod(source);let dependencies=[];if(signature){let{args:args,methodName:methodName}=signature;for(let i=0;i<args.length;i++){let arg=args[i];if(!arg.literal){dependencies.push(arg)}}let dynamicFns=templateInfo.dynamicFns;if(dynamicFns&&dynamicFns[methodName]||signature.static){dependencies.push(methodName);signature.dynamicFn=true}}else{dependencies.push(source)}parts.push({source:source,mode:mode,negate:negate,customEvent:customEvent,signature:signature,dependencies:dependencies,event:notifyEvent});lastIndex=bindingRegex.lastIndex}if(lastIndex&&lastIndex<text.length){let literal=text.substring(lastIndex);if(literal){parts.push({literal:literal})}}if(parts.length){return parts}else{return null}}static _evaluateBinding(inst,part,path,props,oldProps,hasPaths){let value;if(part.signature){value=runMethodEffect(inst,path,props,oldProps,part.signature)}else if(path!=part.source){value=get(inst,part.source)}else{if(hasPaths&&isPath(path)){value=get(inst,path)}else{value=inst.__data[path]}}if(part.negate){value=!value}return value}}return PropertyEffects}));class HostStack{constructor(){this.stack=[]}registerHost(inst){if(this.stack.length){let host=this.stack[this.stack.length-1];host._enqueueClient(inst)}}beginHosting(inst){this.stack.push(inst)}endHosting(inst){let stackLen=this.stack.length;if(stackLen&&this.stack[stackLen-1]==inst){this.stack.pop()}}}const hostStack=new HostStack;function register(prototype){}function normalizeProperties(props){const output={};for(let p in props){const o=props[p];output[p]=typeof o==="function"?{type:o}:o}return output}const PropertiesMixin=dedupingMixin((superClass=>{const base=PropertiesChanged(superClass);function superPropertiesClass(constructor){const superCtor=Object.getPrototypeOf(constructor);return superCtor.prototype instanceof PropertiesMixin?superCtor:null}function ownProperties(constructor){if(!constructor.hasOwnProperty(JSCompiler_renameProperty("__ownProperties",constructor))){let props=null;if(constructor.hasOwnProperty(JSCompiler_renameProperty("properties",constructor))){const properties=constructor.properties;if(properties){props=normalizeProperties(properties)}}constructor.__ownProperties=props}return constructor.__ownProperties}class PropertiesMixin extends base{static get observedAttributes(){if(!this.hasOwnProperty("__observedAttributes")){register(this.prototype);const props=this._properties;this.__observedAttributes=props?Object.keys(props).map((p=>this.attributeNameForProperty(p))):[]}return this.__observedAttributes}static finalize(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__finalized",this))){const superCtor=superPropertiesClass(this);if(superCtor){superCtor.finalize()}this.__finalized=true;this._finalizeClass()}}static _finalizeClass(){const props=ownProperties(this);if(props){this.createProperties(props)}}static get _properties(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__properties",this))){const superCtor=superPropertiesClass(this);this.__properties=Object.assign({},superCtor&&superCtor._properties,ownProperties(this))}return this.__properties}static typeForProperty(name){const info=this._properties[name];return info&&info.type}_initializeProperties(){this.constructor.finalize();super._initializeProperties()}connectedCallback(){if(super.connectedCallback){super.connectedCallback()}this._enableProperties()}disconnectedCallback(){if(super.disconnectedCallback){super.disconnectedCallback()}}}return PropertiesMixin}));const version="3.2.0";const builtCSS=window.ShadyCSS&&window.ShadyCSS["cssBuild"];const ElementMixin=dedupingMixin((base=>{const polymerElementBase=PropertiesMixin(PropertyEffects(base));function propertyDefaults(constructor){if(!constructor.hasOwnProperty(JSCompiler_renameProperty("__propertyDefaults",constructor))){constructor.__propertyDefaults=null;let props=constructor._properties;for(let p in props){let info=props[p];if("value"in info){constructor.__propertyDefaults=constructor.__propertyDefaults||{};constructor.__propertyDefaults[p]=info}}}return constructor.__propertyDefaults}function ownObservers(constructor){if(!constructor.hasOwnProperty(JSCompiler_renameProperty("__ownObservers",constructor))){constructor.__ownObservers=constructor.hasOwnProperty(JSCompiler_renameProperty("observers",constructor))?constructor.observers:null}return constructor.__ownObservers}function createPropertyFromConfig(proto,name,info,allProps){if(info.computed){info.readOnly=true}if(info.computed){if(proto._hasReadOnlyEffect(name)){console.warn(`Cannot redefine computed property '${name}'.`)}else{proto._createComputedProperty(name,info.computed,allProps)}}if(info.readOnly&&!proto._hasReadOnlyEffect(name)){proto._createReadOnlyProperty(name,!info.computed)}else if(info.readOnly===false&&proto._hasReadOnlyEffect(name)){console.warn(`Cannot make readOnly property '${name}' non-readOnly.`)}if(info.reflectToAttribute&&!proto._hasReflectEffect(name)){proto._createReflectedProperty(name)}else if(info.reflectToAttribute===false&&proto._hasReflectEffect(name)){console.warn(`Cannot make reflected property '${name}' non-reflected.`)}if(info.notify&&!proto._hasNotifyEffect(name)){proto._createNotifyingProperty(name)}else if(info.notify===false&&proto._hasNotifyEffect(name)){console.warn(`Cannot make notify property '${name}' non-notify.`)}if(info.observer){proto._createPropertyObserver(name,info.observer,allProps[info.observer])}proto._addPropertyToAttributeMap(name)}function processElementStyles(klass,template,is,baseURI){if(!builtCSS){const templateStyles=template.content.querySelectorAll("style");const stylesWithImports=stylesFromTemplate(template);const linkedStyles=stylesFromModuleImports(is);const firstTemplateChild=template.content.firstElementChild;for(let idx=0;idx<linkedStyles.length;idx++){let s=linkedStyles[idx];s.textContent=klass._processStyleText(s.textContent,baseURI);template.content.insertBefore(s,firstTemplateChild)}let templateStyleIndex=0;for(let i=0;i<stylesWithImports.length;i++){let s=stylesWithImports[i];let templateStyle=templateStyles[templateStyleIndex];if(templateStyle!==s){s=s.cloneNode(true);templateStyle.parentNode.insertBefore(s,templateStyle)}else{templateStyleIndex++}s.textContent=klass._processStyleText(s.textContent,baseURI)}}if(window.ShadyCSS){window.ShadyCSS.prepareTemplate(template,is)}}function getTemplateFromDomModule(is){let template=null;if(is&&!strictTemplatePolicy){template=DomModule.import(is,"template")}return template}class PolymerElement extends polymerElementBase{static get polymerElementVersion(){return version}static _finalizeClass(){super._finalizeClass();const observers=ownObservers(this);if(observers){this.createObservers(observers,this._properties)}this._prepareTemplate()}static _prepareTemplate(){let template=this.template;if(template){if(typeof template==="string"){console.error("template getter must return HTMLTemplateElement");template=null}else{template=template.cloneNode(true)}}this.prototype._template=template}static createProperties(props){for(let p in props){createPropertyFromConfig(this.prototype,p,props[p],props)}}static createObservers(observers,dynamicFns){const proto=this.prototype;for(let i=0;i<observers.length;i++){proto._createMethodObserver(observers[i],dynamicFns)}}static get template(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_template",this))){this._template=this.prototype.hasOwnProperty(JSCompiler_renameProperty("_template",this.prototype))?this.prototype._template:getTemplateFromDomModule(this.is)||Object.getPrototypeOf(this.prototype).constructor.template}return this._template}static set template(value){this._template=value}static get importPath(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_importPath",this))){const meta=this.importMeta;if(meta){this._importPath=pathFromUrl(meta.url)}else{const module=DomModule.import(this.is);this._importPath=module&&module.assetpath||Object.getPrototypeOf(this.prototype).constructor.importPath}}return this._importPath}constructor(){super();this._template;this._importPath;this.rootPath;this.importPath;this.root;this.$}_initializeProperties(){this.constructor.finalize();this.constructor._finalizeTemplate(this.localName);super._initializeProperties();this.rootPath=rootPath;this.importPath=this.constructor.importPath;let p$=propertyDefaults(this.constructor);if(!p$){return}for(let p in p$){let info=p$[p];if(!this.hasOwnProperty(p)){let value=typeof info.value=="function"?info.value.call(this):info.value;if(this._hasAccessor(p)){this._setPendingProperty(p,value,true)}else{this[p]=value}}}}static _processStyleText(cssText,baseURI){return resolveCss(cssText,baseURI)}static _finalizeTemplate(is){const template=this.prototype._template;if(template&&!template.__polymerFinalized){template.__polymerFinalized=true;const importPath=this.importPath;const baseURI=importPath?resolveUrl(importPath):"";processElementStyles(this,template,is,baseURI);this.prototype._bindTemplate(template)}}connectedCallback(){if(window.ShadyCSS&&this._template){window.ShadyCSS.styleElement(this)}super.connectedCallback()}ready(){if(this._template){this.root=this._stampTemplate(this._template);this.$=this.root.$}super.ready()}_readyClients(){if(this._template){this.root=this._attachDom(this.root)}super._readyClients()}_attachDom(dom){const n=wrap(this);if(n.attachShadow){if(dom){if(!n.shadowRoot){n.attachShadow({mode:"open"})}n.shadowRoot.appendChild(dom);return n.shadowRoot}return null}else{throw new Error("ShadowDOM not available. "+"PolymerElement can create dom as children instead of in "+"ShadowDOM by setting `this.root = this;` before `ready`.")}}updateStyles(properties){if(window.ShadyCSS){window.ShadyCSS.styleSubtree(this,properties)}}resolveUrl(url,base){if(!base&&this.importPath){base=resolveUrl(this.importPath)}return resolveUrl(url,base)}static _parseTemplateContent(template,templateInfo,nodeInfo){templateInfo.dynamicFns=templateInfo.dynamicFns||this._properties;return super._parseTemplateContent(template,templateInfo,nodeInfo)}static _addTemplatePropertyEffect(templateInfo,prop,effect){return super._addTemplatePropertyEffect(templateInfo,prop,effect)}}return PolymerElement}));class LiteralString{constructor(string){this.value=string.toString()}toString(){return this.value}}function literalValue(value){if(value instanceof LiteralString){return value.value}else{throw new Error(`non-literal value passed to Polymer's htmlLiteral function: ${value}`)}}function htmlValue(value){if(value instanceof HTMLTemplateElement){return value.innerHTML}else if(value instanceof LiteralString){return literalValue(value)}else{throw new Error(`non-template value passed to Polymer's html function: ${value}`)}}const html=function html(strings,...values){const template=document.createElement("template");template.innerHTML=values.reduce(((acc,v,idx)=>acc+htmlValue(v)+strings[idx+1]),strings[0]);return template};const PolymerElement=ElementMixin(HTMLElement);function mutablePropertyChange$1(inst,property,value,old,mutableData){let isObject;if(mutableData){isObject=typeof value==="object"&&value!==null;if(isObject){old=inst.__dataTemp[property]}}let shouldChange=old!==value&&(old===old||value===value);if(isObject&&shouldChange){inst.__dataTemp[property]=value}return shouldChange}const MutableData=dedupingMixin((superClass=>{class MutableData extends superClass{_shouldPropertyChange(property,value,old){return mutablePropertyChange$1(this,property,value,old,true)}}return MutableData}));const OptionalMutableData=dedupingMixin((superClass=>{class OptionalMutableData extends superClass{static get properties(){return{mutableData:Boolean}}_shouldPropertyChange(property,value,old){return mutablePropertyChange$1(this,property,value,old,this.mutableData)}}return OptionalMutableData}));MutableData._mutablePropertyChange=mutablePropertyChange$1;let newInstance=null;function HTMLTemplateElementExtension(){return newInstance}HTMLTemplateElementExtension.prototype=Object.create(HTMLTemplateElement.prototype,{constructor:{value:HTMLTemplateElementExtension,writable:true}});const DataTemplate=PropertyEffects(HTMLTemplateElementExtension);const MutableDataTemplate=MutableData(DataTemplate);function upgradeTemplate(template,constructor){newInstance=template;Object.setPrototypeOf(template,constructor.prototype);new constructor;newInstance=null}const templateInstanceBase=PropertyEffects(class{});class TemplateInstanceBase extends templateInstanceBase{constructor(props){super();this._configureProperties(props);this.root=this._stampTemplate(this.__dataHost);let children=this.children=[];for(let n=this.root.firstChild;n;n=n.nextSibling){children.push(n);n.__templatizeInstance=this}if(this.__templatizeOwner&&this.__templatizeOwner.__hideTemplateChildren__){this._showHideChildren(true)}let options=this.__templatizeOptions;if(props&&options.instanceProps||!options.instanceProps){this._enableProperties()}}_configureProperties(props){let options=this.__templatizeOptions;if(options.forwardHostProp){for(let hprop in this.__hostProps){this._setPendingProperty(hprop,this.__dataHost["_host_"+hprop])}}for(let iprop in props){this._setPendingProperty(iprop,props[iprop])}}forwardHostProp(prop,value){if(this._setPendingPropertyOrPath(prop,value,false,true)){this.__dataHost._enqueueClient(this)}}_addEventListenerToNode(node,eventName,handler){if(this._methodHost&&this.__templatizeOptions.parentModel){this._methodHost._addEventListenerToNode(node,eventName,(e=>{e.model=this;handler(e)}))}else{let templateHost=this.__dataHost.__dataHost;if(templateHost){templateHost._addEventListenerToNode(node,eventName,handler)}}}_showHideChildren(hide){let c=this.children;for(let i=0;i<c.length;i++){let n=c[i];if(Boolean(hide)!=Boolean(n.__hideTemplateChildren__)){if(n.nodeType===Node.TEXT_NODE){if(hide){n.__polymerTextContent__=n.textContent;n.textContent=""}else{n.textContent=n.__polymerTextContent__}}else if(n.localName==="slot"){if(hide){n.__polymerReplaced__=document.createComment("hidden-slot");wrap(wrap(n).parentNode).replaceChild(n.__polymerReplaced__,n)}else{const replace=n.__polymerReplaced__;if(replace){wrap(wrap(replace).parentNode).replaceChild(n,replace)}}}else if(n.style){if(hide){n.__polymerDisplay__=n.style.display;n.style.display="none"}else{n.style.display=n.__polymerDisplay__}}}n.__hideTemplateChildren__=hide;if(n._showHideChildren){n._showHideChildren(hide)}}}_setUnmanagedPropertyToNode(node,prop,value){if(node.__hideTemplateChildren__&&node.nodeType==Node.TEXT_NODE&&prop=="textContent"){node.__polymerTextContent__=value}else{super._setUnmanagedPropertyToNode(node,prop,value)}}get parentModel(){let model=this.__parentModel;if(!model){let options;model=this;do{model=model.__dataHost.__dataHost}while((options=model.__templatizeOptions)&&!options.parentModel);this.__parentModel=model}return model}dispatchEvent(event){return true}}TemplateInstanceBase.prototype.__dataHost;TemplateInstanceBase.prototype.__templatizeOptions;TemplateInstanceBase.prototype._methodHost;TemplateInstanceBase.prototype.__templatizeOwner;TemplateInstanceBase.prototype.__hostProps;const MutableTemplateInstanceBase=MutableData(TemplateInstanceBase);function findMethodHost(template){let templateHost=template.__dataHost;return templateHost&&templateHost._methodHost||templateHost}function createTemplatizerClass(template,templateInfo,options){let templatizerBase=options.mutableData?MutableTemplateInstanceBase:TemplateInstanceBase;if(templatize.mixin){templatizerBase=templatize.mixin(templatizerBase)}let klass=class extends templatizerBase{};klass.prototype.__templatizeOptions=options;klass.prototype._bindTemplate(template);addNotifyEffects(klass,template,templateInfo,options);return klass}function addPropagateEffects(template,templateInfo,options){let userForwardHostProp=options.forwardHostProp;if(userForwardHostProp){let klass=templateInfo.templatizeTemplateClass;if(!klass){let templatizedBase=options.mutableData?MutableDataTemplate:DataTemplate;klass=templateInfo.templatizeTemplateClass=class TemplatizedTemplate extends templatizedBase{};let hostProps=templateInfo.hostProps;for(let prop in hostProps){klass.prototype._addPropertyEffect("_host_"+prop,klass.prototype.PROPERTY_EFFECT_TYPES.PROPAGATE,{fn:createForwardHostPropEffect(prop,userForwardHostProp)});klass.prototype._createNotifyingProperty("_host_"+prop)}}upgradeTemplate(template,klass);if(template.__dataProto){Object.assign(template.__data,template.__dataProto)}template.__dataTemp={};template.__dataPending=null;template.__dataOld=null;template._enableProperties()}}function createForwardHostPropEffect(hostProp,userForwardHostProp){return function forwardHostProp(template,prop,props){userForwardHostProp.call(template.__templatizeOwner,prop.substring("_host_".length),props[prop])}}function addNotifyEffects(klass,template,templateInfo,options){let hostProps=templateInfo.hostProps||{};for(let iprop in options.instanceProps){delete hostProps[iprop];let userNotifyInstanceProp=options.notifyInstanceProp;if(userNotifyInstanceProp){klass.prototype._addPropertyEffect(iprop,klass.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:createNotifyInstancePropEffect(iprop,userNotifyInstanceProp)})}}if(options.forwardHostProp&&template.__dataHost){for(let hprop in hostProps){klass.prototype._addPropertyEffect(hprop,klass.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:createNotifyHostPropEffect()})}}}function createNotifyInstancePropEffect(instProp,userNotifyInstanceProp){return function notifyInstanceProp(inst,prop,props){userNotifyInstanceProp.call(inst.__templatizeOwner,inst,prop,props[prop])}}function createNotifyHostPropEffect(){return function notifyHostProp(inst,prop,props){inst.__dataHost._setPendingPropertyOrPath("_host_"+prop,props[prop],true,true)}}function templatize(template,owner,options){options=options||{};if(template.__templatizeOwner){throw new Error("A <template> can only be templatized once")}template.__templatizeOwner=owner;const ctor=owner?owner.constructor:TemplateInstanceBase;let templateInfo=ctor._parseTemplate(template);let baseClass=templateInfo.templatizeInstanceClass;if(!baseClass){baseClass=createTemplatizerClass(template,templateInfo,options);templateInfo.templatizeInstanceClass=baseClass}addPropagateEffects(template,templateInfo,options);let klass=class TemplateInstance extends baseClass{};klass.prototype._methodHost=findMethodHost(template);klass.prototype.__dataHost=template;klass.prototype.__templatizeOwner=owner;klass.prototype.__hostProps=templateInfo.hostProps;klass=klass;return klass}function modelForElement(template,node){let model;while(node){if(model=node.__templatizeInstance){if(model.__dataHost!=template){node=model.__dataHost}else{return model}}else{node=wrap(node).parentNode}}return null}const flush=function(){let shadyDOM,debouncers;do{shadyDOM=window.ShadyDOM&&ShadyDOM.flush();if(window.ShadyCSS&&window.ShadyCSS.ScopingShim){window.ShadyCSS.ScopingShim.flush()}debouncers=flushDebouncers()}while(shadyDOM||debouncers)};class DomIf extends PolymerElement{static get is(){return"dom-if"}static get template(){return null}static get properties(){return{if:{type:Boolean,observer:"__debounceRender"},restamp:{type:Boolean,observer:"__debounceRender"}}}constructor(){super();this.__renderDebouncer=null;this.__invalidProps=null;this.__instance=null;this._lastIf=false;this.__ctor=null;this.__hideTemplateChildren__=false}__debounceRender(){this.__renderDebouncer=Debouncer.debounce(this.__renderDebouncer,microTask,(()=>this.__render()));enqueueDebouncer(this.__renderDebouncer)}disconnectedCallback(){super.disconnectedCallback();const parent=wrap(this).parentNode;if(!parent||parent.nodeType==Node.DOCUMENT_FRAGMENT_NODE&&!wrap(parent).host){this.__teardownInstance()}}connectedCallback(){super.connectedCallback();this.style.display="none";if(this.if){this.__debounceRender()}}render(){flush()}__render(){if(this.if){if(!this.__ensureInstance()){return}this._showHideChildren()}else if(this.restamp){this.__teardownInstance()}if(!this.restamp&&this.__instance){this._showHideChildren()}if(this.if!=this._lastIf){this.dispatchEvent(new CustomEvent("dom-change",{bubbles:true,composed:true}));this._lastIf=this.if}}__ensureInstance(){let parentNode=wrap(this).parentNode;if(parentNode){if(!this.__ctor){let template=wrap(this).querySelector("template");if(!template){let observer=new MutationObserver((()=>{if(wrap(this).querySelector("template")){observer.disconnect();this.__render()}else{throw new Error("dom-if requires a <template> child")}}));observer.observe(this,{childList:true});return false}this.__ctor=templatize(template,this,{mutableData:true,forwardHostProp:function(prop,value){if(this.__instance){if(this.if){this.__instance.forwardHostProp(prop,value)}else{this.__invalidProps=this.__invalidProps||Object.create(null);this.__invalidProps[root(prop)]=true}}}})}if(!this.__instance){this.__instance=new this.__ctor;wrap(parentNode).insertBefore(this.__instance.root,this)}else{this.__syncHostProperties();let c$=this.__instance.children;if(c$&&c$.length){let lastChild=wrap(this).previousSibling;if(lastChild!==c$[c$.length-1]){for(let i=0,n;i<c$.length&&(n=c$[i]);i++){wrap(parentNode).insertBefore(n,this)}}}}}return true}__syncHostProperties(){let props=this.__invalidProps;if(props){for(let prop in props){this.__instance._setPendingProperty(prop,this.__dataHost[prop])}this.__invalidProps=null;this.__instance._flushProperties()}}__teardownInstance(){if(this.__instance){let c$=this.__instance.children;if(c$&&c$.length){let parent=wrap(c$[0]).parentNode;if(parent){parent=wrap(parent);for(let i=0,n;i<c$.length&&(n=c$[i]);i++){parent.removeChild(n)}}}this.__instance=null;this.__invalidProps=null}}_showHideChildren(){let hidden=this.__hideTemplateChildren__||!this.if;if(this.__instance){this.__instance._showHideChildren(hidden)}}}customElements.define(DomIf.is,DomIf);const domRepeatBase=OptionalMutableData(PolymerElement);class DomRepeat extends domRepeatBase{static get is(){return"dom-repeat"}static get template(){return null}static get properties(){return{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},itemsIndexAs:{type:String,value:"itemsIndex"},sort:{type:Function,observer:"__sortChanged"},filter:{type:Function,observer:"__filterChanged"},observe:{type:String,observer:"__observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:true,readOnly:true},initialCount:{type:Number,observer:"__initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"__computeFrameTime(targetFramerate)"}}}static get observers(){return["__itemsChanged(items.*)"]}constructor(){super();this.__instances=[];this.__limit=Infinity;this.__pool=[];this.__renderDebouncer=null;this.__itemsIdxToInstIdx={};this.__chunkCount=null;this.__lastChunkTime=null;this.__sortFn=null;this.__filterFn=null;this.__observePaths=null;this.__ctor=null;this.__isDetached=true;this.template=null}disconnectedCallback(){super.disconnectedCallback();this.__isDetached=true;for(let i=0;i<this.__instances.length;i++){this.__detachInstance(i)}}connectedCallback(){super.connectedCallback();this.style.display="none";if(this.__isDetached){this.__isDetached=false;let wrappedParent=wrap(wrap(this).parentNode);for(let i=0;i<this.__instances.length;i++){this.__attachInstance(i,wrappedParent)}}}__ensureTemplatized(){if(!this.__ctor){let template=this.template=this.querySelector("template");if(!template){let observer=new MutationObserver((()=>{if(this.querySelector("template")){observer.disconnect();this.__render()}else{throw new Error("dom-repeat requires a <template> child")}}));observer.observe(this,{childList:true});return false}let instanceProps={};instanceProps[this.as]=true;instanceProps[this.indexAs]=true;instanceProps[this.itemsIndexAs]=true;this.__ctor=templatize(template,this,{mutableData:this.mutableData,parentModel:true,instanceProps:instanceProps,forwardHostProp:function(prop,value){let i$=this.__instances;for(let i=0,inst;i<i$.length&&(inst=i$[i]);i++){inst.forwardHostProp(prop,value)}},notifyInstanceProp:function(inst,prop,value){if(matches(this.as,prop)){let idx=inst[this.itemsIndexAs];if(prop==this.as){this.items[idx]=value}let path=translate(this.as,`${JSCompiler_renameProperty("items",this)}.${idx}`,prop);this.notifyPath(path,value)}}})}return true}__getMethodHost(){return this.__dataHost._methodHost||this.__dataHost}__functionFromPropertyValue(functionOrMethodName){if(typeof functionOrMethodName==="string"){let methodName=functionOrMethodName;let obj=this.__getMethodHost();return function(){return obj[methodName].apply(obj,arguments)}}return functionOrMethodName}__sortChanged(sort){this.__sortFn=this.__functionFromPropertyValue(sort);if(this.items){this.__debounceRender(this.__render)}}__filterChanged(filter){this.__filterFn=this.__functionFromPropertyValue(filter);if(this.items){this.__debounceRender(this.__render)}}__computeFrameTime(rate){return Math.ceil(1e3/rate)}__initializeChunking(){if(this.initialCount){this.__limit=this.initialCount;this.__chunkCount=this.initialCount;this.__lastChunkTime=performance.now()}}__tryRenderChunk(){if(this.items&&this.__limit<this.items.length){this.__debounceRender(this.__requestRenderChunk)}}__requestRenderChunk(){requestAnimationFrame((()=>this.__renderChunk()))}__renderChunk(){let currChunkTime=performance.now();let ratio=this._targetFrameTime/(currChunkTime-this.__lastChunkTime);this.__chunkCount=Math.round(this.__chunkCount*ratio)||1;this.__limit+=this.__chunkCount;this.__lastChunkTime=currChunkTime;this.__debounceRender(this.__render)}__observeChanged(){this.__observePaths=this.observe&&this.observe.replace(".*",".").split(" ")}__itemsChanged(change){if(this.items&&!Array.isArray(this.items)){console.warn("dom-repeat expected array for `items`, found",this.items)}if(!this.__handleItemPath(change.path,change.value)){this.__initializeChunking();this.__debounceRender(this.__render)}}__handleObservedPaths(path){if(this.__sortFn||this.__filterFn){if(!path){this.__debounceRender(this.__render,this.delay)}else if(this.__observePaths){let paths=this.__observePaths;for(let i=0;i<paths.length;i++){if(path.indexOf(paths[i])===0){this.__debounceRender(this.__render,this.delay)}}}}}__debounceRender(fn,delay=0){this.__renderDebouncer=Debouncer.debounce(this.__renderDebouncer,delay>0?timeOut.after(delay):microTask,fn.bind(this));enqueueDebouncer(this.__renderDebouncer)}render(){this.__debounceRender(this.__render);flush()}__render(){if(!this.__ensureTemplatized()){return}this.__applyFullRefresh();this.__pool.length=0;this._setRenderedItemCount(this.__instances.length);this.dispatchEvent(new CustomEvent("dom-change",{bubbles:true,composed:true}));this.__tryRenderChunk()}__applyFullRefresh(){let items=this.items||[];let isntIdxToItemsIdx=new Array(items.length);for(let i=0;i<items.length;i++){isntIdxToItemsIdx[i]=i}if(this.__filterFn){isntIdxToItemsIdx=isntIdxToItemsIdx.filter(((i,idx,array)=>this.__filterFn(items[i],idx,array)))}if(this.__sortFn){isntIdxToItemsIdx.sort(((a,b)=>this.__sortFn(items[a],items[b])))}const itemsIdxToInstIdx=this.__itemsIdxToInstIdx={};let instIdx=0;const limit=Math.min(isntIdxToItemsIdx.length,this.__limit);for(;instIdx<limit;instIdx++){let inst=this.__instances[instIdx];let itemIdx=isntIdxToItemsIdx[instIdx];let item=items[itemIdx];itemsIdxToInstIdx[itemIdx]=instIdx;if(inst){inst._setPendingProperty(this.as,item);inst._setPendingProperty(this.indexAs,instIdx);inst._setPendingProperty(this.itemsIndexAs,itemIdx);inst._flushProperties()}else{this.__insertInstance(item,instIdx,itemIdx)}}for(let i=this.__instances.length-1;i>=instIdx;i--){this.__detachAndRemoveInstance(i)}}__detachInstance(idx){let inst=this.__instances[idx];const wrappedRoot=wrap(inst.root);for(let i=0;i<inst.children.length;i++){let el=inst.children[i];wrappedRoot.appendChild(el)}return inst}__attachInstance(idx,parent){let inst=this.__instances[idx];parent.insertBefore(inst.root,this)}__detachAndRemoveInstance(idx){let inst=this.__detachInstance(idx);if(inst){this.__pool.push(inst)}this.__instances.splice(idx,1)}__stampInstance(item,instIdx,itemIdx){let model={};model[this.as]=item;model[this.indexAs]=instIdx;model[this.itemsIndexAs]=itemIdx;return new this.__ctor(model)}__insertInstance(item,instIdx,itemIdx){let inst=this.__pool.pop();if(inst){inst._setPendingProperty(this.as,item);inst._setPendingProperty(this.indexAs,instIdx);inst._setPendingProperty(this.itemsIndexAs,itemIdx);inst._flushProperties()}else{inst=this.__stampInstance(item,instIdx,itemIdx)}let beforeRow=this.__instances[instIdx+1];let beforeNode=beforeRow?beforeRow.children[0]:this;wrap(wrap(this).parentNode).insertBefore(inst.root,beforeNode);this.__instances[instIdx]=inst;return inst}_showHideChildren(hidden){for(let i=0;i<this.__instances.length;i++){this.__instances[i]._showHideChildren(hidden)}}__handleItemPath(path,value){let itemsPath=path.slice(6);let dot=itemsPath.indexOf(".");let itemsIdx=dot<0?itemsPath:itemsPath.substring(0,dot);if(itemsIdx==parseInt(itemsIdx,10)){let itemSubPath=dot<0?"":itemsPath.substring(dot+1);this.__handleObservedPaths(itemSubPath);let instIdx=this.__itemsIdxToInstIdx[itemsIdx];let inst=this.__instances[instIdx];if(inst){let itemPath=this.as+(itemSubPath?"."+itemSubPath:"");inst._setPendingPropertyOrPath(itemPath,value,false,true);inst._flushProperties()}return true}}itemForElement(el){let instance=this.modelForElement(el);return instance&&instance[this.as]}indexForElement(el){let instance=this.modelForElement(el);return instance&&instance[this.indexAs]}modelForElement(el){return modelForElement(this.template,el)}}customElements.define(DomRepeat.is,DomRepeat);const nativeShadow=!(window["ShadyDOM"]&&window["ShadyDOM"]["inUse"]);let nativeCssVariables_;function calcCssVariables(settings){if(settings&&settings["shimcssproperties"]){nativeCssVariables_=false}else{nativeCssVariables_=nativeShadow||Boolean(!navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/)&&window.CSS&&CSS.supports&&CSS.supports("box-shadow","0 0 0 var(--foo)"))}}let cssBuild;if(window.ShadyCSS&&window.ShadyCSS.cssBuild!==undefined){cssBuild=window.ShadyCSS.cssBuild}const disableRuntime=Boolean(window.ShadyCSS&&window.ShadyCSS.disableRuntime);if(window.ShadyCSS&&window.ShadyCSS.nativeCss!==undefined){nativeCssVariables_=window.ShadyCSS.nativeCss}else if(window.ShadyCSS){calcCssVariables(window.ShadyCSS);window.ShadyCSS=undefined}else{calcCssVariables(window["WebComponents"]&&window["WebComponents"]["flags"])}const nativeCssVariables=nativeCssVariables_;class StyleNode{constructor(){this["start"]=0;this["end"]=0;this["previous"]=null;this["parent"]=null;this["rules"]=null;this["parsedCssText"]="";this["cssText"]="";this["atRule"]=false;this["type"]=0;this["keyframesName"]="";this["selector"]="";this["parsedSelector"]=""}}function parse(text){text=clean(text);return parseCss(lex(text),text)}function clean(cssText){return cssText.replace(RX.comments,"").replace(RX.port,"")}function lex(text){let root=new StyleNode;root["start"]=0;root["end"]=text.length;let n=root;for(let i=0,l=text.length;i<l;i++){if(text[i]===OPEN_BRACE){if(!n["rules"]){n["rules"]=[]}let p=n;let previous=p["rules"][p["rules"].length-1]||null;n=new StyleNode;n["start"]=i+1;n["parent"]=p;n["previous"]=previous;p["rules"].push(n)}else if(text[i]===CLOSE_BRACE){n["end"]=i+1;n=n["parent"]||root}}return root}function parseCss(node,text){let t=text.substring(node["start"],node["end"]-1);node["parsedCssText"]=node["cssText"]=t.trim();if(node["parent"]){let ss=node["previous"]?node["previous"]["end"]:node["parent"]["start"];t=text.substring(ss,node["start"]-1);t=_expandUnicodeEscapes(t);t=t.replace(RX.multipleSpaces," ");t=t.substring(t.lastIndexOf(";")+1);let s=node["parsedSelector"]=node["selector"]=t.trim();node["atRule"]=s.indexOf(AT_START)===0;if(node["atRule"]){if(s.indexOf(MEDIA_START)===0){node["type"]=types.MEDIA_RULE}else if(s.match(RX.keyframesRule)){node["type"]=types.KEYFRAMES_RULE;node["keyframesName"]=node["selector"].split(RX.multipleSpaces).pop()}}else{if(s.indexOf(VAR_START)===0){node["type"]=types.MIXIN_RULE}else{node["type"]=types.STYLE_RULE}}}let r$=node["rules"];if(r$){for(let i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){parseCss(r,text)}}return node}function _expandUnicodeEscapes(s){return s.replace(/\\([0-9a-f]{1,6})\s/gi,(function(){let code=arguments[1],repeat=6-code.length;while(repeat--){code="0"+code}return"\\"+code}))}function stringify(node,preserveProperties,text=""){let cssText="";if(node["cssText"]||node["rules"]){let r$=node["rules"];if(r$&&!_hasMixinRules(r$)){for(let i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){cssText=stringify(r,preserveProperties,cssText)}}else{cssText=preserveProperties?node["cssText"]:removeCustomProps(node["cssText"]);cssText=cssText.trim();if(cssText){cssText=" "+cssText+"\n"}}}if(cssText){if(node["selector"]){text+=node["selector"]+" "+OPEN_BRACE+"\n"}text+=cssText;if(node["selector"]){text+=CLOSE_BRACE+"\n\n"}}return text}function _hasMixinRules(rules){let r=rules[0];return Boolean(r)&&Boolean(r["selector"])&&r["selector"].indexOf(VAR_START)===0}function removeCustomProps(cssText){cssText=removeCustomPropAssignment(cssText);return removeCustomPropApply(cssText)}function removeCustomPropAssignment(cssText){return cssText.replace(RX.customProp,"").replace(RX.mixinProp,"")}function removeCustomPropApply(cssText){return cssText.replace(RX.mixinApply,"").replace(RX.varApply,"")}const types={STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1e3};const OPEN_BRACE="{";const CLOSE_BRACE="}";const RX={comments:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g};const VAR_START="--";const MEDIA_START="@media";const AT_START="@";const VAR_ASSIGN=/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};{])+)|\{([^}]*)\}(?:(?=[;\s}])|$))/gi;const MIXIN_MATCH=/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi;const MEDIA_MATCH=/@media\s(.*)/;const styleTextSet=new Set;const scopingAttribute="shady-unscoped";function processUnscopedStyle(style){const text=style.textContent;if(!styleTextSet.has(text)){styleTextSet.add(text);const newStyle=style.cloneNode(true);document.head.appendChild(newStyle)}}function isUnscopedStyle(style){return style.hasAttribute(scopingAttribute)}function toCssText(rules,callback){if(!rules){return""}if(typeof rules==="string"){rules=parse(rules)}if(callback){forEachRule(rules,callback)}return stringify(rules,nativeCssVariables)}function rulesForStyle(style){if(!style["__cssRules"]&&style.textContent){style["__cssRules"]=parse(style.textContent)}return style["__cssRules"]||null}function forEachRule(node,styleRuleCallback,keyframesRuleCallback,onlyActiveRules){if(!node){return}let skipRules=false;let type=node["type"];if(onlyActiveRules){if(type===types.MEDIA_RULE){let matchMedia=node["selector"].match(MEDIA_MATCH);if(matchMedia){if(!window.matchMedia(matchMedia[1]).matches){skipRules=true}}}}if(type===types.STYLE_RULE){styleRuleCallback(node)}else if(keyframesRuleCallback&&type===types.KEYFRAMES_RULE){keyframesRuleCallback(node)}else if(type===types.MIXIN_RULE){skipRules=true}let r$=node["rules"];if(r$&&!skipRules){for(let i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){forEachRule(r,styleRuleCallback,keyframesRuleCallback,onlyActiveRules)}}}function findMatchingParen(text,start){let level=0;for(let i=start,l=text.length;i<l;i++){if(text[i]==="("){level++}else if(text[i]===")"){if(--level===0){return i}}}return-1}function processVariableAndFallback(str,callback){let start=str.indexOf("var(");if(start===-1){return callback(str,"","","")}let end=findMatchingParen(str,start+3);let inner=str.substring(start+4,end);let prefix=str.substring(0,start);let suffix=processVariableAndFallback(str.substring(end+1),callback);let comma=inner.indexOf(",");if(comma===-1){return callback(prefix,inner.trim(),"",suffix)}let value=inner.substring(0,comma).trim();let fallback=inner.substring(comma+1).trim();return callback(prefix,value,fallback,suffix)}window["ShadyDOM"]&&window["ShadyDOM"]["wrap"]||(node=>node);function getIsExtends(element){let localName=element["localName"];let is="",typeExtension="";if(localName){if(localName.indexOf("-")>-1){is=localName}else{typeExtension=localName;is=element.getAttribute&&element.getAttribute("is")||""}}else{is=element.is;typeExtension=element.extends}return{is:is,typeExtension:typeExtension}}function gatherStyleText(element){const styleTextParts=[];const styles=element.querySelectorAll("style");for(let i=0;i<styles.length;i++){const style=styles[i];if(isUnscopedStyle(style)){if(!nativeShadow){processUnscopedStyle(style);style.parentNode.removeChild(style)}}else{styleTextParts.push(style.textContent);style.parentNode.removeChild(style)}}return styleTextParts.join("").trim()}const CSS_BUILD_ATTR="css-build";function getCssBuild(element){if(cssBuild!==undefined){return cssBuild}if(element.__cssBuild===undefined){const attrValue=element.getAttribute(CSS_BUILD_ATTR);if(attrValue){element.__cssBuild=attrValue}else{const buildComment=getBuildComment(element);if(buildComment!==""){removeBuildComment(element)}element.__cssBuild=buildComment}}return element.__cssBuild||""}function elementHasBuiltCss(element){return getCssBuild(element)!==""}function getBuildComment(element){const buildComment=element.localName==="template"?element.content.firstChild:element.firstChild;if(buildComment instanceof Comment){const commentParts=buildComment.textContent.trim().split(":");if(commentParts[0]===CSS_BUILD_ATTR){return commentParts[1]}}return""}function removeBuildComment(element){const buildComment=element.localName==="template"?element.content.firstChild:element.firstChild;buildComment.parentNode.removeChild(buildComment)}function updateNativeProperties(element,properties){for(let p in properties){if(p===null){element.style.removeProperty(p)}else{element.style.setProperty(p,properties[p])}}}function getComputedStyleValue(element,property){const value=window.getComputedStyle(element).getPropertyValue(property);if(!value){return""}else{return value.trim()}}function detectMixin(cssText){const has=MIXIN_MATCH.test(cssText)||VAR_ASSIGN.test(cssText);MIXIN_MATCH.lastIndex=0;VAR_ASSIGN.lastIndex=0;return has}const APPLY_NAME_CLEAN=/;\s*/m;const INITIAL_INHERIT=/^\s*(initial)|(inherit)\s*$/;const IMPORTANT=/\s*!important/;const MIXIN_VAR_SEP="_-_";class MixinMap{constructor(){this._map={}}set(name,props){name=name.trim();this._map[name]={properties:props,dependants:{}}}get(name){name=name.trim();return this._map[name]||null}}let invalidCallback=null;class ApplyShim{constructor(){this._currentElement=null;this._measureElement=null;this._map=new MixinMap}detectMixin(cssText){return detectMixin(cssText)}gatherStyles(template){const styleText=gatherStyleText(template.content);if(styleText){const style=document.createElement("style");style.textContent=styleText;template.content.insertBefore(style,template.content.firstChild);return style}return null}transformTemplate(template,elementName){if(template._gatheredStyle===undefined){template._gatheredStyle=this.gatherStyles(template)}const style=template._gatheredStyle;return style?this.transformStyle(style,elementName):null}transformStyle(style,elementName=""){let ast=rulesForStyle(style);this.transformRules(ast,elementName);style.textContent=toCssText(ast);return ast}transformCustomStyle(style){let ast=rulesForStyle(style);forEachRule(ast,(rule=>{if(rule["selector"]===":root"){rule["selector"]="html"}this.transformRule(rule)}));style.textContent=toCssText(ast);return ast}transformRules(rules,elementName){this._currentElement=elementName;forEachRule(rules,(r=>{this.transformRule(r)}));this._currentElement=null}transformRule(rule){rule["cssText"]=this.transformCssText(rule["parsedCssText"],rule);if(rule["selector"]===":root"){rule["selector"]=":host > *"}}transformCssText(cssText,rule){cssText=cssText.replace(VAR_ASSIGN,((matchText,propertyName,valueProperty,valueMixin)=>this._produceCssProperties(matchText,propertyName,valueProperty,valueMixin,rule)));return this._consumeCssProperties(cssText,rule)}_getInitialValueForProperty(property){if(!this._measureElement){this._measureElement=document.createElement("meta");this._measureElement.setAttribute("apply-shim-measure","");this._measureElement.style.all="initial";document.head.appendChild(this._measureElement)}return window.getComputedStyle(this._measureElement).getPropertyValue(property)}_fallbacksFromPreviousRules(startRule){let topRule=startRule;while(topRule["parent"]){topRule=topRule["parent"]}const fallbacks={};let seenStartRule=false;forEachRule(topRule,(r=>{seenStartRule=seenStartRule||r===startRule;if(seenStartRule){return}if(r["selector"]===startRule["selector"]){Object.assign(fallbacks,this._cssTextToMap(r["parsedCssText"]))}}));return fallbacks}_consumeCssProperties(text,rule){let m=null;while(m=MIXIN_MATCH.exec(text)){let matchText=m[0];let mixinName=m[1];let idx=m.index;let applyPos=idx+matchText.indexOf("@apply");let afterApplyPos=idx+matchText.length;let textBeforeApply=text.slice(0,applyPos);let textAfterApply=text.slice(afterApplyPos);let defaults=rule?this._fallbacksFromPreviousRules(rule):{};Object.assign(defaults,this._cssTextToMap(textBeforeApply));let replacement=this._atApplyToCssProperties(mixinName,defaults);text=`${textBeforeApply}${replacement}${textAfterApply}`;MIXIN_MATCH.lastIndex=idx+replacement.length}return text}_atApplyToCssProperties(mixinName,fallbacks){mixinName=mixinName.replace(APPLY_NAME_CLEAN,"");let vars=[];let mixinEntry=this._map.get(mixinName);if(!mixinEntry){this._map.set(mixinName,{});mixinEntry=this._map.get(mixinName)}if(mixinEntry){if(this._currentElement){mixinEntry.dependants[this._currentElement]=true}let p,parts,f;const properties=mixinEntry.properties;for(p in properties){f=fallbacks&&fallbacks[p];parts=[p,": var(",mixinName,MIXIN_VAR_SEP,p];if(f){parts.push(",",f.replace(IMPORTANT,""))}parts.push(")");if(IMPORTANT.test(properties[p])){parts.push(" !important")}vars.push(parts.join(""))}}return vars.join("; ")}_replaceInitialOrInherit(property,value){let match=INITIAL_INHERIT.exec(value);if(match){if(match[1]){value=this._getInitialValueForProperty(property)}else{value="apply-shim-inherit"}}return value}_cssTextToMap(text,replaceInitialOrInherit=false){let props=text.split(";");let property,value;let out={};for(let i=0,p,sp;i<props.length;i++){p=props[i];if(p){sp=p.split(":");if(sp.length>1){property=sp[0].trim();value=sp.slice(1).join(":");if(replaceInitialOrInherit){value=this._replaceInitialOrInherit(property,value)}out[property]=value}}}return out}_invalidateMixinEntry(mixinEntry){if(!invalidCallback){return}for(let elementName in mixinEntry.dependants){if(elementName!==this._currentElement){invalidCallback(elementName)}}}_produceCssProperties(matchText,propertyName,valueProperty,valueMixin,rule){if(valueProperty){processVariableAndFallback(valueProperty,((prefix,value)=>{if(value&&this._map.get(value)){valueMixin=`@apply ${value};`}}))}if(!valueMixin){return matchText}let mixinAsProperties=this._consumeCssProperties(""+valueMixin,rule);let prefix=matchText.slice(0,matchText.indexOf("--"));let mixinValues=this._cssTextToMap(mixinAsProperties,true);let combinedProps=mixinValues;let mixinEntry=this._map.get(propertyName);let oldProps=mixinEntry&&mixinEntry.properties;if(oldProps){combinedProps=Object.assign(Object.create(oldProps),mixinValues)}else{this._map.set(propertyName,combinedProps)}let out=[];let p,v;let needToInvalidate=false;for(p in combinedProps){v=mixinValues[p];if(v===undefined){v="initial"}if(oldProps&&!(p in oldProps)){needToInvalidate=true}out.push(`${propertyName}${MIXIN_VAR_SEP}${p}: ${v}`)}if(needToInvalidate){this._invalidateMixinEntry(mixinEntry)}if(mixinEntry){mixinEntry.properties=combinedProps}if(valueProperty){prefix=`${matchText};${prefix}`}return`${prefix}${out.join("; ")};`}}ApplyShim.prototype["detectMixin"]=ApplyShim.prototype.detectMixin;ApplyShim.prototype["transformStyle"]=ApplyShim.prototype.transformStyle;ApplyShim.prototype["transformCustomStyle"]=ApplyShim.prototype.transformCustomStyle;ApplyShim.prototype["transformRules"]=ApplyShim.prototype.transformRules;ApplyShim.prototype["transformRule"]=ApplyShim.prototype.transformRule;ApplyShim.prototype["transformTemplate"]=ApplyShim.prototype.transformTemplate;ApplyShim.prototype["_separator"]=MIXIN_VAR_SEP;Object.defineProperty(ApplyShim.prototype,"invalidCallback",{get(){return invalidCallback},set(cb){invalidCallback=cb}});const templateMap={};const CURRENT_VERSION="_applyShimCurrentVersion";const NEXT_VERSION="_applyShimNextVersion";const VALIDATING_VERSION="_applyShimValidatingVersion";const promise=Promise.resolve();function invalidate(elementName){let template=templateMap[elementName];if(template){invalidateTemplate(template)}}function invalidateTemplate(template){template[CURRENT_VERSION]=template[CURRENT_VERSION]||0;template[VALIDATING_VERSION]=template[VALIDATING_VERSION]||0;template[NEXT_VERSION]=(template[NEXT_VERSION]||0)+1}function templateIsValid(template){return template[CURRENT_VERSION]===template[NEXT_VERSION]}function templateIsValidating(template){return!templateIsValid(template)&&template[VALIDATING_VERSION]===template[NEXT_VERSION]}function startValidatingTemplate(template){template[VALIDATING_VERSION]=template[NEXT_VERSION];if(!template._validating){template._validating=true;promise.then((function(){template[CURRENT_VERSION]=template[NEXT_VERSION];template._validating=false}))}}let readyPromise=null;let whenReady=window["HTMLImports"]&&window["HTMLImports"]["whenReady"]||null;let resolveFn;function documentWait(callback){requestAnimationFrame((function(){if(whenReady){whenReady(callback)}else{if(!readyPromise){readyPromise=new Promise((resolve=>{resolveFn=resolve}));if(document.readyState==="complete"){resolveFn()}else{document.addEventListener("readystatechange",(()=>{if(document.readyState==="complete"){resolveFn()}}))}}readyPromise.then((function(){callback&&callback()}))}}))}const SEEN_MARKER="__seenByShadyCSS";const CACHED_STYLE="__shadyCSSCachedStyle";let transformFn=null;let validateFn=null;class CustomStyleInterface$1{constructor(){this["customStyles"]=[];this["enqueued"]=false;documentWait((()=>{if(window["ShadyCSS"]["flushCustomStyles"]){window["ShadyCSS"]["flushCustomStyles"]()}}))}enqueueDocumentValidation(){if(this["enqueued"]||!validateFn){return}this["enqueued"]=true;documentWait(validateFn)}addCustomStyle(style){if(!style[SEEN_MARKER]){style[SEEN_MARKER]=true;this["customStyles"].push(style);this.enqueueDocumentValidation()}}getStyleForCustomStyle(customStyle){if(customStyle[CACHED_STYLE]){return customStyle[CACHED_STYLE]}let style;if(customStyle["getStyle"]){style=customStyle["getStyle"]()}else{style=customStyle}return style}processStyles(){const cs=this["customStyles"];for(let i=0;i<cs.length;i++){const customStyle=cs[i];if(customStyle[CACHED_STYLE]){continue}const style=this.getStyleForCustomStyle(customStyle);if(style){const styleToTransform=style["__appliedElement"]||style;if(transformFn){transformFn(styleToTransform)}customStyle[CACHED_STYLE]=styleToTransform}}return cs}}CustomStyleInterface$1.prototype["addCustomStyle"]=CustomStyleInterface$1.prototype.addCustomStyle;CustomStyleInterface$1.prototype["getStyleForCustomStyle"]=CustomStyleInterface$1.prototype.getStyleForCustomStyle;CustomStyleInterface$1.prototype["processStyles"]=CustomStyleInterface$1.prototype.processStyles;Object.defineProperties(CustomStyleInterface$1.prototype,{transformCallback:{get(){return transformFn},set(fn){transformFn=fn}},validateCallback:{get(){return validateFn},set(fn){let needsEnqueue=false;if(!validateFn){needsEnqueue=true}validateFn=fn;if(needsEnqueue){this.enqueueDocumentValidation()}}}});const applyShim=new ApplyShim;class ApplyShimInterface{constructor(){this.customStyleInterface=null;applyShim["invalidCallback"]=invalidate}ensure(){if(this.customStyleInterface){return}if(window.ShadyCSS.CustomStyleInterface){this.customStyleInterface=window.ShadyCSS.CustomStyleInterface;this.customStyleInterface["transformCallback"]=style=>{applyShim.transformCustomStyle(style)};this.customStyleInterface["validateCallback"]=()=>{requestAnimationFrame((()=>{if(this.customStyleInterface["enqueued"]){this.flushCustomStyles()}}))}}}prepareTemplate(template,elementName){this.ensure();if(elementHasBuiltCss(template)){return}templateMap[elementName]=template;let ast=applyShim.transformTemplate(template,elementName);template["_styleAst"]=ast}flushCustomStyles(){this.ensure();if(!this.customStyleInterface){return}let styles=this.customStyleInterface["processStyles"]();if(!this.customStyleInterface["enqueued"]){return}for(let i=0;i<styles.length;i++){let cs=styles[i];let style=this.customStyleInterface["getStyleForCustomStyle"](cs);if(style){applyShim.transformCustomStyle(style)}}this.customStyleInterface["enqueued"]=false}styleSubtree(element,properties){this.ensure();if(properties){updateNativeProperties(element,properties)}if(element.shadowRoot){this.styleElement(element);let shadowChildren=element.shadowRoot.children||element.shadowRoot.childNodes;for(let i=0;i<shadowChildren.length;i++){this.styleSubtree(shadowChildren[i])}}else{let children=element.children||element.childNodes;for(let i=0;i<children.length;i++){this.styleSubtree(children[i])}}}styleElement(element){this.ensure();let{is:is}=getIsExtends(element);let template=templateMap[is];if(template&&elementHasBuiltCss(template)){return}if(template&&!templateIsValid(template)){if(!templateIsValidating(template)){this.prepareTemplate(template,is);startValidatingTemplate(template)}let root=element.shadowRoot;if(root){let style=root.querySelector("style");if(style){style["__cssRules"]=template["_styleAst"];style.textContent=toCssText(template["_styleAst"])}}}}styleDocument(properties){this.ensure();this.styleSubtree(document.body,properties)}}if(!window.ShadyCSS||!window.ShadyCSS.ScopingShim){const applyShimInterface=new ApplyShimInterface;let CustomStyleInterface=window.ShadyCSS&&window.ShadyCSS.CustomStyleInterface;window.ShadyCSS={prepareTemplate(template,elementName,elementExtends){applyShimInterface.flushCustomStyles();applyShimInterface.prepareTemplate(template,elementName)},prepareTemplateStyles(template,elementName,elementExtends){window.ShadyCSS.prepareTemplate(template,elementName,elementExtends)},prepareTemplateDom(template,elementName){},styleSubtree(element,properties){applyShimInterface.flushCustomStyles();applyShimInterface.styleSubtree(element,properties)},styleElement(element){applyShimInterface.flushCustomStyles();applyShimInterface.styleElement(element)},styleDocument(properties){applyShimInterface.flushCustomStyles();applyShimInterface.styleDocument(properties)},getComputedStyleValue(element,property){return getComputedStyleValue(element,property)},flushCustomStyles(){applyShimInterface.flushCustomStyles()},nativeCss:nativeCssVariables,nativeShadow:nativeShadow,cssBuild:cssBuild,disableRuntime:disableRuntime};if(CustomStyleInterface){window.ShadyCSS.CustomStyleInterface=CustomStyleInterface}}window.ShadyCSS.ApplyShim=applyShim;const GestureEventListeners=dedupingMixin((superClass=>{class GestureEventListeners extends superClass{_addEventListenerToNode(node,eventName,handler){if(!addListener(node,eventName,handler)){super._addEventListenerToNode(node,eventName,handler)}}_removeEventListenerFromNode(node,eventName,handler){if(!removeListener(node,eventName,handler)){super._removeEventListenerFromNode(node,eventName,handler)}}}return GestureEventListeners}));let scheduled=false;let beforeRenderQueue=[];let afterRenderQueue=[];function schedule(){scheduled=true;requestAnimationFrame((function(){scheduled=false;flushQueue(beforeRenderQueue);setTimeout((function(){runQueue(afterRenderQueue)}))}))}function flushQueue(queue){while(queue.length){callMethod(queue.shift())}}function runQueue(queue){for(let i=0,l=queue.length;i<l;i++){callMethod(queue.shift())}}function callMethod(info){const context=info[0];const callback=info[1];const args=info[2];try{callback.apply(context,args)}catch(e){setTimeout((()=>{throw e}))}}function beforeNextRender(context,callback,args){if(!scheduled){schedule()}beforeRenderQueue.push([context,callback,args])}function afterNextRender(context,callback,args){if(!scheduled){schedule()}afterRenderQueue.push([context,callback,args])}function resolve(){document.body.removeAttribute("unresolved")}if(document.readyState==="interactive"||document.readyState==="complete"){resolve()}else{window.addEventListener("DOMContentLoaded",resolve)}function newSplice(index,removed,addedCount){return{index:index,removed:removed,addedCount:addedCount}}const EDIT_LEAVE=0;const EDIT_UPDATE=1;const EDIT_ADD=2;const EDIT_DELETE=3;function calcEditDistances(current,currentStart,currentEnd,old,oldStart,oldEnd){let rowCount=oldEnd-oldStart+1;let columnCount=currentEnd-currentStart+1;let distances=new Array(rowCount);for(let i=0;i<rowCount;i++){distances[i]=new Array(columnCount);distances[i][0]=i}for(let j=0;j<columnCount;j++)distances[0][j]=j;for(let i=1;i<rowCount;i++){for(let j=1;j<columnCount;j++){if(equals(current[currentStart+j-1],old[oldStart+i-1]))distances[i][j]=distances[i-1][j-1];else{let north=distances[i-1][j]+1;let west=distances[i][j-1]+1;distances[i][j]=north<west?north:west}}}return distances}function spliceOperationsFromEditDistances(distances){let i=distances.length-1;let j=distances[0].length-1;let current=distances[i][j];let edits=[];while(i>0||j>0){if(i==0){edits.push(EDIT_ADD);j--;continue}if(j==0){edits.push(EDIT_DELETE);i--;continue}let northWest=distances[i-1][j-1];let west=distances[i-1][j];let north=distances[i][j-1];let min;if(west<north)min=west<northWest?west:northWest;else min=north<northWest?north:northWest;if(min==northWest){if(northWest==current){edits.push(EDIT_LEAVE)}else{edits.push(EDIT_UPDATE);current=northWest}i--;j--}else if(min==west){edits.push(EDIT_DELETE);i--;current=west}else{edits.push(EDIT_ADD);j--;current=north}}edits.reverse();return edits}function calcSplices(current,currentStart,currentEnd,old,oldStart,oldEnd){let prefixCount=0;let suffixCount=0;let splice;let minLength=Math.min(currentEnd-currentStart,oldEnd-oldStart);if(currentStart==0&&oldStart==0)prefixCount=sharedPrefix(current,old,minLength);if(currentEnd==current.length&&oldEnd==old.length)suffixCount=sharedSuffix(current,old,minLength-prefixCount);currentStart+=prefixCount;oldStart+=prefixCount;currentEnd-=suffixCount;oldEnd-=suffixCount;if(currentEnd-currentStart==0&&oldEnd-oldStart==0)return[];if(currentStart==currentEnd){splice=newSplice(currentStart,[],0);while(oldStart<oldEnd)splice.removed.push(old[oldStart++]);return[splice]}else if(oldStart==oldEnd)return[newSplice(currentStart,[],currentEnd-currentStart)];let ops=spliceOperationsFromEditDistances(calcEditDistances(current,currentStart,currentEnd,old,oldStart,oldEnd));splice=undefined;let splices=[];let index=currentStart;let oldIndex=oldStart;for(let i=0;i<ops.length;i++){switch(ops[i]){case EDIT_LEAVE:if(splice){splices.push(splice);splice=undefined}index++;oldIndex++;break;case EDIT_UPDATE:if(!splice)splice=newSplice(index,[],0);splice.addedCount++;index++;splice.removed.push(old[oldIndex]);oldIndex++;break;case EDIT_ADD:if(!splice)splice=newSplice(index,[],0);splice.addedCount++;index++;break;case EDIT_DELETE:if(!splice)splice=newSplice(index,[],0);splice.removed.push(old[oldIndex]);oldIndex++;break}}if(splice){splices.push(splice)}return splices}function sharedPrefix(current,old,searchLength){for(let i=0;i<searchLength;i++)if(!equals(current[i],old[i]))return i;return searchLength}function sharedSuffix(current,old,searchLength){let index1=current.length;let index2=old.length;let count=0;while(count<searchLength&&equals(current[--index1],old[--index2]))count++;return count}function calculateSplices(current,previous){return calcSplices(current,0,current.length,previous,0,previous.length)}function equals(currentValue,previousValue){return currentValue===previousValue}function isSlot(node){return node.localName==="slot"}let FlattenedNodesObserver=class{static getFlattenedNodes(node){const wrapped=wrap(node);if(isSlot(node)){node=node;return wrapped.assignedNodes({flatten:true})}else{return Array.from(wrapped.childNodes).map((node=>{if(isSlot(node)){node=node;return wrap(node).assignedNodes({flatten:true})}else{return[node]}})).reduce(((a,b)=>a.concat(b)),[])}}constructor(target,callback){this._shadyChildrenObserver=null;this._nativeChildrenObserver=null;this._connected=false;this._target=target;this.callback=callback;this._effectiveNodes=[];this._observer=null;this._scheduled=false;this._boundSchedule=()=>{this._schedule()};this.connect();this._schedule()}connect(){if(isSlot(this._target)){this._listenSlots([this._target])}else if(wrap(this._target).children){this._listenSlots(wrap(this._target).children);if(window.ShadyDOM){this._shadyChildrenObserver=ShadyDOM.observeChildren(this._target,(mutations=>{this._processMutations(mutations)}))}else{this._nativeChildrenObserver=new MutationObserver((mutations=>{this._processMutations(mutations)}));this._nativeChildrenObserver.observe(this._target,{childList:true})}}this._connected=true}disconnect(){if(isSlot(this._target)){this._unlistenSlots([this._target])}else if(wrap(this._target).children){this._unlistenSlots(wrap(this._target).children);if(window.ShadyDOM&&this._shadyChildrenObserver){ShadyDOM.unobserveChildren(this._shadyChildrenObserver);this._shadyChildrenObserver=null}else if(this._nativeChildrenObserver){this._nativeChildrenObserver.disconnect();this._nativeChildrenObserver=null}}this._connected=false}_schedule(){if(!this._scheduled){this._scheduled=true;microTask.run((()=>this.flush()))}}_processMutations(mutations){this._processSlotMutations(mutations);this.flush()}_processSlotMutations(mutations){if(mutations){for(let i=0;i<mutations.length;i++){let mutation=mutations[i];if(mutation.addedNodes){this._listenSlots(mutation.addedNodes)}if(mutation.removedNodes){this._unlistenSlots(mutation.removedNodes)}}}}flush(){if(!this._connected){return false}if(window.ShadyDOM){ShadyDOM.flush()}if(this._nativeChildrenObserver){this._processSlotMutations(this._nativeChildrenObserver.takeRecords())}else if(this._shadyChildrenObserver){this._processSlotMutations(this._shadyChildrenObserver.takeRecords())}this._scheduled=false;let info={target:this._target,addedNodes:[],removedNodes:[]};let newNodes=this.constructor.getFlattenedNodes(this._target);let splices=calculateSplices(newNodes,this._effectiveNodes);for(let i=0,s;i<splices.length&&(s=splices[i]);i++){for(let j=0,n;j<s.removed.length&&(n=s.removed[j]);j++){info.removedNodes.push(n)}}for(let i=0,s;i<splices.length&&(s=splices[i]);i++){for(let j=s.index;j<s.index+s.addedCount;j++){info.addedNodes.push(newNodes[j])}}this._effectiveNodes=newNodes;let didFlush=false;if(info.addedNodes.length||info.removedNodes.length){didFlush=true;this.callback.call(this._target,info)}return didFlush}_listenSlots(nodeList){for(let i=0;i<nodeList.length;i++){let n=nodeList[i];if(isSlot(n)){n.addEventListener("slotchange",this._boundSchedule)}}}_unlistenSlots(nodeList){for(let i=0;i<nodeList.length;i++){let n=nodeList[i];if(isSlot(n)){n.removeEventListener("slotchange",this._boundSchedule)}}}};const p=Element.prototype;const normalizedMatchesSelector=p.matches||p.matchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector||p.webkitMatchesSelector;const matchesSelector=function(node,selector){return normalizedMatchesSelector.call(node,selector)};class DomApiNative{constructor(node){this.node=node}observeNodes(callback){return new FlattenedNodesObserver(this.node,callback)}unobserveNodes(observerHandle){observerHandle.disconnect()}notifyObserver(){}deepContains(node){if(wrap(this.node).contains(node)){return true}let n=node;let doc=node.ownerDocument;while(n&&n!==doc&&n!==this.node){n=wrap(n).parentNode||wrap(n).host}return n===this.node}getOwnerRoot(){return wrap(this.node).getRootNode()}getDistributedNodes(){return this.node.localName==="slot"?wrap(this.node).assignedNodes({flatten:true}):[]}getDestinationInsertionPoints(){let ip$=[];let n=wrap(this.node).assignedSlot;while(n){ip$.push(n);n=wrap(n).assignedSlot}return ip$}importNode(node,deep){let doc=this.node instanceof Document?this.node:this.node.ownerDocument;return wrap(doc).importNode(node,deep)}getEffectiveChildNodes(){return FlattenedNodesObserver.getFlattenedNodes(this.node)}queryDistributedElements(selector){let c$=this.getEffectiveChildNodes();let list=[];for(let i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){if(c.nodeType===Node.ELEMENT_NODE&&matchesSelector(c,selector)){list.push(c)}}return list}get activeElement(){let node=this.node;return node._activeElement!==undefined?node._activeElement:node.activeElement}}function forwardMethods(proto,methods){for(let i=0;i<methods.length;i++){let method=methods[i];proto[method]=function(){return this.node[method].apply(this.node,arguments)}}}function forwardReadOnlyProperties(proto,properties){for(let i=0;i<properties.length;i++){let name=properties[i];Object.defineProperty(proto,name,{get:function(){const domApi=this;return domApi.node[name]},configurable:true})}}function forwardProperties(proto,properties){for(let i=0;i<properties.length;i++){let name=properties[i];Object.defineProperty(proto,name,{get:function(){return this.node[name]},set:function(value){this.node[name]=value},configurable:true})}}class EventApi{constructor(event){this.event=event}get rootTarget(){return this.path[0]}get localTarget(){return this.event.target}get path(){return this.event.composedPath()}}DomApiNative.prototype.cloneNode;DomApiNative.prototype.appendChild;DomApiNative.prototype.insertBefore;DomApiNative.prototype.removeChild;DomApiNative.prototype.replaceChild;DomApiNative.prototype.setAttribute;DomApiNative.prototype.removeAttribute;DomApiNative.prototype.querySelector;DomApiNative.prototype.querySelectorAll;DomApiNative.prototype.parentNode;DomApiNative.prototype.firstChild;DomApiNative.prototype.lastChild;DomApiNative.prototype.nextSibling;DomApiNative.prototype.previousSibling;DomApiNative.prototype.firstElementChild;DomApiNative.prototype.lastElementChild;DomApiNative.prototype.nextElementSibling;DomApiNative.prototype.previousElementSibling;DomApiNative.prototype.childNodes;DomApiNative.prototype.children;DomApiNative.prototype.classList;DomApiNative.prototype.textContent;DomApiNative.prototype.innerHTML;let DomApiImpl=DomApiNative;if(window["ShadyDOM"]&&window["ShadyDOM"]["inUse"]&&window["ShadyDOM"]["noPatch"]&&window["ShadyDOM"]["Wrapper"]){class Wrapper extends window["ShadyDOM"]["Wrapper"]{}Object.getOwnPropertyNames(DomApiNative.prototype).forEach((prop=>{if(prop!="activeElement"){Wrapper.prototype[prop]=DomApiNative.prototype[prop]}}));forwardReadOnlyProperties(Wrapper.prototype,["classList"]);DomApiImpl=Wrapper;Object.defineProperties(EventApi.prototype,{localTarget:{get(){return this.event.currentTarget},configurable:true},path:{get(){return window["ShadyDOM"]["composedPath"](this.event)},configurable:true}})}else{forwardMethods(DomApiNative.prototype,["cloneNode","appendChild","insertBefore","removeChild","replaceChild","setAttribute","removeAttribute","querySelector","querySelectorAll"]);forwardReadOnlyProperties(DomApiNative.prototype,["parentNode","firstChild","lastChild","nextSibling","previousSibling","firstElementChild","lastElementChild","nextElementSibling","previousElementSibling","childNodes","children","classList"]);forwardProperties(DomApiNative.prototype,["textContent","innerHTML"])}const dom=function(obj){obj=obj||document;if(obj instanceof DomApiImpl){return obj}if(obj instanceof EventApi){return obj}let helper=obj["__domApi"];if(!helper){if(obj instanceof Event){helper=new EventApi(obj)}else{helper=new DomApiImpl(obj)}obj["__domApi"]=helper}return helper};let styleInterface=window.ShadyCSS;const LegacyElementMixin=dedupingMixin((base=>{const legacyElementBase=GestureEventListeners(ElementMixin(base));const DIRECTION_MAP={x:"pan-x",y:"pan-y",none:"none",all:"auto"};class LegacyElement extends legacyElementBase{constructor(){super();this.isAttached;this.__boundListeners;this._debouncers}static get importMeta(){return this.prototype.importMeta}created(){}connectedCallback(){super.connectedCallback();this.isAttached=true;this.attached()}attached(){}disconnectedCallback(){super.disconnectedCallback();this.isAttached=false;this.detached()}detached(){}attributeChangedCallback(name,old,value,namespace){if(old!==value){super.attributeChangedCallback(name,old,value,namespace);this.attributeChanged(name,old,value)}}attributeChanged(name,old,value){}_initializeProperties(){let proto=Object.getPrototypeOf(this);if(!proto.hasOwnProperty("__hasRegisterFinished")){this._registered();proto.__hasRegisterFinished=true}super._initializeProperties();this.root=this;this.created();this._applyListeners()}_registered(){}ready(){this._ensureAttributes();super.ready()}_ensureAttributes(){}_applyListeners(){}serialize(value){return this._serializeValue(value)}deserialize(value,type){return this._deserializeValue(value,type)}reflectPropertyToAttribute(property,attribute,value){this._propertyToAttribute(property,attribute,value)}serializeValueToAttribute(value,attribute,node){this._valueToNodeAttribute(node||this,value,attribute)}extend(prototype,api){if(!(prototype&&api)){return prototype||api}let n$=Object.getOwnPropertyNames(api);for(let i=0,n;i<n$.length&&(n=n$[i]);i++){let pd=Object.getOwnPropertyDescriptor(api,n);if(pd){Object.defineProperty(prototype,n,pd)}}return prototype}mixin(target,source){for(let i in source){target[i]=source[i]}return target}chainObject(object,prototype){if(object&&prototype&&object!==prototype){object.__proto__=prototype}return object}instanceTemplate(template){let content=this.constructor._contentForTemplate(template);let dom=document.importNode(content,true);return dom}fire(type,detail,options){options=options||{};detail=detail===null||detail===undefined?{}:detail;let event=new Event(type,{bubbles:options.bubbles===undefined?true:options.bubbles,cancelable:Boolean(options.cancelable),composed:options.composed===undefined?true:options.composed});event.detail=detail;let node=options.node||this;wrap(node).dispatchEvent(event);return event}listen(node,eventName,methodName){node=node||this;let hbl=this.__boundListeners||(this.__boundListeners=new WeakMap);let bl=hbl.get(node);if(!bl){bl={};hbl.set(node,bl)}let key=eventName+methodName;if(!bl[key]){bl[key]=this._addMethodEventListenerToNode(node,eventName,methodName,this)}}unlisten(node,eventName,methodName){node=node||this;let bl=this.__boundListeners&&this.__boundListeners.get(node);let key=eventName+methodName;let handler=bl&&bl[key];if(handler){this._removeEventListenerFromNode(node,eventName,handler);bl[key]=null}}setScrollDirection(direction,node){setTouchAction(node||this,DIRECTION_MAP[direction]||"auto")}$$(slctr){return this.root.querySelector(slctr)}get domHost(){let root=wrap(this).getRootNode();return root instanceof DocumentFragment?root.host:root}distributeContent(){const thisEl=this;const domApi=dom(thisEl);if(window.ShadyDOM&&domApi.shadowRoot){ShadyDOM.flush()}}getEffectiveChildNodes(){const thisEl=this;const domApi=dom(thisEl);return domApi.getEffectiveChildNodes()}queryDistributedElements(selector){const thisEl=this;const domApi=dom(thisEl);return domApi.queryDistributedElements(selector)}getEffectiveChildren(){let list=this.getEffectiveChildNodes();return list.filter((function(n){return n.nodeType===Node.ELEMENT_NODE}))}getEffectiveTextContent(){let cn=this.getEffectiveChildNodes();let tc=[];for(let i=0,c;c=cn[i];i++){if(c.nodeType!==Node.COMMENT_NODE){tc.push(c.textContent)}}return tc.join("")}queryEffectiveChildren(selector){let e$=this.queryDistributedElements(selector);return e$&&e$[0]}queryAllEffectiveChildren(selector){return this.queryDistributedElements(selector)}getContentChildNodes(slctr){let content=this.root.querySelector(slctr||"slot");return content?dom(content).getDistributedNodes():[]}getContentChildren(slctr){let children=this.getContentChildNodes(slctr).filter((function(n){return n.nodeType===Node.ELEMENT_NODE}));return children}isLightDescendant(node){const thisNode=this;return thisNode!==node&&wrap(thisNode).contains(node)&&wrap(thisNode).getRootNode()===wrap(node).getRootNode()}isLocalDescendant(node){return this.root===wrap(node).getRootNode()}scopeSubtree(container,shouldObserve){}getComputedStyleValue(property){return styleInterface.getComputedStyleValue(this,property)}debounce(jobName,callback,wait){this._debouncers=this._debouncers||{};return this._debouncers[jobName]=Debouncer.debounce(this._debouncers[jobName],wait>0?timeOut.after(wait):microTask,callback.bind(this))}isDebouncerActive(jobName){this._debouncers=this._debouncers||{};let debouncer=this._debouncers[jobName];return!!(debouncer&&debouncer.isActive())}flushDebouncer(jobName){this._debouncers=this._debouncers||{};let debouncer=this._debouncers[jobName];if(debouncer){debouncer.flush()}}cancelDebouncer(jobName){this._debouncers=this._debouncers||{};let debouncer=this._debouncers[jobName];if(debouncer){debouncer.cancel()}}async(callback,waitTime){return waitTime>0?timeOut.run(callback.bind(this),waitTime):~microTask.run(callback.bind(this))}cancelAsync(handle){handle<0?microTask.cancel(~handle):timeOut.cancel(handle)}create(tag,props){let elt=document.createElement(tag);if(props){if(elt.setProperties){elt.setProperties(props)}else{for(let n in props){elt[n]=props[n]}}}return elt}elementMatches(selector,node){return matchesSelector(node||this,selector)}toggleAttribute(name,bool){let node=this;if(arguments.length===3){node=arguments[2]}if(arguments.length==1){bool=!node.hasAttribute(name)}if(bool){wrap(node).setAttribute(name,"");return true}else{wrap(node).removeAttribute(name);return false}}toggleClass(name,bool,node){node=node||this;if(arguments.length==1){bool=!node.classList.contains(name)}if(bool){node.classList.add(name)}else{node.classList.remove(name)}}transform(transformText,node){node=node||this;node.style.webkitTransform=transformText;node.style.transform=transformText}translate3d(x,y,z,node){node=node||this;this.transform("translate3d("+x+","+y+","+z+")",node)}arrayDelete(arrayOrPath,item){let index;if(Array.isArray(arrayOrPath)){index=arrayOrPath.indexOf(item);if(index>=0){return arrayOrPath.splice(index,1)}}else{let arr=get(this,arrayOrPath);index=arr.indexOf(item);if(index>=0){return this.splice(arrayOrPath,index,1)}}return null}_logger(level,args){if(Array.isArray(args)&&args.length===1&&Array.isArray(args[0])){args=args[0]}switch(level){case"log":case"warn":case"error":console[level](...args)}}_log(...args){this._logger("log",args)}_warn(...args){this._logger("warn",args)}_error(...args){this._logger("error",args)}_logf(methodName,...args){return["[%s::%s]",this.is,methodName,...args]}}LegacyElement.prototype.is="";return LegacyElement}));const lifecycleProps={attached:true,detached:true,ready:true,created:true,beforeRegister:true,registered:true,attributeChanged:true,listeners:true,hostAttributes:true};const excludeOnInfo={attached:true,detached:true,ready:true,created:true,beforeRegister:true,registered:true,attributeChanged:true,behaviors:true,_noAccessors:true};const excludeOnBehaviors=Object.assign({listeners:true,hostAttributes:true,properties:true,observers:true},excludeOnInfo);function copyProperties(source,target,excludeProps){const noAccessors=source._noAccessors;const propertyNames=Object.getOwnPropertyNames(source);for(let i=0;i<propertyNames.length;i++){let p=propertyNames[i];if(p in excludeProps){continue}if(noAccessors){target[p]=source[p]}else{let pd=Object.getOwnPropertyDescriptor(source,p);if(pd){pd.configurable=true;Object.defineProperty(target,p,pd)}}}}function mixinBehaviors(behaviors,klass){return GenerateClassFromInfo({},LegacyElementMixin(klass),behaviors)}function applyBehaviors(proto,behaviors,lifecycle){for(let i=0;i<behaviors.length;i++){applyInfo(proto,behaviors[i],lifecycle,excludeOnBehaviors)}}function applyInfo(proto,info,lifecycle,excludeProps){copyProperties(info,proto,excludeProps);for(let p in lifecycleProps){if(info[p]){lifecycle[p]=lifecycle[p]||[];lifecycle[p].push(info[p])}}}function flattenBehaviors(behaviors,list,exclude){list=list||[];for(let i=behaviors.length-1;i>=0;i--){let b=behaviors[i];if(b){if(Array.isArray(b)){flattenBehaviors(b,list)}else{if(list.indexOf(b)<0&&(!exclude||exclude.indexOf(b)<0)){list.unshift(b)}}}else{console.warn("behavior is null, check for missing or 404 import")}}return list}function mergeProperties(target,source){for(const p in source){const targetInfo=target[p];const sourceInfo=source[p];if(!("value"in sourceInfo)&&targetInfo&&"value"in targetInfo){target[p]=Object.assign({value:targetInfo.value},sourceInfo)}else{target[p]=sourceInfo}}}function GenerateClassFromInfo(info,Base,behaviors){let behaviorList;const lifecycle={};class PolymerGenerated extends Base{static _finalizeClass(){if(!this.hasOwnProperty(JSCompiler_renameProperty("generatedFrom",this))){super._finalizeClass()}else{if(behaviorList){for(let i=0,b;i<behaviorList.length;i++){b=behaviorList[i];if(b.properties){this.createProperties(b.properties)}if(b.observers){this.createObservers(b.observers,b.properties)}}}if(info.properties){this.createProperties(info.properties)}if(info.observers){this.createObservers(info.observers,info.properties)}this._prepareTemplate()}}static get properties(){const properties={};if(behaviorList){for(let i=0;i<behaviorList.length;i++){mergeProperties(properties,behaviorList[i].properties)}}mergeProperties(properties,info.properties);return properties}static get observers(){let observers=[];if(behaviorList){for(let i=0,b;i<behaviorList.length;i++){b=behaviorList[i];if(b.observers){observers=observers.concat(b.observers)}}}if(info.observers){observers=observers.concat(info.observers)}return observers}created(){super.created();const list=lifecycle.created;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}_registered(){const generatedProto=PolymerGenerated.prototype;if(!generatedProto.hasOwnProperty("__hasRegisterFinished")){generatedProto.__hasRegisterFinished=true;super._registered();const proto=Object.getPrototypeOf(this);let list=lifecycle.beforeRegister;if(list){for(let i=0;i<list.length;i++){list[i].call(proto)}}list=lifecycle.registered;if(list){for(let i=0;i<list.length;i++){list[i].call(proto)}}}}_applyListeners(){super._applyListeners();const list=lifecycle.listeners;if(list){for(let i=0;i<list.length;i++){const listeners=list[i];if(listeners){for(let l in listeners){this._addMethodEventListenerToNode(this,l,listeners[l])}}}}}_ensureAttributes(){const list=lifecycle.hostAttributes;if(list){for(let i=list.length-1;i>=0;i--){const hostAttributes=list[i];for(let a in hostAttributes){this._ensureAttribute(a,hostAttributes[a])}}}super._ensureAttributes()}ready(){super.ready();let list=lifecycle.ready;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}attached(){super.attached();let list=lifecycle.attached;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}detached(){super.detached();let list=lifecycle.detached;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}attributeChanged(name,old,value){super.attributeChanged();let list=lifecycle.attributeChanged;if(list){for(let i=0;i<list.length;i++){list[i].call(this,name,old,value)}}}}if(behaviors){if(!Array.isArray(behaviors)){behaviors=[behaviors]}let superBehaviors=Base.prototype.behaviors;behaviorList=flattenBehaviors(behaviors,null,superBehaviors);PolymerGenerated.prototype.behaviors=superBehaviors?superBehaviors.concat(behaviors):behaviorList}const copyPropertiesToProto=proto=>{if(behaviorList){applyBehaviors(proto,behaviorList,lifecycle)}applyInfo(proto,info,lifecycle,excludeOnInfo)};{copyPropertiesToProto(PolymerGenerated.prototype)}PolymerGenerated.generatedFrom=info;return PolymerGenerated}const Class=function(info,mixin){if(!info){console.warn("Polymer.Class requires `info` argument")}let klass=mixin?mixin(LegacyElementMixin(HTMLElement)):LegacyElementMixin(HTMLElement);klass=GenerateClassFromInfo(info,klass,info.behaviors);klass.is=klass.prototype.is=info.is;return klass};let mutablePropertyChange;(()=>{mutablePropertyChange=MutableData._mutablePropertyChange})();const OptionalMutableDataBehavior={properties:{mutableData:Boolean},_shouldPropertyChange(property,value,old){return mutablePropertyChange(this,property,value,old,this.mutableData)}};const Polymer=function(info){let klass;if(typeof info==="function"){klass=info}else{klass=Polymer.Class(info)}customElements.define(klass.is,klass);return klass};Polymer.Class=Class;const Templatizer={templatize(template,mutableData){this._templatizerTemplate=template;this.ctor=templatize(template,this,{mutableData:Boolean(mutableData),parentModel:this._parentModel,instanceProps:this._instanceProps,forwardHostProp:this._forwardHostPropV2,notifyInstanceProp:this._notifyInstancePropV2})},stamp(model){return new this.ctor(model)},modelForElement(el){return modelForElement(this._templatizerTemplate,el)}};const domBindBase=GestureEventListeners(OptionalMutableData(PropertyEffects(HTMLElement)));class DomBind extends domBindBase{static get observedAttributes(){return["mutable-data"]}constructor(){super();this.root=null;this.$=null;this.__children=null}attributeChangedCallback(){this.mutableData=true}connectedCallback(){this.style.display="none";this.render()}disconnectedCallback(){this.__removeChildren()}__insertChildren(){wrap(wrap(this).parentNode).insertBefore(this.root,this)}__removeChildren(){if(this.__children){for(let i=0;i<this.__children.length;i++){this.root.appendChild(this.__children[i])}}}render(){let template;if(!this.__children){template=template||this.querySelector("template");if(!template){let observer=new MutationObserver((()=>{template=this.querySelector("template");if(template){observer.disconnect();this.render()}else{throw new Error("dom-bind requires a <template> child")}}));observer.observe(this,{childList:true});return}this.root=this._stampTemplate(template);this.$=this.root.$;this.__children=[];for(let n=this.root.firstChild;n;n=n.nextSibling){this.__children[this.__children.length]=n}this._enableProperties()}this.__insertChildren();this.dispatchEvent(new CustomEvent("dom-change",{bubbles:true,composed:true}))}}customElements.define("dom-bind",DomBind);let ArraySelectorMixin=dedupingMixin((superClass=>{let elementBase=ElementMixin(superClass);class ArraySelectorMixin extends elementBase{static get properties(){return{items:{type:Array},multi:{type:Boolean,value:false},selected:{type:Object,notify:true},selectedItem:{type:Object,notify:true},toggle:{type:Boolean,value:false}}}static get observers(){return["__updateSelection(multi, items.*)"]}constructor(){super();this.__lastItems=null;this.__lastMulti=null;this.__selectedMap=null}__updateSelection(multi,itemsInfo){let path=itemsInfo.path;if(path==JSCompiler_renameProperty("items",this)){let newItems=itemsInfo.base||[];let lastItems=this.__lastItems;let lastMulti=this.__lastMulti;if(multi!==lastMulti){this.clearSelection()}if(lastItems){let splices=calculateSplices(newItems,lastItems);this.__applySplices(splices)}this.__lastItems=newItems;this.__lastMulti=multi}else if(itemsInfo.path==`${JSCompiler_renameProperty("items",this)}.splices`){this.__applySplices(itemsInfo.value.indexSplices)}else{let part=path.slice(`${JSCompiler_renameProperty("items",this)}.`.length);let idx=parseInt(part,10);if(part.indexOf(".")<0&&part==idx){this.__deselectChangedIdx(idx)}}}__applySplices(splices){let selected=this.__selectedMap;for(let i=0;i<splices.length;i++){let s=splices[i];selected.forEach(((idx,item)=>{if(idx<s.index);else if(idx>=s.index+s.removed.length){selected.set(item,idx+s.addedCount-s.removed.length)}else{selected.set(item,-1)}}));for(let j=0;j<s.addedCount;j++){let idx=s.index+j;if(selected.has(this.items[idx])){selected.set(this.items[idx],idx)}}}this.__updateLinks();let sidx=0;selected.forEach(((idx,item)=>{if(idx<0){if(this.multi){this.splice(JSCompiler_renameProperty("selected",this),sidx,1)}else{this.selected=this.selectedItem=null}selected.delete(item)}else{sidx++}}))}__updateLinks(){this.__dataLinkedPaths={};if(this.multi){let sidx=0;this.__selectedMap.forEach((idx=>{if(idx>=0){this.linkPaths(`${JSCompiler_renameProperty("items",this)}.${idx}`,`${JSCompiler_renameProperty("selected",this)}.${sidx++}`)}}))}else{this.__selectedMap.forEach((idx=>{this.linkPaths(JSCompiler_renameProperty("selected",this),`${JSCompiler_renameProperty("items",this)}.${idx}`);this.linkPaths(JSCompiler_renameProperty("selectedItem",this),`${JSCompiler_renameProperty("items",this)}.${idx}`)}))}}clearSelection(){this.__dataLinkedPaths={};this.__selectedMap=new Map;this.selected=this.multi?[]:null;this.selectedItem=null}isSelected(item){return this.__selectedMap.has(item)}isIndexSelected(idx){return this.isSelected(this.items[idx])}__deselectChangedIdx(idx){let sidx=this.__selectedIndexForItemIndex(idx);if(sidx>=0){let i=0;this.__selectedMap.forEach(((idx,item)=>{if(sidx==i++){this.deselect(item)}}))}}__selectedIndexForItemIndex(idx){let selected=this.__dataLinkedPaths[`${JSCompiler_renameProperty("items",this)}.${idx}`];if(selected){return parseInt(selected.slice(`${JSCompiler_renameProperty("selected",this)}.`.length),10)}}deselect(item){let idx=this.__selectedMap.get(item);if(idx>=0){this.__selectedMap.delete(item);let sidx;if(this.multi){sidx=this.__selectedIndexForItemIndex(idx)}this.__updateLinks();if(this.multi){this.splice(JSCompiler_renameProperty("selected",this),sidx,1)}else{this.selected=this.selectedItem=null}}}deselectIndex(idx){this.deselect(this.items[idx])}select(item){this.selectIndex(this.items.indexOf(item))}selectIndex(idx){let item=this.items[idx];if(!this.isSelected(item)){if(!this.multi){this.__selectedMap.clear()}this.__selectedMap.set(item,idx);this.__updateLinks();if(this.multi){this.push(JSCompiler_renameProperty("selected",this),item)}else{this.selected=this.selectedItem=item}}else if(this.toggle){this.deselectIndex(idx)}}}return ArraySelectorMixin}));let baseArraySelector=ArraySelectorMixin(PolymerElement);class ArraySelector extends baseArraySelector{static get is(){return"array-selector"}static get template(){return null}}customElements.define(ArraySelector.is,ArraySelector);const customStyleInterface=new CustomStyleInterface$1;if(!window.ShadyCSS){window.ShadyCSS={prepareTemplate(template,elementName,elementExtends){},prepareTemplateDom(template,elementName){},prepareTemplateStyles(template,elementName,elementExtends){},styleSubtree(element,properties){customStyleInterface.processStyles();updateNativeProperties(element,properties)},styleElement(element){customStyleInterface.processStyles()},styleDocument(properties){customStyleInterface.processStyles();updateNativeProperties(document.body,properties)},getComputedStyleValue(element,property){return getComputedStyleValue(element,property)},flushCustomStyles(){},nativeCss:nativeCssVariables,nativeShadow:nativeShadow,cssBuild:cssBuild,disableRuntime:disableRuntime}}window.ShadyCSS.CustomStyleInterface=customStyleInterface;const attr="include";const CustomStyleInterface=window.ShadyCSS.CustomStyleInterface;class CustomStyle extends HTMLElement{constructor(){super();this._style=null;CustomStyleInterface.addCustomStyle(this)}getStyle(){if(this._style){return this._style}const style=this.querySelector("style");if(!style){return null}this._style=style;const include=style.getAttribute(attr);if(include){style.removeAttribute(attr);style.textContent=cssFromModules(include)+style.textContent}if(this.ownerDocument!==window.document){window.document.head.appendChild(this)}return this._style}}window.customElements.define("custom-style",CustomStyle);const Base=LegacyElementMixin(HTMLElement).prototype;export{Base,Debouncer,DomIf,DomRepeat,FlattenedNodesObserver,OptionalMutableDataBehavior,Polymer,PolymerElement,TemplateInstanceBase,Templatizer,afterNextRender,animationFrame,beforeNextRender,calculateSplices,dashToCamelCase,dedupingMixin,dom,enqueueDebouncer,flush,gestures$1 as gestures,get,html,idlePeriod,matches,microTask,mixinBehaviors,templatize,timeOut,translate,useShadow}; \ No newline at end of file +window.JSCompiler_renameProperty=function(t,e){return t};let t=0,e=0,s=[],n=0,r=document.createTextNode("");new window.MutationObserver((function(){const t=s.length;for(let e=0;e<t;e++){let t=s[e];if(t)try{t()}catch(t){setTimeout((()=>{throw t}))}}s.splice(0,t),e+=t})).observe(r,{characterData:!0});const i={after:t=>({run:e=>window.setTimeout(e,t),cancel(t){window.clearTimeout(t)}}),run:(t,e)=>window.setTimeout(t,e),cancel(t){window.clearTimeout(t)}},o={run:t=>window.requestAnimationFrame(t),cancel(t){window.cancelAnimationFrame(t)}},a={run:t=>window.requestIdleCallback?window.requestIdleCallback(t):window.setTimeout(t,16),cancel(t){window.cancelIdleCallback?window.cancelIdleCallback(t):window.clearTimeout(t)}},l={run:e=>(r.textContent=n++,s.push(e),t++),cancel(t){const n=t-e;if(n>=0){if(!s[n])throw new Error("invalid async handle: "+t);s[n]=null}}};let h=0;const d=function(t){let e=t.__mixinApplications;e||(e=new WeakMap,t.__mixinApplications=e);let s=h++;return function(n){let r=n.__mixinSet;if(r&&r[s])return n;let i=e,o=i.get(n);o||(o=t(n),i.set(n,o));let a=Object.create(o.__mixinSet||r||null);return a[s]=!0,o.__mixinSet=a,o}};class c{constructor(){this._asyncModule=null,this._callback=null,this._timer=null}setConfig(t,e){this._asyncModule=t,this._callback=e,this._timer=this._asyncModule.run((()=>{this._timer=null,u.delete(this),this._callback()}))}cancel(){this.isActive()&&(this._cancelAsync(),u.delete(this))}_cancelAsync(){this.isActive()&&(this._asyncModule.cancel(this._timer),this._timer=null)}flush(){this.isActive()&&(this.cancel(),this._callback())}isActive(){return null!=this._timer}static debounce(t,e,s){return t instanceof c?t._cancelAsync():t=new c,t.setConfig(e,s),t}}let u=new Set;const p=function(t){u.add(t)},_=function(){const t=Boolean(u.size);return u.forEach((t=>{try{t.flush()}catch(t){setTimeout((()=>{throw t}))}})),t};let f,m,y=/(url\()([^)]*)(\))/g,g=/(^\/)|(^#)|(^[\w-\d]*:)/;function b(t,e){if(t&&g.test(t))return t;if(void 0===f){f=!1;try{const t=new URL("b","http://a");t.pathname="c%20d",f="http://a/c%20d"===t.href}catch(t){}}return e||(e=document.baseURI||window.location.href),f?new URL(t,e).href:(m||(m=document.implementation.createHTMLDocument("temp"),m.base=m.createElement("base"),m.head.appendChild(m.base),m.anchor=m.createElement("a"),m.body.appendChild(m.anchor)),m.base.href=e,m.anchor.href=t,m.anchor.href||t)}function P(t,e){return t.replace(y,(function(t,s,n,r){return s+"'"+b(n.replace(/["']/g,""),e)+"'"+r}))}function C(t){return t.substring(0,t.lastIndexOf("/")+1)}const v=!window.ShadyDOM;Boolean(!window.ShadyCSS||window.ShadyCSS.nativeCss);let S=C(document.baseURI||window.location.href),w=window.Polymer&&window.Polymer.sanitizeDOMValue||void 0;const E=window.ShadyDOM&&window.ShadyDOM.noPatch&&window.ShadyDOM.wrap?window.ShadyDOM.wrap:t=>t;let T="string"==typeof document.head.style.touchAction,O="__polymerGestures",N="__polymerGesturesHandled",x="__polymerGesturesTouchAction",A=["mousedown","mousemove","mouseup","click"],I=[0,1,4,2],M=function(){try{return 1===new MouseEvent("test",{buttons:1}).buttons}catch(t){return!1}}();function R(t){return A.indexOf(t)>-1}let L=!1;function k(t){R(t)}!function(){try{let t=Object.defineProperty({},"passive",{get(){L=!0}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(t){}}();let D=navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);const F=[],H={button:!0,input:!0,keygen:!0,meter:!0,output:!0,textarea:!0,progress:!0,select:!0},z={button:!0,command:!0,fieldset:!0,input:!0,keygen:!0,optgroup:!0,option:!0,select:!0,textarea:!0};function j(t){let e=Array.prototype.slice.call(t.labels||[]);if(!e.length){e=[];let s=t.getRootNode();if(t.id){let n=s.querySelectorAll(`label[for = ${t.id}]`);for(let t=0;t<n.length;t++)e.push(n[t])}}return e}let B=function(t){let e=t.sourceCapabilities;var s;if((!e||e.firesTouchEvents)&&(t[N]={skip:!0},"click"===t.type)){let e=!1,n=U(t);for(let t=0;t<n.length;t++){if(n[t].nodeType===Node.ELEMENT_NODE)if("label"===n[t].localName)F.push(n[t]);else if(s=n[t],H[s.localName]){let s=j(n[t]);for(let t=0;t<s.length;t++)e=e||F.indexOf(s[t])>-1}if(n[t]===Y.mouse.target)return}if(e)return;t.preventDefault(),t.stopPropagation()}};function q(t){let e=D?["click"]:A;for(let s,n=0;n<e.length;n++)s=e[n],t?(F.length=0,document.addEventListener(s,B,!0)):document.removeEventListener(s,B,!0)}function $(t){let e=t.type;if(!R(e))return!1;if("mousemove"===e){let e=void 0===t.buttons?1:t.buttons;return t instanceof window.MouseEvent&&!M&&(e=I[t.which]||0),Boolean(1&e)}return 0===(void 0===t.button?0:t.button)}let Y={mouse:{target:null,mouseIgnoreJob:null},touch:{x:0,y:0,id:-1,scrollDecided:!1}};function J(t,e,s){t.movefn=e,t.upfn=s,document.addEventListener("mousemove",e),document.addEventListener("mouseup",s)}function V(t){document.removeEventListener("mousemove",t.movefn),document.removeEventListener("mouseup",t.upfn),t.movefn=null,t.upfn=null}document.addEventListener("touchend",(function(t){Y.mouse.mouseIgnoreJob||q(!0),Y.mouse.target=U(t)[0],Y.mouse.mouseIgnoreJob=c.debounce(Y.mouse.mouseIgnoreJob,i.after(2500),(function(){q(),Y.mouse.target=null,Y.mouse.mouseIgnoreJob=null}))}),!!L&&{passive:!0});const U=window.ShadyDOM&&window.ShadyDOM.noPatch?window.ShadyDOM.composedPath:t=>t.composedPath&&t.composedPath()||[],X={},W=[];function G(t,e){let s=document.elementFromPoint(t,e),n=s;for(;n&&n.shadowRoot&&!window.ShadyDOM;){let r=n;if(n=n.shadowRoot.elementFromPoint(t,e),r===n)break;n&&(s=n)}return s}function Z(t){const e=U(t);return e.length>0?e[0]:t.target}function K(t){let e,s=t.type,n=t.currentTarget.__polymerGestures;if(!n)return;let r=n[s];if(r){if(!t[N]&&(t[N]={},"touch"===s.slice(0,5))){let e=(t=t).changedTouches[0];if("touchstart"===s&&1===t.touches.length&&(Y.touch.id=e.identifier),Y.touch.id!==e.identifier)return;T||"touchstart"!==s&&"touchmove"!==s||function(t){let e=t.changedTouches[0],s=t.type;if("touchstart"===s)Y.touch.x=e.clientX,Y.touch.y=e.clientY,Y.touch.scrollDecided=!1;else if("touchmove"===s){if(Y.touch.scrollDecided)return;Y.touch.scrollDecided=!0;let s=function(t){let e="auto",s=U(t);for(let t,n=0;n<s.length;n++)if(t=s[n],t[x]){e=t[x];break}return e}(t),n=!1,r=Math.abs(Y.touch.x-e.clientX),i=Math.abs(Y.touch.y-e.clientY);t.cancelable&&("none"===s?n=!0:"pan-x"===s?n=i>r:"pan-y"===s&&(n=r>i)),n?t.preventDefault():rt("track")}}(t)}if(e=t[N],!e.skip){for(let s,n=0;n<W.length;n++)s=W[n],r[s.name]&&!e[s.name]&&s.flow&&s.flow.start.indexOf(t.type)>-1&&s.reset&&s.reset();for(let n,i=0;i<W.length;i++)n=W[i],r[n.name]&&!e[n.name]&&(e[n.name]=!0,n[s](t))}}}function Q(t,e,s){return!!X[e]&&(function(t,e,s){let n=X[e],r=n.deps,i=n.name,o=t[O];o||(t[O]=o={});for(let e,s,n=0;n<r.length;n++)e=r[n],D&&R(e)&&"click"!==e||(s=o[e],s||(o[e]=s={_count:0}),0===s._count&&t.addEventListener(e,K,k(e)),s[i]=(s[i]||0)+1,s._count=(s._count||0)+1);t.addEventListener(e,s),n.touchAction&&st(t,n.touchAction)}(t,e,s),!0)}function tt(t,e,s){return!!X[e]&&(function(t,e,s){let n=X[e],r=n.deps,i=n.name,o=t[O];if(o)for(let e,s,n=0;n<r.length;n++)e=r[n],s=o[e],s&&s[i]&&(s[i]=(s[i]||1)-1,s._count=(s._count||1)-1,0===s._count&&t.removeEventListener(e,K,k(e)));t.removeEventListener(e,s)}(t,e,s),!0)}function et(t){W.push(t);for(let e=0;e<t.emits.length;e++)X[t.emits[e]]=t}function st(t,e){T&&t instanceof HTMLElement&&l.run((()=>{t.style.touchAction=e})),t[x]=e}function nt(t,e,s){let n=new Event(e,{bubbles:!0,cancelable:!0,composed:!0});if(n.detail=s,E(t).dispatchEvent(n),n.defaultPrevented){let t=s.preventer||s.sourceEvent;t&&t.preventDefault&&t.preventDefault()}}function rt(t){let e=function(t){for(let e,s=0;s<W.length;s++){e=W[s];for(let s,n=0;n<e.emits.length;n++)if(s=e.emits[n],s===t)return e}return null}(t);e.info&&(e.info.prevent=!0)}function it(t,e,s,n){e&&nt(e,t,{x:s.clientX,y:s.clientY,sourceEvent:s,preventer:n,prevent:function(t){return rt(t)}})}function ot(t,e,s){if(t.prevent)return!1;if(t.started)return!0;let n=Math.abs(t.x-e),r=Math.abs(t.y-s);return n>=5||r>=5}function at(t,e,s){if(!e)return;let n,r=t.moves[t.moves.length-2],i=t.moves[t.moves.length-1],o=i.x-t.x,a=i.y-t.y,l=0;r&&(n=i.x-r.x,l=i.y-r.y),nt(e,"track",{state:t.state,x:s.clientX,y:s.clientY,dx:o,dy:a,ddx:n,ddy:l,sourceEvent:s,hover:function(){return G(s.clientX,s.clientY)}})}function lt(t,e,s){let n=Math.abs(e.clientX-t.x),r=Math.abs(e.clientY-t.y),i=Z(s||e);!i||z[i.localName]&&i.hasAttribute("disabled")||(isNaN(n)||isNaN(r)||n<=25&&r<=25||function(t){if("click"===t.type){if(0===t.detail)return!0;let e=Z(t);if(!e.nodeType||e.nodeType!==Node.ELEMENT_NODE)return!0;let s=e.getBoundingClientRect(),n=t.pageX,r=t.pageY;return!(n>=s.left&&n<=s.right&&r>=s.top&&r<=s.bottom)}return!1}(e))&&(t.prevent||nt(i,"tap",{x:e.clientX,y:e.clientY,sourceEvent:e,preventer:s}))}et({name:"downup",deps:["mousedown","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["down","up"],info:{movefn:null,upfn:null},reset:function(){V(this.info)},mousedown:function(t){if(!$(t))return;let e=Z(t),s=this;J(this.info,(function(t){$(t)||(it("up",e,t),V(s.info))}),(function(t){$(t)&&it("up",e,t),V(s.info)})),it("down",e,t)},touchstart:function(t){it("down",Z(t),t.changedTouches[0],t)},touchend:function(t){it("up",Z(t),t.changedTouches[0],t)}}),et({name:"track",touchAction:"none",deps:["mousedown","touchstart","touchmove","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["track"],info:{x:0,y:0,state:"start",started:!1,moves:[],addMove:function(t){this.moves.length>2&&this.moves.shift(),this.moves.push(t)},movefn:null,upfn:null,prevent:!1},reset:function(){this.info.state="start",this.info.started=!1,this.info.moves=[],this.info.x=0,this.info.y=0,this.info.prevent=!1,V(this.info)},mousedown:function(t){if(!$(t))return;let e=Z(t),s=this,n=function(t){let n=t.clientX,r=t.clientY;ot(s.info,n,r)&&(s.info.state=s.info.started?"mouseup"===t.type?"end":"track":"start","start"===s.info.state&&rt("tap"),s.info.addMove({x:n,y:r}),$(t)||(s.info.state="end",V(s.info)),e&&at(s.info,e,t),s.info.started=!0)};J(this.info,n,(function(t){s.info.started&&n(t),V(s.info)})),this.info.x=t.clientX,this.info.y=t.clientY},touchstart:function(t){let e=t.changedTouches[0];this.info.x=e.clientX,this.info.y=e.clientY},touchmove:function(t){let e=Z(t),s=t.changedTouches[0],n=s.clientX,r=s.clientY;ot(this.info,n,r)&&("start"===this.info.state&&rt("tap"),this.info.addMove({x:n,y:r}),at(this.info,e,s),this.info.state="track",this.info.started=!0)},touchend:function(t){let e=Z(t),s=t.changedTouches[0];this.info.started&&(this.info.state="end",this.info.addMove({x:s.clientX,y:s.clientY}),at(this.info,e,s))}}),et({name:"tap",deps:["mousedown","click","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["click","touchend"]},emits:["tap"],info:{x:NaN,y:NaN,prevent:!1},reset:function(){this.info.x=NaN,this.info.y=NaN,this.info.prevent=!1},mousedown:function(t){$(t)&&(this.info.x=t.clientX,this.info.y=t.clientY)},click:function(t){$(t)&<(this.info,t)},touchstart:function(t){const e=t.changedTouches[0];this.info.x=e.clientX,this.info.y=e.clientY},touchend:function(t){lt(this.info,t.changedTouches[0],t)}});const ht=Z,dt=Q,ct=tt;var ut=Object.freeze({__proto__:null,gestures:X,recognizers:W,deepTargetFind:G,addListener:Q,removeListener:tt,register:et,setTouchAction:st,prevent:rt,resetMouseCanceller:function(){Y.mouse.mouseIgnoreJob&&Y.mouse.mouseIgnoreJob.flush()},findOriginalTarget:ht,add:dt,remove:ct});let pt={},_t={};class ft extends HTMLElement{static get observedAttributes(){return["id"]}static import(t,e){if(t){let s=function(t){return pt[t]||_t[t.toLowerCase()]}(t);return s&&e?s.querySelector(e):s}return null}attributeChangedCallback(t,e,s,n){e!==s&&this.register()}get assetpath(){if(!this.__assetpath){const t=window.HTMLImports&&HTMLImports.importForElement?HTMLImports.importForElement(this)||document:this.ownerDocument,e=b(this.getAttribute("assetpath")||"",t.baseURI);this.__assetpath=C(e)}return this.__assetpath}register(t){var e;(t=t||this.id)&&(this.id=t,function(t,e){pt[t]=_t[t.toLowerCase()]=e}(t,this),(e=this).querySelector("style")&&console.warn("dom-module %s has style outside template",e.id))}}ft.prototype.modules=pt,customElements.define("dom-module",ft);function mt(t){return ft.import(t)}function yt(t){const e=P((t.body?t.body:t).textContent,t.baseURI),s=document.createElement("style");return s.textContent=e,s}function gt(t){const e=t.trim().split(/\s+/),s=[];for(let t=0;t<e.length;t++)s.push(...bt(e[t]));return s}function bt(t){const e=mt(t);if(!e)return console.warn("Could not find style data in module named",t),[];if(void 0===e._styles){const t=[];t.push(...Ct(e));const s=e.querySelector("template");s&&t.push(...Pt(s,e.assetpath)),e._styles=t}return e._styles}function Pt(t,e){if(!t._styles){const s=[],n=t.content.querySelectorAll("style");for(let t=0;t<n.length;t++){let r=n[t],i=r.getAttribute("include");i&&s.push(...gt(i).filter((function(t,e,s){return s.indexOf(t)===e}))),e&&(r.textContent=P(r.textContent,e)),s.push(r)}t._styles=s}return t._styles}function Ct(t){const e=[],s=t.querySelectorAll("link[rel=import][type~=css]");for(let t=0;t<s.length;t++){let n=s[t];if(n.import){const t=n.import,s=n.hasAttribute("shady-unscoped");if(s&&!t._unscopedStyle){const e=yt(t);e.setAttribute("shady-unscoped",""),t._unscopedStyle=e}else t._style||(t._style=yt(t));e.push(s?t._unscopedStyle:t._style)}}return e}function vt(t){let e=mt(t);if(e&&void 0===e._cssText){let t=function(t){let e="",s=Ct(t);for(let t=0;t<s.length;t++)e+=s[t].textContent;return e}(e),s=e.querySelector("template");s&&(t+=function(t,e){let s="";const n=Pt(t,e);for(let t=0;t<n.length;t++){let e=n[t];e.parentNode&&e.parentNode.removeChild(e),s+=e.textContent}return s}(s,e.assetpath)),e._cssText=t||null}return e||console.warn("Could not find style data in module named",t),e&&e._cssText||""}function St(t){return t.indexOf(".")>=0}function wt(t){let e=t.indexOf(".");return-1===e?t:t.slice(0,e)}function Et(t,e){return 0===t.indexOf(e+".")}function Tt(t,e){return 0===e.indexOf(t+".")}function Ot(t,e,s){return e+s.slice(t.length)}function Nt(t,e){return t===e||Et(t,e)||Tt(t,e)}function xt(t){if(Array.isArray(t)){let e=[];for(let s=0;s<t.length;s++){let n=t[s].toString().split(".");for(let t=0;t<n.length;t++)e.push(n[t])}return e.join(".")}return t}function At(t){return Array.isArray(t)?xt(t).split("."):t.toString().split(".")}function It(t,e,s){let n=t,r=At(e);for(let t=0;t<r.length;t++){if(!n)return;n=n[r[t]]}return s&&(s.path=r.join(".")),n}function Mt(t,e,s){let n=t,r=At(e),i=r[r.length-1];if(r.length>1){for(let t=0;t<r.length-1;t++){if(n=n[r[t]],!n)return}n[i]=s}else n[e]=s;return r.join(".")}const Rt={},Lt=/-[a-z]/g,kt=/([A-Z])/g;function Dt(t){return Rt[t]||(Rt[t]=t.indexOf("-")<0?t:t.replace(Lt,(t=>t[1].toUpperCase())))}function Ft(t){return Rt[t]||(Rt[t]=t.replace(kt,"-$1").toLowerCase())}const Ht=l,zt=d((t=>class extends t{static createProperties(t){const e=this.prototype;for(let s in t)s in e||e._createPropertyAccessor(s)}static attributeNameForProperty(t){return t.toLowerCase()}static typeForProperty(t){}_createPropertyAccessor(t,e){this._addPropertyToAttributeMap(t),this.hasOwnProperty("__dataHasAccessor")||(this.__dataHasAccessor=Object.assign({},this.__dataHasAccessor)),this.__dataHasAccessor[t]||(this.__dataHasAccessor[t]=!0,this._definePropertyAccessor(t,e))}_addPropertyToAttributeMap(t){if(this.hasOwnProperty("__dataAttributes")||(this.__dataAttributes=Object.assign({},this.__dataAttributes)),!this.__dataAttributes[t]){const e=this.constructor.attributeNameForProperty(t);this.__dataAttributes[e]=t}}_definePropertyAccessor(t,e){Object.defineProperty(this,t,{get(){return this._getProperty(t)},set:e?function(){}:function(e){this._setProperty(t,e)}})}constructor(){super(),this.__dataEnabled=!1,this.__dataReady=!1,this.__dataInvalid=!1,this.__data={},this.__dataPending=null,this.__dataOld=null,this.__dataInstanceProps=null,this.__serializing=!1,this._initializeProperties()}ready(){this.__dataReady=!0,this._flushProperties()}_initializeProperties(){for(let t in this.__dataHasAccessor)this.hasOwnProperty(t)&&(this.__dataInstanceProps=this.__dataInstanceProps||{},this.__dataInstanceProps[t]=this[t],delete this[t])}_initializeInstanceProperties(t){Object.assign(this,t)}_setProperty(t,e){this._setPendingProperty(t,e)&&this._invalidateProperties()}_getProperty(t){return this.__data[t]}_setPendingProperty(t,e,s){let n=this.__data[t],r=this._shouldPropertyChange(t,e,n);return r&&(this.__dataPending||(this.__dataPending={},this.__dataOld={}),this.__dataOld&&!(t in this.__dataOld)&&(this.__dataOld[t]=n),this.__data[t]=e,this.__dataPending[t]=e),r}_invalidateProperties(){!this.__dataInvalid&&this.__dataReady&&(this.__dataInvalid=!0,Ht.run((()=>{this.__dataInvalid&&(this.__dataInvalid=!1,this._flushProperties())})))}_enableProperties(){this.__dataEnabled||(this.__dataEnabled=!0,this.__dataInstanceProps&&(this._initializeInstanceProperties(this.__dataInstanceProps),this.__dataInstanceProps=null),this.ready())}_flushProperties(){const t=this.__data,e=this.__dataPending,s=this.__dataOld;this._shouldPropertiesChange(t,e,s)&&(this.__dataPending=null,this.__dataOld=null,this._propertiesChanged(t,e,s))}_shouldPropertiesChange(t,e,s){return Boolean(e)}_propertiesChanged(t,e,s){}_shouldPropertyChange(t,e,s){return s!==e&&(s==s||e==e)}attributeChangedCallback(t,e,s,n){e!==s&&this._attributeToProperty(t,s),super.attributeChangedCallback&&super.attributeChangedCallback(t,e,s,n)}_attributeToProperty(t,e,s){if(!this.__serializing){const n=this.__dataAttributes,r=n&&n[t]||t;this[r]=this._deserializeValue(e,s||this.constructor.typeForProperty(r))}}_propertyToAttribute(t,e,s){this.__serializing=!0,s=arguments.length<3?this[t]:s,this._valueToNodeAttribute(this,s,e||this.constructor.attributeNameForProperty(t)),this.__serializing=!1}_valueToNodeAttribute(t,e,s){const n=this._serializeValue(e);void 0===n?t.removeAttribute(s):("class"!==s&&"name"!==s&&"slot"!==s||(t=E(t)),t.setAttribute(s,n))}_serializeValue(t){switch(typeof t){case"boolean":return t?"":void 0;default:return null!=t?t.toString():void 0}}_deserializeValue(t,e){switch(e){case Boolean:return null!==t;case Number:return Number(t);default:return t}}})),jt={};let Bt=HTMLElement.prototype;for(;Bt;){let t=Object.getOwnPropertyNames(Bt);for(let e=0;e<t.length;e++)jt[t[e]]=!0;Bt=Object.getPrototypeOf(Bt)}const qt=d((t=>{const e=zt(t);return class extends e{static createPropertiesForAttributes(){let t=this.observedAttributes;for(let e=0;e<t.length;e++)this.prototype._createPropertyAccessor(Dt(t[e]))}static attributeNameForProperty(t){return Ft(t)}_initializeProperties(){this.__dataProto&&(this._initializeProtoProperties(this.__dataProto),this.__dataProto=null),super._initializeProperties()}_initializeProtoProperties(t){for(let e in t)this._setProperty(e,t[e])}_ensureAttribute(t,e){const s=this;s.hasAttribute(t)||this._valueToNodeAttribute(s,e,t)}_serializeValue(t){switch(typeof t){case"object":if(t instanceof Date)return t.toString();if(t)try{return JSON.stringify(t)}catch(t){return""}default:return super._serializeValue(t)}}_deserializeValue(t,e){let s;switch(e){case Object:try{s=JSON.parse(t)}catch(e){s=t}break;case Array:try{s=JSON.parse(t)}catch(e){s=null,console.warn("Polymer::Attributes: couldn't decode Array as JSON: "+t)}break;case Date:s=isNaN(t)?String(t):Number(t),s=new Date(s);break;default:s=super._deserializeValue(t,e)}return s}_definePropertyAccessor(t,e){!function(t,e){if(!jt[e]){let s=t[e];void 0!==s&&(t.__data?t._setPendingProperty(e,s):(t.__dataProto?t.hasOwnProperty(JSCompiler_renameProperty("__dataProto",t))||(t.__dataProto=Object.create(t.__dataProto)):t.__dataProto={},t.__dataProto[e]=s))}}(this,t),super._definePropertyAccessor(t,e)}_hasAccessor(t){return this.__dataHasAccessor&&this.__dataHasAccessor[t]}_isPropertyPending(t){return Boolean(this.__dataPending&&t in this.__dataPending)}}})),$t=document.createTreeWalker(document,NodeFilter.SHOW_ALL,null,!1),Yt={"dom-if":!0,"dom-repeat":!0};function Jt(t){let e=t.getAttribute("is");if(e&&Yt[e]){let s=t;for(s.removeAttribute("is"),t=s.ownerDocument.createElement(e),s.parentNode.replaceChild(t,s),t.appendChild(s);s.attributes.length;)t.setAttribute(s.attributes[0].name,s.attributes[0].value),s.removeAttribute(s.attributes[0].name)}return t}function Vt(t,e){let s=e.parentInfo&&Vt(t,e.parentInfo);if(!s)return t;$t.currentNode=s;for(let t=$t.firstChild(),s=0;t;t=$t.nextSibling())if(e.parentIndex===s++)return t}function Ut(t,e,s,n){n.id&&(e[n.id]=s)}function Xt(t,e,s){if(s.events&&s.events.length)for(let n,r=0,i=s.events;r<i.length&&(n=i[r]);r++)t._addMethodEventListenerToNode(e,n.name,n.value,t)}function Wt(t,e,s){s.templateInfo&&(e._templateInfo=s.templateInfo)}const Gt=d((t=>class extends t{static _parseTemplate(t,e){if(!t._templateInfo){let e=t._templateInfo={};e.nodeInfoList=[],e.stripWhiteSpace=!0,this._parseTemplateContent(t,e,{parent:null})}return t._templateInfo}static _parseTemplateContent(t,e,s){return this._parseTemplateNode(t.content,e,s)}static _parseTemplateNode(t,e,s){let n,r=t;return"template"!=r.localName||r.hasAttribute("preserve-content")?"slot"===r.localName&&(e.hasInsertionPoint=!0):n=this._parseTemplateNestedTemplate(r,e,s)||n,$t.currentNode=r,$t.firstChild()&&(n=this._parseTemplateChildNodes(r,e,s)||n),r.hasAttributes&&r.hasAttributes()&&(n=this._parseTemplateNodeAttributes(r,e,s)||n),n}static _parseTemplateChildNodes(t,e,s){if("script"!==t.localName&&"style"!==t.localName){$t.currentNode=t;for(let n,r=$t.firstChild(),i=0;r;r=n){if("template"==r.localName&&(r=Jt(r)),$t.currentNode=r,n=$t.nextSibling(),r.nodeType===Node.TEXT_NODE){let s=n;for(;s&&s.nodeType===Node.TEXT_NODE;)r.textContent+=s.textContent,n=$t.nextSibling(),t.removeChild(s),s=n;if(e.stripWhiteSpace&&!r.textContent.trim()){t.removeChild(r);continue}}let o={parentIndex:i,parentInfo:s};this._parseTemplateNode(r,e,o)&&(o.infoIndex=e.nodeInfoList.push(o)-1),$t.currentNode=r,$t.parentNode()&&i++}}}static _parseTemplateNestedTemplate(t,e,s){let n=this._parseTemplate(t,e);return(n.content=t.content.ownerDocument.createDocumentFragment()).appendChild(t.content),s.templateInfo=n,!0}static _parseTemplateNodeAttributes(t,e,s){let n=!1,r=Array.from(t.attributes);for(let i,o=r.length-1;i=r[o];o--)n=this._parseTemplateNodeAttribute(t,e,s,i.name,i.value)||n;return n}static _parseTemplateNodeAttribute(t,e,s,n,r){return"on-"===n.slice(0,3)?(t.removeAttribute(n),s.events=s.events||[],s.events.push({name:n.slice(3),value:r}),!0):"id"===n&&(s.id=r,!0)}static _contentForTemplate(t){let e=t._templateInfo;return e&&e.content||t.content}_stampTemplate(t){t&&!t.content&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate&&HTMLTemplateElement.decorate(t);let e=this.constructor._parseTemplate(t),s=e.nodeInfoList,n=e.content||t.content,r=document.importNode(n,!0);r.__noInsertionPoint=!e.hasInsertionPoint;let i=r.nodeList=new Array(s.length);r.$={};for(let t,e=0,n=s.length;e<n&&(t=s[e]);e++){let s=i[e]=Vt(r,t);Ut(0,r.$,s,t),Wt(0,s,t),Xt(this,s,t)}return r=r,r}_addMethodEventListenerToNode(t,e,s,n){let r=function(t,e,s){return t=t._methodHost||t,function(e){t[s]?t[s](e,e.detail):console.warn("listener method `"+s+"` not defined")}}(n=n||t,0,s);return this._addEventListenerToNode(t,e,r),r}_addEventListenerToNode(t,e,s){t.addEventListener(e,s)}_removeEventListenerFromNode(t,e,s){t.removeEventListener(e,s)}}));let Zt=0;const Kt={COMPUTE:"__computeEffects",REFLECT:"__reflectEffects",NOTIFY:"__notifyEffects",PROPAGATE:"__propagateEffects",OBSERVE:"__observeEffects",READ_ONLY:"__readOnly"},Qt=/[A-Z]/;function te(t,e){let s=t[e];if(s){if(!t.hasOwnProperty(e)){s=t[e]=Object.create(t[e]);for(let t in s){let e=s[t],n=s[t]=Array(e.length);for(let t=0;t<e.length;t++)n[t]=e[t]}}}else s=t[e]={};return s}function ee(t,e,s,n,r,i){if(e){let o=!1,a=Zt++;for(let l in s)se(t,e,a,l,s,n,r,i)&&(o=!0);return o}return!1}function se(t,e,s,n,r,i,o,a){let l=!1,h=e[o?wt(n):n];if(h)for(let e,d=0,c=h.length;d<c&&(e=h[d]);d++)e.info&&e.info.lastRun===s||o&&!ne(n,e.trigger)||(e.info&&(e.info.lastRun=s),e.fn(t,n,r,i,e.info,o,a),l=!0);return l}function ne(t,e){if(e){let s=e.name;return s==t||!(!e.structured||!Et(s,t))||!(!e.wildcard||!Tt(s,t))}return!0}function re(t,e,s,n,r){let i="string"==typeof r.method?t[r.method]:r.method,o=r.property;i?i.call(t,t.__data[o],n[o]):r.dynamicFn||console.warn("observer method `"+r.method+"` not defined")}function ie(t,e,s){let n=wt(e);if(n!==e){return oe(t,Ft(n)+"-changed",s[e],e),!0}return!1}function oe(t,e,s,n){let r={value:s,queueProperty:!0};n&&(r.path=n),E(t).dispatchEvent(new CustomEvent(e,{detail:r}))}function ae(t,e,s,n,r,i){let o=(i?wt(e):e)!=e?e:null,a=o?It(t,o):t.__data[e];o&&void 0===a&&(a=s[e]),oe(t,r.eventName,a,o)}function le(t,e,s,n,r){let i=t.__data[e];w&&(i=w(i,r.attrName,"attribute",t)),t._propertyToAttribute(e,r.attrName,i)}function he(t,e,s,n,r){let i=me(t,e,s,n,r),o=r.methodInfo;t.__dataHasAccessor&&t.__dataHasAccessor[o]?t._setPendingProperty(o,i,!0):t[o]=i}function de(t,e,s,n,r,i,o){s.bindings=s.bindings||[];let a={kind:n,target:r,parts:i,literal:o,isCompound:1!==i.length};if(s.bindings.push(a),function(t){return Boolean(t.target)&&"attribute"!=t.kind&&"text"!=t.kind&&!t.isCompound&&"{"===t.parts[0].mode}(a)){let{event:t,negate:e}=a.parts[0];a.listenerEvent=t||Ft(r)+"-changed",a.listenerNegate=e}let l=e.nodeInfoList.length;for(let s=0;s<a.parts.length;s++){let n=a.parts[s];n.compoundIndex=s,ce(t,e,a,n,l)}}function ce(t,e,s,n,r){if(!n.literal)if("attribute"===s.kind&&"-"===s.target[0])console.warn("Cannot set attribute "+s.target+' because "-" is not a valid attribute starting character');else{let i=n.dependencies,o={index:r,binding:s,part:n,evaluator:t};for(let s=0;s<i.length;s++){let n=i[s];"string"==typeof n&&(n=Ce(n),n.wildcard=!0),t._addTemplatePropertyEffect(e,n.rootProperty,{fn:ue,info:o,trigger:n})}}}function ue(t,e,s,n,r,i,o){let a=o[r.index],l=r.binding,h=r.part;if(i&&h.source&&e.length>h.source.length&&"property"==l.kind&&!l.isCompound&&a.__isPropertyEffectsClient&&a.__dataHasAccessor&&a.__dataHasAccessor[l.target]){let n=s[e];e=Ot(h.source,l.target,e),a._setPendingPropertyOrPath(e,n,!1,!0)&&t._enqueueClient(a)}else{!function(t,e,s,n,r){r=function(t,e,s,n){if(s.isCompound){let r=t.__dataCompoundStorage[s.target];r[n.compoundIndex]=e,e=r.join("")}"attribute"!==s.kind&&("textContent"!==s.target&&("value"!==s.target||"input"!==t.localName&&"textarea"!==t.localName)||(e=null==e?"":e));return e}(e,r,s,n),w&&(r=w(r,s.target,s.kind,e));if("attribute"==s.kind)t._valueToNodeAttribute(e,r,s.target);else{let n=s.target;e.__isPropertyEffectsClient&&e.__dataHasAccessor&&e.__dataHasAccessor[n]?e[Kt.READ_ONLY]&&e[Kt.READ_ONLY][n]||e._setPendingProperty(n,r)&&t._enqueueClient(e):t._setUnmanagedPropertyToNode(e,n,r)}}(t,a,l,h,r.evaluator._evaluateBinding(t,h,e,s,n,i))}}function pe(t,e){if(e.isCompound){let s=t.__dataCompoundStorage||(t.__dataCompoundStorage={}),n=e.parts,r=new Array(n.length);for(let t=0;t<n.length;t++)r[t]=n[t].literal;let i=e.target;s[i]=r,e.literal&&"property"==e.kind&&(t[i]=e.literal)}}function _e(t,e,s){if(s.listenerEvent){let n=s.parts[0];t.addEventListener(s.listenerEvent,(function(t){!function(t,e,s,n,r){let i,o=t.detail,a=o&&o.path;a?(n=Ot(s,n,a),i=o&&o.value):i=t.currentTarget[s],i=r?!i:i,e[Kt.READ_ONLY]&&e[Kt.READ_ONLY][n]||!e._setPendingPropertyOrPath(n,i,!0,Boolean(a))||o&&o.queueProperty||e._invalidateProperties()}(t,e,s.target,n.source,n.negate)}))}}function fe(t,e,s,n,r,i){i=e.static||i&&("object"!=typeof i||i[e.methodName]);let o={methodName:e.methodName,args:e.args,methodInfo:r,dynamicFn:i};for(let r,i=0;i<e.args.length&&(r=e.args[i]);i++)r.literal||t._addPropertyEffect(r.rootProperty,s,{fn:n,info:o,trigger:r});i&&t._addPropertyEffect(e.methodName,s,{fn:n,info:o})}function me(t,e,s,n,r){let i=t._methodHost||t,o=i[r.methodName];if(o){let n=t._marshalArgs(r.args,e,s);return o.apply(i,n)}r.dynamicFn||console.warn("method `"+r.methodName+"` not defined")}const ye=[],ge=new RegExp("(\\[\\[|{{)\\s*(?:(!)\\s*)?((?:[a-zA-Z_$][\\w.:$\\-*]*)\\s*(?:\\(\\s*(?:(?:(?:((?:[a-zA-Z_$][\\w.:$\\-*]*)|(?:[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)|(?:(?:'(?:[^'\\\\]|\\\\.)*')|(?:\"(?:[^\"\\\\]|\\\\.)*\")))\\s*)(?:,\\s*(?:((?:[a-zA-Z_$][\\w.:$\\-*]*)|(?:[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)|(?:(?:'(?:[^'\\\\]|\\\\.)*')|(?:\"(?:[^\"\\\\]|\\\\.)*\")))\\s*))*)?)\\)\\s*)?)(?:]]|}})","g");function be(t){let e="";for(let s=0;s<t.length;s++){e+=t[s].literal||""}return e}function Pe(t){let e=t.match(/([^\s]+?)\(([\s\S]*)\)/);if(e){let t={methodName:e[1],static:!0,args:ye};if(e[2].trim()){return function(t,e){return e.args=t.map((function(t){let s=Ce(t);return s.literal||(e.static=!1),s}),this),e}(e[2].replace(/\\,/g,",").split(","),t)}return t}return null}function Ce(t){let e=t.trim().replace(/,/g,",").replace(/\\(.)/g,"$1"),s={name:e,value:"",literal:!1},n=e[0];switch("-"===n&&(n=e[1]),n>="0"&&n<="9"&&(n="#"),n){case"'":case'"':s.value=e.slice(1,-1),s.literal=!0;break;case"#":s.value=Number(e),s.literal=!0}return s.literal||(s.rootProperty=wt(e),s.structured=St(e),s.structured&&(s.wildcard=".*"==e.slice(-2),s.wildcard&&(s.name=e.slice(0,-2)))),s}function ve(t,e,s){let n=It(t,s);return void 0===n&&(n=e[s]),n}function Se(t,e,s,n){t.notifyPath(s+".splices",{indexSplices:n}),t.notifyPath(s+".length",e.length)}function we(t,e,s,n,r,i){Se(t,e,s,[{index:n,addedCount:r,removed:i,object:e,type:"splice"}])}const Ee=d((t=>{const e=Gt(qt(t));return class extends e{constructor(){super(),this.__isPropertyEffectsClient=!0,this.__dataCounter=0,this.__dataClientsReady,this.__dataPendingClients,this.__dataToNotify,this.__dataLinkedPaths,this.__dataHasPaths,this.__dataCompoundStorage,this.__dataHost,this.__dataTemp,this.__dataClientsInitialized,this.__data,this.__dataPending,this.__dataOld,this.__computeEffects,this.__reflectEffects,this.__notifyEffects,this.__propagateEffects,this.__observeEffects,this.__readOnly,this.__templateInfo}get PROPERTY_EFFECT_TYPES(){return Kt}_initializeProperties(){super._initializeProperties(),Te.registerHost(this),this.__dataClientsReady=!1,this.__dataPendingClients=null,this.__dataToNotify=null,this.__dataLinkedPaths=null,this.__dataHasPaths=!1,this.__dataCompoundStorage=this.__dataCompoundStorage||null,this.__dataHost=this.__dataHost||null,this.__dataTemp={},this.__dataClientsInitialized=!1}_initializeProtoProperties(t){this.__data=Object.create(t),this.__dataPending=Object.create(t),this.__dataOld={}}_initializeInstanceProperties(t){let e=this[Kt.READ_ONLY];for(let s in t)e&&e[s]||(this.__dataPending=this.__dataPending||{},this.__dataOld=this.__dataOld||{},this.__data[s]=this.__dataPending[s]=t[s])}_addPropertyEffect(t,e,s){this._createPropertyAccessor(t,e==Kt.READ_ONLY);let n=te(this,e)[t];n||(n=this[e][t]=[]),n.push(s)}_removePropertyEffect(t,e,s){let n=te(this,e)[t],r=n.indexOf(s);r>=0&&n.splice(r,1)}_hasPropertyEffect(t,e){let s=this[e];return Boolean(s&&s[t])}_hasReadOnlyEffect(t){return this._hasPropertyEffect(t,Kt.READ_ONLY)}_hasNotifyEffect(t){return this._hasPropertyEffect(t,Kt.NOTIFY)}_hasReflectEffect(t){return this._hasPropertyEffect(t,Kt.REFLECT)}_hasComputedEffect(t){return this._hasPropertyEffect(t,Kt.COMPUTE)}_setPendingPropertyOrPath(t,e,s,n){if(n||wt(Array.isArray(t)?t[0]:t)!==t){if(!n){let s=It(this,t);if(!(t=Mt(this,t,e))||!super._shouldPropertyChange(t,e,s))return!1}if(this.__dataHasPaths=!0,this._setPendingProperty(t,e,s))return function(t,e,s){let n=t.__dataLinkedPaths;if(n){let r;for(let i in n){let o=n[i];Tt(i,e)?(r=Ot(i,o,e),t._setPendingPropertyOrPath(r,s,!0,!0)):Tt(o,e)&&(r=Ot(o,i,e),t._setPendingPropertyOrPath(r,s,!0,!0))}}}(this,t,e),!0}else{if(this.__dataHasAccessor&&this.__dataHasAccessor[t])return this._setPendingProperty(t,e,s);this[t]=e}return!1}_setUnmanagedPropertyToNode(t,e,s){s===t[e]&&"object"!=typeof s||(t[e]=s)}_setPendingProperty(t,e,s){let n=this.__dataHasPaths&&St(t),r=n?this.__dataTemp:this.__data;return!!this._shouldPropertyChange(t,e,r[t])&&(this.__dataPending||(this.__dataPending={},this.__dataOld={}),t in this.__dataOld||(this.__dataOld[t]=this.__data[t]),n?this.__dataTemp[t]=e:this.__data[t]=e,this.__dataPending[t]=e,(n||this[Kt.NOTIFY]&&this[Kt.NOTIFY][t])&&(this.__dataToNotify=this.__dataToNotify||{},this.__dataToNotify[t]=s),!0)}_setProperty(t,e){this._setPendingProperty(t,e,!0)&&this._invalidateProperties()}_invalidateProperties(){this.__dataReady&&this._flushProperties()}_enqueueClient(t){this.__dataPendingClients=this.__dataPendingClients||[],t!==this&&this.__dataPendingClients.push(t)}_flushProperties(){this.__dataCounter++,super._flushProperties(),this.__dataCounter--}_flushClients(){this.__dataClientsReady?this.__enableOrFlushClients():(this.__dataClientsReady=!0,this._readyClients(),this.__dataReady=!0)}__enableOrFlushClients(){let t=this.__dataPendingClients;if(t){this.__dataPendingClients=null;for(let e=0;e<t.length;e++){let s=t[e];s.__dataEnabled?s.__dataPending&&s._flushProperties():s._enableProperties()}}}_readyClients(){this.__enableOrFlushClients()}setProperties(t,e){for(let s in t)!e&&this[Kt.READ_ONLY]&&this[Kt.READ_ONLY][s]||this._setPendingPropertyOrPath(s,t[s],!0);this._invalidateProperties()}ready(){this._flushProperties(),this.__dataClientsReady||this._flushClients(),this.__dataPending&&this._flushProperties()}_propertiesChanged(t,e,s){let n=this.__dataHasPaths;this.__dataHasPaths=!1,function(t,e,s,n){let r=t[Kt.COMPUTE];if(r){let i=e;for(;ee(t,r,i,s,n);)Object.assign(s,t.__dataOld),Object.assign(e,t.__dataPending),i=t.__dataPending,t.__dataPending=null}}(this,e,s,n);let r=this.__dataToNotify;this.__dataToNotify=null,this._propagatePropertyChanges(e,s,n),this._flushClients(),ee(this,this[Kt.REFLECT],e,s,n),ee(this,this[Kt.OBSERVE],e,s,n),r&&function(t,e,s,n,r){let i,o,a=t[Kt.NOTIFY],l=Zt++;for(let o in e)e[o]&&(a&&se(t,a,l,o,s,n,r)||r&&ie(t,o,s))&&(i=!0);i&&(o=t.__dataHost)&&o._invalidateProperties&&o._invalidateProperties()}(this,r,e,s,n),1==this.__dataCounter&&(this.__dataTemp={})}_propagatePropertyChanges(t,e,s){this[Kt.PROPAGATE]&&ee(this,this[Kt.PROPAGATE],t,e,s);let n=this.__templateInfo;for(;n;)ee(this,n.propertyEffects,t,e,s,n.nodeList),n=n.nextTemplateInfo}linkPaths(t,e){t=xt(t),e=xt(e),this.__dataLinkedPaths=this.__dataLinkedPaths||{},this.__dataLinkedPaths[t]=e}unlinkPaths(t){t=xt(t),this.__dataLinkedPaths&&delete this.__dataLinkedPaths[t]}notifySplices(t,e){let s={path:""};Se(this,It(this,t,s),s.path,e)}get(t,e){return It(e||this,t)}set(t,e,s){s?Mt(s,t,e):this[Kt.READ_ONLY]&&this[Kt.READ_ONLY][t]||this._setPendingPropertyOrPath(t,e,!0)&&this._invalidateProperties()}push(t,...e){let s={path:""},n=It(this,t,s),r=n.length,i=n.push(...e);return e.length&&we(this,n,s.path,r,e.length,[]),i}pop(t){let e={path:""},s=It(this,t,e),n=Boolean(s.length),r=s.pop();return n&&we(this,s,e.path,s.length,0,[r]),r}splice(t,e,s,...n){let r,i={path:""},o=It(this,t,i);return e<0?e=o.length-Math.floor(-e):e&&(e=Math.floor(e)),r=2===arguments.length?o.splice(e):o.splice(e,s,...n),(n.length||r.length)&&we(this,o,i.path,e,n.length,r),r}shift(t){let e={path:""},s=It(this,t,e),n=Boolean(s.length),r=s.shift();return n&&we(this,s,e.path,0,0,[r]),r}unshift(t,...e){let s={path:""},n=It(this,t,s),r=n.unshift(...e);return e.length&&we(this,n,s.path,0,e.length,[]),r}notifyPath(t,e){let s;if(1==arguments.length){let n={path:""};e=It(this,t,n),s=n.path}else s=Array.isArray(t)?xt(t):t;this._setPendingPropertyOrPath(s,e,!0,!0)&&this._invalidateProperties()}_createReadOnlyProperty(t,e){var s;this._addPropertyEffect(t,Kt.READ_ONLY),e&&(this["_set"+(s=t,s[0].toUpperCase()+s.substring(1))]=function(e){this._setProperty(t,e)})}_createPropertyObserver(t,e,s){let n={property:t,method:e,dynamicFn:Boolean(s)};this._addPropertyEffect(t,Kt.OBSERVE,{fn:re,info:n,trigger:{name:t}}),s&&this._addPropertyEffect(e,Kt.OBSERVE,{fn:re,info:n,trigger:{name:e}})}_createMethodObserver(t,e){let s=Pe(t);if(!s)throw new Error("Malformed observer expression '"+t+"'");fe(this,s,Kt.OBSERVE,me,null,e)}_createNotifyingProperty(t){this._addPropertyEffect(t,Kt.NOTIFY,{fn:ae,info:{eventName:Ft(t)+"-changed",property:t}})}_createReflectedProperty(t){let e=this.constructor.attributeNameForProperty(t);"-"===e[0]?console.warn("Property "+t+" cannot be reflected to attribute "+e+' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.'):this._addPropertyEffect(t,Kt.REFLECT,{fn:le,info:{attrName:e}})}_createComputedProperty(t,e,s){let n=Pe(e);if(!n)throw new Error("Malformed computed expression '"+e+"'");fe(this,n,Kt.COMPUTE,he,t,s)}_marshalArgs(t,e,s){const n=this.__data,r=[];for(let i=0,o=t.length;i<o;i++){let{name:o,structured:a,wildcard:l,value:h,literal:d}=t[i];if(!d)if(l){const t=Tt(o,e),r=ve(n,s,t?e:o);h={path:t?e:o,value:r,base:t?It(n,o):r}}else h=a?ve(n,s,o):n[o];r[i]=h}return r}static addPropertyEffect(t,e,s){this.prototype._addPropertyEffect(t,e,s)}static createPropertyObserver(t,e,s){this.prototype._createPropertyObserver(t,e,s)}static createMethodObserver(t,e){this.prototype._createMethodObserver(t,e)}static createNotifyingProperty(t){this.prototype._createNotifyingProperty(t)}static createReadOnlyProperty(t,e){this.prototype._createReadOnlyProperty(t,e)}static createReflectedProperty(t){this.prototype._createReflectedProperty(t)}static createComputedProperty(t,e,s){this.prototype._createComputedProperty(t,e,s)}static bindTemplate(t){return this.prototype._bindTemplate(t)}_bindTemplate(t,e){let s=this.constructor._parseTemplate(t),n=this.__templateInfo==s;if(!n)for(let t in s.propertyEffects)this._createPropertyAccessor(t);if(e&&(s=Object.create(s),s.wasPreBound=n,!n&&this.__templateInfo)){let t=this.__templateInfoLast||this.__templateInfo;return this.__templateInfoLast=t.nextTemplateInfo=s,s.previousTemplateInfo=t,s}return this.__templateInfo=s}static _addTemplatePropertyEffect(t,e,s){(t.hostProps=t.hostProps||{})[e]=!0;let n=t.propertyEffects=t.propertyEffects||{};(n[e]=n[e]||[]).push(s)}_stampTemplate(t){Te.beginHosting(this);let e=super._stampTemplate(t);Te.endHosting(this);let s=this._bindTemplate(t,!0);if(s.nodeList=e.nodeList,!s.wasPreBound){let t=s.childNodes=[];for(let s=e.firstChild;s;s=s.nextSibling)t.push(s)}return e.templateInfo=s,function(t,e){let{nodeList:s,nodeInfoList:n}=e;if(n.length)for(let e=0;e<n.length;e++){let r=n[e],i=s[e],o=r.bindings;if(o)for(let e=0;e<o.length;e++){let s=o[e];pe(i,s),_e(i,t,s)}i.__dataHost=t}}(this,s),this.__dataReady&&ee(this,s.propertyEffects,this.__data,null,!1,s.nodeList),e}_removeBoundDom(t){let e=t.templateInfo;e.previousTemplateInfo&&(e.previousTemplateInfo.nextTemplateInfo=e.nextTemplateInfo),e.nextTemplateInfo&&(e.nextTemplateInfo.previousTemplateInfo=e.previousTemplateInfo),this.__templateInfoLast==e&&(this.__templateInfoLast=e.previousTemplateInfo),e.previousTemplateInfo=e.nextTemplateInfo=null;let s=e.childNodes;for(let t=0;t<s.length;t++){let e=s[t];e.parentNode.removeChild(e)}}static _parseTemplateNode(t,e,s){let n=super._parseTemplateNode(t,e,s);if(t.nodeType===Node.TEXT_NODE){let r=this._parseBindings(t.textContent,e);r&&(t.textContent=be(r)||" ",de(this,e,s,"text","textContent",r),n=!0)}return n}static _parseTemplateNodeAttribute(t,e,s,n,r){let i=this._parseBindings(r,e);if(i){let r=n,o="property";Qt.test(n)?o="attribute":"$"==n[n.length-1]&&(n=n.slice(0,-1),o="attribute");let a=be(i);return a&&"attribute"==o&&("class"==n&&t.hasAttribute("class")&&(a+=" "+t.getAttribute(n)),t.setAttribute(n,a)),"input"===t.localName&&"value"===r&&t.setAttribute(r,""),t.removeAttribute(r),"property"===o&&(n=Dt(n)),de(this,e,s,o,n,i,a),!0}return super._parseTemplateNodeAttribute(t,e,s,n,r)}static _parseTemplateNestedTemplate(t,e,s){let n=super._parseTemplateNestedTemplate(t,e,s),r=s.templateInfo.hostProps;for(let t in r){de(this,e,s,"property","_host_"+t,[{mode:"{",source:t,dependencies:[t]}])}return n}static _parseBindings(t,e){let s,n=[],r=0;for(;null!==(s=ge.exec(t));){s.index>r&&n.push({literal:t.slice(r,s.index)});let i=s[1][0],o=Boolean(s[2]),a=s[3].trim(),l=!1,h="",d=-1;"{"==i&&(d=a.indexOf("::"))>0&&(h=a.substring(d+2),a=a.substring(0,d),l=!0);let c=Pe(a),u=[];if(c){let{args:t,methodName:s}=c;for(let e=0;e<t.length;e++){let s=t[e];s.literal||u.push(s)}let n=e.dynamicFns;(n&&n[s]||c.static)&&(u.push(s),c.dynamicFn=!0)}else u.push(a);n.push({source:a,mode:i,negate:o,customEvent:l,signature:c,dependencies:u,event:h}),r=ge.lastIndex}if(r&&r<t.length){let e=t.substring(r);e&&n.push({literal:e})}return n.length?n:null}static _evaluateBinding(t,e,s,n,r,i){let o;return o=e.signature?me(t,s,n,0,e.signature):s!=e.source?It(t,e.source):i&&St(s)?It(t,s):t.__data[s],e.negate&&(o=!o),o}}}));const Te=new class{constructor(){this.stack=[]}registerHost(t){if(this.stack.length){this.stack[this.stack.length-1]._enqueueClient(t)}}beginHosting(t){this.stack.push(t)}endHosting(t){let e=this.stack.length;e&&this.stack[e-1]==t&&this.stack.pop()}};const Oe=d((t=>{const e=zt(t);function s(t){const e=Object.getPrototypeOf(t);return e.prototype instanceof r?e:null}function n(t){if(!t.hasOwnProperty(JSCompiler_renameProperty("__ownProperties",t))){let e=null;if(t.hasOwnProperty(JSCompiler_renameProperty("properties",t))){const s=t.properties;s&&(e=function(t){const e={};for(let s in t){const n=t[s];e[s]="function"==typeof n?{type:n}:n}return e}(s))}t.__ownProperties=e}return t.__ownProperties}class r extends e{static get observedAttributes(){if(!this.hasOwnProperty("__observedAttributes")){this.prototype;const t=this._properties;this.__observedAttributes=t?Object.keys(t).map((t=>this.attributeNameForProperty(t))):[]}return this.__observedAttributes}static finalize(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__finalized",this))){const t=s(this);t&&t.finalize(),this.__finalized=!0,this._finalizeClass()}}static _finalizeClass(){const t=n(this);t&&this.createProperties(t)}static get _properties(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__properties",this))){const t=s(this);this.__properties=Object.assign({},t&&t._properties,n(this))}return this.__properties}static typeForProperty(t){const e=this._properties[t];return e&&e.type}_initializeProperties(){this.constructor.finalize(),super._initializeProperties()}connectedCallback(){super.connectedCallback&&super.connectedCallback(),this._enableProperties()}disconnectedCallback(){super.disconnectedCallback&&super.disconnectedCallback()}}return r})),Ne=window.ShadyCSS&&window.ShadyCSS.cssBuild,xe=d((t=>{const e=Oe(Ee(t));function s(t,e,s,n){s.computed&&(s.readOnly=!0),s.computed&&(t._hasReadOnlyEffect(e)?console.warn(`Cannot redefine computed property '${e}'.`):t._createComputedProperty(e,s.computed,n)),s.readOnly&&!t._hasReadOnlyEffect(e)?t._createReadOnlyProperty(e,!s.computed):!1===s.readOnly&&t._hasReadOnlyEffect(e)&&console.warn(`Cannot make readOnly property '${e}' non-readOnly.`),s.reflectToAttribute&&!t._hasReflectEffect(e)?t._createReflectedProperty(e):!1===s.reflectToAttribute&&t._hasReflectEffect(e)&&console.warn(`Cannot make reflected property '${e}' non-reflected.`),s.notify&&!t._hasNotifyEffect(e)?t._createNotifyingProperty(e):!1===s.notify&&t._hasNotifyEffect(e)&&console.warn(`Cannot make notify property '${e}' non-notify.`),s.observer&&t._createPropertyObserver(e,s.observer,n[s.observer]),t._addPropertyToAttributeMap(e)}function n(t,e,s,n){if(!Ne){const r=e.content.querySelectorAll("style"),i=Pt(e),o=function(t){let e=mt(t);return e?Ct(e):[]}(s),a=e.content.firstElementChild;for(let s=0;s<o.length;s++){let r=o[s];r.textContent=t._processStyleText(r.textContent,n),e.content.insertBefore(r,a)}let l=0;for(let e=0;e<i.length;e++){let s=i[e],o=r[l];o!==s?(s=s.cloneNode(!0),o.parentNode.insertBefore(s,o)):l++,s.textContent=t._processStyleText(s.textContent,n)}}window.ShadyCSS&&window.ShadyCSS.prepareTemplate(e,s)}return class extends e{static get polymerElementVersion(){return"3.2.0"}static _finalizeClass(){super._finalizeClass();const t=((e=this).hasOwnProperty(JSCompiler_renameProperty("__ownObservers",e))||(e.__ownObservers=e.hasOwnProperty(JSCompiler_renameProperty("observers",e))?e.observers:null),e.__ownObservers);var e;t&&this.createObservers(t,this._properties),this._prepareTemplate()}static _prepareTemplate(){let t=this.template;t&&("string"==typeof t?(console.error("template getter must return HTMLTemplateElement"),t=null):t=t.cloneNode(!0)),this.prototype._template=t}static createProperties(t){for(let e in t)s(this.prototype,e,t[e],t)}static createObservers(t,e){const s=this.prototype;for(let n=0;n<t.length;n++)s._createMethodObserver(t[n],e)}static get template(){return this.hasOwnProperty(JSCompiler_renameProperty("_template",this))||(this._template=this.prototype.hasOwnProperty(JSCompiler_renameProperty("_template",this.prototype))?this.prototype._template:function(t){let e=null;return t&&(e=ft.import(t,"template")),e}(this.is)||Object.getPrototypeOf(this.prototype).constructor.template),this._template}static set template(t){this._template=t}static get importPath(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_importPath",this))){const t=this.importMeta;if(t)this._importPath=C(t.url);else{const t=ft.import(this.is);this._importPath=t&&t.assetpath||Object.getPrototypeOf(this.prototype).constructor.importPath}}return this._importPath}constructor(){super(),this._template,this._importPath,this.rootPath,this.importPath,this.root,this.$}_initializeProperties(){this.constructor.finalize(),this.constructor._finalizeTemplate(this.localName),super._initializeProperties(),this.rootPath=S,this.importPath=this.constructor.importPath;let t=function(t){if(!t.hasOwnProperty(JSCompiler_renameProperty("__propertyDefaults",t))){t.__propertyDefaults=null;let e=t._properties;for(let s in e){let n=e[s];"value"in n&&(t.__propertyDefaults=t.__propertyDefaults||{},t.__propertyDefaults[s]=n)}}return t.__propertyDefaults}(this.constructor);if(t)for(let e in t){let s=t[e];if(!this.hasOwnProperty(e)){let t="function"==typeof s.value?s.value.call(this):s.value;this._hasAccessor(e)?this._setPendingProperty(e,t,!0):this[e]=t}}}static _processStyleText(t,e){return P(t,e)}static _finalizeTemplate(t){const e=this.prototype._template;if(e&&!e.__polymerFinalized){e.__polymerFinalized=!0;const s=this.importPath;n(this,e,t,s?b(s):""),this.prototype._bindTemplate(e)}}connectedCallback(){window.ShadyCSS&&this._template&&window.ShadyCSS.styleElement(this),super.connectedCallback()}ready(){this._template&&(this.root=this._stampTemplate(this._template),this.$=this.root.$),super.ready()}_readyClients(){this._template&&(this.root=this._attachDom(this.root)),super._readyClients()}_attachDom(t){const e=E(this);if(e.attachShadow)return t?(e.shadowRoot||e.attachShadow({mode:"open"}),e.shadowRoot.appendChild(t),e.shadowRoot):null;throw new Error("ShadowDOM not available. PolymerElement can create dom as children instead of in ShadowDOM by setting `this.root = this;` before `ready`.")}updateStyles(t){window.ShadyCSS&&window.ShadyCSS.styleSubtree(this,t)}resolveUrl(t,e){return!e&&this.importPath&&(e=b(this.importPath)),b(t,e)}static _parseTemplateContent(t,e,s){return e.dynamicFns=e.dynamicFns||this._properties,super._parseTemplateContent(t,e,s)}static _addTemplatePropertyEffect(t,e,s){return super._addTemplatePropertyEffect(t,e,s)}}}));class Ae{constructor(t){this.value=t.toString()}toString(){return this.value}}function Ie(t){if(t instanceof HTMLTemplateElement)return t.innerHTML;if(t instanceof Ae)return function(t){if(t instanceof Ae)return t.value;throw new Error("non-literal value passed to Polymer's htmlLiteral function: "+t)}(t);throw new Error("non-template value passed to Polymer's html function: "+t)}const Me=function(t,...e){const s=document.createElement("template");return s.innerHTML=e.reduce(((e,s,n)=>e+Ie(s)+t[n+1]),t[0]),s},Re=xe(HTMLElement);function Le(t,e,s,n,r){let i;r&&(i="object"==typeof s&&null!==s,i&&(n=t.__dataTemp[e]));let o=n!==s&&(n==n||s==s);return i&&o&&(t.__dataTemp[e]=s),o}const ke=d((t=>class extends t{_shouldPropertyChange(t,e,s){return Le(this,t,e,s,!0)}})),De=d((t=>class extends t{static get properties(){return{mutableData:Boolean}}_shouldPropertyChange(t,e,s){return Le(this,t,e,s,this.mutableData)}}));ke._mutablePropertyChange=Le;let Fe=null;function He(){return Fe}He.prototype=Object.create(HTMLTemplateElement.prototype,{constructor:{value:He,writable:!0}});const ze=Ee(He),je=ke(ze);const Be=Ee(class{});class qe extends Be{constructor(t){super(),this._configureProperties(t),this.root=this._stampTemplate(this.__dataHost);let e=this.children=[];for(let t=this.root.firstChild;t;t=t.nextSibling)e.push(t),t.__templatizeInstance=this;this.__templatizeOwner&&this.__templatizeOwner.__hideTemplateChildren__&&this._showHideChildren(!0);let s=this.__templatizeOptions;(t&&s.instanceProps||!s.instanceProps)&&this._enableProperties()}_configureProperties(t){if(this.__templatizeOptions.forwardHostProp)for(let t in this.__hostProps)this._setPendingProperty(t,this.__dataHost["_host_"+t]);for(let e in t)this._setPendingProperty(e,t[e])}forwardHostProp(t,e){this._setPendingPropertyOrPath(t,e,!1,!0)&&this.__dataHost._enqueueClient(this)}_addEventListenerToNode(t,e,s){if(this._methodHost&&this.__templatizeOptions.parentModel)this._methodHost._addEventListenerToNode(t,e,(t=>{t.model=this,s(t)}));else{let n=this.__dataHost.__dataHost;n&&n._addEventListenerToNode(t,e,s)}}_showHideChildren(t){let e=this.children;for(let s=0;s<e.length;s++){let n=e[s];if(Boolean(t)!=Boolean(n.__hideTemplateChildren__))if(n.nodeType===Node.TEXT_NODE)t?(n.__polymerTextContent__=n.textContent,n.textContent=""):n.textContent=n.__polymerTextContent__;else if("slot"===n.localName)if(t)n.__polymerReplaced__=document.createComment("hidden-slot"),E(E(n).parentNode).replaceChild(n.__polymerReplaced__,n);else{const t=n.__polymerReplaced__;t&&E(E(t).parentNode).replaceChild(n,t)}else n.style&&(t?(n.__polymerDisplay__=n.style.display,n.style.display="none"):n.style.display=n.__polymerDisplay__);n.__hideTemplateChildren__=t,n._showHideChildren&&n._showHideChildren(t)}}_setUnmanagedPropertyToNode(t,e,s){t.__hideTemplateChildren__&&t.nodeType==Node.TEXT_NODE&&"textContent"==e?t.__polymerTextContent__=s:super._setUnmanagedPropertyToNode(t,e,s)}get parentModel(){let t=this.__parentModel;if(!t){let e;t=this;do{t=t.__dataHost.__dataHost}while((e=t.__templatizeOptions)&&!e.parentModel);this.__parentModel=t}return t}dispatchEvent(t){return!0}}qe.prototype.__dataHost,qe.prototype.__templatizeOptions,qe.prototype._methodHost,qe.prototype.__templatizeOwner,qe.prototype.__hostProps;const $e=ke(qe);function Ye(t,e,s){let n=s.mutableData?$e:qe;Xe.mixin&&(n=Xe.mixin(n));let r=class extends n{};return r.prototype.__templatizeOptions=s,r.prototype._bindTemplate(t),function(t,e,s,n){let r=s.hostProps||{};for(let e in n.instanceProps){delete r[e];let s=n.notifyInstanceProp;s&&t.prototype._addPropertyEffect(e,t.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:Ue(e,s)})}if(n.forwardHostProp&&e.__dataHost)for(let e in r)t.prototype._addPropertyEffect(e,t.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:function(t,e,s){t.__dataHost._setPendingPropertyOrPath("_host_"+e,s[e],!0,!0)}})}(r,t,e,s),r}function Je(t,e,s){let n=s.forwardHostProp;if(n){let r=e.templatizeTemplateClass;if(!r){let t=s.mutableData?je:ze;r=e.templatizeTemplateClass=class extends t{};let i=e.hostProps;for(let t in i)r.prototype._addPropertyEffect("_host_"+t,r.prototype.PROPERTY_EFFECT_TYPES.PROPAGATE,{fn:Ve(t,n)}),r.prototype._createNotifyingProperty("_host_"+t)}!function(t,e){Fe=t,Object.setPrototypeOf(t,e.prototype),new e,Fe=null}(t,r),t.__dataProto&&Object.assign(t.__data,t.__dataProto),t.__dataTemp={},t.__dataPending=null,t.__dataOld=null,t._enableProperties()}}function Ve(t,e){return function(t,s,n){e.call(t.__templatizeOwner,s.substring("_host_".length),n[s])}}function Ue(t,e){return function(t,s,n){e.call(t.__templatizeOwner,t,s,n[s])}}function Xe(t,e,s){if(s=s||{},t.__templatizeOwner)throw new Error("A <template> can only be templatized once");t.__templatizeOwner=e;let n=(e?e.constructor:qe)._parseTemplate(t),r=n.templatizeInstanceClass;r||(r=Ye(t,n,s),n.templatizeInstanceClass=r),Je(t,n,s);let i=class extends r{};return i.prototype._methodHost=function(t){let e=t.__dataHost;return e&&e._methodHost||e}(t),i.prototype.__dataHost=t,i.prototype.__templatizeOwner=e,i.prototype.__hostProps=n.hostProps,i=i,i}function We(t,e){let s;for(;e;)if(s=e.__templatizeInstance){if(s.__dataHost==t)return s;e=s.__dataHost}else e=E(e).parentNode;return null}const Ge=function(){let t,e;do{t=window.ShadyDOM&&ShadyDOM.flush(),window.ShadyCSS&&window.ShadyCSS.ScopingShim&&window.ShadyCSS.ScopingShim.flush(),e=_()}while(t||e)};class Ze extends Re{static get is(){return"dom-if"}static get template(){return null}static get properties(){return{if:{type:Boolean,observer:"__debounceRender"},restamp:{type:Boolean,observer:"__debounceRender"}}}constructor(){super(),this.__renderDebouncer=null,this.__invalidProps=null,this.__instance=null,this._lastIf=!1,this.__ctor=null,this.__hideTemplateChildren__=!1}__debounceRender(){this.__renderDebouncer=c.debounce(this.__renderDebouncer,l,(()=>this.__render())),p(this.__renderDebouncer)}disconnectedCallback(){super.disconnectedCallback();const t=E(this).parentNode;t&&(t.nodeType!=Node.DOCUMENT_FRAGMENT_NODE||E(t).host)||this.__teardownInstance()}connectedCallback(){super.connectedCallback(),this.style.display="none",this.if&&this.__debounceRender()}render(){Ge()}__render(){if(this.if){if(!this.__ensureInstance())return;this._showHideChildren()}else this.restamp&&this.__teardownInstance();!this.restamp&&this.__instance&&this._showHideChildren(),this.if!=this._lastIf&&(this.dispatchEvent(new CustomEvent("dom-change",{bubbles:!0,composed:!0})),this._lastIf=this.if)}__ensureInstance(){let t=E(this).parentNode;if(t){if(!this.__ctor){let t=E(this).querySelector("template");if(!t){let t=new MutationObserver((()=>{if(!E(this).querySelector("template"))throw new Error("dom-if requires a <template> child");t.disconnect(),this.__render()}));return t.observe(this,{childList:!0}),!1}this.__ctor=Xe(t,this,{mutableData:!0,forwardHostProp:function(t,e){this.__instance&&(this.if?this.__instance.forwardHostProp(t,e):(this.__invalidProps=this.__invalidProps||Object.create(null),this.__invalidProps[wt(t)]=!0))}})}if(this.__instance){this.__syncHostProperties();let e=this.__instance.children;if(e&&e.length){if(E(this).previousSibling!==e[e.length-1])for(let s,n=0;n<e.length&&(s=e[n]);n++)E(t).insertBefore(s,this)}}else this.__instance=new this.__ctor,E(t).insertBefore(this.__instance.root,this)}return!0}__syncHostProperties(){let t=this.__invalidProps;if(t){for(let e in t)this.__instance._setPendingProperty(e,this.__dataHost[e]);this.__invalidProps=null,this.__instance._flushProperties()}}__teardownInstance(){if(this.__instance){let t=this.__instance.children;if(t&&t.length){let e=E(t[0]).parentNode;if(e){e=E(e);for(let s,n=0;n<t.length&&(s=t[n]);n++)e.removeChild(s)}}this.__instance=null,this.__invalidProps=null}}_showHideChildren(){let t=this.__hideTemplateChildren__||!this.if;this.__instance&&this.__instance._showHideChildren(t)}}customElements.define(Ze.is,Ze);const Ke=De(Re);class Qe extends Ke{static get is(){return"dom-repeat"}static get template(){return null}static get properties(){return{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},itemsIndexAs:{type:String,value:"itemsIndex"},sort:{type:Function,observer:"__sortChanged"},filter:{type:Function,observer:"__filterChanged"},observe:{type:String,observer:"__observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!0,readOnly:!0},initialCount:{type:Number,observer:"__initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"__computeFrameTime(targetFramerate)"}}}static get observers(){return["__itemsChanged(items.*)"]}constructor(){super(),this.__instances=[],this.__limit=1/0,this.__pool=[],this.__renderDebouncer=null,this.__itemsIdxToInstIdx={},this.__chunkCount=null,this.__lastChunkTime=null,this.__sortFn=null,this.__filterFn=null,this.__observePaths=null,this.__ctor=null,this.__isDetached=!0,this.template=null}disconnectedCallback(){super.disconnectedCallback(),this.__isDetached=!0;for(let t=0;t<this.__instances.length;t++)this.__detachInstance(t)}connectedCallback(){if(super.connectedCallback(),this.style.display="none",this.__isDetached){this.__isDetached=!1;let t=E(E(this).parentNode);for(let e=0;e<this.__instances.length;e++)this.__attachInstance(e,t)}}__ensureTemplatized(){if(!this.__ctor){let t=this.template=this.querySelector("template");if(!t){let t=new MutationObserver((()=>{if(!this.querySelector("template"))throw new Error("dom-repeat requires a <template> child");t.disconnect(),this.__render()}));return t.observe(this,{childList:!0}),!1}let e={};e[this.as]=!0,e[this.indexAs]=!0,e[this.itemsIndexAs]=!0,this.__ctor=Xe(t,this,{mutableData:this.mutableData,parentModel:!0,instanceProps:e,forwardHostProp:function(t,e){let s=this.__instances;for(let n,r=0;r<s.length&&(n=s[r]);r++)n.forwardHostProp(t,e)},notifyInstanceProp:function(t,e,s){if(Nt(this.as,e)){let n=t[this.itemsIndexAs];e==this.as&&(this.items[n]=s);let r=Ot(this.as,`${JSCompiler_renameProperty("items",this)}.${n}`,e);this.notifyPath(r,s)}}})}return!0}__getMethodHost(){return this.__dataHost._methodHost||this.__dataHost}__functionFromPropertyValue(t){if("string"==typeof t){let e=t,s=this.__getMethodHost();return function(){return s[e].apply(s,arguments)}}return t}__sortChanged(t){this.__sortFn=this.__functionFromPropertyValue(t),this.items&&this.__debounceRender(this.__render)}__filterChanged(t){this.__filterFn=this.__functionFromPropertyValue(t),this.items&&this.__debounceRender(this.__render)}__computeFrameTime(t){return Math.ceil(1e3/t)}__initializeChunking(){this.initialCount&&(this.__limit=this.initialCount,this.__chunkCount=this.initialCount,this.__lastChunkTime=performance.now())}__tryRenderChunk(){this.items&&this.__limit<this.items.length&&this.__debounceRender(this.__requestRenderChunk)}__requestRenderChunk(){requestAnimationFrame((()=>this.__renderChunk()))}__renderChunk(){let t=performance.now(),e=this._targetFrameTime/(t-this.__lastChunkTime);this.__chunkCount=Math.round(this.__chunkCount*e)||1,this.__limit+=this.__chunkCount,this.__lastChunkTime=t,this.__debounceRender(this.__render)}__observeChanged(){this.__observePaths=this.observe&&this.observe.replace(".*",".").split(" ")}__itemsChanged(t){this.items&&!Array.isArray(this.items)&&console.warn("dom-repeat expected array for `items`, found",this.items),this.__handleItemPath(t.path,t.value)||(this.__initializeChunking(),this.__debounceRender(this.__render))}__handleObservedPaths(t){if(this.__sortFn||this.__filterFn)if(t){if(this.__observePaths){let e=this.__observePaths;for(let s=0;s<e.length;s++)0===t.indexOf(e[s])&&this.__debounceRender(this.__render,this.delay)}}else this.__debounceRender(this.__render,this.delay)}__debounceRender(t,e=0){this.__renderDebouncer=c.debounce(this.__renderDebouncer,e>0?i.after(e):l,t.bind(this)),p(this.__renderDebouncer)}render(){this.__debounceRender(this.__render),Ge()}__render(){this.__ensureTemplatized()&&(this.__applyFullRefresh(),this.__pool.length=0,this._setRenderedItemCount(this.__instances.length),this.dispatchEvent(new CustomEvent("dom-change",{bubbles:!0,composed:!0})),this.__tryRenderChunk())}__applyFullRefresh(){let t=this.items||[],e=new Array(t.length);for(let s=0;s<t.length;s++)e[s]=s;this.__filterFn&&(e=e.filter(((e,s,n)=>this.__filterFn(t[e],s,n)))),this.__sortFn&&e.sort(((e,s)=>this.__sortFn(t[e],t[s])));const s=this.__itemsIdxToInstIdx={};let n=0;const r=Math.min(e.length,this.__limit);for(;n<r;n++){let r=this.__instances[n],i=e[n],o=t[i];s[i]=n,r?(r._setPendingProperty(this.as,o),r._setPendingProperty(this.indexAs,n),r._setPendingProperty(this.itemsIndexAs,i),r._flushProperties()):this.__insertInstance(o,n,i)}for(let t=this.__instances.length-1;t>=n;t--)this.__detachAndRemoveInstance(t)}__detachInstance(t){let e=this.__instances[t];const s=E(e.root);for(let t=0;t<e.children.length;t++){let n=e.children[t];s.appendChild(n)}return e}__attachInstance(t,e){let s=this.__instances[t];e.insertBefore(s.root,this)}__detachAndRemoveInstance(t){let e=this.__detachInstance(t);e&&this.__pool.push(e),this.__instances.splice(t,1)}__stampInstance(t,e,s){let n={};return n[this.as]=t,n[this.indexAs]=e,n[this.itemsIndexAs]=s,new this.__ctor(n)}__insertInstance(t,e,s){let n=this.__pool.pop();n?(n._setPendingProperty(this.as,t),n._setPendingProperty(this.indexAs,e),n._setPendingProperty(this.itemsIndexAs,s),n._flushProperties()):n=this.__stampInstance(t,e,s);let r=this.__instances[e+1],i=r?r.children[0]:this;return E(E(this).parentNode).insertBefore(n.root,i),this.__instances[e]=n,n}_showHideChildren(t){for(let e=0;e<this.__instances.length;e++)this.__instances[e]._showHideChildren(t)}__handleItemPath(t,e){let s=t.slice(6),n=s.indexOf("."),r=n<0?s:s.substring(0,n);if(r==parseInt(r,10)){let t=n<0?"":s.substring(n+1);this.__handleObservedPaths(t);let i=this.__itemsIdxToInstIdx[r],o=this.__instances[i];if(o){let s=this.as+(t?"."+t:"");o._setPendingPropertyOrPath(s,e,!1,!0),o._flushProperties()}return!0}}itemForElement(t){let e=this.modelForElement(t);return e&&e[this.as]}indexForElement(t){let e=this.modelForElement(t);return e&&e[this.indexAs]}modelForElement(t){return We(this.template,t)}}customElements.define(Qe.is,Qe);const ts=!(window.ShadyDOM&&window.ShadyDOM.inUse);let es,ss;function ns(t){es=(!t||!t.shimcssproperties)&&(ts||Boolean(!navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/)&&window.CSS&&CSS.supports&&CSS.supports("box-shadow","0 0 0 var(--foo)")))}window.ShadyCSS&&void 0!==window.ShadyCSS.cssBuild&&(ss=window.ShadyCSS.cssBuild);const rs=Boolean(window.ShadyCSS&&window.ShadyCSS.disableRuntime);window.ShadyCSS&&void 0!==window.ShadyCSS.nativeCss?es=window.ShadyCSS.nativeCss:window.ShadyCSS?(ns(window.ShadyCSS),window.ShadyCSS=void 0):ns(window.WebComponents&&window.WebComponents.flags);const is=es;class os{constructor(){this.start=0,this.end=0,this.previous=null,this.parent=null,this.rules=null,this.parsedCssText="",this.cssText="",this.atRule=!1,this.type=0,this.keyframesName="",this.selector="",this.parsedSelector=""}}function as(t){return ls(function(t){let e=new os;e.start=0,e.end=t.length;let s=e;for(let n=0,r=t.length;n<r;n++)if(t[n]===cs){s.rules||(s.rules=[]);let t=s,e=t.rules[t.rules.length-1]||null;s=new os,s.start=n+1,s.parent=t,s.previous=e,t.rules.push(s)}else t[n]===us&&(s.end=n+1,s=s.parent||e);return e}(t=t.replace(ps.comments,"").replace(ps.port,"")),t)}function ls(t,e){let s=e.substring(t.start,t.end-1);if(t.parsedCssText=t.cssText=s.trim(),t.parent){let n=t.previous?t.previous.end:t.parent.start;s=e.substring(n,t.start-1),s=function(t){return t.replace(/\\([0-9a-f]{1,6})\s/gi,(function(){let t=arguments[1],e=6-t.length;for(;e--;)t="0"+t;return"\\"+t}))}(s),s=s.replace(ps.multipleSpaces," "),s=s.substring(s.lastIndexOf(";")+1);let r=t.parsedSelector=t.selector=s.trim();t.atRule=0===r.indexOf(ms),t.atRule?0===r.indexOf(fs)?t.type=ds.MEDIA_RULE:r.match(ps.keyframesRule)&&(t.type=ds.KEYFRAMES_RULE,t.keyframesName=t.selector.split(ps.multipleSpaces).pop()):0===r.indexOf(_s)?t.type=ds.MIXIN_RULE:t.type=ds.STYLE_RULE}let n=t.rules;if(n)for(let t,s=0,r=n.length;s<r&&(t=n[s]);s++)ls(t,e);return t}function hs(t,e,s=""){let n="";if(t.cssText||t.rules){let s=t.rules;if(s&&!function(t){let e=t[0];return Boolean(e)&&Boolean(e.selector)&&0===e.selector.indexOf(_s)}(s))for(let t,r=0,i=s.length;r<i&&(t=s[r]);r++)n=hs(t,e,n);else n=e?t.cssText:function(t){return function(t){return t.replace(ps.mixinApply,"").replace(ps.varApply,"")}(t=function(t){return t.replace(ps.customProp,"").replace(ps.mixinProp,"")}(t))}(t.cssText),n=n.trim(),n&&(n=" "+n+"\n")}return n&&(t.selector&&(s+=t.selector+" "+cs+"\n"),s+=n,t.selector&&(s+=us+"\n\n")),s}const ds={STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1e3},cs="{",us="}",ps={comments:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g},_s="--",fs="@media",ms="@",ys=/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};{])+)|\{([^}]*)\}(?:(?=[;\s}])|$))/gi,gs=/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,bs=/@media\s(.*)/,Ps=new Set;function Cs(t){const e=t.textContent;if(!Ps.has(e)){Ps.add(e);const s=t.cloneNode(!0);document.head.appendChild(s)}}function vs(t){return t.hasAttribute("shady-unscoped")}function Ss(t,e){return t?("string"==typeof t&&(t=as(t)),e&&Es(t,e),hs(t,is)):""}function ws(t){return!t.__cssRules&&t.textContent&&(t.__cssRules=as(t.textContent)),t.__cssRules||null}function Es(t,e,s,n){if(!t)return;let r=!1,i=t.type;if(n&&i===ds.MEDIA_RULE){let e=t.selector.match(bs);e&&(window.matchMedia(e[1]).matches||(r=!0))}i===ds.STYLE_RULE?e(t):s&&i===ds.KEYFRAMES_RULE?s(t):i===ds.MIXIN_RULE&&(r=!0);let o=t.rules;if(o&&!r)for(let t,r=0,i=o.length;r<i&&(t=o[r]);r++)Es(t,e,s,n)}function Ts(t,e){let s=t.indexOf("var(");if(-1===s)return e(t,"","","");let n=function(t,e){let s=0;for(let n=e,r=t.length;n<r;n++)if("("===t[n])s++;else if(")"===t[n]&&0==--s)return n;return-1}(t,s+3),r=t.substring(s+4,n),i=t.substring(0,s),o=Ts(t.substring(n+1),e),a=r.indexOf(",");return-1===a?e(i,r.trim(),"",o):e(i,r.substring(0,a).trim(),r.substring(a+1).trim(),o)}window.ShadyDOM&&window.ShadyDOM.wrap;function Os(t){if(void 0!==ss)return ss;if(void 0===t.__cssBuild){const e=t.getAttribute("css-build");if(e)t.__cssBuild=e;else{const e=function(t){const e="template"===t.localName?t.content.firstChild:t.firstChild;if(e instanceof Comment){const t=e.textContent.trim().split(":");if("css-build"===t[0])return t[1]}return""}(t);""!==e&&function(t){const e="template"===t.localName?t.content.firstChild:t.firstChild;e.parentNode.removeChild(e)}(t),t.__cssBuild=e}}return t.__cssBuild||""}function Ns(t){return""!==Os(t)}function xs(t,e){for(let s in e)null===s?t.style.removeProperty(s):t.style.setProperty(s,e[s])}function As(t,e){const s=window.getComputedStyle(t).getPropertyValue(e);return s?s.trim():""}const Is=/;\s*/m,Ms=/^\s*(initial)|(inherit)\s*$/,Rs=/\s*!important/;class Ls{constructor(){this._map={}}set(t,e){t=t.trim(),this._map[t]={properties:e,dependants:{}}}get(t){return t=t.trim(),this._map[t]||null}}let ks=null;class Ds{constructor(){this._currentElement=null,this._measureElement=null,this._map=new Ls}detectMixin(t){return function(t){const e=gs.test(t)||ys.test(t);return gs.lastIndex=0,ys.lastIndex=0,e}(t)}gatherStyles(t){const e=function(t){const e=[],s=t.querySelectorAll("style");for(let t=0;t<s.length;t++){const n=s[t];vs(n)?ts||(Cs(n),n.parentNode.removeChild(n)):(e.push(n.textContent),n.parentNode.removeChild(n))}return e.join("").trim()}(t.content);if(e){const s=document.createElement("style");return s.textContent=e,t.content.insertBefore(s,t.content.firstChild),s}return null}transformTemplate(t,e){void 0===t._gatheredStyle&&(t._gatheredStyle=this.gatherStyles(t));const s=t._gatheredStyle;return s?this.transformStyle(s,e):null}transformStyle(t,e=""){let s=ws(t);return this.transformRules(s,e),t.textContent=Ss(s),s}transformCustomStyle(t){let e=ws(t);return Es(e,(t=>{":root"===t.selector&&(t.selector="html"),this.transformRule(t)})),t.textContent=Ss(e),e}transformRules(t,e){this._currentElement=e,Es(t,(t=>{this.transformRule(t)})),this._currentElement=null}transformRule(t){t.cssText=this.transformCssText(t.parsedCssText,t),":root"===t.selector&&(t.selector=":host > *")}transformCssText(t,e){return t=t.replace(ys,((t,s,n,r)=>this._produceCssProperties(t,s,n,r,e))),this._consumeCssProperties(t,e)}_getInitialValueForProperty(t){return this._measureElement||(this._measureElement=document.createElement("meta"),this._measureElement.setAttribute("apply-shim-measure",""),this._measureElement.style.all="initial",document.head.appendChild(this._measureElement)),window.getComputedStyle(this._measureElement).getPropertyValue(t)}_fallbacksFromPreviousRules(t){let e=t;for(;e.parent;)e=e.parent;const s={};let n=!1;return Es(e,(e=>{n=n||e===t,n||e.selector===t.selector&&Object.assign(s,this._cssTextToMap(e.parsedCssText))})),s}_consumeCssProperties(t,e){let s=null;for(;s=gs.exec(t);){let n=s[0],r=s[1],i=s.index,o=i+n.indexOf("@apply"),a=i+n.length,l=t.slice(0,o),h=t.slice(a),d=e?this._fallbacksFromPreviousRules(e):{};Object.assign(d,this._cssTextToMap(l));let c=this._atApplyToCssProperties(r,d);t=`${l}${c}${h}`,gs.lastIndex=i+c.length}return t}_atApplyToCssProperties(t,e){t=t.replace(Is,"");let s=[],n=this._map.get(t);if(n||(this._map.set(t,{}),n=this._map.get(t)),n){let r,i,o;this._currentElement&&(n.dependants[this._currentElement]=!0);const a=n.properties;for(r in a)o=e&&e[r],i=[r,": var(",t,"_-_",r],o&&i.push(",",o.replace(Rs,"")),i.push(")"),Rs.test(a[r])&&i.push(" !important"),s.push(i.join(""))}return s.join("; ")}_replaceInitialOrInherit(t,e){let s=Ms.exec(e);return s&&(e=s[1]?this._getInitialValueForProperty(t):"apply-shim-inherit"),e}_cssTextToMap(t,e=!1){let s,n,r=t.split(";"),i={};for(let t,o,a=0;a<r.length;a++)t=r[a],t&&(o=t.split(":"),o.length>1&&(s=o[0].trim(),n=o.slice(1).join(":"),e&&(n=this._replaceInitialOrInherit(s,n)),i[s]=n));return i}_invalidateMixinEntry(t){if(ks)for(let e in t.dependants)e!==this._currentElement&&ks(e)}_produceCssProperties(t,e,s,n,r){if(s&&Ts(s,((t,e)=>{e&&this._map.get(e)&&(n=`@apply ${e};`)})),!n)return t;let i=this._consumeCssProperties(""+n,r),o=t.slice(0,t.indexOf("--")),a=this._cssTextToMap(i,!0),l=a,h=this._map.get(e),d=h&&h.properties;d?l=Object.assign(Object.create(d),a):this._map.set(e,l);let c,u,p=[],_=!1;for(c in l)u=a[c],void 0===u&&(u="initial"),d&&!(c in d)&&(_=!0),p.push(`${e}_-_${c}: ${u}`);return _&&this._invalidateMixinEntry(h),h&&(h.properties=l),s&&(o=`${t};${o}`),`${o}${p.join("; ")};`}}Ds.prototype.detectMixin=Ds.prototype.detectMixin,Ds.prototype.transformStyle=Ds.prototype.transformStyle,Ds.prototype.transformCustomStyle=Ds.prototype.transformCustomStyle,Ds.prototype.transformRules=Ds.prototype.transformRules,Ds.prototype.transformRule=Ds.prototype.transformRule,Ds.prototype.transformTemplate=Ds.prototype.transformTemplate,Ds.prototype._separator="_-_",Object.defineProperty(Ds.prototype,"invalidCallback",{get:()=>ks,set(t){ks=t}});const Fs={},Hs="_applyShimCurrentVersion",zs="_applyShimNextVersion",js="_applyShimValidatingVersion",Bs=Promise.resolve();function qs(t){let e=Fs[t];e&&function(t){t[Hs]=t[Hs]||0,t[js]=t[js]||0,t[zs]=(t[zs]||0)+1}(e)}function $s(t){return t[Hs]===t[zs]}let Ys,Js=null,Vs=window.HTMLImports&&window.HTMLImports.whenReady||null;function Us(t){requestAnimationFrame((function(){Vs?Vs(t):(Js||(Js=new Promise((t=>{Ys=t})),"complete"===document.readyState?Ys():document.addEventListener("readystatechange",(()=>{"complete"===document.readyState&&Ys()}))),Js.then((function(){t&&t()})))}))}const Xs="__shadyCSSCachedStyle";let Ws=null,Gs=null;class Zs{constructor(){this.customStyles=[],this.enqueued=!1,Us((()=>{window.ShadyCSS.flushCustomStyles&&window.ShadyCSS.flushCustomStyles()}))}enqueueDocumentValidation(){!this.enqueued&&Gs&&(this.enqueued=!0,Us(Gs))}addCustomStyle(t){t.__seenByShadyCSS||(t.__seenByShadyCSS=!0,this.customStyles.push(t),this.enqueueDocumentValidation())}getStyleForCustomStyle(t){if(t[Xs])return t[Xs];let e;return e=t.getStyle?t.getStyle():t,e}processStyles(){const t=this.customStyles;for(let e=0;e<t.length;e++){const s=t[e];if(s[Xs])continue;const n=this.getStyleForCustomStyle(s);if(n){const t=n.__appliedElement||n;Ws&&Ws(t),s[Xs]=t}}return t}}Zs.prototype.addCustomStyle=Zs.prototype.addCustomStyle,Zs.prototype.getStyleForCustomStyle=Zs.prototype.getStyleForCustomStyle,Zs.prototype.processStyles=Zs.prototype.processStyles,Object.defineProperties(Zs.prototype,{transformCallback:{get:()=>Ws,set(t){Ws=t}},validateCallback:{get:()=>Gs,set(t){let e=!1;Gs||(e=!0),Gs=t,e&&this.enqueueDocumentValidation()}}});const Ks=new Ds;class Qs{constructor(){this.customStyleInterface=null,Ks.invalidCallback=qs}ensure(){this.customStyleInterface||window.ShadyCSS.CustomStyleInterface&&(this.customStyleInterface=window.ShadyCSS.CustomStyleInterface,this.customStyleInterface.transformCallback=t=>{Ks.transformCustomStyle(t)},this.customStyleInterface.validateCallback=()=>{requestAnimationFrame((()=>{this.customStyleInterface.enqueued&&this.flushCustomStyles()}))})}prepareTemplate(t,e){if(this.ensure(),Ns(t))return;Fs[e]=t;let s=Ks.transformTemplate(t,e);t._styleAst=s}flushCustomStyles(){if(this.ensure(),!this.customStyleInterface)return;let t=this.customStyleInterface.processStyles();if(this.customStyleInterface.enqueued){for(let e=0;e<t.length;e++){let s=t[e],n=this.customStyleInterface.getStyleForCustomStyle(s);n&&Ks.transformCustomStyle(n)}this.customStyleInterface.enqueued=!1}}styleSubtree(t,e){if(this.ensure(),e&&xs(t,e),t.shadowRoot){this.styleElement(t);let e=t.shadowRoot.children||t.shadowRoot.childNodes;for(let t=0;t<e.length;t++)this.styleSubtree(e[t])}else{let e=t.children||t.childNodes;for(let t=0;t<e.length;t++)this.styleSubtree(e[t])}}styleElement(t){this.ensure();let{is:e}=function(t){let e=t.localName,s="",n="";return e?e.indexOf("-")>-1?s=e:(n=e,s=t.getAttribute&&t.getAttribute("is")||""):(s=t.is,n=t.extends),{is:s,typeExtension:n}}(t),s=Fs[e];if((!s||!Ns(s))&&s&&!$s(s)){(function(t){return!$s(t)&&t[js]===t[zs]})(s)||(this.prepareTemplate(s,e),function(t){t[js]=t[zs],t._validating||(t._validating=!0,Bs.then((function(){t[Hs]=t[zs],t._validating=!1})))}(s));let n=t.shadowRoot;if(n){let t=n.querySelector("style");t&&(t.__cssRules=s._styleAst,t.textContent=Ss(s._styleAst))}}}styleDocument(t){this.ensure(),this.styleSubtree(document.body,t)}}if(!window.ShadyCSS||!window.ShadyCSS.ScopingShim){const t=new Qs;let e=window.ShadyCSS&&window.ShadyCSS.CustomStyleInterface;window.ShadyCSS={prepareTemplate(e,s,n){t.flushCustomStyles(),t.prepareTemplate(e,s)},prepareTemplateStyles(t,e,s){window.ShadyCSS.prepareTemplate(t,e,s)},prepareTemplateDom(t,e){},styleSubtree(e,s){t.flushCustomStyles(),t.styleSubtree(e,s)},styleElement(e){t.flushCustomStyles(),t.styleElement(e)},styleDocument(e){t.flushCustomStyles(),t.styleDocument(e)},getComputedStyleValue:(t,e)=>As(t,e),flushCustomStyles(){t.flushCustomStyles()},nativeCss:is,nativeShadow:ts,cssBuild:ss,disableRuntime:rs},e&&(window.ShadyCSS.CustomStyleInterface=e)}window.ShadyCSS.ApplyShim=Ks;const tn=d((t=>class extends t{_addEventListenerToNode(t,e,s){Q(t,e,s)||super._addEventListenerToNode(t,e,s)}_removeEventListenerFromNode(t,e,s){tt(t,e,s)||super._removeEventListenerFromNode(t,e,s)}}));let en=!1,sn=[],nn=[];function rn(){en=!0,requestAnimationFrame((function(){en=!1,function(t){for(;t.length;)on(t.shift())}(sn),setTimeout((function(){!function(t){for(let e=0,s=t.length;e<s;e++)on(t.shift())}(nn)}))}))}function on(t){const e=t[0],s=t[1],n=t[2];try{s.apply(e,n)}catch(t){setTimeout((()=>{throw t}))}}function an(t,e,s){en||rn(),sn.push([t,e,s])}function ln(t,e,s){en||rn(),nn.push([t,e,s])}function hn(){document.body.removeAttribute("unresolved")}function dn(t,e,s){return{index:t,removed:e,addedCount:s}}"interactive"===document.readyState||"complete"===document.readyState?hn():window.addEventListener("DOMContentLoaded",hn);function cn(t,e,s,n,r,i){let o,a=0,l=0,h=Math.min(s-e,i-r);if(0==e&&0==r&&(a=function(t,e,s){for(let n=0;n<s;n++)if(!pn(t[n],e[n]))return n;return s}(t,n,h)),s==t.length&&i==n.length&&(l=function(t,e,s){let n=t.length,r=e.length,i=0;for(;i<s&&pn(t[--n],e[--r]);)i++;return i}(t,n,h-a)),r+=a,i-=l,(s-=l)-(e+=a)==0&&i-r==0)return[];if(e==s){for(o=dn(e,[],0);r<i;)o.removed.push(n[r++]);return[o]}if(r==i)return[dn(e,[],s-e)];let d=function(t){let e=t.length-1,s=t[0].length-1,n=t[e][s],r=[];for(;e>0||s>0;){if(0==e){r.push(2),s--;continue}if(0==s){r.push(3),e--;continue}let i,o=t[e-1][s-1],a=t[e-1][s],l=t[e][s-1];i=a<l?a<o?a:o:l<o?l:o,i==o?(o==n?r.push(0):(r.push(1),n=o),e--,s--):i==a?(r.push(3),e--,n=a):(r.push(2),s--,n=l)}return r.reverse(),r}(function(t,e,s,n,r,i){let o=i-r+1,a=s-e+1,l=new Array(o);for(let t=0;t<o;t++)l[t]=new Array(a),l[t][0]=t;for(let t=0;t<a;t++)l[0][t]=t;for(let s=1;s<o;s++)for(let i=1;i<a;i++)if(pn(t[e+i-1],n[r+s-1]))l[s][i]=l[s-1][i-1];else{let t=l[s-1][i]+1,e=l[s][i-1]+1;l[s][i]=t<e?t:e}return l}(t,e,s,n,r,i));o=void 0;let c=[],u=e,p=r;for(let t=0;t<d.length;t++)switch(d[t]){case 0:o&&(c.push(o),o=void 0),u++,p++;break;case 1:o||(o=dn(u,[],0)),o.addedCount++,u++,o.removed.push(n[p]),p++;break;case 2:o||(o=dn(u,[],0)),o.addedCount++,u++;break;case 3:o||(o=dn(u,[],0)),o.removed.push(n[p]),p++}return o&&c.push(o),c}function un(t,e){return cn(t,0,t.length,e,0,e.length)}function pn(t,e){return t===e}function _n(t){return"slot"===t.localName}let fn=class{static getFlattenedNodes(t){const e=E(t);return _n(t)?(t=t,e.assignedNodes({flatten:!0})):Array.from(e.childNodes).map((t=>_n(t)?E(t=t).assignedNodes({flatten:!0}):[t])).reduce(((t,e)=>t.concat(e)),[])}constructor(t,e){this._shadyChildrenObserver=null,this._nativeChildrenObserver=null,this._connected=!1,this._target=t,this.callback=e,this._effectiveNodes=[],this._observer=null,this._scheduled=!1,this._boundSchedule=()=>{this._schedule()},this.connect(),this._schedule()}connect(){_n(this._target)?this._listenSlots([this._target]):E(this._target).children&&(this._listenSlots(E(this._target).children),window.ShadyDOM?this._shadyChildrenObserver=ShadyDOM.observeChildren(this._target,(t=>{this._processMutations(t)})):(this._nativeChildrenObserver=new MutationObserver((t=>{this._processMutations(t)})),this._nativeChildrenObserver.observe(this._target,{childList:!0}))),this._connected=!0}disconnect(){_n(this._target)?this._unlistenSlots([this._target]):E(this._target).children&&(this._unlistenSlots(E(this._target).children),window.ShadyDOM&&this._shadyChildrenObserver?(ShadyDOM.unobserveChildren(this._shadyChildrenObserver),this._shadyChildrenObserver=null):this._nativeChildrenObserver&&(this._nativeChildrenObserver.disconnect(),this._nativeChildrenObserver=null)),this._connected=!1}_schedule(){this._scheduled||(this._scheduled=!0,l.run((()=>this.flush())))}_processMutations(t){this._processSlotMutations(t),this.flush()}_processSlotMutations(t){if(t)for(let e=0;e<t.length;e++){let s=t[e];s.addedNodes&&this._listenSlots(s.addedNodes),s.removedNodes&&this._unlistenSlots(s.removedNodes)}}flush(){if(!this._connected)return!1;window.ShadyDOM&&ShadyDOM.flush(),this._nativeChildrenObserver?this._processSlotMutations(this._nativeChildrenObserver.takeRecords()):this._shadyChildrenObserver&&this._processSlotMutations(this._shadyChildrenObserver.takeRecords()),this._scheduled=!1;let t={target:this._target,addedNodes:[],removedNodes:[]},e=this.constructor.getFlattenedNodes(this._target),s=un(e,this._effectiveNodes);for(let e,n=0;n<s.length&&(e=s[n]);n++)for(let s,n=0;n<e.removed.length&&(s=e.removed[n]);n++)t.removedNodes.push(s);for(let n,r=0;r<s.length&&(n=s[r]);r++)for(let s=n.index;s<n.index+n.addedCount;s++)t.addedNodes.push(e[s]);this._effectiveNodes=e;let n=!1;return(t.addedNodes.length||t.removedNodes.length)&&(n=!0,this.callback.call(this._target,t)),n}_listenSlots(t){for(let e=0;e<t.length;e++){let s=t[e];_n(s)&&s.addEventListener("slotchange",this._boundSchedule)}}_unlistenSlots(t){for(let e=0;e<t.length;e++){let s=t[e];_n(s)&&s.removeEventListener("slotchange",this._boundSchedule)}}};const mn=Element.prototype,yn=mn.matches||mn.matchesSelector||mn.mozMatchesSelector||mn.msMatchesSelector||mn.oMatchesSelector||mn.webkitMatchesSelector,gn=function(t,e){return yn.call(t,e)};class bn{constructor(t){this.node=t}observeNodes(t){return new fn(this.node,t)}unobserveNodes(t){t.disconnect()}notifyObserver(){}deepContains(t){if(E(this.node).contains(t))return!0;let e=t,s=t.ownerDocument;for(;e&&e!==s&&e!==this.node;)e=E(e).parentNode||E(e).host;return e===this.node}getOwnerRoot(){return E(this.node).getRootNode()}getDistributedNodes(){return"slot"===this.node.localName?E(this.node).assignedNodes({flatten:!0}):[]}getDestinationInsertionPoints(){let t=[],e=E(this.node).assignedSlot;for(;e;)t.push(e),e=E(e).assignedSlot;return t}importNode(t,e){let s=this.node instanceof Document?this.node:this.node.ownerDocument;return E(s).importNode(t,e)}getEffectiveChildNodes(){return fn.getFlattenedNodes(this.node)}queryDistributedElements(t){let e=this.getEffectiveChildNodes(),s=[];for(let n,r=0,i=e.length;r<i&&(n=e[r]);r++)n.nodeType===Node.ELEMENT_NODE&&gn(n,t)&&s.push(n);return s}get activeElement(){let t=this.node;return void 0!==t._activeElement?t._activeElement:t.activeElement}}function Pn(t,e){for(let s=0;s<e.length;s++){let n=e[s];Object.defineProperty(t,n,{get:function(){return this.node[n]},configurable:!0})}}class Cn{constructor(t){this.event=t}get rootTarget(){return this.path[0]}get localTarget(){return this.event.target}get path(){return this.event.composedPath()}}bn.prototype.cloneNode,bn.prototype.appendChild,bn.prototype.insertBefore,bn.prototype.removeChild,bn.prototype.replaceChild,bn.prototype.setAttribute,bn.prototype.removeAttribute,bn.prototype.querySelector,bn.prototype.querySelectorAll,bn.prototype.parentNode,bn.prototype.firstChild,bn.prototype.lastChild,bn.prototype.nextSibling,bn.prototype.previousSibling,bn.prototype.firstElementChild,bn.prototype.lastElementChild,bn.prototype.nextElementSibling,bn.prototype.previousElementSibling,bn.prototype.childNodes,bn.prototype.children,bn.prototype.classList,bn.prototype.textContent,bn.prototype.innerHTML;let vn=bn;if(window.ShadyDOM&&window.ShadyDOM.inUse&&window.ShadyDOM.noPatch&&window.ShadyDOM.Wrapper){class t extends window.ShadyDOM.Wrapper{}Object.getOwnPropertyNames(bn.prototype).forEach((e=>{"activeElement"!=e&&(t.prototype[e]=bn.prototype[e])})),Pn(t.prototype,["classList"]),vn=t,Object.defineProperties(Cn.prototype,{localTarget:{get(){return this.event.currentTarget},configurable:!0},path:{get(){return window.ShadyDOM.composedPath(this.event)},configurable:!0}})}else!function(t,e){for(let s=0;s<e.length;s++){let n=e[s];t[n]=function(){return this.node[n].apply(this.node,arguments)}}}(bn.prototype,["cloneNode","appendChild","insertBefore","removeChild","replaceChild","setAttribute","removeAttribute","querySelector","querySelectorAll"]),Pn(bn.prototype,["parentNode","firstChild","lastChild","nextSibling","previousSibling","firstElementChild","lastElementChild","nextElementSibling","previousElementSibling","childNodes","children","classList"]),function(t,e){for(let s=0;s<e.length;s++){let n=e[s];Object.defineProperty(t,n,{get:function(){return this.node[n]},set:function(t){this.node[n]=t},configurable:!0})}}(bn.prototype,["textContent","innerHTML"]);const Sn=function(t){if((t=t||document)instanceof vn)return t;if(t instanceof Cn)return t;let e=t.__domApi;return e||(e=t instanceof Event?new Cn(t):new vn(t),t.__domApi=e),e};let wn=window.ShadyCSS;const En=d((t=>{const e=tn(xe(t)),s={x:"pan-x",y:"pan-y",none:"none",all:"auto"};class n extends e{constructor(){super(),this.isAttached,this.__boundListeners,this._debouncers}static get importMeta(){return this.prototype.importMeta}created(){}connectedCallback(){super.connectedCallback(),this.isAttached=!0,this.attached()}attached(){}disconnectedCallback(){super.disconnectedCallback(),this.isAttached=!1,this.detached()}detached(){}attributeChangedCallback(t,e,s,n){e!==s&&(super.attributeChangedCallback(t,e,s,n),this.attributeChanged(t,e,s))}attributeChanged(t,e,s){}_initializeProperties(){let t=Object.getPrototypeOf(this);t.hasOwnProperty("__hasRegisterFinished")||(this._registered(),t.__hasRegisterFinished=!0),super._initializeProperties(),this.root=this,this.created(),this._applyListeners()}_registered(){}ready(){this._ensureAttributes(),super.ready()}_ensureAttributes(){}_applyListeners(){}serialize(t){return this._serializeValue(t)}deserialize(t,e){return this._deserializeValue(t,e)}reflectPropertyToAttribute(t,e,s){this._propertyToAttribute(t,e,s)}serializeValueToAttribute(t,e,s){this._valueToNodeAttribute(s||this,t,e)}extend(t,e){if(!t||!e)return t||e;let s=Object.getOwnPropertyNames(e);for(let n,r=0;r<s.length&&(n=s[r]);r++){let s=Object.getOwnPropertyDescriptor(e,n);s&&Object.defineProperty(t,n,s)}return t}mixin(t,e){for(let s in e)t[s]=e[s];return t}chainObject(t,e){return t&&e&&t!==e&&(t.__proto__=e),t}instanceTemplate(t){let e=this.constructor._contentForTemplate(t);return document.importNode(e,!0)}fire(t,e,s){s=s||{},e=null==e?{}:e;let n=new Event(t,{bubbles:void 0===s.bubbles||s.bubbles,cancelable:Boolean(s.cancelable),composed:void 0===s.composed||s.composed});n.detail=e;let r=s.node||this;return E(r).dispatchEvent(n),n}listen(t,e,s){t=t||this;let n=this.__boundListeners||(this.__boundListeners=new WeakMap),r=n.get(t);r||(r={},n.set(t,r));let i=e+s;r[i]||(r[i]=this._addMethodEventListenerToNode(t,e,s,this))}unlisten(t,e,s){t=t||this;let n=this.__boundListeners&&this.__boundListeners.get(t),r=e+s,i=n&&n[r];i&&(this._removeEventListenerFromNode(t,e,i),n[r]=null)}setScrollDirection(t,e){st(e||this,s[t]||"auto")}$$(t){return this.root.querySelector(t)}get domHost(){let t=E(this).getRootNode();return t instanceof DocumentFragment?t.host:t}distributeContent(){const t=Sn(this);window.ShadyDOM&&t.shadowRoot&&ShadyDOM.flush()}getEffectiveChildNodes(){return Sn(this).getEffectiveChildNodes()}queryDistributedElements(t){return Sn(this).queryDistributedElements(t)}getEffectiveChildren(){return this.getEffectiveChildNodes().filter((function(t){return t.nodeType===Node.ELEMENT_NODE}))}getEffectiveTextContent(){let t=this.getEffectiveChildNodes(),e=[];for(let s,n=0;s=t[n];n++)s.nodeType!==Node.COMMENT_NODE&&e.push(s.textContent);return e.join("")}queryEffectiveChildren(t){let e=this.queryDistributedElements(t);return e&&e[0]}queryAllEffectiveChildren(t){return this.queryDistributedElements(t)}getContentChildNodes(t){let e=this.root.querySelector(t||"slot");return e?Sn(e).getDistributedNodes():[]}getContentChildren(t){return this.getContentChildNodes(t).filter((function(t){return t.nodeType===Node.ELEMENT_NODE}))}isLightDescendant(t){const e=this;return e!==t&&E(e).contains(t)&&E(e).getRootNode()===E(t).getRootNode()}isLocalDescendant(t){return this.root===E(t).getRootNode()}scopeSubtree(t,e){}getComputedStyleValue(t){return wn.getComputedStyleValue(this,t)}debounce(t,e,s){return this._debouncers=this._debouncers||{},this._debouncers[t]=c.debounce(this._debouncers[t],s>0?i.after(s):l,e.bind(this))}isDebouncerActive(t){this._debouncers=this._debouncers||{};let e=this._debouncers[t];return!(!e||!e.isActive())}flushDebouncer(t){this._debouncers=this._debouncers||{};let e=this._debouncers[t];e&&e.flush()}cancelDebouncer(t){this._debouncers=this._debouncers||{};let e=this._debouncers[t];e&&e.cancel()}async(t,e){return e>0?i.run(t.bind(this),e):~l.run(t.bind(this))}cancelAsync(t){t<0?l.cancel(~t):i.cancel(t)}create(t,e){let s=document.createElement(t);if(e)if(s.setProperties)s.setProperties(e);else for(let t in e)s[t]=e[t];return s}elementMatches(t,e){return gn(e||this,t)}toggleAttribute(t,e){let s=this;return 3===arguments.length&&(s=arguments[2]),1==arguments.length&&(e=!s.hasAttribute(t)),e?(E(s).setAttribute(t,""),!0):(E(s).removeAttribute(t),!1)}toggleClass(t,e,s){s=s||this,1==arguments.length&&(e=!s.classList.contains(t)),e?s.classList.add(t):s.classList.remove(t)}transform(t,e){(e=e||this).style.webkitTransform=t,e.style.transform=t}translate3d(t,e,s,n){n=n||this,this.transform("translate3d("+t+","+e+","+s+")",n)}arrayDelete(t,e){let s;if(Array.isArray(t)){if(s=t.indexOf(e),s>=0)return t.splice(s,1)}else{if(s=It(this,t).indexOf(e),s>=0)return this.splice(t,s,1)}return null}_logger(t,e){switch(Array.isArray(e)&&1===e.length&&Array.isArray(e[0])&&(e=e[0]),t){case"log":case"warn":case"error":console[t](...e)}}_log(...t){this._logger("log",t)}_warn(...t){this._logger("warn",t)}_error(...t){this._logger("error",t)}_logf(t,...e){return["[%s::%s]",this.is,t,...e]}}return n.prototype.is="",n})),Tn={attached:!0,detached:!0,ready:!0,created:!0,beforeRegister:!0,registered:!0,attributeChanged:!0,listeners:!0,hostAttributes:!0},On={attached:!0,detached:!0,ready:!0,created:!0,beforeRegister:!0,registered:!0,attributeChanged:!0,behaviors:!0,_noAccessors:!0},Nn=Object.assign({listeners:!0,hostAttributes:!0,properties:!0,observers:!0},On);function xn(t,e){return Rn({},En(e),t)}function An(t,e,s,n){!function(t,e,s){const n=t._noAccessors,r=Object.getOwnPropertyNames(t);for(let i=0;i<r.length;i++){let o=r[i];if(!(o in s))if(n)e[o]=t[o];else{let s=Object.getOwnPropertyDescriptor(t,o);s&&(s.configurable=!0,Object.defineProperty(e,o,s))}}}(e,t,n);for(let t in Tn)e[t]&&(s[t]=s[t]||[],s[t].push(e[t]))}function In(t,e,s){e=e||[];for(let n=t.length-1;n>=0;n--){let r=t[n];r?Array.isArray(r)?In(r,e):e.indexOf(r)<0&&(!s||s.indexOf(r)<0)&&e.unshift(r):console.warn("behavior is null, check for missing or 404 import")}return e}function Mn(t,e){for(const s in e){const n=t[s],r=e[s];t[s]=!("value"in r)&&n&&"value"in n?Object.assign({value:n.value},r):r}}function Rn(t,e,s){let n;const r={};class i extends e{static _finalizeClass(){if(this.hasOwnProperty(JSCompiler_renameProperty("generatedFrom",this))){if(n)for(let t,e=0;e<n.length;e++)t=n[e],t.properties&&this.createProperties(t.properties),t.observers&&this.createObservers(t.observers,t.properties);t.properties&&this.createProperties(t.properties),t.observers&&this.createObservers(t.observers,t.properties),this._prepareTemplate()}else super._finalizeClass()}static get properties(){const e={};if(n)for(let t=0;t<n.length;t++)Mn(e,n[t].properties);return Mn(e,t.properties),e}static get observers(){let e=[];if(n)for(let t,s=0;s<n.length;s++)t=n[s],t.observers&&(e=e.concat(t.observers));return t.observers&&(e=e.concat(t.observers)),e}created(){super.created();const t=r.created;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}_registered(){const t=i.prototype;if(!t.hasOwnProperty("__hasRegisterFinished")){t.__hasRegisterFinished=!0,super._registered();const e=Object.getPrototypeOf(this);let s=r.beforeRegister;if(s)for(let t=0;t<s.length;t++)s[t].call(e);if(s=r.registered,s)for(let t=0;t<s.length;t++)s[t].call(e)}}_applyListeners(){super._applyListeners();const t=r.listeners;if(t)for(let e=0;e<t.length;e++){const s=t[e];if(s)for(let t in s)this._addMethodEventListenerToNode(this,t,s[t])}}_ensureAttributes(){const t=r.hostAttributes;if(t)for(let e=t.length-1;e>=0;e--){const s=t[e];for(let t in s)this._ensureAttribute(t,s[t])}super._ensureAttributes()}ready(){super.ready();let t=r.ready;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}attached(){super.attached();let t=r.attached;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}detached(){super.detached();let t=r.detached;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}attributeChanged(t,e,s){super.attributeChanged();let n=r.attributeChanged;if(n)for(let r=0;r<n.length;r++)n[r].call(this,t,e,s)}}if(s){Array.isArray(s)||(s=[s]);let t=e.prototype.behaviors;n=In(s,null,t),i.prototype.behaviors=t?t.concat(s):n}return(e=>{n&&function(t,e,s){for(let n=0;n<e.length;n++)An(t,e[n],s,Nn)}(e,n,r),An(e,t,r,On)})(i.prototype),i.generatedFrom=t,i}let Ln;Ln=ke._mutablePropertyChange;const kn={properties:{mutableData:Boolean},_shouldPropertyChange(t,e,s){return Ln(this,t,e,s,this.mutableData)}},Dn=function(t){let e;return e="function"==typeof t?t:Dn.Class(t),customElements.define(e.is,e),e};Dn.Class=function(t,e){t||console.warn("Polymer.Class requires `info` argument");let s=e?e(En(HTMLElement)):En(HTMLElement);return s=Rn(t,s,t.behaviors),s.is=s.prototype.is=t.is,s};const Fn={templatize(t,e){this._templatizerTemplate=t,this.ctor=Xe(t,this,{mutableData:Boolean(e),parentModel:this._parentModel,instanceProps:this._instanceProps,forwardHostProp:this._forwardHostPropV2,notifyInstanceProp:this._notifyInstancePropV2})},stamp(t){return new this.ctor(t)},modelForElement(t){return We(this._templatizerTemplate,t)}},Hn=tn(De(Ee(HTMLElement)));customElements.define("dom-bind",class extends Hn{static get observedAttributes(){return["mutable-data"]}constructor(){super(),this.root=null,this.$=null,this.__children=null}attributeChangedCallback(){this.mutableData=!0}connectedCallback(){this.style.display="none",this.render()}disconnectedCallback(){this.__removeChildren()}__insertChildren(){E(E(this).parentNode).insertBefore(this.root,this)}__removeChildren(){if(this.__children)for(let t=0;t<this.__children.length;t++)this.root.appendChild(this.__children[t])}render(){let t;if(!this.__children){if(t=t||this.querySelector("template"),!t){let e=new MutationObserver((()=>{if(t=this.querySelector("template"),!t)throw new Error("dom-bind requires a <template> child");e.disconnect(),this.render()}));return void e.observe(this,{childList:!0})}this.root=this._stampTemplate(t),this.$=this.root.$,this.__children=[];for(let t=this.root.firstChild;t;t=t.nextSibling)this.__children[this.__children.length]=t;this._enableProperties()}this.__insertChildren(),this.dispatchEvent(new CustomEvent("dom-change",{bubbles:!0,composed:!0}))}});let zn=d((t=>{let e=xe(t);return class extends e{static get properties(){return{items:{type:Array},multi:{type:Boolean,value:!1},selected:{type:Object,notify:!0},selectedItem:{type:Object,notify:!0},toggle:{type:Boolean,value:!1}}}static get observers(){return["__updateSelection(multi, items.*)"]}constructor(){super(),this.__lastItems=null,this.__lastMulti=null,this.__selectedMap=null}__updateSelection(t,e){let s=e.path;if(s==JSCompiler_renameProperty("items",this)){let s=e.base||[],n=this.__lastItems;if(t!==this.__lastMulti&&this.clearSelection(),n){let t=un(s,n);this.__applySplices(t)}this.__lastItems=s,this.__lastMulti=t}else if(e.path==JSCompiler_renameProperty("items",this)+".splices")this.__applySplices(e.value.indexSplices);else{let t=s.slice((JSCompiler_renameProperty("items",this)+".").length),e=parseInt(t,10);t.indexOf(".")<0&&t==e&&this.__deselectChangedIdx(e)}}__applySplices(t){let e=this.__selectedMap;for(let s=0;s<t.length;s++){let n=t[s];e.forEach(((t,s)=>{t<n.index||(t>=n.index+n.removed.length?e.set(s,t+n.addedCount-n.removed.length):e.set(s,-1))}));for(let t=0;t<n.addedCount;t++){let s=n.index+t;e.has(this.items[s])&&e.set(this.items[s],s)}}this.__updateLinks();let s=0;e.forEach(((t,n)=>{t<0?(this.multi?this.splice(JSCompiler_renameProperty("selected",this),s,1):this.selected=this.selectedItem=null,e.delete(n)):s++}))}__updateLinks(){if(this.__dataLinkedPaths={},this.multi){let t=0;this.__selectedMap.forEach((e=>{e>=0&&this.linkPaths(`${JSCompiler_renameProperty("items",this)}.${e}`,`${JSCompiler_renameProperty("selected",this)}.${t++}`)}))}else this.__selectedMap.forEach((t=>{this.linkPaths(JSCompiler_renameProperty("selected",this),`${JSCompiler_renameProperty("items",this)}.${t}`),this.linkPaths(JSCompiler_renameProperty("selectedItem",this),`${JSCompiler_renameProperty("items",this)}.${t}`)}))}clearSelection(){this.__dataLinkedPaths={},this.__selectedMap=new Map,this.selected=this.multi?[]:null,this.selectedItem=null}isSelected(t){return this.__selectedMap.has(t)}isIndexSelected(t){return this.isSelected(this.items[t])}__deselectChangedIdx(t){let e=this.__selectedIndexForItemIndex(t);if(e>=0){let t=0;this.__selectedMap.forEach(((s,n)=>{e==t++&&this.deselect(n)}))}}__selectedIndexForItemIndex(t){let e=this.__dataLinkedPaths[`${JSCompiler_renameProperty("items",this)}.${t}`];if(e)return parseInt(e.slice((JSCompiler_renameProperty("selected",this)+".").length),10)}deselect(t){let e=this.__selectedMap.get(t);if(e>=0){let s;this.__selectedMap.delete(t),this.multi&&(s=this.__selectedIndexForItemIndex(e)),this.__updateLinks(),this.multi?this.splice(JSCompiler_renameProperty("selected",this),s,1):this.selected=this.selectedItem=null}}deselectIndex(t){this.deselect(this.items[t])}select(t){this.selectIndex(this.items.indexOf(t))}selectIndex(t){let e=this.items[t];this.isSelected(e)?this.toggle&&this.deselectIndex(t):(this.multi||this.__selectedMap.clear(),this.__selectedMap.set(e,t),this.__updateLinks(),this.multi?this.push(JSCompiler_renameProperty("selected",this),e):this.selected=this.selectedItem=e)}}}))(Re);class jn extends zn{static get is(){return"array-selector"}static get template(){return null}}customElements.define(jn.is,jn);const Bn=new Zs;window.ShadyCSS||(window.ShadyCSS={prepareTemplate(t,e,s){},prepareTemplateDom(t,e){},prepareTemplateStyles(t,e,s){},styleSubtree(t,e){Bn.processStyles(),xs(t,e)},styleElement(t){Bn.processStyles()},styleDocument(t){Bn.processStyles(),xs(document.body,t)},getComputedStyleValue:(t,e)=>As(t,e),flushCustomStyles(){},nativeCss:is,nativeShadow:ts,cssBuild:ss,disableRuntime:rs}),window.ShadyCSS.CustomStyleInterface=Bn;const qn=window.ShadyCSS.CustomStyleInterface;class $n extends HTMLElement{constructor(){super(),this._style=null,qn.addCustomStyle(this)}getStyle(){if(this._style)return this._style;const t=this.querySelector("style");if(!t)return null;this._style=t;const e=t.getAttribute("include");return e&&(t.removeAttribute("include"),t.textContent=function(t){let e=t.trim().split(/\s+/),s="";for(let t=0;t<e.length;t++)s+=vt(e[t]);return s}(e)+t.textContent),this.ownerDocument!==window.document&&window.document.head.appendChild(this),this._style}}window.customElements.define("custom-style",$n);const Yn=En(HTMLElement).prototype;export{Yn as Base,c as Debouncer,Ze as DomIf,Qe as DomRepeat,fn as FlattenedNodesObserver,kn as OptionalMutableDataBehavior,Dn as Polymer,Re as PolymerElement,qe as TemplateInstanceBase,Fn as Templatizer,ln as afterNextRender,o as animationFrame,an as beforeNextRender,un as calculateSplices,Dt as dashToCamelCase,d as dedupingMixin,Sn as dom,p as enqueueDebouncer,Ge as flush,ut as gestures,It as get,Me as html,a as idlePeriod,Nt as matches,l as microTask,xn as mixinBehaviors,Xe as templatize,i as timeOut,Ot as translate,v as useShadow}; \ No newline at end of file
diff --git a/third_party/polymer/v3_0/minify_polymer.py b/third_party/polymer/v3_0/minify_polymer.py index e67181f..c7aabe8 100644 --- a/third_party/polymer/v3_0/minify_polymer.py +++ b/third_party/polymer/v3_0/minify_polymer.py
@@ -50,6 +50,9 @@ minified_js = os.path.join(tmp_out_dir, 'polymer_bundled.min.js') node.RunNode([ node_modules.PathToTerser(), bundled_js, + '--compress', + '--mangle', + '--module', # TODO(dpapad): Figure out a way to deduplicate LICENSE headers. In the # meantime exclude such comments to reduce file size. '--comments', 'false',
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium index abb7c5f..1bb5d59 100644 --- a/third_party/protobuf/README.chromium +++ b/third_party/protobuf/README.chromium
@@ -97,3 +97,9 @@ Imports https://github.com/protocolbuffers/protobuf/commit/ed8b2e6f62afee17e2f8249be3b9b69eb0666532 to remove uses of std::iterator. + +- 0026-remove-sprintf.patch + + Imports + https://github.com/protocolbuffers/protobuf/commit/c0fc2e881bc36aafb0bf539bf41889611370f60c + to remove use of sprintf.
diff --git a/third_party/protobuf/patches/0026-remove-sprintf.patch b/third_party/protobuf/patches/0026-remove-sprintf.patch new file mode 100644 index 0000000..6629a6b --- /dev/null +++ b/third_party/protobuf/patches/0026-remove-sprintf.patch
@@ -0,0 +1,15 @@ +diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc +index 594c8eac6..f986b11e7 100644 +--- a/src/google/protobuf/stubs/strutil.cc ++++ b/src/google/protobuf/stubs/strutil.cc +@@ -503,8 +503,8 @@ int CEscapeInternal(const char* src, int src_len, char* dest, + (last_hex_escape && isxdigit(*src)))) { + if (dest_len - used < 4) // need space for 4 letter escape + return -1; +- sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"), +- static_cast<uint8_t>(*src)); ++ snprintf(dest + used, 5, (use_hex ? "\\x%02x" : "\\%03o"), ++ static_cast<uint8_t>(*src)); + is_hex_escape = use_hex; + used += 4; + } else {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc index 2722594..9c133dd1 100644 --- a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc +++ b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
@@ -504,8 +504,8 @@ (last_hex_escape && isxdigit(*src)))) { if (dest_len - used < 4) // need space for 4 letter escape return -1; - sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"), - static_cast<uint8>(*src)); + snprintf(dest + used, 5, (use_hex ? "\\x%02x" : "\\%03o"), + static_cast<uint8>(*src)); is_hex_escape = use_hex; used += 4; } else {
diff --git a/third_party/rust/camino/v1/BUILD.gn b/third_party/rust/camino/v1/BUILD.gn new file mode 100644 index 0000000..8042879 --- /dev/null +++ b/third_party/rust/camino/v1/BUILD.gn
@@ -0,0 +1,32 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/rust/cargo_crate.gni") + +cargo_crate("lib") { + crate_name = "camino" + epoch = "1" + crate_type = "rlib" + + # Only for usage from third-party crates. Add the crate to + # third_party.toml to use it from first-party code. + visibility = [ "//third_party/rust/*" ] + crate_root = "crate/src/lib.rs" + + # Unit tests skipped. Generate with --with-tests to include them. + build_native_rust_unit_tests = false + sources = [ "crate/src/lib.rs" ] + edition = "2018" + cargo_pkg_version = "1.0.9" + cargo_pkg_authors = "Without Boats <saoirse@without.boats>, Ashley Williams <ashley666ashley@gmail.com>, Steve Klabnik <steve@steveklabnik.com>, Rain <rain@sunshowers.io>" + cargo_pkg_name = "camino" + cargo_pkg_description = "UTF-8 paths" + deps = [ "//third_party/rust/serde/v1:lib" ] + features = [ + "serde", + "serde1", + ] + build_root = "crate/build.rs" + build_sources = [ "crate/build.rs" ] +}
diff --git a/third_party/rust/camino/v1/README.chromium b/third_party/rust/camino/v1/README.chromium new file mode 100644 index 0000000..5814b9f --- /dev/null +++ b/third_party/rust/camino/v1/README.chromium
@@ -0,0 +1,6 @@ +Name: camino +URL: https://crates.io/crates/camino +Description: UTF-8 paths +Version: 1.0.9 +Security Critical: no +License: Apache 2.0
diff --git a/third_party/rust/camino/v1/crate/.cargo_vcs_info.json b/third_party/rust/camino/v1/crate/.cargo_vcs_info.json new file mode 100644 index 0000000..c1ea121 --- /dev/null +++ b/third_party/rust/camino/v1/crate/.cargo_vcs_info.json
@@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "09448fddde9f8ad1fe7981ad406356c5c94b8598" + }, + "path_in_vcs": "" +} \ No newline at end of file
diff --git a/third_party/rust/camino/v1/crate/.gitignore b/third_party/rust/camino/v1/crate/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/third_party/rust/camino/v1/crate/.gitignore
@@ -0,0 +1,2 @@ +/target +Cargo.lock
diff --git a/third_party/rust/camino/v1/crate/CHANGELOG.md b/third_party/rust/camino/v1/crate/CHANGELOG.md new file mode 100644 index 0000000..b9a04de --- /dev/null +++ b/third_party/rust/camino/v1/crate/CHANGELOG.md
@@ -0,0 +1,95 @@ +# Changelog + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.9] - 2022-05-19 + +### Fixed + +- Documentation fixes. + +## [1.0.8] - 2022-05-09 + +### Added + +- New methods `canonicalize_utf8`, `read_link_utf8` and `read_dir_utf8` return `Utf8PathBuf`s, erroring out if a resulting path is not valid UTF-8. +- New feature `proptest1` introduces proptest `Arbitrary` impls for `Utf8PathBuf` and + `Box<Utf8Path>` ([#18], thanks [mcronce](https://github.com/mcronce) for your first contribution!) + +[#18]: https://github.com/camino-rs/camino/pull/18 + +## [1.0.7] - 2022-01-16 + +### Added + +- `Utf8Path::is_symlink` checks whether a path is a symlink. Note that while `std::path::Path` only + provides this method for version 1.58 and above, `camino` polyfills the method for all Rust versions + it supports. + +### Changed + +- Update repository links to new location [camino-rs/camino](https://github.com/camino-rs/camino). +- Update `structopt` example to clap 3's builtin derive feature. + (camino continues to work with structopt as before.) + +## [1.0.6] - 2022-01-16 + +(This release was yanked due to a publishing issue.) + +## [1.0.5] - 2021-07-27 + +### Added + +- `Utf8PathBuf::into_std_path_buf` converts a `Utf8PathBuf` to a `PathBuf`; equivalent to the + `From<Utf8PathBuf> for PathBuf` impl, but may aid in type inference. +- `Utf8Path::as_std_path` converts a `Utf8Path` to a `Path`; equivalent to the + `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference. + +## [1.0.4] - 2021-03-19 + +### Fixed + +- `Hash` impls for `Utf8PathBuf` and `Utf8Path` now match as required by the `Borrow` contract ([#9]). + +[#9]: https://github.com/camino-rs/camino/issues/9 + +## [1.0.3] - 2021-03-11 + +### Added + +- `TryFrom<PathBuf> for Utf8PathBuf` and `TryFrom<&Path> for &Utf8Path`, both of which return new error types ([#6]). +- `AsRef<Utf8Path>`, `AsRef<Path>`, `AsRef<str>` and `AsRef<OsStr>` impls for `Utf8Components`, `Utf8Component` and + `Iter`. + +[#6]: https://github.com/camino-rs/camino/issues/6 + +## [1.0.2] - 2021-03-02 + +### Added + +- `From` impls for converting a `&Utf8Path` or a `Utf8PathBuf` into `Box<Path>`, `Rc<Path>`, `Arc<Path>` and `Cow<'a, Path>`. +- `PartialEq` and `PartialOrd` implementations comparing `Utf8Path` and `Utf8PathBuf` with `Path`, `PathBuf` and its + variants, and comparing `OsStr`, `OsString` and its variants. + +## [1.0.1] - 2021-02-25 + +### Added + +- More `PartialEq` and `PartialOrd` implementations. +- MSRV lowered to 1.34. + +## [1.0.0] - 2021-02-23 + +Initial release. + +[1.0.9]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.9 +[1.0.8]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.8 +[1.0.7]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.7 +[1.0.6]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.6 +[1.0.5]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.5 +[1.0.4]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.4 +[1.0.3]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.3 +[1.0.2]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.2 +[1.0.1]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.1 +[1.0.0]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.0
diff --git a/third_party/rust/camino/v1/crate/CODE_OF_CONDUCT.md b/third_party/rust/camino/v1/crate/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2ea2606d --- /dev/null +++ b/third_party/rust/camino/v1/crate/CODE_OF_CONDUCT.md
@@ -0,0 +1,133 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at the email +address: [codeofconduct@sunshowers.io](mailto:codeofconduct@sunshowers.io). +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations +
diff --git a/third_party/rust/camino/v1/crate/Cargo.toml b/third_party/rust/camino/v1/crate/Cargo.toml new file mode 100644 index 0000000..cd2bd9f --- /dev/null +++ b/third_party/rust/camino/v1/crate/Cargo.toml
@@ -0,0 +1,58 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "camino" +version = "1.0.9" +authors = [ + "Without Boats <saoirse@without.boats>", + "Ashley Williams <ashley666ashley@gmail.com>", + "Steve Klabnik <steve@steveklabnik.com>", + "Rain <rain@sunshowers.io>", +] +exclude = [ + ".cargo/**/*", + ".github/**/*", +] +description = "UTF-8 paths" +documentation = "https://docs.rs/camino" +readme = "README.md" +keywords = [ + "paths", + "utf8", + "unicode", + "filesystem", +] +categories = [ + "development-tools", + "filesystem", + "os", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/camino-rs/camino" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg=doc_cfg"] + +[dependencies.proptest] +version = "1.0.0" +optional = true + +[dependencies.serde] +version = "1" +features = ["derive"] +optional = true + +[features] +proptest1 = ["proptest"] +serde1 = ["serde"]
diff --git a/third_party/rust/camino/v1/crate/Cargo.toml.orig b/third_party/rust/camino/v1/crate/Cargo.toml.orig new file mode 100644 index 0000000..17f7523 --- /dev/null +++ b/third_party/rust/camino/v1/crate/Cargo.toml.orig
@@ -0,0 +1,33 @@ +[workspace] +members = [".", "camino-examples"] + +[package] +name = "camino" +description = "UTF-8 paths" +version = "1.0.9" +license = "MIT OR Apache-2.0" +readme = "README.md" +keywords = ["paths", "utf8", "unicode", "filesystem"] +categories = ["development-tools", "filesystem", "os"] +repository = "https://github.com/camino-rs/camino" +documentation = "https://docs.rs/camino" +authors = [ + "Without Boats <saoirse@without.boats>", + "Ashley Williams <ashley666ashley@gmail.com>", + "Steve Klabnik <steve@steveklabnik.com>", + "Rain <rain@sunshowers.io>", +] +edition = "2018" +exclude = [".cargo/**/*", ".github/**/*"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg=doc_cfg"] + +[dependencies] +proptest = { version = "1.0.0", optional = true } +serde = { version = "1", features = ["derive"], optional = true } + +[features] +serde1 = ["serde"] +proptest1 = ["proptest"]
diff --git a/third_party/rust/camino/v1/crate/LICENSE-APACHE b/third_party/rust/camino/v1/crate/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/third_party/rust/camino/v1/crate/LICENSE-APACHE
@@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.
diff --git a/third_party/rust/camino/v1/crate/LICENSE-MIT b/third_party/rust/camino/v1/crate/LICENSE-MIT new file mode 100644 index 0000000..31aa7938 --- /dev/null +++ b/third_party/rust/camino/v1/crate/LICENSE-MIT
@@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/camino/v1/crate/README.md b/third_party/rust/camino/v1/crate/README.md new file mode 100644 index 0000000..9fad93a --- /dev/null +++ b/third_party/rust/camino/v1/crate/README.md
@@ -0,0 +1,132 @@ +# camino - UTF-8 encoded paths + +[](https://crates.io/crates/camino) +[](https://crates.io/crates/camino) +[](https://docs.rs/camino) +[](https://camino-rs.github.io/camino/rustdoc/camino/) +[](LICENSE-APACHE) +[](LICENSE-MIT) + +This repository contains the source code for `camino`, an extension of the `std::path` module that adds new +[`Utf8PathBuf`] and [`Utf8Path`] types. + +## What is camino? + +`camino`'s [`Utf8PathBuf`] and [`Utf8Path`] types are like the standard library's [`PathBuf`] and [`Path`] types, except +they are guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their +contents as strings, they implement `Display`, etc. + +The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library, +since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a +number of reasons: +* Unicode won. There are still some legacy codebases that store paths in encodings like [Shift JIS], but most + have been converted to Unicode at this point. +* Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths + as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32 + API boundaries.) +* There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such + system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers. +* The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) asks: given a + Makefile or other metadata file (such as `Cargo.toml`) that lists the names of other files, how should the names in + the Makefile be matched with the ones on disk? This has *no general, cross-platform solution* in systems that support + non-UTF-8 paths. However, restricting paths to UTF-8 eliminates this problem. + +[Shift JIS]: https://en.wikipedia.org/wiki/Shift_JIS + +Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to `str`s +as necessary. However, because this invariant is not encoded in the `Path` type, conversions such as +`path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience. + +Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them +as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions. + +## Examples + +The documentation for [`Utf8PathBuf`] and [`Utf8Path`] contains several examples. + +For examples of how to use `camino` with other libraries like `serde` and `clap`, see the [`camino-examples`] directory. + +## API design + +`camino` is a very thin wrapper around `std::path`. [`Utf8Path`] and [`Utf8PathBuf`] are drop-in replacements +for [`Path`] and [`PathBuf`]. + +Most APIs are the same, but those at the boundary with `str` are different. Some examples: +* `Path::to_str() -> Option<&str>` has been renamed to `Utf8Path::as_str() -> &str`. +* [`Utf8Path`] implements `Display`, and `Path::display()` has been removed. +* Iterating over a [`Utf8Path`] returns `&str`, not `&OsStr`. + +Every [`Utf8Path`] is a valid [`Path`], so [`Utf8Path`] implements `AsRef<Path>`. Any APIs that accept `impl AsRef<Path>` +will continue to work with [`Utf8Path`] instances. + +## Should you use camino? + +`camino` trades off some utility for a great deal of simplicity. Whether `camino` is appropriate for a project or not +is ultimately a case-by-case decision. Here are some general guidelines that may help. + +*You should consider using camino if...* + +* **You're building portable, cross-platform software.** While both Unix and Windows platforms support different kinds + of non-Unicode paths, Unicode is the common subset that's supported across them. +* **Your system has files that contain the names of other files.** If you don't use UTF-8 paths, you will run into the + makefile problem described above, which has no general, cross-platform solution. +* **You're interacting with existing systems that already assume UTF-8 paths.** In that case you won't be adding any new + burdens on downstream consumers. +* **You're building something brand new and are willing to ask your users to rename their paths if necessary.** Projects + that don't have to worry about legacy compatibility have more flexibility in choosing what paths they support. + +In general, using camino is the right choice for most projects. + +*You should **NOT** use camino, if...* + +* **You're writing a core system utility.** If you're writing, say, an `mv` or `cat` replacement, you should + **not** use camino. Instead, use [`std::path::Path`] and add extensive tests for non-UTF-8 paths. +* **You have legacy compatibility constraints.** For example, Git supports non-UTF-8 paths. If your tool needs to handle + arbitrary Git repositories, it should use its own path type that's a wrapper around `Vec<u8>`. + * [`std::path::Path`] supports arbitrary bytestrings [on Unix] but not on Windows. +* **There's some other reason you need to support non-UTF-8 paths.** Some tools like disk recovery utilities need to + handle potentially corrupt filenames: only being able to handle UTF-8 paths would greatly diminish their utility. + +[on Unix]: https://doc.rust-lang.org/std/os/unix/ffi/index.html + +## Optional features + +By default, `camino` has **no dependencies** other than `std`. There are some optional features that enable +dependencies: +* `serde1` adds serde [`Serialize`] and [`Deserialize`] impls for [`Utf8PathBuf`] and [`Utf8Path`] + (zero-copy). +* `proptest1` adds [proptest](https://altsysrq.github.io/proptest-book/) [`Arbitrary`] + implementations for [`Utf8PathBuf`] and `Box<Utf8Path>`. + +## Rust version support + +The minimum supported Rust version (MSRV) for `camino` with default features is **1.34**. This project is tested in CI +against the latest stable version of Rust and the MSRV. +* *Stable APIs* added in later Rust versions are supported either through conditional compilation in `build.rs`, or through backfills that also work on older versions. +* *Deprecations* are kept in sync with the version of Rust they're added in. +* *Unstable APIs* are currently not supported. Please + [file an issue on GitHub](https://github.com/camino-rs/camino/issues/new) if you need an unstable API. + +`camino` is designed to be a core library and has a conservative MSRV policy. MSRV increases will only happen for +a compelling enough reason, and will involve at least a minor version bump. + +Optional features may pull in dependencies that require a newer version of Rust. + +## License + +This project is available under the terms of either the [Apache 2.0 license](LICENSE-APACHE) or the [MIT +license](LICENSE-MIT). + +This project's documentation is adapted from [The Rust Programming Language](https://github.com/rust-lang/rust/), which is +available under the terms of either the [Apache 2.0 license](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE) +or the [MIT license](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT). + +[`Utf8PathBuf`]: https://docs.rs/camino/*/camino/struct.Utf8PathBuf.html +[`Utf8Path`]: https://docs.rs/camino/*/camino/struct.Utf8Path.html +[`PathBuf`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html +[`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +[`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html +[`Serialize`]: https://docs.rs/serde/1/serde/trait.Serialize.html +[`Deserialize`]: https://docs.rs/serde/1/serde/trait.Deserialize.html +[`camino-examples`]: https://github.com/camino-rs/camino/tree/main/camino-examples +[`Arbitrary`]: https://docs.rs/proptest/1/proptest/arbitrary/trait.Arbitrary.html
diff --git a/third_party/rust/camino/v1/crate/build.rs b/third_party/rust/camino/v1/crate/build.rs new file mode 100644 index 0000000..bc3e448 --- /dev/null +++ b/third_party/rust/camino/v1/crate/build.rs
@@ -0,0 +1,40 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Adapted from +//! https://github.com/dtolnay/syn/blob/a54fb0098c6679f1312113ae2eec0305c51c7390/build.rs. + +use std::{env, process::Command, str}; + +// The rustc-cfg strings below are *not* public API. Please let us know by +// opening a GitHub issue if your build environment requires some way to enable +// these cfgs other than by executing our build script. +fn main() { + let compiler = match rustc_version() { + Some(compiler) => compiler, + None => return, + }; + + // NOTE: + // Adding a new cfg gated by Rust version MUST be accompanied by an addition to the matrix in + // .github/workflows/ci.yml. + if compiler.minor >= 44 { + println!("cargo:rustc-cfg=path_buf_capacity"); + } +} + +struct Compiler { + minor: u32, +} + +fn rustc_version() -> Option<Compiler> { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + let minor = pieces.next()?.parse().ok()?; + Some(Compiler { minor }) +}
diff --git a/third_party/rust/camino/v1/crate/clippy.toml b/third_party/rust/camino/v1/crate/clippy.toml new file mode 100644 index 0000000..b32f6d50a --- /dev/null +++ b/third_party/rust/camino/v1/crate/clippy.toml
@@ -0,0 +1 @@ +msrv = "1.34.0"
diff --git a/third_party/rust/camino/v1/crate/rustfmt.toml b/third_party/rust/camino/v1/crate/rustfmt.toml new file mode 100644 index 0000000..80eeb40 --- /dev/null +++ b/third_party/rust/camino/v1/crate/rustfmt.toml
@@ -0,0 +1,2 @@ +edition = "2018" +use_field_init_shorthand = true
diff --git a/third_party/rust/camino/v1/crate/src/lib.rs b/third_party/rust/camino/v1/crate/src/lib.rs new file mode 100644 index 0000000..4a1b6df --- /dev/null +++ b/third_party/rust/camino/v1/crate/src/lib.rs
@@ -0,0 +1,2773 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +#![warn(missing_docs)] +#![cfg_attr(doc_cfg, feature(doc_cfg, doc_auto_cfg))] + +//! UTF-8 encoded paths. +//! +//! `camino` is an extension of the `std::path` module that adds new [`Utf8PathBuf`] and [`Utf8Path`] +//! types. These are like the standard library's [`PathBuf`] and [`Path`] types, except they are +//! guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their +//! contents as strings, they implement `Display`, etc. +//! +//! The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library, +//! since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a +//! number of reasons: +//! * Unicode won. There are still some legacy codebases that store paths in encodings like Shift-JIS, but most +//! have been converted to Unicode at this point. +//! * Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths +//! as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32 +//! API boundaries.) +//! * There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such +//! system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers. +//! * The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) +//! (which also applies to `Cargo.toml`, and any other metadata file that lists the names of other files) has *no general, +//! cross-platform solution* in systems that support non-UTF-8 paths. However, restricting paths to UTF-8 eliminates +//! this problem. +//! +//! Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to `str`s +//! as necessary. However, because this invariant is not encoded in the `Path` type, conversions such as +//! `path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience. +//! +//! Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them +//! as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions. + +use std::{ + borrow::{Borrow, Cow}, + cmp::Ordering, + convert::{Infallible, TryFrom, TryInto}, + error, + ffi::{OsStr, OsString}, + fmt, + fs::{self, Metadata}, + hash::{Hash, Hasher}, + io, + iter::FusedIterator, + ops::Deref, + path::*, + rc::Rc, + str::FromStr, + sync::Arc, +}; + +#[cfg(feature = "proptest1")] +mod proptest_impls; +#[cfg(feature = "serde1")] +mod serde_impls; +#[cfg(test)] +mod tests; + +/// An owned, mutable UTF-8 path (akin to [`String`]). +/// +/// This type provides methods like [`push`] and [`set_extension`] that mutate +/// the path in place. It also implements [`Deref`] to [`Utf8Path`], meaning that +/// all methods on [`Utf8Path`] slices are available on `Utf8PathBuf` values as well. +/// +/// [`push`]: Utf8PathBuf::push +/// [`set_extension`]: Utf8PathBuf::set_extension +/// +/// # Examples +/// +/// You can use [`push`] to build up a `Utf8PathBuf` from +/// components: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let mut path = Utf8PathBuf::new(); +/// +/// path.push(r"C:\"); +/// path.push("windows"); +/// path.push("system32"); +/// +/// path.set_extension("dll"); +/// ``` +/// +/// However, [`push`] is best used for dynamic situations. This is a better way +/// to do this when you know all of the components ahead of time: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let path: Utf8PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect(); +/// ``` +/// +/// We can still do better than this! Since these are all strings, we can use +/// `From::from`: +/// +/// ``` +/// use camino::Utf8PathBuf; +/// +/// let path = Utf8PathBuf::from(r"C:\windows\system32.dll"); +/// ``` +/// +/// Which method works best depends on what kind of situation you're in. +// NB: Internal PathBuf must only contain utf8 data +#[derive(Clone, Default)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde1", serde(transparent))] +#[repr(transparent)] +pub struct Utf8PathBuf(PathBuf); + +impl Utf8PathBuf { + /// Allocates an empty `Utf8PathBuf`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let path = Utf8PathBuf::new(); + /// ``` + pub fn new() -> Utf8PathBuf { + Utf8PathBuf(PathBuf::new()) + } + + /// Creates a new `Utf8PathBuf` from a `PathBuf` containing valid UTF-8 characters. + /// + /// Errors with the original `PathBuf` if it is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], use the + /// `TryFrom<PathBuf>` impl. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::PathBuf; + /// + /// let unicode_path = PathBuf::from("/valid/unicode"); + /// Utf8PathBuf::from_path_buf(unicode_path).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// let non_unicode_path = PathBuf::from(non_unicode_str); + /// # #[cfg(unix)] + /// Utf8PathBuf::from_path_buf(non_unicode_path).expect_err("non-Unicode path failed"); + /// ``` + pub fn from_path_buf(path: PathBuf) -> Result<Utf8PathBuf, PathBuf> { + match path.into_os_string().into_string() { + Ok(string) => Ok(Utf8PathBuf::from(string)), + Err(os_string) => Err(PathBuf::from(os_string)), + } + } + + /// Converts a `Utf8PathBuf` to a [`PathBuf`]. + /// + /// This is equivalent to the `From<Utf8PathBuf> for PathBuf` impl, but may aid in type + /// inference. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::path::PathBuf; + /// + /// let utf8_path_buf = Utf8PathBuf::from("foo.txt"); + /// let std_path_buf = utf8_path_buf.into_std_path_buf(); + /// assert_eq!(std_path_buf.to_str(), Some("foo.txt")); + /// + /// // Convert back to a Utf8PathBuf. + /// let new_utf8_path_buf = Utf8PathBuf::from_path_buf(std_path_buf).unwrap(); + /// assert_eq!(new_utf8_path_buf, "foo.txt"); + /// ``` + pub fn into_std_path_buf(self) -> PathBuf { + self.into() + } + + /// Creates a new `Utf8PathBuf` with a given capacity used to create the internal [`PathBuf`]. + /// See [`with_capacity`] defined on [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::with_capacity(10); + /// let capacity = path.capacity(); + /// + /// // This push is done without reallocating + /// path.push(r"C:\"); + /// + /// assert_eq!(capacity, path.capacity()); + /// ``` + /// + /// [`with_capacity`]: PathBuf::with_capacity + #[cfg(path_buf_capacity)] + pub fn with_capacity(capacity: usize) -> Utf8PathBuf { + Utf8PathBuf(PathBuf::with_capacity(capacity)) + } + + /// Coerces to a [`Utf8Path`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let p = Utf8PathBuf::from("/test"); + /// assert_eq!(Utf8Path::new("/test"), p.as_path()); + /// ``` + pub fn as_path(&self) -> &Utf8Path { + // SAFETY: every Utf8PathBuf constructor ensures that self is valid UTF-8 + unsafe { Utf8Path::assume_utf8(&*self.0) } + } + + /// Extends `self` with `path`. + /// + /// If `path` is absolute, it replaces the current path. + /// + /// On Windows: + /// + /// * if `path` has a root but no prefix (e.g., `\windows`), it + /// replaces everything except for the prefix (if any) of `self`. + /// * if `path` has a prefix but no root, it replaces `self`. + /// + /// # Examples + /// + /// Pushing a relative path extends the existing path: + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::from("/tmp"); + /// path.push("file.bk"); + /// assert_eq!(path, Utf8PathBuf::from("/tmp/file.bk")); + /// ``` + /// + /// Pushing an absolute path replaces the existing path: + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut path = Utf8PathBuf::from("/tmp"); + /// path.push("/etc"); + /// assert_eq!(path, Utf8PathBuf::from("/etc")); + /// ``` + pub fn push(&mut self, path: impl AsRef<Utf8Path>) { + self.0.push(&path.as_ref().0) + } + + /// Truncates `self` to [`self.parent`]. + /// + /// Returns `false` and does nothing if [`self.parent`] is [`None`]. + /// Otherwise, returns `true`. + /// + /// [`self.parent`]: Utf8Path::parent + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/spirited/away.rs"); + /// + /// p.pop(); + /// assert_eq!(Utf8Path::new("/spirited"), p); + /// p.pop(); + /// assert_eq!(Utf8Path::new("/"), p); + /// ``` + pub fn pop(&mut self) -> bool { + self.0.pop() + } + + /// Updates [`self.file_name`] to `file_name`. + /// + /// If [`self.file_name`] was [`None`], this is equivalent to pushing + /// `file_name`. + /// + /// Otherwise it is equivalent to calling [`pop`] and then pushing + /// `file_name`. The new path will be a sibling of the original path. + /// (That is, it will have the same parent.) + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`pop`]: Utf8PathBuf::pop + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let mut buf = Utf8PathBuf::from("/"); + /// assert_eq!(buf.file_name(), None); + /// buf.set_file_name("bar"); + /// assert_eq!(buf, Utf8PathBuf::from("/bar")); + /// assert!(buf.file_name().is_some()); + /// buf.set_file_name("baz.txt"); + /// assert_eq!(buf, Utf8PathBuf::from("/baz.txt")); + /// ``` + pub fn set_file_name(&mut self, file_name: impl AsRef<str>) { + self.0.set_file_name(file_name.as_ref()) + } + + /// Updates [`self.extension`] to `extension`. + /// + /// Returns `false` and does nothing if [`self.file_name`] is [`None`], + /// returns `true` and updates the extension otherwise. + /// + /// If [`self.extension`] is [`None`], the extension is added; otherwise + /// it is replaced. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// [`self.extension`]: Utf8Path::extension + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let mut p = Utf8PathBuf::from("/feel/the"); + /// + /// p.set_extension("force"); + /// assert_eq!(Utf8Path::new("/feel/the.force"), p.as_path()); + /// + /// p.set_extension("dark_side"); + /// assert_eq!(Utf8Path::new("/feel/the.dark_side"), p.as_path()); + /// ``` + pub fn set_extension(&mut self, extension: impl AsRef<str>) -> bool { + self.0.set_extension(extension.as_ref()) + } + + /// Consumes the `Utf8PathBuf`, yielding its internal [`String`] storage. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// + /// let p = Utf8PathBuf::from("/the/head"); + /// let s = p.into_string(); + /// assert_eq!(s, "/the/head"); + /// ``` + pub fn into_string(self) -> String { + self.into_os_string().into_string().unwrap() + } + + /// Consumes the `Utf8PathBuf`, yielding its internal [`OsString`] storage. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8PathBuf; + /// use std::ffi::OsStr; + /// + /// let p = Utf8PathBuf::from("/the/head"); + /// let s = p.into_os_string(); + /// assert_eq!(s, OsStr::new("/the/head")); + /// ``` + pub fn into_os_string(self) -> OsString { + self.0.into_os_string() + } + + /// Converts this `Utf8PathBuf` into a [boxed](Box) [`Utf8Path`]. + pub fn into_boxed_path(self) -> Box<Utf8Path> { + let ptr = Box::into_raw(self.0.into_boxed_path()) as *mut Utf8Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was constructed by consuming self so it represents an owned path + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to + // *mut Utf8Path is valid + unsafe { Box::from_raw(ptr) } + } + + /// Invokes [`capacity`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`capacity`]: PathBuf::capacity + #[cfg(path_buf_capacity)] + pub fn capacity(&self) -> usize { + self.0.capacity() + } + + /// Invokes [`clear`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`clear`]: PathBuf::clear + #[cfg(path_buf_capacity)] + pub fn clear(&mut self) { + self.0.clear() + } + + /// Invokes [`reserve`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`reserve`]: PathBuf::reserve + #[cfg(path_buf_capacity)] + pub fn reserve(&mut self, additional: usize) { + self.0.reserve(additional) + } + + /// Invokes [`reserve_exact`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`reserve_exact`]: PathBuf::reserve_exact + #[cfg(path_buf_capacity)] + pub fn reserve_exact(&mut self, additional: usize) { + self.0.reserve_exact(additional) + } + + /// Invokes [`shrink_to_fit`] on the underlying instance of [`PathBuf`]. + /// + /// *Requires Rust 1.44 or newer.* + /// + /// [`shrink_to_fit`]: PathBuf::shrink_to_fit + #[cfg(path_buf_capacity)] + pub fn shrink_to_fit(&mut self) { + self.0.shrink_to_fit() + } +} + +impl Deref for Utf8PathBuf { + type Target = Utf8Path; + + fn deref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl fmt::Debug for Utf8PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl fmt::Display for Utf8PathBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl<P: AsRef<Utf8Path>> Extend<P> for Utf8PathBuf { + fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) { + for path in iter { + self.push(path); + } + } +} + +/// A slice of a UTF-8 path (akin to [`str`]). +/// +/// This type supports a number of operations for inspecting a path, including +/// breaking the path into its components (separated by `/` on Unix and by either +/// `/` or `\` on Windows), extracting the file name, determining whether the path +/// is absolute, and so on. +/// +/// This is an *unsized* type, meaning that it must always be used behind a +/// pointer like `&` or [`Box`]. For an owned version of this type, +/// see [`Utf8PathBuf`]. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// // Note: this example does work on Windows +/// let path = Utf8Path::new("./foo/bar.txt"); +/// +/// let parent = path.parent(); +/// assert_eq!(parent, Some(Utf8Path::new("./foo"))); +/// +/// let file_stem = path.file_stem(); +/// assert_eq!(file_stem, Some("bar")); +/// +/// let extension = path.extension(); +/// assert_eq!(extension, Some("txt")); +/// ``` +// NB: Internal Path must only contain utf8 data +#[repr(transparent)] +pub struct Utf8Path(Path); + +impl Utf8Path { + /// Directly wraps a string slice as a `Utf8Path` slice. + /// + /// This is a cost-free conversion. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// Utf8Path::new("foo.txt"); + /// ``` + /// + /// You can create `Utf8Path`s from `String`s, or even other `Utf8Path`s: + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let string = String::from("foo.txt"); + /// let from_string = Utf8Path::new(&string); + /// let from_path = Utf8Path::new(&from_string); + /// assert_eq!(from_string, from_path); + /// ``` + pub fn new(s: &(impl AsRef<str> + ?Sized)) -> &Utf8Path { + let path = Path::new(s.as_ref()); + // SAFETY: s is a str which means it is always valid UTF-8 + unsafe { Utf8Path::assume_utf8(path) } + } + + /// Converts a [`Path`] to a `Utf8Path`. + /// + /// Returns `None` if the path is not valid UTF-8. + /// + /// For a version that returns a type that implements [`std::error::Error`], use the + /// `TryFrom<&Path>` impl. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::ffi::OsStr; + /// # #[cfg(unix)] + /// use std::os::unix::ffi::OsStrExt; + /// use std::path::Path; + /// + /// let unicode_path = Path::new("/valid/unicode"); + /// Utf8Path::from_path(unicode_path).expect("valid Unicode path succeeded"); + /// + /// // Paths on Unix can be non-UTF-8. + /// # #[cfg(unix)] + /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); + /// # #[cfg(unix)] + /// let non_unicode_path = Path::new(non_unicode_str); + /// # #[cfg(unix)] + /// assert!(Utf8Path::from_path(non_unicode_path).is_none(), "non-Unicode path failed"); + /// ``` + pub fn from_path(path: &Path) -> Option<&Utf8Path> { + path.as_os_str().to_str().map(Utf8Path::new) + } + + /// Converts a `Utf8Path` to a [`Path`]. + /// + /// This is equivalent to the `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::path::Path; + /// + /// let utf8_path = Utf8Path::new("foo.txt"); + /// let std_path: &Path = utf8_path.as_std_path(); + /// assert_eq!(std_path.to_str(), Some("foo.txt")); + /// + /// // Convert back to a Utf8Path. + /// let new_utf8_path = Utf8Path::from_path(std_path).unwrap(); + /// assert_eq!(new_utf8_path, "foo.txt"); + /// ``` + pub fn as_std_path(&self) -> &Path { + self.as_ref() + } + + /// Yields the underlying [`str`] slice. + /// + /// Unlike [`Path::to_str`], this always returns a slice because the contents of a `Utf8Path` + /// are guaranteed to be valid UTF-8. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let s = Utf8Path::new("foo.txt").as_str(); + /// assert_eq!(s, "foo.txt"); + /// ``` + /// + /// [`str`]: str + pub fn as_str(&self) -> &str { + // SAFETY: every Utf8Path constructor ensures that self is valid UTF-8 + unsafe { assume_utf8(self.as_os_str()) } + } + + /// Yields the underlying [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let os_str = Utf8Path::new("foo.txt").as_os_str(); + /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt")); + /// ``` + pub fn as_os_str(&self) -> &OsStr { + self.0.as_os_str() + } + + /// Converts a `Utf8Path` to an owned [`Utf8PathBuf`]. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path_buf = Utf8Path::new("foo.txt").to_path_buf(); + /// assert_eq!(path_buf, Utf8PathBuf::from("foo.txt")); + /// ``` + pub fn to_path_buf(&self) -> Utf8PathBuf { + Utf8PathBuf(self.0.to_path_buf()) + } + + /// Returns `true` if the `Utf8Path` is absolute, i.e., if it is independent of + /// the current directory. + /// + /// * On Unix, a path is absolute if it starts with the root, so + /// `is_absolute` and [`has_root`] are equivalent. + /// + /// * On Windows, a path is absolute if it has a prefix and starts with the + /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(!Utf8Path::new("foo.txt").is_absolute()); + /// ``` + /// + /// [`has_root`]: Utf8Path::has_root + pub fn is_absolute(&self) -> bool { + self.0.is_absolute() + } + + /// Returns `true` if the `Utf8Path` is relative, i.e., not absolute. + /// + /// See [`is_absolute`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(Utf8Path::new("foo.txt").is_relative()); + /// ``` + /// + /// [`is_absolute`]: Utf8Path::is_absolute + pub fn is_relative(&self) -> bool { + self.0.is_relative() + } + + /// Returns `true` if the `Utf8Path` has a root. + /// + /// * On Unix, a path has a root if it begins with `/`. + /// + /// * On Windows, a path has a root if it: + /// * has no prefix and begins with a separator, e.g., `\windows` + /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows` + /// * has any non-disk prefix, e.g., `\\server\share` + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert!(Utf8Path::new("/etc/passwd").has_root()); + /// ``` + pub fn has_root(&self) -> bool { + self.0.has_root() + } + + /// Returns the `Path` without its final component, if there is one. + /// + /// Returns [`None`] if the path terminates in a root or prefix. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/foo/bar"); + /// let parent = path.parent().unwrap(); + /// assert_eq!(parent, Utf8Path::new("/foo")); + /// + /// let grand_parent = parent.parent().unwrap(); + /// assert_eq!(grand_parent, Utf8Path::new("/")); + /// assert_eq!(grand_parent.parent(), None); + /// ``` + pub fn parent(&self) -> Option<&Utf8Path> { + self.0.parent().map(|path| { + // SAFETY: self is valid UTF-8, so parent is valid UTF-8 as well + unsafe { Utf8Path::assume_utf8(path) } + }) + } + + /// Produces an iterator over `Utf8Path` and its ancestors. + /// + /// The iterator will yield the `Utf8Path` that is returned if the [`parent`] method is used zero + /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`, + /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns + /// [`None`], the iterator will do likewise. The iterator will always yield at least one value, + /// namely `&self`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut ancestors = Utf8Path::new("/foo/bar").ancestors(); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo/bar"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/"))); + /// assert_eq!(ancestors.next(), None); + /// + /// let mut ancestors = Utf8Path::new("../foo/bar").ancestors(); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo/bar"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo"))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new(".."))); + /// assert_eq!(ancestors.next(), Some(Utf8Path::new(""))); + /// assert_eq!(ancestors.next(), None); + /// ``` + /// + /// [`parent`]: Utf8Path::parent + pub fn ancestors(&self) -> Utf8Ancestors<'_> { + Utf8Ancestors(self.0.ancestors()) + } + + /// Returns the final component of the `Utf8Path`, if there is one. + /// + /// If the path is a normal file, this is the file name. If it's the path of a directory, this + /// is the directory name. + /// + /// Returns [`None`] if the path terminates in `..`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!(Some("bin"), Utf8Path::new("/usr/bin/").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("tmp/foo.txt").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.").file_name()); + /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.//").file_name()); + /// assert_eq!(None, Utf8Path::new("foo.txt/..").file_name()); + /// assert_eq!(None, Utf8Path::new("/").file_name()); + /// ``` + pub fn file_name(&self) -> Option<&str> { + self.0.file_name().map(|s| { + // SAFETY: self is valid UTF-8, so file_name is valid UTF-8 as well + unsafe { assume_utf8(s) } + }) + } + + /// Returns a path that, when joined onto `base`, yields `self`. + /// + /// # Errors + /// + /// If `base` is not a prefix of `self` (i.e., [`starts_with`] + /// returns `false`), returns [`Err`]. + /// + /// [`starts_with`]: Utf8Path::starts_with + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/test/haha/foo.txt"); + /// + /// assert_eq!(path.strip_prefix("/"), Ok(Utf8Path::new("test/haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test"), Ok(Utf8Path::new("haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test/"), Ok(Utf8Path::new("haha/foo.txt"))); + /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Utf8Path::new(""))); + /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Utf8Path::new(""))); + /// + /// assert!(path.strip_prefix("test").is_err()); + /// assert!(path.strip_prefix("/haha").is_err()); + /// + /// let prefix = Utf8PathBuf::from("/test/"); + /// assert_eq!(path.strip_prefix(prefix), Ok(Utf8Path::new("haha/foo.txt"))); + /// ``` + pub fn strip_prefix(&self, base: impl AsRef<Path>) -> Result<&Utf8Path, StripPrefixError> { + self.0.strip_prefix(base).map(|path| { + // SAFETY: self is valid UTF-8, and strip_prefix returns a part of self (or an empty + // string), so it is valid UTF-8 as well. + unsafe { Utf8Path::assume_utf8(path) } + }) + } + + /// Determines whether `base` is a prefix of `self`. + /// + /// Only considers whole path components to match. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/etc/passwd"); + /// + /// assert!(path.starts_with("/etc")); + /// assert!(path.starts_with("/etc/")); + /// assert!(path.starts_with("/etc/passwd")); + /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay + /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay + /// + /// assert!(!path.starts_with("/e")); + /// assert!(!path.starts_with("/etc/passwd.txt")); + /// + /// assert!(!Utf8Path::new("/etc/foo.rs").starts_with("/etc/foo")); + /// ``` + pub fn starts_with(&self, base: impl AsRef<Path>) -> bool { + self.0.starts_with(base) + } + + /// Determines whether `child` is a suffix of `self`. + /// + /// Only considers whole path components to match. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/etc/resolv.conf"); + /// + /// assert!(path.ends_with("resolv.conf")); + /// assert!(path.ends_with("etc/resolv.conf")); + /// assert!(path.ends_with("/etc/resolv.conf")); + /// + /// assert!(!path.ends_with("/resolv.conf")); + /// assert!(!path.ends_with("conf")); // use .extension() instead + /// ``` + pub fn ends_with(&self, base: impl AsRef<Path>) -> bool { + self.0.ends_with(base) + } + + /// Extracts the stem (non-extension) portion of [`self.file_name`]. + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// The stem is: + /// + /// * [`None`], if there is no file name; + /// * The entire file name if there is no embedded `.`; + /// * The entire file name if the file name begins with `.` and has no other `.`s within; + /// * Otherwise, the portion of the file name before the final `.` + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("foo", Utf8Path::new("foo.rs").file_stem().unwrap()); + /// assert_eq!("foo.tar", Utf8Path::new("foo.tar.gz").file_stem().unwrap()); + /// ``` + pub fn file_stem(&self) -> Option<&str> { + self.0.file_stem().map(|s| { + // SAFETY: self is valid UTF-8, so file_stem is valid UTF-8 as well + unsafe { assume_utf8(s) } + }) + } + + /// Extracts the extension of [`self.file_name`], if possible. + /// + /// The extension is: + /// + /// * [`None`], if there is no file name; + /// * [`None`], if there is no embedded `.`; + /// * [`None`], if the file name begins with `.` and has no other `.`s within; + /// * Otherwise, the portion of the file name after the final `.` + /// + /// [`self.file_name`]: Utf8Path::file_name + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// assert_eq!("rs", Utf8Path::new("foo.rs").extension().unwrap()); + /// assert_eq!("gz", Utf8Path::new("foo.tar.gz").extension().unwrap()); + /// ``` + pub fn extension(&self) -> Option<&str> { + self.0.extension().map(|s| { + // SAFETY: self is valid UTF-8, so extension is valid UTF-8 as well + unsafe { assume_utf8(s) } + }) + } + + /// Creates an owned [`Utf8PathBuf`] with `path` adjoined to `self`. + /// + /// See [`Utf8PathBuf::push`] for more details on what it means to adjoin a path. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// assert_eq!(Utf8Path::new("/etc").join("passwd"), Utf8PathBuf::from("/etc/passwd")); + /// ``` + pub fn join(&self, path: impl AsRef<Utf8Path>) -> Utf8PathBuf { + Utf8PathBuf(self.0.join(&path.as_ref().0)) + } + + /// Creates an owned [`PathBuf`] with `path` adjoined to `self`. + /// + /// See [`PathBuf::push`] for more details on what it means to adjoin a path. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// use std::path::PathBuf; + /// + /// assert_eq!(Utf8Path::new("/etc").join_os("passwd"), PathBuf::from("/etc/passwd")); + /// ``` + pub fn join_os(&self, path: impl AsRef<Path>) -> PathBuf { + self.0.join(path) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the given file name. + /// + /// See [`Utf8PathBuf::set_file_name`] for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/tmp/foo.txt"); + /// assert_eq!(path.with_file_name("bar.txt"), Utf8PathBuf::from("/tmp/bar.txt")); + /// + /// let path = Utf8Path::new("/tmp"); + /// assert_eq!(path.with_file_name("var"), Utf8PathBuf::from("/var")); + /// ``` + pub fn with_file_name(&self, file_name: impl AsRef<str>) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_file_name(file_name.as_ref())) + } + + /// Creates an owned [`Utf8PathBuf`] like `self` but with the given extension. + /// + /// See [`Utf8PathBuf::set_extension`] for more details. + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("foo.rs"); + /// assert_eq!(path.with_extension("txt"), Utf8PathBuf::from("foo.txt")); + /// + /// let path = Utf8Path::new("foo.tar.gz"); + /// assert_eq!(path.with_extension(""), Utf8PathBuf::from("foo.tar")); + /// assert_eq!(path.with_extension("xz"), Utf8PathBuf::from("foo.tar.xz")); + /// assert_eq!(path.with_extension("").with_extension("txt"), Utf8PathBuf::from("foo.txt")); + /// ``` + pub fn with_extension(&self, extension: impl AsRef<str>) -> Utf8PathBuf { + Utf8PathBuf(self.0.with_extension(extension.as_ref())) + } + + /// Produces an iterator over the [`Utf8Component`]s of the path. + /// + /// When parsing the path, there is a small amount of normalization: + /// + /// * Repeated separators are ignored, so `a/b` and `a//b` both have + /// `a` and `b` as components. + /// + /// * Occurrences of `.` are normalized away, except if they are at the + /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and + /// `a/b` all have `a` and `b` as components, but `./a/b` starts with + /// an additional [`CurDir`] component. + /// + /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent. + /// + /// Note that no other normalization takes place; in particular, `a/c` + /// and `a/b/../c` are distinct, to account for the possibility that `b` + /// is a symbolic link (so its parent isn't `a`). + /// + /// # Examples + /// + /// ``` + /// use camino::{Utf8Component, Utf8Path}; + /// + /// let mut components = Utf8Path::new("/tmp/foo.txt").components(); + /// + /// assert_eq!(components.next(), Some(Utf8Component::RootDir)); + /// assert_eq!(components.next(), Some(Utf8Component::Normal("tmp"))); + /// assert_eq!(components.next(), Some(Utf8Component::Normal("foo.txt"))); + /// assert_eq!(components.next(), None) + /// ``` + /// + /// [`CurDir`]: Utf8Component::CurDir + pub fn components(&self) -> Utf8Components { + Utf8Components(self.0.components()) + } + + /// Produces an iterator over the path's components viewed as [`str`] + /// slices. + /// + /// For more information about the particulars of how the path is separated + /// into components, see [`components`]. + /// + /// [`components`]: Utf8Path::components + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut it = Utf8Path::new("/tmp/foo.txt").iter(); + /// assert_eq!(it.next(), Some(std::path::MAIN_SEPARATOR.to_string().as_str())); + /// assert_eq!(it.next(), Some("tmp")); + /// assert_eq!(it.next(), Some("foo.txt")); + /// assert_eq!(it.next(), None) + /// ``` + pub fn iter(&self) -> Iter<'_> { + Iter { + inner: self.components(), + } + } + + /// Queries the file system to get information about a file, directory, etc. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. + /// + /// This is an alias to [`fs::metadata`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/Minas/tirith"); + /// let metadata = path.metadata().expect("metadata call failed"); + /// println!("{:?}", metadata.file_type()); + /// ``` + pub fn metadata(&self) -> io::Result<fs::Metadata> { + self.0.metadata() + } + + /// Queries the metadata about a file without following symlinks. + /// + /// This is an alias to [`fs::symlink_metadata`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/Minas/tirith"); + /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed"); + /// println!("{:?}", metadata.file_type()); + /// ``` + pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> { + self.0.symlink_metadata() + } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not + /// be. For a version that returns a [`Utf8PathBuf`], see + /// [`canonicalize_utf8`](Self::canonicalize_utf8). + /// + /// This is an alias to [`fs::canonicalize`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// use std::path::PathBuf; + /// + /// let path = Utf8Path::new("/foo/test/../test/bar.rs"); + /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); + /// ``` + pub fn canonicalize(&self) -> io::Result<PathBuf> { + self.0.canonicalize() + } + + /// Returns the canonical, absolute form of the path with all intermediate + /// components normalized and symbolic links resolved. + /// + /// This method attempts to convert the resulting [`PathBuf`] into a [`Utf8PathBuf`]. For a + /// version that does not attempt to do this conversion, see + /// [`canonicalize`](Self::canonicalize). + /// + /// # Errors + /// + /// The I/O operation may return an error: see the [`fs::canonicalize`] + /// documentation for more. + /// + /// If the resulting path is not UTF-8, an [`io::Error`] is returned with the + /// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a + /// [`FromPathBufError`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::{Utf8Path, Utf8PathBuf}; + /// + /// let path = Utf8Path::new("/foo/test/../test/bar.rs"); + /// assert_eq!(path.canonicalize_utf8().unwrap(), Utf8PathBuf::from("/foo/test/bar.rs")); + /// ``` + pub fn canonicalize_utf8(&self) -> io::Result<Utf8PathBuf> { + self.canonicalize().and_then(|path| { + path.try_into() + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) + }) + } + + /// Reads a symbolic link, returning the file that the link points to. + /// + /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not + /// be. For a version that returns a [`Utf8PathBuf`], see + /// [`read_link_utf8`](Self::read_link_utf8). + /// + /// This is an alias to [`fs::read_link`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa/sky_castle.rs"); + /// let path_link = path.read_link().expect("read_link call failed"); + /// ``` + pub fn read_link(&self) -> io::Result<PathBuf> { + self.0.read_link() + } + + /// Reads a symbolic link, returning the file that the link points to. + /// + /// This method attempts to convert the resulting [`PathBuf`] into a [`Utf8PathBuf`]. For a + /// version that does not attempt to do this conversion, see [`read_link`](Self::read_link). + /// + /// # Errors + /// + /// The I/O operation may return an error: see the [`fs::read_link`] + /// documentation for more. + /// + /// If the resulting path is not UTF-8, an [`io::Error`] is returned with the + /// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a + /// [`FromPathBufError`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa/sky_castle.rs"); + /// let path_link = path.read_link_utf8().expect("read_link call failed"); + /// ``` + pub fn read_link_utf8(&self) -> io::Result<Utf8PathBuf> { + self.read_link().and_then(|path| { + path.try_into() + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err)) + }) + } + + /// Returns an iterator over the entries within a directory. + /// + /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New + /// errors may be encountered after an iterator is initially constructed. + /// + /// This is an alias to [`fs::read_dir`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa"); + /// for entry in path.read_dir().expect("read_dir call failed") { + /// if let Ok(entry) = entry { + /// println!("{:?}", entry.path()); + /// } + /// } + /// ``` + pub fn read_dir(&self) -> io::Result<fs::ReadDir> { + self.0.read_dir() + } + + /// Returns an iterator over the entries within a directory. + /// + /// The iterator will yield instances of [`io::Result`]`<`[`Utf8DirEntry`]`>`. New + /// errors may be encountered after an iterator is initially constructed. + /// + /// # Errors + /// + /// The I/O operation may return an error: see the [`fs::read_dir`] + /// documentation for more. + /// + /// If a directory entry is not UTF-8, an [`io::Error`] is returned with the + /// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a + /// [`FromPathBufError`]. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("/laputa"); + /// for entry in path.read_dir_utf8().expect("read_dir call failed") { + /// if let Ok(entry) = entry { + /// println!("{}", entry.path()); + /// } + /// } + /// ``` + #[inline] + pub fn read_dir_utf8(&self) -> io::Result<ReadDirUtf8> { + self.0.read_dir().map(|inner| ReadDirUtf8 { inner }) + } + + /// Returns `true` if the path points at an existing entity. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert!(!Utf8Path::new("does_not_exist.txt").exists()); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`]. + pub fn exists(&self) -> bool { + self.0.exists() + } + + /// Returns `true` if the path exists on disk and is pointing at a regular file. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert_eq!(Utf8Path::new("./is_a_directory/").is_file(), false); + /// assert_eq!(Utf8Path::new("a_file.txt").is_file(), true); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_file`] if it was [`Ok`]. + /// + /// When the goal is simply to read from (or write to) the source, the most + /// reliable way to test the source can be read (or written to) is to open + /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on + /// a Unix-like system for example. See [`fs::File::open`] or + /// [`fs::OpenOptions::open`] for more information. + pub fn is_file(&self) -> bool { + self.0.is_file() + } + + /// Returns `true` if the path exists on disk and is pointing at a directory. + /// + /// This function will traverse symbolic links to query information about the + /// destination file. In case of broken symbolic links this will return `false`. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return `false`. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// assert_eq!(Utf8Path::new("./is_a_directory/").is_dir(), true); + /// assert_eq!(Utf8Path::new("a_file.txt").is_dir(), false); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_dir`] if it was [`Ok`]. + pub fn is_dir(&self) -> bool { + self.0.is_dir() + } + + /// Returns `true` if the path exists on disk and is pointing at a symbolic link. + /// + /// This function will not traverse symbolic links. + /// In case of a broken symbolic link this will also return true. + /// + /// If you cannot access the directory containing the file, e.g., because of a + /// permission error, this will return false. + /// + /// # Examples + /// + #[cfg_attr(unix, doc = "```no_run")] + #[cfg_attr(not(unix), doc = "```ignore")] + /// use camino::Utf8Path; + /// use std::os::unix::fs::symlink; + /// + /// let link_path = Utf8Path::new("link"); + /// symlink("/origin_does_not_exist/", link_path).unwrap(); + /// assert_eq!(link_path.is_symlink(), true); + /// assert_eq!(link_path.exists(), false); + /// ``` + /// + /// # See Also + /// + /// This is a convenience function that coerces errors to false. If you want to + /// check errors, call [`Utf8Path::symlink_metadata`] and handle its [`Result`]. Then call + /// [`fs::Metadata::is_symlink`] if it was [`Ok`]. + #[must_use] + pub fn is_symlink(&self) -> bool { + self.symlink_metadata() + .map(|m| m.file_type().is_symlink()) + .unwrap_or(false) + } + + /// Converts a `Box<Utf8Path>` into a [`Utf8PathBuf`] without copying or allocating. + pub fn into_path_buf(self: Box<Utf8Path>) -> Utf8PathBuf { + let ptr = Box::into_raw(self) as *mut Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was constructed by consuming self so it represents an owned path. + // * Utf8Path is marked as #[repr(transparent)] so the conversion from a *mut Utf8Path to a + // *mut Path is valid. + let boxed_path = unsafe { Box::from_raw(ptr) }; + Utf8PathBuf(boxed_path.into_path_buf()) + } + + // invariant: Path must be guaranteed to be utf-8 data + unsafe fn assume_utf8(path: &Path) -> &Utf8Path { + // SAFETY: Utf8Path is marked as #[repr(transparent)] so the conversion from a + // *const Path to a *const Utf8Path is valid. + &*(path as *const Path as *const Utf8Path) + } +} + +impl Clone for Box<Utf8Path> { + fn clone(&self) -> Self { + let boxed: Box<Path> = self.0.into(); + let ptr = Box::into_raw(boxed) as *mut Utf8Path; + // SAFETY: + // * self is valid UTF-8 + // * ptr was created by consuming a Box<Path> so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to + // *mut Utf8Path is valid + unsafe { Box::from_raw(ptr) } + } +} + +impl fmt::Display for Utf8Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl fmt::Debug for Utf8Path { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_str(), f) + } +} + +/// An iterator over [`Utf8Path`] and its ancestors. +/// +/// This `struct` is created by the [`ancestors`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// let path = Utf8Path::new("/foo/bar"); +/// +/// for ancestor in path.ancestors() { +/// println!("{}", ancestor); +/// } +/// ``` +/// +/// [`ancestors`]: Utf8Path::ancestors +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct Utf8Ancestors<'a>(Ancestors<'a>); + +impl<'a> fmt::Debug for Utf8Ancestors<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl<'a> Iterator for Utf8Ancestors<'a> { + type Item = &'a Utf8Path; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(|path| { + // SAFETY: Utf8Ancestors was constructed from a Utf8Path, so it is guaranteed to + // be valid UTF-8 + unsafe { Utf8Path::assume_utf8(path) } + }) + } +} + +impl<'a> FusedIterator for Utf8Ancestors<'a> {} + +/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`]. +/// +/// This `struct` is created by the [`components`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// # Examples +/// +/// ``` +/// use camino::Utf8Path; +/// +/// let path = Utf8Path::new("/tmp/foo/bar.txt"); +/// +/// for component in path.components() { +/// println!("{:?}", component); +/// } +/// ``` +/// +/// [`components`]: Utf8Path::components +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +pub struct Utf8Components<'a>(Components<'a>); + +impl<'a> Utf8Components<'a> { + /// Extracts a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut components = Utf8Path::new("/tmp/foo/bar.txt").components(); + /// components.next(); + /// components.next(); + /// + /// assert_eq!(Utf8Path::new("foo/bar.txt"), components.as_path()); + /// ``` + pub fn as_path(&self) -> &'a Utf8Path { + // SAFETY: Utf8Components was constructed from a Utf8Path, so it is guaranteed to be valid + // UTF-8 + unsafe { Utf8Path::assume_utf8(self.0.as_path()) } + } +} + +impl<'a> Iterator for Utf8Components<'a> { + type Item = Utf8Component<'a>; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next().map(|component| { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { Utf8Component::new(component) } + }) + } +} + +impl<'a> FusedIterator for Utf8Components<'a> {} + +impl<'a> DoubleEndedIterator for Utf8Components<'a> { + fn next_back(&mut self) -> Option<Self::Item> { + self.0.next_back().map(|component| { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { Utf8Component::new(component) } + }) + } +} + +impl<'a> fmt::Debug for Utf8Components<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl AsRef<Utf8Path> for Utf8Components<'_> { + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef<Path> for Utf8Components<'_> { + fn as_ref(&self) -> &Path { + self.as_path().as_ref() + } +} + +impl AsRef<str> for Utf8Components<'_> { + fn as_ref(&self) -> &str { + self.as_path().as_ref() + } +} + +impl AsRef<OsStr> for Utf8Components<'_> { + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`], as [`str`] slices. +/// +/// This `struct` is created by the [`iter`] method on [`Utf8Path`]. +/// See its documentation for more. +/// +/// [`iter`]: Utf8Path::iter +#[derive(Clone)] +pub struct Iter<'a> { + inner: Utf8Components<'a>, +} + +impl fmt::Debug for Iter<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + struct DebugHelper<'a>(&'a Utf8Path); + + impl fmt::Debug for DebugHelper<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.0.iter()).finish() + } + } + + f.debug_tuple("Iter") + .field(&DebugHelper(self.as_path())) + .finish() + } +} + +impl<'a> Iter<'a> { + /// Extracts a slice corresponding to the portion of the path remaining for iteration. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let mut iter = Utf8Path::new("/tmp/foo/bar.txt").iter(); + /// iter.next(); + /// iter.next(); + /// + /// assert_eq!(Utf8Path::new("foo/bar.txt"), iter.as_path()); + /// ``` + pub fn as_path(&self) -> &'a Utf8Path { + self.inner.as_path() + } +} + +impl AsRef<Utf8Path> for Iter<'_> { + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef<Path> for Iter<'_> { + fn as_ref(&self) -> &Path { + self.as_path().as_ref() + } +} + +impl AsRef<str> for Iter<'_> { + fn as_ref(&self) -> &str { + self.as_path().as_ref() + } +} + +impl AsRef<OsStr> for Iter<'_> { + fn as_ref(&self) -> &OsStr { + self.as_path().as_os_str() + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a str; + + fn next(&mut self) -> Option<&'a str> { + self.inner.next().map(|component| component.as_str()) + } +} + +impl<'a> DoubleEndedIterator for Iter<'a> { + fn next_back(&mut self) -> Option<&'a str> { + self.inner.next_back().map(|component| component.as_str()) + } +} + +impl FusedIterator for Iter<'_> {} + +/// A single component of a path. +/// +/// A `Utf8Component` roughly corresponds to a substring between path separators +/// (`/` or `\`). +/// +/// This `enum` is created by iterating over [`Utf8Components`], which in turn is +/// created by the [`components`](Utf8Path::components) method on [`Utf8Path`]. +/// +/// # Examples +/// +/// ```rust +/// use camino::{Utf8Component, Utf8Path}; +/// +/// let path = Utf8Path::new("/tmp/foo/bar.txt"); +/// let components = path.components().collect::<Vec<_>>(); +/// assert_eq!(&components, &[ +/// Utf8Component::RootDir, +/// Utf8Component::Normal("tmp"), +/// Utf8Component::Normal("foo"), +/// Utf8Component::Normal("bar.txt"), +/// ]); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum Utf8Component<'a> { + /// A Windows path prefix, e.g., `C:` or `\\server\share`. + /// + /// There is a large variety of prefix types, see [`Utf8Prefix`]'s documentation + /// for more. + /// + /// Does not occur on Unix. + Prefix(Utf8PrefixComponent<'a>), + + /// The root directory component, appears after any prefix and before anything else. + /// + /// It represents a separator that designates that a path starts from root. + RootDir, + + /// A reference to the current directory, i.e., `.`. + CurDir, + + /// A reference to the parent directory, i.e., `..`. + ParentDir, + + /// A normal component, e.g., `a` and `b` in `a/b`. + /// + /// This variant is the most common one, it represents references to files + /// or directories. + Normal(&'a str), +} + +impl<'a> Utf8Component<'a> { + unsafe fn new(component: Component<'a>) -> Utf8Component<'a> { + match component { + Component::Prefix(prefix) => Utf8Component::Prefix(Utf8PrefixComponent(prefix)), + Component::RootDir => Utf8Component::RootDir, + Component::CurDir => Utf8Component::CurDir, + Component::ParentDir => Utf8Component::ParentDir, + Component::Normal(s) => Utf8Component::Normal(assume_utf8(s)), + } + } + + /// Extracts the underlying [`str`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` + pub fn as_str(&self) -> &'a str { + // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { assume_utf8(self.as_os_str()) } + } + + /// Extracts the underlying [`OsStr`] slice. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// let path = Utf8Path::new("./tmp/foo/bar.txt"); + /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect(); + /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]); + /// ``` + pub fn as_os_str(&self) -> &'a OsStr { + match *self { + Utf8Component::Prefix(prefix) => prefix.as_os_str(), + Utf8Component::RootDir => Component::RootDir.as_os_str(), + Utf8Component::CurDir => Component::CurDir.as_os_str(), + Utf8Component::ParentDir => Component::ParentDir.as_os_str(), + Utf8Component::Normal(s) => OsStr::new(s), + } + } +} + +impl<'a> fmt::Debug for Utf8Component<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.as_os_str(), f) + } +} + +impl<'a> fmt::Display for Utf8Component<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +impl AsRef<Utf8Path> for Utf8Component<'_> { + fn as_ref(&self) -> &Utf8Path { + self.as_str().as_ref() + } +} + +impl AsRef<Path> for Utf8Component<'_> { + fn as_ref(&self) -> &Path { + self.as_os_str().as_ref() + } +} + +impl AsRef<str> for Utf8Component<'_> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<OsStr> for Utf8Component<'_> { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +/// Windows path prefixes, e.g., `C:` or `\\server\share`. +/// +/// Windows uses a variety of path prefix styles, including references to drive +/// volumes (like `C:`), network shared folders (like `\\server\share`), and +/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with +/// `\\?\`), in which case `/` is *not* treated as a separator and essentially +/// no normalization is performed. +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Component, Utf8Path, Utf8Prefix}; +/// use camino::Utf8Prefix::*; +/// +/// fn get_path_prefix(s: &str) -> Utf8Prefix { +/// let path = Utf8Path::new(s); +/// match path.components().next().unwrap() { +/// Utf8Component::Prefix(prefix_component) => prefix_component.kind(), +/// _ => panic!(), +/// } +/// } +/// +/// # if cfg!(windows) { +/// assert_eq!(Verbatim("pictures"), get_path_prefix(r"\\?\pictures\kittens")); +/// assert_eq!(VerbatimUNC("server", "share"), get_path_prefix(r"\\?\UNC\server\share")); +/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\")); +/// assert_eq!(DeviceNS("BrainInterface"), get_path_prefix(r"\\.\BrainInterface")); +/// assert_eq!(UNC("server", "share"), get_path_prefix(r"\\server\share")); +/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris")); +/// # } +/// ``` +#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub enum Utf8Prefix<'a> { + /// Verbatim prefix, e.g., `\\?\cat_pics`. + /// + /// Verbatim prefixes consist of `\\?\` immediately followed by the given + /// component. + Verbatim(&'a str), + + /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_, + /// e.g., `\\?\UNC\server\share`. + /// + /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the + /// server's hostname and a share name. + VerbatimUNC(&'a str, &'a str), + + /// Verbatim disk prefix, e.g., `\\?\C:`. + /// + /// Verbatim disk prefixes consist of `\\?\` immediately followed by the + /// drive letter and `:`. + VerbatimDisk(u8), + + /// Device namespace prefix, e.g., `\\.\COM42`. + /// + /// Device namespace prefixes consist of `\\.\` immediately followed by the + /// device name. + DeviceNS(&'a str), + + /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g. + /// `\\server\share`. + /// + /// UNC prefixes consist of the server's hostname and a share name. + UNC(&'a str, &'a str), + + /// Prefix `C:` for the given disk drive. + Disk(u8), +} + +impl<'a> Utf8Prefix<'a> { + /// Determines if the prefix is verbatim, i.e., begins with `\\?\`. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Prefix::*; + /// + /// assert!(Verbatim("pictures").is_verbatim()); + /// assert!(VerbatimUNC("server", "share").is_verbatim()); + /// assert!(VerbatimDisk(b'C').is_verbatim()); + /// assert!(!DeviceNS("BrainInterface").is_verbatim()); + /// assert!(!UNC("server", "share").is_verbatim()); + /// assert!(!Disk(b'C').is_verbatim()); + /// ``` + pub fn is_verbatim(&self) -> bool { + use Utf8Prefix::*; + match self { + Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true, + _ => false, + } + } +} + +/// A structure wrapping a Windows path prefix as well as its unparsed string +/// representation. +/// +/// In addition to the parsed [`Utf8Prefix`] information returned by [`kind`], +/// `Utf8PrefixComponent` also holds the raw and unparsed [`str`] slice, +/// returned by [`as_str`]. +/// +/// Instances of this `struct` can be obtained by matching against the +/// [`Prefix` variant] on [`Utf8Component`]. +/// +/// Does not occur on Unix. +/// +/// # Examples +/// +/// ``` +/// # if cfg!(windows) { +/// use camino::{Utf8Component, Utf8Path, Utf8Prefix}; +/// use std::ffi::OsStr; +/// +/// let path = Utf8Path::new(r"c:\you\later\"); +/// match path.components().next().unwrap() { +/// Utf8Component::Prefix(prefix_component) => { +/// assert_eq!(Utf8Prefix::Disk(b'C'), prefix_component.kind()); +/// assert_eq!("c:", prefix_component.as_str()); +/// } +/// _ => unreachable!(), +/// } +/// # } +/// ``` +/// +/// [`as_str`]: Utf8PrefixComponent::as_str +/// [`kind`]: Utf8PrefixComponent::kind +/// [`Prefix` variant]: Utf8Component::Prefix +#[repr(transparent)] +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct Utf8PrefixComponent<'a>(PrefixComponent<'a>); + +impl<'a> Utf8PrefixComponent<'a> { + /// Returns the parsed prefix data. + /// + /// See [`Utf8Prefix`]'s documentation for more information on the different + /// kinds of prefixes. + pub fn kind(&self) -> Utf8Prefix<'a> { + // SAFETY for all the below unsafe blocks: the path self was originally constructed from was + // UTF-8 so any parts of it are valid UTF-8 + match self.0.kind() { + Prefix::Verbatim(prefix) => Utf8Prefix::Verbatim(unsafe { assume_utf8(prefix) }), + Prefix::VerbatimUNC(server, share) => { + let server = unsafe { assume_utf8(server) }; + let share = unsafe { assume_utf8(share) }; + Utf8Prefix::VerbatimUNC(server, share) + } + Prefix::VerbatimDisk(drive) => Utf8Prefix::VerbatimDisk(drive), + Prefix::DeviceNS(prefix) => Utf8Prefix::DeviceNS(unsafe { assume_utf8(prefix) }), + Prefix::UNC(server, share) => { + let server = unsafe { assume_utf8(server) }; + let share = unsafe { assume_utf8(share) }; + Utf8Prefix::UNC(server, share) + } + Prefix::Disk(drive) => Utf8Prefix::Disk(drive), + } + } + + /// Returns the [`str`] slice for this prefix. + pub fn as_str(&self) -> &'a str { + // SAFETY: Utf8PrefixComponent was constructed from a Utf8Path, so it is guaranteed to be + // valid UTF-8 + unsafe { assume_utf8(self.as_os_str()) } + } + + /// Returns the raw [`OsStr`] slice for this prefix. + pub fn as_os_str(&self) -> &'a OsStr { + self.0.as_os_str() + } +} + +impl<'a> fmt::Debug for Utf8PrefixComponent<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl<'a> fmt::Display for Utf8PrefixComponent<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.as_str(), f) + } +} + +// --- +// read_dir_utf8 +// --- + +/// Iterator over the entries in a directory. +/// +/// This iterator is returned from [`Utf8Path::read_dir_utf8`] and will yield instances of +/// <code>[io::Result]<[Utf8DirEntry]></code>. Through a [`Utf8 DirEntry`] information like the entry's path +/// and possibly other metadata can be learned. +/// +/// The order in which this iterator returns entries is platform and filesystem +/// dependent. +/// +/// # Errors +/// +/// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent +/// IO error during iteration. +/// +/// If a directory entry is not UTF-8, an [`io::Error`] is returned with the +/// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a [`FromPathBufError`]. +#[derive(Debug)] +pub struct ReadDirUtf8 { + inner: fs::ReadDir, +} + +impl Iterator for ReadDirUtf8 { + type Item = io::Result<Utf8DirEntry>; + + fn next(&mut self) -> Option<io::Result<Utf8DirEntry>> { + self.inner + .next() + .map(|entry| entry.and_then(Utf8DirEntry::new)) + } +} + +/// Entries returned by the [`ReadDirUtf8`] iterator. +/// +/// An instance of `Utf8DirEntry` represents an entry inside of a directory on the filesystem. Each +/// entry can be inspected via methods to learn about the full path or possibly other metadata. +#[derive(Debug)] +pub struct Utf8DirEntry { + inner: fs::DirEntry, + path: Utf8PathBuf, +} + +impl Utf8DirEntry { + fn new(inner: fs::DirEntry) -> io::Result<Self> { + let path = inner + .path() + .try_into() + .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; + Ok(Self { inner, path }) + } + + /// Returns the full path to the file that this entry represents. + /// + /// The full path is created by joining the original path to `read_dir` + /// with the filename of this entry. + /// + /// # Examples + /// + /// ```no_run + /// use camino::Utf8Path; + /// + /// fn main() -> std::io::Result<()> { + /// for entry in Utf8Path::new(".").read_dir_utf8()? { + /// let dir = entry?; + /// println!("{}", dir.path()); + /// } + /// Ok(()) + /// } + /// ``` + /// + /// This prints output like: + /// + /// ```text + /// ./whatever.txt + /// ./foo.html + /// ./hello_world.rs + /// ``` + /// + /// The exact text, of course, depends on what files you have in `.`. + #[inline] + pub fn path(&self) -> &Utf8Path { + &self.path + } + + /// Returns the metadata for the file that this entry points at. + /// + /// This function will not traverse symlinks if this entry points at a symlink. To traverse + /// symlinks use [`Utf8Path::metadata`] or [`fs::File::metadata`]. + /// + /// # Platform-specific behavior + /// + /// On Windows this function is cheap to call (no extra system calls + /// needed), but on Unix platforms this function is the equivalent of + /// calling `symlink_metadata` on the path. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() { + /// for entry in entries { + /// if let Ok(entry) = entry { + /// // Here, `entry` is a `Utf8DirEntry`. + /// if let Ok(metadata) = entry.metadata() { + /// // Now let's show our entry's permissions! + /// println!("{}: {:?}", entry.path(), metadata.permissions()); + /// } else { + /// println!("Couldn't get metadata for {}", entry.path()); + /// } + /// } + /// } + /// } + /// ``` + #[inline] + pub fn metadata(&self) -> io::Result<Metadata> { + self.inner.metadata() + } + + /// Returns the file type for the file that this entry points at. + /// + /// This function will not traverse symlinks if this entry points at a + /// symlink. + /// + /// # Platform-specific behavior + /// + /// On Windows and most Unix platforms this function is free (no extra + /// system calls needed), but some Unix platforms may require the equivalent + /// call to `symlink_metadata` to learn about the target file type. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() { + /// for entry in entries { + /// if let Ok(entry) = entry { + /// // Here, `entry` is a `DirEntry`. + /// if let Ok(file_type) = entry.file_type() { + /// // Now let's show our entry's file type! + /// println!("{}: {:?}", entry.path(), file_type); + /// } else { + /// println!("Couldn't get file type for {}", entry.path()); + /// } + /// } + /// } + /// } + /// ``` + #[inline] + pub fn file_type(&self) -> io::Result<fs::FileType> { + self.inner.file_type() + } + + /// Returns the bare file name of this directory entry without any other + /// leading path component. + /// + /// # Examples + /// + /// ``` + /// use camino::Utf8Path; + /// + /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() { + /// for entry in entries { + /// if let Ok(entry) = entry { + /// // Here, `entry` is a `DirEntry`. + /// println!("{}", entry.file_name()); + /// } + /// } + /// } + /// ``` + pub fn file_name(&self) -> &str { + self.path + .file_name() + .expect("path created through DirEntry must have a filename") + } + + /// Returns the original [`fs::DirEntry`] within this [`Utf8DirEntry`]. + #[inline] + pub fn into_inner(self) -> fs::DirEntry { + self.inner + } +} + +impl From<String> for Utf8PathBuf { + fn from(string: String) -> Utf8PathBuf { + Utf8PathBuf(string.into()) + } +} + +impl FromStr for Utf8PathBuf { + type Err = Infallible; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(Utf8PathBuf(s.into())) + } +} + +// --- +// From impls: borrowed -> borrowed +// --- + +impl<'a> From<&'a str> for &'a Utf8Path { + fn from(s: &'a str) -> &'a Utf8Path { + Utf8Path::new(s) + } +} + +// --- +// From impls: borrowed -> owned +// --- + +impl<T: ?Sized + AsRef<str>> From<&T> for Utf8PathBuf { + fn from(s: &T) -> Utf8PathBuf { + Utf8PathBuf::from(s.as_ref().to_owned()) + } +} + +impl<T: ?Sized + AsRef<str>> From<&T> for Box<Utf8Path> { + fn from(s: &T) -> Box<Utf8Path> { + Utf8PathBuf::from(s).into_boxed_path() + } +} + +impl From<&'_ Utf8Path> for Arc<Utf8Path> { + fn from(path: &Utf8Path) -> Arc<Utf8Path> { + let arc: Arc<Path> = Arc::from(AsRef::<Path>::as_ref(path)); + let ptr = Arc::into_raw(arc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Arc<Path> so it represents an arced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Arc::from_raw(ptr) } + } +} + +impl From<&'_ Utf8Path> for Rc<Utf8Path> { + fn from(path: &Utf8Path) -> Rc<Utf8Path> { + let rc: Rc<Path> = Rc::from(AsRef::<Path>::as_ref(path)); + let ptr = Rc::into_raw(rc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Rc<Path> so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Rc::from_raw(ptr) } + } +} + +impl<'a> From<&'a Utf8Path> for Cow<'a, Utf8Path> { + fn from(path: &'a Utf8Path) -> Cow<'a, Utf8Path> { + Cow::Borrowed(path) + } +} + +impl From<&'_ Utf8Path> for Box<Path> { + fn from(path: &Utf8Path) -> Box<Path> { + AsRef::<Path>::as_ref(path).into() + } +} + +impl From<&'_ Utf8Path> for Arc<Path> { + fn from(path: &Utf8Path) -> Arc<Path> { + AsRef::<Path>::as_ref(path).into() + } +} + +impl From<&'_ Utf8Path> for Rc<Path> { + fn from(path: &Utf8Path) -> Rc<Path> { + AsRef::<Path>::as_ref(path).into() + } +} + +impl<'a> From<&'a Utf8Path> for Cow<'a, Path> { + fn from(path: &'a Utf8Path) -> Cow<'a, Path> { + Cow::Borrowed(path.as_ref()) + } +} + +// --- +// From impls: owned -> owned +// --- + +impl From<Box<Utf8Path>> for Utf8PathBuf { + fn from(path: Box<Utf8Path>) -> Utf8PathBuf { + path.into_path_buf() + } +} + +impl From<Utf8PathBuf> for Box<Utf8Path> { + fn from(path: Utf8PathBuf) -> Box<Utf8Path> { + path.into_boxed_path() + } +} + +impl<'a> From<Cow<'a, Utf8Path>> for Utf8PathBuf { + fn from(path: Cow<'a, Utf8Path>) -> Utf8PathBuf { + path.into_owned() + } +} + +impl From<Utf8PathBuf> for String { + fn from(path: Utf8PathBuf) -> String { + path.into_string() + } +} + +impl From<Utf8PathBuf> for OsString { + fn from(path: Utf8PathBuf) -> OsString { + path.into_os_string() + } +} + +impl<'a> From<Utf8PathBuf> for Cow<'a, Utf8Path> { + fn from(path: Utf8PathBuf) -> Cow<'a, Utf8Path> { + Cow::Owned(path) + } +} + +impl From<Utf8PathBuf> for Arc<Utf8Path> { + fn from(path: Utf8PathBuf) -> Arc<Utf8Path> { + let arc: Arc<Path> = Arc::from(path.0); + let ptr = Arc::into_raw(arc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Arc<Path> so it represents an arced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Arc::from_raw(ptr) } + } +} + +impl From<Utf8PathBuf> for Rc<Utf8Path> { + fn from(path: Utf8PathBuf) -> Rc<Utf8Path> { + let rc: Rc<Path> = Rc::from(path.0); + let ptr = Rc::into_raw(rc) as *const Utf8Path; + // SAFETY: + // * path is valid UTF-8 + // * ptr was created by consuming an Rc<Path> so it represents an rced pointer + // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to + // *const Utf8Path is valid + unsafe { Rc::from_raw(ptr) } + } +} + +impl From<Utf8PathBuf> for PathBuf { + fn from(path: Utf8PathBuf) -> PathBuf { + path.0 + } +} + +impl From<Utf8PathBuf> for Box<Path> { + fn from(path: Utf8PathBuf) -> Box<Path> { + PathBuf::from(path).into_boxed_path() + } +} + +impl From<Utf8PathBuf> for Arc<Path> { + fn from(path: Utf8PathBuf) -> Arc<Path> { + PathBuf::from(path).into() + } +} + +impl From<Utf8PathBuf> for Rc<Path> { + fn from(path: Utf8PathBuf) -> Rc<Path> { + PathBuf::from(path).into() + } +} + +impl<'a> From<Utf8PathBuf> for Cow<'a, Path> { + fn from(path: Utf8PathBuf) -> Cow<'a, Path> { + PathBuf::from(path).into() + } +} + +// --- +// TryFrom impls +// --- + +impl TryFrom<PathBuf> for Utf8PathBuf { + type Error = FromPathBufError; + + fn try_from(path: PathBuf) -> Result<Utf8PathBuf, Self::Error> { + Utf8PathBuf::from_path_buf(path).map_err(|path| FromPathBufError { + path, + error: FromPathError(()), + }) + } +} + +impl<'a> TryFrom<&'a Path> for &'a Utf8Path { + type Error = FromPathError; + + fn try_from(path: &'a Path) -> Result<&'a Utf8Path, Self::Error> { + Utf8Path::from_path(path).ok_or(FromPathError(())) + } +} + +/// A possible error value while converting a [`PathBuf`] to a [`Utf8PathBuf`]. +/// +/// Produced by the `TryFrom<PathBuf>` implementation for [`Utf8PathBuf`]. +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8PathBuf, FromPathBufError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::PathBuf; +/// +/// let unicode_path = PathBuf::from("/valid/unicode"); +/// let utf8_path_buf: Utf8PathBuf = unicode_path.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = PathBuf::from(non_unicode_str); +/// # #[cfg(unix)] +/// let err: FromPathBufError = Utf8PathBuf::try_from(non_unicode_path.clone()) +/// .expect_err("non-Unicode path failed"); +/// # #[cfg(unix)] +/// assert_eq!(err.as_path(), &non_unicode_path); +/// # #[cfg(unix)] +/// assert_eq!(err.into_path_buf(), non_unicode_path); +/// ``` +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct FromPathBufError { + path: PathBuf, + error: FromPathError, +} + +impl FromPathBufError { + /// Returns the [`Path`] slice that was attempted to be converted to [`Utf8PathBuf`]. + pub fn as_path(&self) -> &Path { + &self.path + } + + /// Returns the [`PathBuf`] that was attempted to be converted to [`Utf8PathBuf`]. + pub fn into_path_buf(self) -> PathBuf { + self.path + } + + /// Fetch a [`FromPathError`] for more about the conversion failure. + /// + /// At the moment this struct does not contain any additional information, but is provided for + /// completeness. + pub fn from_path_error(&self) -> FromPathError { + self.error + } +} + +impl fmt::Display for FromPathBufError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "PathBuf contains invalid UTF-8: {}", self.path.display()) + } +} + +impl error::Error for FromPathBufError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(&self.error) + } +} + +/// A possible error value while converting a [`Path`] to a [`Utf8Path`]. +/// +/// Produced by the `TryFrom<&Path>` implementation for [`&Utf8Path`](Utf8Path). +/// +/// +/// # Examples +/// +/// ``` +/// use camino::{Utf8Path, FromPathError}; +/// use std::convert::{TryFrom, TryInto}; +/// use std::ffi::OsStr; +/// # #[cfg(unix)] +/// use std::os::unix::ffi::OsStrExt; +/// use std::path::Path; +/// +/// let unicode_path = Path::new("/valid/unicode"); +/// let utf8_path: &Utf8Path = unicode_path.try_into().expect("valid Unicode path succeeded"); +/// +/// // Paths on Unix can be non-UTF-8. +/// # #[cfg(unix)] +/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF"); +/// # #[cfg(unix)] +/// let non_unicode_path = Path::new(non_unicode_str); +/// # #[cfg(unix)] +/// let err: FromPathError = <&Utf8Path>::try_from(non_unicode_path) +/// .expect_err("non-Unicode path failed"); +/// ``` +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct FromPathError(()); + +impl fmt::Display for FromPathError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Path contains invalid UTF-8") + } +} + +impl error::Error for FromPathError { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + None + } +} + +// --- +// AsRef impls +// --- + +impl AsRef<Utf8Path> for Utf8Path { + fn as_ref(&self) -> &Utf8Path { + self + } +} + +impl AsRef<Utf8Path> for Utf8PathBuf { + fn as_ref(&self) -> &Utf8Path { + self.as_path() + } +} + +impl AsRef<Utf8Path> for str { + fn as_ref(&self) -> &Utf8Path { + Utf8Path::new(self) + } +} + +impl AsRef<Utf8Path> for String { + fn as_ref(&self) -> &Utf8Path { + Utf8Path::new(self) + } +} + +impl AsRef<Path> for Utf8Path { + fn as_ref(&self) -> &Path { + &self.0 + } +} + +impl AsRef<Path> for Utf8PathBuf { + fn as_ref(&self) -> &Path { + &*self.0 + } +} + +impl AsRef<str> for Utf8Path { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<str> for Utf8PathBuf { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<OsStr> for Utf8Path { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +impl AsRef<OsStr> for Utf8PathBuf { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +} + +// --- +// Borrow and ToOwned +// --- + +impl Borrow<Utf8Path> for Utf8PathBuf { + fn borrow(&self) -> &Utf8Path { + self.as_path() + } +} + +impl ToOwned for Utf8Path { + type Owned = Utf8PathBuf; + + fn to_owned(&self) -> Utf8PathBuf { + self.to_path_buf() + } +} + +impl<P: AsRef<Utf8Path>> std::iter::FromIterator<P> for Utf8PathBuf { + fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> Utf8PathBuf { + let mut buf = Utf8PathBuf::new(); + buf.extend(iter); + buf + } +} + +// --- +// [Partial]Eq, [Partial]Ord, Hash +// --- + +impl PartialEq for Utf8PathBuf { + fn eq(&self, other: &Utf8PathBuf) -> bool { + self.components() == other.components() + } +} + +impl Eq for Utf8PathBuf {} + +impl Hash for Utf8PathBuf { + fn hash<H: Hasher>(&self, state: &mut H) { + self.as_path().hash(state) + } +} + +impl PartialOrd for Utf8PathBuf { + fn partial_cmp(&self, other: &Utf8PathBuf) -> Option<Ordering> { + self.components().partial_cmp(other.components()) + } +} + +impl Ord for Utf8PathBuf { + fn cmp(&self, other: &Utf8PathBuf) -> Ordering { + self.components().cmp(other.components()) + } +} + +impl PartialEq for Utf8Path { + fn eq(&self, other: &Utf8Path) -> bool { + self.components().eq(other.components()) + } +} + +impl Eq for Utf8Path {} + +impl Hash for Utf8Path { + fn hash<H: Hasher>(&self, state: &mut H) { + for component in self.components() { + component.hash(state) + } + } +} + +impl PartialOrd for Utf8Path { + fn partial_cmp(&self, other: &Utf8Path) -> Option<Ordering> { + self.components().partial_cmp(other.components()) + } +} + +impl Ord for Utf8Path { + fn cmp(&self, other: &Utf8Path) -> Ordering { + self.components().cmp(other.components()) + } +} + +impl<'a> IntoIterator for &'a Utf8PathBuf { + type Item = &'a str; + type IntoIter = Iter<'a>; + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +impl<'a> IntoIterator for &'a Utf8Path { + type Item = &'a str; + type IntoIter = Iter<'a>; + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +macro_rules! impl_cmp { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Utf8Path as PartialEq>::eq(self, other) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Utf8Path as PartialEq>::eq(self, other) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(self, other) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(self, other) + } + } + }; +} + +impl_cmp!(Utf8PathBuf, Utf8Path); +impl_cmp!(Utf8PathBuf, &'a Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, &'b Utf8Path); +impl_cmp!(Cow<'a, Utf8Path>, Utf8PathBuf); + +macro_rules! impl_cmp_std_path { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Path as PartialEq>::eq(self.as_ref(), other) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Path as PartialEq>::eq(self, other.as_ref()) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self.as_ref(), other) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self, other.as_ref()) + } + } + }; +} + +impl_cmp_std_path!(Utf8PathBuf, Path); +impl_cmp_std_path!(Utf8PathBuf, &'a Path); +impl_cmp_std_path!(Utf8PathBuf, Cow<'a, Path>); +impl_cmp_std_path!(Utf8PathBuf, PathBuf); +impl_cmp_std_path!(Utf8Path, Path); +impl_cmp_std_path!(Utf8Path, &'a Path); +impl_cmp_std_path!(Utf8Path, Cow<'a, Path>); +impl_cmp_std_path!(Utf8Path, PathBuf); +impl_cmp_std_path!(&'a Utf8Path, Path); +impl_cmp_std_path!(&'a Utf8Path, Cow<'b, Path>); +impl_cmp_std_path!(&'a Utf8Path, PathBuf); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +macro_rules! impl_cmp_str { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Utf8Path as PartialEq>::eq(self, Utf8Path::new(other)) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Utf8Path as PartialEq>::eq(Utf8Path::new(self), other) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(self, Utf8Path::new(other)) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> { + <Utf8Path as PartialOrd>::partial_cmp(Utf8Path::new(self), other) + } + } + }; +} + +impl_cmp_str!(Utf8PathBuf, str); +impl_cmp_str!(Utf8PathBuf, &'a str); +impl_cmp_str!(Utf8PathBuf, Cow<'a, str>); +impl_cmp_str!(Utf8PathBuf, String); +impl_cmp_str!(Utf8Path, str); +impl_cmp_str!(Utf8Path, &'a str); +impl_cmp_str!(Utf8Path, Cow<'a, str>); +impl_cmp_str!(Utf8Path, String); +impl_cmp_str!(&'a Utf8Path, str); +impl_cmp_str!(&'a Utf8Path, Cow<'b, str>); +impl_cmp_str!(&'a Utf8Path, String); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +macro_rules! impl_cmp_os_str { + ($lhs:ty, $rhs: ty) => { + impl<'a, 'b> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + <Path as PartialEq>::eq(self.as_ref(), other.as_ref()) + } + } + + impl<'a, 'b> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + <Path as PartialEq>::eq(self.as_ref(), other.as_ref()) + } + } + + impl<'a, 'b> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_ref()) + } + } + + impl<'a, 'b> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> { + <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_ref()) + } + } + }; +} + +impl_cmp_os_str!(Utf8PathBuf, OsStr); +impl_cmp_os_str!(Utf8PathBuf, &'a OsStr); +impl_cmp_os_str!(Utf8PathBuf, Cow<'a, OsStr>); +impl_cmp_os_str!(Utf8PathBuf, OsString); +impl_cmp_os_str!(Utf8Path, OsStr); +impl_cmp_os_str!(Utf8Path, &'a OsStr); +impl_cmp_os_str!(Utf8Path, Cow<'a, OsStr>); +impl_cmp_os_str!(Utf8Path, OsString); +impl_cmp_os_str!(&'a Utf8Path, OsStr); +impl_cmp_os_str!(&'a Utf8Path, Cow<'b, OsStr>); +impl_cmp_os_str!(&'a Utf8Path, OsString); +// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117) + +// invariant: OsStr must be guaranteed to be utf8 data +unsafe fn assume_utf8(string: &OsStr) -> &str { + &*(string as *const OsStr as *const str) +}
diff --git a/third_party/rust/camino/v1/crate/src/proptest_impls.rs b/third_party/rust/camino/v1/crate/src/proptest_impls.rs new file mode 100644 index 0000000..997c88c --- /dev/null +++ b/third_party/rust/camino/v1/crate/src/proptest_impls.rs
@@ -0,0 +1,61 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! [proptest::Arbitrary](Arbitrary) implementation for `Utf8PathBuf` and `Box<Utf8Path>`. Note +//! that implementions for `Rc<Utf8Path>` and `Arc<Utf8Path>` are not currently possible due to +//! orphan rules - this crate doesn't define `Rc`/`Arc` nor `Arbitrary`, so it can't define those +//! implementations. + +// NOTE: #[cfg(feature = "proptest1")] is specified here to work with `doc_cfg`. + +use proptest::{arbitrary::StrategyFor, prelude::*, strategy::MapInto}; + +use crate::{Utf8Path, Utf8PathBuf}; + +/// The [`Arbitrary`] impl for `Utf8PathBuf` returns a path with between 0 and 8 components, +/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is +/// randomly generated, and may itself contain one or more separators.) +/// +/// On Unix, this generates an absolute path half of the time and a relative path the other half. +/// +/// On Windows, this implementation doesn't currently generate +/// [`Utf8PrefixComponent`](crate::Utf8PrefixComponent) instances, though in the future it might. +#[cfg(feature = "proptest1")] +impl Arbitrary for Utf8PathBuf { + type Parameters = <String as Arbitrary>::Parameters; + type Strategy = BoxedStrategy<Self>; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + ( + any::<bool>(), + prop::collection::vec(any_with::<String>(args), 0..8), + ) + .prop_map(|(is_relative, components)| { + let initial_component = + is_relative.then(|| format!("{}", std::path::MAIN_SEPARATOR)); + initial_component + .into_iter() + .chain(components.into_iter()) + .collect() + }) + .boxed() + } +} + +/// The [`Arbitrary`] impl for `Box<Utf8Path>` returns a path with between 0 and 8 components, +/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is +/// randomly generated, and may itself contain one or more separators.) +/// +/// On Unix, this generates an absolute path half of the time and a relative path the other half. +/// +/// On Windows, this implementation doesn't currently generate +/// [`Utf8PrefixComponent`](crate::Utf8PrefixComponent) instances, though in the future it might. +#[cfg(feature = "proptest1")] +impl Arbitrary for Box<Utf8Path> { + type Parameters = <Utf8PathBuf as Arbitrary>::Parameters; + type Strategy = MapInto<StrategyFor<Utf8PathBuf>, Self>; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + any_with::<Utf8PathBuf>(args).prop_map_into() + } +}
diff --git a/third_party/rust/camino/v1/crate/src/serde_impls.rs b/third_party/rust/camino/v1/crate/src/serde_impls.rs new file mode 100644 index 0000000..d4c4eca --- /dev/null +++ b/third_party/rust/camino/v1/crate/src/serde_impls.rs
@@ -0,0 +1,57 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +//! Serde implementations for `Utf8Path`. +//! +//! The Serde implementations for `Utf8PathBuf` are derived, but `Utf8Path` is an unsized type which +//! the derive impls can't handle. Implement these by hand. + +use crate::Utf8Path; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use std::fmt; + +struct Utf8PathVisitor; + +impl<'a> de::Visitor<'a> for Utf8PathVisitor { + type Value = &'a Utf8Path; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed path") + } + + fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(v.as_ref()) + } + + fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E> + where + E: de::Error, + { + std::str::from_utf8(v) + .map(AsRef::as_ref) + .map_err(|_| de::Error::invalid_value(de::Unexpected::Bytes(v), &self)) + } +} + +#[cfg(feature = "serde1")] +impl<'de: 'a, 'a> Deserialize<'de> for &'a Utf8Path { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(Utf8PathVisitor) + } +} + +#[cfg(feature = "serde1")] +impl Serialize for Utf8Path { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + self.as_str().serialize(serializer) + } +}
diff --git a/third_party/rust/camino/v1/crate/src/tests.rs b/third_party/rust/camino/v1/crate/src/tests.rs new file mode 100644 index 0000000..305b7609 --- /dev/null +++ b/third_party/rust/camino/v1/crate/src/tests.rs
@@ -0,0 +1,46 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +// Test that all required impls exist. + +use crate::{Utf8Path, Utf8PathBuf}; +use std::{ + borrow::Cow, + path::{Path, PathBuf}, + rc::Rc, + sync::Arc, +}; + +macro_rules! all_into { + ($t:ty, $x:ident) => { + test_into::<$t, Utf8PathBuf>($x.clone()); + test_into::<$t, Box<Utf8Path>>($x.clone()); + test_into::<$t, Arc<Utf8Path>>($x.clone()); + test_into::<$t, Rc<Utf8Path>>($x.clone()); + test_into::<$t, Cow<'_, Utf8Path>>($x.clone()); + test_into::<$t, PathBuf>($x.clone()); + test_into::<$t, Box<Path>>($x.clone()); + test_into::<$t, Arc<Path>>($x.clone()); + test_into::<$t, Rc<Path>>($x.clone()); + test_into::<$t, Cow<'_, Path>>($x.clone()); + }; +} + +#[test] +fn test_borrowed_into() { + let utf8_path = Utf8Path::new("test/path"); + all_into!(&Utf8Path, utf8_path); +} + +#[test] +fn test_owned_into() { + let utf8_path_buf = Utf8PathBuf::from("test/path"); + all_into!(Utf8PathBuf, utf8_path_buf); +} + +fn test_into<T, U>(orig: T) +where + T: Into<U>, +{ + let _ = orig.into(); +}
diff --git a/third_party/rust/camino/v1/crate/tests/integration_tests.rs b/third_party/rust/camino/v1/crate/tests/integration_tests.rs new file mode 100644 index 0000000..a8b00f2f --- /dev/null +++ b/third_party/rust/camino/v1/crate/tests/integration_tests.rs
@@ -0,0 +1,115 @@ +// Copyright (c) The camino Contributors +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use camino::{Utf8Path, Utf8PathBuf}; +use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + path::Path, +}; + +static PATH_CORPUS: &[&str] = &[ + "", + "foo", + "foo/bar", + "foo//bar", + "foo/bar/baz", + "foo/bar/./baz", + "foo/bar/../baz", + "../foo/bar/./../baz", + "/foo", + "/foo/bar", + "/", + "///", + // --- + // Windows-only paths + // --- + #[cfg(windows)] + "foo\\bar", + #[cfg(windows)] + "\\foo\\bar", + #[cfg(windows)] + "C:\\foo", + #[cfg(windows)] + "C:foo\\bar", + #[cfg(windows)] + "C:\\foo\\..\\.\\bar", + #[cfg(windows)] + "\\\\server\\foo\\bar", + #[cfg(windows)] + "\\\\.\\C:\\foo\\bar.txt", +]; + +#[test] +fn test_borrow_eq_ord() { + // Utf8PathBuf implements Borrow<Utf8Path> so equality and ordering comparisons should + // match. + for (idx, &path1) in PATH_CORPUS.iter().enumerate() { + for &path2 in &PATH_CORPUS[idx..] { + let borrowed1 = Utf8Path::new(path1); + let borrowed2 = Utf8Path::new(path2); + let owned1 = Utf8PathBuf::from(path1); + let owned2 = Utf8PathBuf::from(path2); + + assert_eq!( + borrowed1 == borrowed2, + owned1 == owned2, + "Eq impls match: {} == {}", + borrowed1, + borrowed2 + ); + assert_eq!( + borrowed1.cmp(borrowed2), + owned1.cmp(&owned2), + "Ord impls match: {} and {}", + borrowed1, + borrowed2 + ); + + // Also check against std paths. + let std1 = Path::new(path1); + let std2 = Path::new(path2); + assert_eq!( + borrowed1, std1, + "Eq between Path and Utf8Path: {}", + borrowed1 + ); + assert_eq!( + borrowed1 == borrowed2, + std1 == std2, + "Eq impl matches Path: {} == {}", + borrowed1, + borrowed2 + ); + assert_eq!( + borrowed1.cmp(borrowed2), + std1.cmp(std2), + "Ord impl matches Path: {} and {}", + borrowed1, + borrowed2 + ); + } + } +} + +#[test] +fn test_borrow_hash() { + // Utf8PathBuf implements Borrow<Utf8Path> so hash comparisons should match. + fn hash_output(x: impl Hash) -> u64 { + let mut hasher = DefaultHasher::new(); + x.hash(&mut hasher); + hasher.finish() + } + + for &path in PATH_CORPUS { + let borrowed = Utf8Path::new(path); + let owned = Utf8PathBuf::from(path); + + assert_eq!( + hash_output(&owned), + hash_output(borrowed), + "consistent Hash: {}", + borrowed + ); + } +}
diff --git a/third_party/rust/cargo_metadata/v0_14/BUILD.gn b/third_party/rust/cargo_metadata/v0_14/BUILD.gn new file mode 100644 index 0000000..5d339738 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/BUILD.gn
@@ -0,0 +1,28 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/rust/cargo_crate.gni") + +cargo_crate("test_support") { + crate_name = "cargo_metadata" + epoch = "0.14" + crate_type = "rlib" + testonly = "true" + crate_root = "crate/src/lib.rs" + build_native_rust_unit_tests = false + sources = [ "crate/src/lib.rs" ] + edition = "2018" + cargo_pkg_version = "0.14.2" + cargo_pkg_authors = + "Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>" + cargo_pkg_name = "cargo_metadata" + cargo_pkg_description = "structured access to the output of `cargo metadata`" + deps = [ + "//third_party/rust/camino/v1:lib", + "//third_party/rust/cargo_platform/v0_1:lib", + "//third_party/rust/semver/v1:lib", + "//third_party/rust/serde/v1:lib", + "//third_party/rust/serde_json/v1:lib", + ] +}
diff --git a/third_party/rust/cargo_metadata/v0_14/README.chromium b/third_party/rust/cargo_metadata/v0_14/README.chromium new file mode 100644 index 0000000..ac8329c6 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/README.chromium
@@ -0,0 +1,6 @@ +Name: cargo_metadata +URL: https://crates.io/crates/cargo_metadata +Description: structured access to the output of `cargo metadata` +Version: 0.14.2 +Security Critical: no +License: MIT
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/.cargo_vcs_info.json b/third_party/rust/cargo_metadata/v0_14/crate/.cargo_vcs_info.json new file mode 100644 index 0000000..fa70ceff --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/.cargo_vcs_info.json
@@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "f615f7164534eb52fb9525bdb5eee5731f652968" + }, + "path_in_vcs": "" +} \ No newline at end of file
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/.github/workflows/main.yml b/third_party/rust/cargo_metadata/v0_14/crate/.github/workflows/main.yml new file mode 100644 index 0000000..8a97ed4 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/.github/workflows/main.yml
@@ -0,0 +1,35 @@ +name: CI +on: [push, pull_request] + +jobs: + rustfmt: + name: rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install rust + run: rustup update --no-self-update stable && rustup default stable + - name: Check formatting + run: cargo fmt -- --check + + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + include: + - rust: stable + - rust: beta + - rust: nightly + - rust: 1.40.0 + steps: + - uses: actions/checkout@v2 + - name: Install rust + run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} + - name: Run tests + run: | + cargo build --verbose + cargo build --verbose --no-default-features + cargo test --verbose + cargo test --verbose --no-default-features + cargo test --verbose --all-features
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/.gitignore b/third_party/rust/cargo_metadata/v0_14/crate/.gitignore new file mode 100644 index 0000000..34856db --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/.gitignore
@@ -0,0 +1,3 @@ +Cargo.lock +.idea/ +target
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml new file mode 100644 index 0000000..cbb937e --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml
@@ -0,0 +1,49 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "cargo_metadata" +version = "0.14.2" +authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"] +description = "structured access to the output of `cargo metadata`" +readme = "README.md" +license = "MIT" +repository = "https://github.com/oli-obk/cargo_metadata" +[package.metadata.cargo_metadata_test] +other_field = "foo" +some_field = true +[dependencies.camino] +version = "1.0.1" +features = ["serde1"] + +[dependencies.cargo-platform] +version = "0.1" + +[dependencies.derive_builder] +version = "0.9.0" +optional = true + +[dependencies.semver] +version = "1" +features = ["serde"] + +[dependencies.serde] +version = "1.0.107" +features = ["derive"] + +[dependencies.serde_json] +version = "1.0.59" +features = ["unbounded_depth"] + +[features] +builder = ["derive_builder"] +default = []
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml.orig b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml.orig new file mode 100644 index 0000000..c34928a --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml.orig
@@ -0,0 +1,25 @@ +[package] +name = "cargo_metadata" +version = "0.14.2" +authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"] +repository = "https://github.com/oli-obk/cargo_metadata" +description = "structured access to the output of `cargo metadata`" +license = "MIT" +readme = "README.md" +edition = "2018" + +[dependencies] +camino = { version = "1.0.1", features = ["serde1"] } +cargo-platform = "0.1" +derive_builder = { version = "0.9.0", optional = true } +semver = { version = "1", features = ["serde"] } +serde = { version = "1.0.107", features = ["derive"] } +serde_json = { version = "1.0.59", features = ["unbounded_depth"] } + +[features] +default = [] +builder = ["derive_builder"] + +[package.metadata.cargo_metadata_test] +some_field = true +other_field = "foo"
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/LICENSE-MIT b/third_party/rust/cargo_metadata/v0_14/crate/LICENSE-MIT new file mode 100644 index 0000000..31aa7938 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/LICENSE-MIT
@@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/README.md b/third_party/rust/cargo_metadata/v0_14/crate/README.md new file mode 100644 index 0000000..03743f3 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/README.md
@@ -0,0 +1,12 @@ +# cargo_metadata + +Structured access to the output of `cargo metadata`. Usually used from within a `cargo-*` executable. + +Also supports serialization to aid in implementing `--message-format=json`-like +output generation in `cargo-*` subcommands, since some of the types in what +`cargo --message-format=json` emits are exactly the same as the ones from `cargo metadata`. + +[](https://travis-ci.org/oli-obk/cargo_metadata) +[](https://crates.io/crates/cargo_metadata) + +[Documentation](https://docs.rs/cargo_metadata/)
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/dependency.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/dependency.rs new file mode 100644 index 0000000..89bcf9f2 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/src/dependency.rs
@@ -0,0 +1,90 @@ +//! This module contains `Dependency` and the types/functions it uses for deserialization. + +use std::fmt; + +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use semver::VersionReq; +use serde::{Deserialize, Deserializer, Serialize}; + +#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash, Serialize, Deserialize)] +/// Dependencies can come in three kinds +pub enum DependencyKind { + #[serde(rename = "normal")] + /// The 'normal' kind + Normal, + #[serde(rename = "dev")] + /// Those used in tests only + Development, + #[serde(rename = "build")] + /// Those used in build scripts only + Build, + #[doc(hidden)] + #[serde(other)] + Unknown, +} + +impl Default for DependencyKind { + fn default() -> DependencyKind { + DependencyKind::Normal + } +} + +impl fmt::Display for DependencyKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = serde_json::to_string(self).unwrap(); + // skip opening and closing quotes + f.write_str(&s[1..s.len() - 1]) + } +} + +/// The `kind` can be `null`, which is interpreted as the default - `Normal`. +pub(super) fn parse_dependency_kind<'de, D>(d: D) -> Result<DependencyKind, D::Error> +where + D: Deserializer<'de>, +{ + Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or_default()) +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency of the main crate +pub struct Dependency { + /// Name as given in the `Cargo.toml` + pub name: String, + /// The source of dependency + pub source: Option<String>, + /// The required version + pub req: VersionReq, + /// The kind of dependency this is + #[serde(deserialize_with = "parse_dependency_kind")] + pub kind: DependencyKind, + /// Whether this dependency is required or optional + pub optional: bool, + /// Whether the default features in this dependency are used. + pub uses_default_features: bool, + /// The list of features enabled for this dependency. + pub features: Vec<String>, + /// The target this dependency is specific to. + /// + /// Use the [`Display`] trait to access the contents. + /// + /// [`Display`]: std::fmt::Display + pub target: Option<Platform>, + /// If the dependency is renamed, this is the new name for the dependency + /// as a string. None if it is not renamed. + pub rename: Option<String>, + /// The URL of the index of the registry where this dependency is from. + /// + /// If None, the dependency is from crates.io. + pub registry: Option<String>, + /// The file system path for a local path dependency. + /// + /// Only produced on cargo 1.51+ + pub path: Option<Utf8PathBuf>, +} + +pub use cargo_platform::Platform;
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/diagnostic.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/diagnostic.rs new file mode 100644 index 0000000..dbe2112 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/src/diagnostic.rs
@@ -0,0 +1,160 @@ +//! This module contains `Diagnostic` and the types/functions it uses for deserialization. + +#[cfg(feature = "builder")] +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use std::fmt; + +/// The error code associated to this diagnostic. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticCode { + /// The code itself. + pub code: String, + /// An explanation for the code + pub explanation: Option<String>, +} + +/// A line of code associated with the Diagnostic +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpanLine { + /// The line of code associated with the error + pub text: String, + /// Start of the section of the line to highlight. 1-based, character offset in self.text + pub highlight_start: usize, + /// End of the section of the line to highlight. 1-based, character offset in self.text + pub highlight_end: usize, +} + +/// Macro expansion information associated with a diagnostic. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpanMacroExpansion { + /// span where macro was applied to generate this code; note that + /// this may itself derive from a macro (if + /// `span.expansion.is_some()`) + pub span: DiagnosticSpan, + + /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") + pub macro_decl_name: String, + + /// span where macro was defined (if known) + pub def_site_span: Option<DiagnosticSpan>, +} + +/// A section of the source code associated with a Diagnostic +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct DiagnosticSpan { + /// The file name or the macro name this diagnostic comes from. + pub file_name: String, + /// The byte offset in the file where this diagnostic starts from. + pub byte_start: u32, + /// The byte offset in the file where this diagnostic ends. + pub byte_end: u32, + /// 1-based. The line in the file. + pub line_start: usize, + /// 1-based. The line in the file. + pub line_end: usize, + /// 1-based, character offset. + pub column_start: usize, + /// 1-based, character offset. + pub column_end: usize, + /// Is this a "primary" span -- meaning the point, or one of the points, + /// where the error occurred? + /// + /// There are rare cases where multiple spans are marked as primary, + /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can + /// be two separate spans both "primary". Top (parent) messages should + /// always have at least one primary span, unless it has 0 spans. Child + /// messages may have 0 or more primary spans. + pub is_primary: bool, + /// Source text from the start of line_start to the end of line_end. + pub text: Vec<DiagnosticSpanLine>, + /// Label that should be placed at this location (if any) + pub label: Option<String>, + /// If we are suggesting a replacement, this will contain text + /// that should be sliced in atop this span. + pub suggested_replacement: Option<String>, + /// If the suggestion is approximate + pub suggestion_applicability: Option<Applicability>, + /// Macro invocations that created the code at this span, if any. + pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>, +} + +/// Whether a suggestion can be safely applied. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum Applicability { + /// The suggested replacement can be applied automatically safely + MachineApplicable, + /// The suggested replacement has placeholders that will need to be manually + /// replaced. + HasPlaceholders, + /// The suggested replacement may be incorrect in some circumstances. Needs + /// human review. + MaybeIncorrect, + /// The suggested replacement will probably not work. + Unspecified, +} + +/// The diagnostic level +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +#[serde(rename_all = "lowercase")] +pub enum DiagnosticLevel { + /// Internal compiler error + #[serde(rename = "error: internal compiler error")] + Ice, + /// Error + Error, + /// Warning + Warning, + /// Failure note + #[serde(rename = "failure-note")] + FailureNote, + /// Note + Note, + /// Help + Help, +} + +/// A diagnostic message generated by rustc +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct Diagnostic { + /// The error message of this diagnostic. + pub message: String, + /// The associated error code for this diagnostic + pub code: Option<DiagnosticCode>, + /// "error: internal compiler error", "error", "warning", "note", "help" + pub level: DiagnosticLevel, + /// A list of source code spans this diagnostic is associated with. + pub spans: Vec<DiagnosticSpan>, + /// Associated diagnostic messages. + pub children: Vec<Diagnostic>, + /// The message as rustc would render it + pub rendered: Option<String>, +} + +impl fmt::Display for Diagnostic { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(ref rendered) = self.rendered { + f.write_str(rendered)?; + } else { + f.write_str("cargo didn't render this message")?; + } + Ok(()) + } +}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/errors.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/errors.rs new file mode 100644 index 0000000..7172057e --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/src/errors.rs
@@ -0,0 +1,110 @@ +use std::fmt; +use std::io; +use std::str::Utf8Error; +use std::string::FromUtf8Error; + +/// Custom result type for `cargo_metadata::Error` +pub type Result<T> = ::std::result::Result<T, Error>; + +/// Error returned when executing/parsing `cargo metadata` fails. +/// +/// # Note about Backtraces +/// +/// This error type does not contain backtraces, but each error variant +/// comes from _one_ specific place, so it's not really needed for the +/// inside of this crate. If you need a backtrace down to, but not inside +/// of, a failed call of `cargo_metadata` you can do one of multiple thinks: +/// +/// 1. Convert it to a `failure::Error` (possible using the `?` operator), +/// which is similar to a `Box<::std::error::Error + 'static + Send + Sync>`. +/// 2. Have appropriate variants in your own error type. E.g. you could wrap +/// a `failure::Context<Error>` or add a `failure::Backtrace` field (which +/// is empty if `RUST_BACKTRACE` is not set, so it's simple to use). +/// 3. You still can place a failure based error into a `error_chain` if you +/// really want to. (Either through foreign_links or by making it a field +/// value of a `ErrorKind` variant). +/// +#[derive(Debug)] +pub enum Error { + /// Error during execution of `cargo metadata` + CargoMetadata { + /// stderr returned by the `cargo metadata` command + stderr: String, + }, + + /// IO Error during execution of `cargo metadata` + Io(io::Error), + + /// Output of `cargo metadata` was not valid utf8 + Utf8(Utf8Error), + + /// Error output of `cargo metadata` was not valid utf8 + ErrUtf8(FromUtf8Error), + + /// Deserialization error (structure of json did not match expected structure) + Json(::serde_json::Error), + + /// The output did not contain any json + NoJson, +} + +impl From<io::Error> for Error { + fn from(v: io::Error) -> Self { + Error::Io(v) + } +} + +impl From<Utf8Error> for Error { + fn from(v: Utf8Error) -> Self { + Error::Utf8(v) + } +} + +impl From<FromUtf8Error> for Error { + fn from(v: FromUtf8Error) -> Self { + Error::ErrUtf8(v) + } +} + +impl From<::serde_json::Error> for Error { + fn from(v: ::serde_json::Error) -> Self { + Error::Json(v) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::CargoMetadata { stderr } => { + write!( + f, + "`cargo metadata` exited with an error: {}", + stderr.trim_end() + ) + } + Error::Io(err) => write!(f, "failed to start `cargo metadata`: {}", err), + Error::Utf8(err) => write!(f, "cannot convert the stdout of `cargo metadata`: {}", err), + Error::ErrUtf8(err) => { + write!(f, "cannot convert the stderr of `cargo metadata`: {}", err) + } + Error::Json(err) => write!(f, "failed to interpret `cargo metadata`'s json: {}", err), + Error::NoJson => write!( + f, + "could not find any json in the output of `cargo metadata`" + ), + } + } +} + +impl ::std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::CargoMetadata { .. } => None, + Error::Io(err) => Some(err), + Error::Utf8(err) => Some(err), + Error::ErrUtf8(err) => Some(err), + Error::Json(err) => Some(err), + Error::NoJson => None, + } + } +}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/lib.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/lib.rs new file mode 100644 index 0000000..c88d324 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/src/lib.rs
@@ -0,0 +1,641 @@ +#![deny(missing_docs)] +//! Structured access to the output of `cargo metadata` and `cargo --message-format=json`. +//! Usually used from within a `cargo-*` executable +//! +//! See the [cargo book](https://doc.rust-lang.org/cargo/index.html) for +//! details on cargo itself. +//! +//! ## Examples +//! +//! ```rust +//! # extern crate cargo_metadata; +//! # use std::path::Path; +//! let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path")); +//! +//! let mut cmd = cargo_metadata::MetadataCommand::new(); +//! let manifest_path = match args.next() { +//! Some(ref p) if p == "--manifest-path" => { +//! cmd.manifest_path(args.next().unwrap()); +//! } +//! Some(p) => { +//! cmd.manifest_path(p.trim_start_matches("--manifest-path=")); +//! } +//! None => {} +//! }; +//! +//! let _metadata = cmd.exec().unwrap(); +//! ``` +//! +//! Pass features flags +//! +//! ```rust +//! # // This should be kept in sync with the equivalent example in the readme. +//! # extern crate cargo_metadata; +//! # use std::path::Path; +//! # fn main() { +//! use cargo_metadata::{MetadataCommand, CargoOpt}; +//! +//! let _metadata = MetadataCommand::new() +//! .manifest_path("./Cargo.toml") +//! .features(CargoOpt::AllFeatures) +//! .exec() +//! .unwrap(); +//! # } +//! ``` +//! +//! Parse message-format output: +//! +//! ``` +//! # extern crate cargo_metadata; +//! use std::process::{Stdio, Command}; +//! use cargo_metadata::Message; +//! +//! let mut command = Command::new("cargo") +//! .args(&["build", "--message-format=json-render-diagnostics"]) +//! .stdout(Stdio::piped()) +//! .spawn() +//! .unwrap(); +//! +//! let reader = std::io::BufReader::new(command.stdout.take().unwrap()); +//! for message in cargo_metadata::Message::parse_stream(reader) { +//! match message.unwrap() { +//! Message::CompilerMessage(msg) => { +//! println!("{:?}", msg); +//! }, +//! Message::CompilerArtifact(artifact) => { +//! println!("{:?}", artifact); +//! }, +//! Message::BuildScriptExecuted(script) => { +//! println!("{:?}", script); +//! }, +//! Message::BuildFinished(finished) => { +//! println!("{:?}", finished); +//! }, +//! _ => () // Unknown message +//! } +//! } +//! +//! let output = command.wait().expect("Couldn't get cargo's exit status"); +//! ``` + +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use std::collections::HashMap; +use std::env; +use std::fmt; +use std::path::PathBuf; +use std::process::Command; +use std::str::from_utf8; + +pub use camino; +pub use semver::{Version, VersionReq}; + +pub use dependency::{Dependency, DependencyKind}; +use diagnostic::Diagnostic; +pub use errors::{Error, Result}; +#[allow(deprecated)] +pub use messages::parse_messages; +pub use messages::{ + Artifact, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, Message, MessageIter, +}; +use serde::{Deserialize, Serialize}; + +mod dependency; +pub mod diagnostic; +mod errors; +mod messages; + +/// An "opaque" identifier for a package. +/// It is possible to inspect the `repr` field, if the need arises, but its +/// precise format is an implementation detail and is subject to change. +/// +/// `Metadata` can be indexed by `PackageId`. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[serde(transparent)] +pub struct PackageId { + /// The underlying string representation of id. + pub repr: String, +} + +impl std::fmt::Display for PackageId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.repr, f) + } +} + +// Helpers for default metadata fields +fn is_null(value: &serde_json::Value) -> bool { + match value { + serde_json::Value::Null => true, + _ => false, + } +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// Starting point for metadata returned by `cargo metadata` +pub struct Metadata { + /// A list of all crates referenced by this crate (and the crate itself) + pub packages: Vec<Package>, + /// A list of all workspace members + pub workspace_members: Vec<PackageId>, + /// Dependencies graph + pub resolve: Option<Resolve>, + /// Workspace root + pub workspace_root: Utf8PathBuf, + /// Build directory + pub target_directory: Utf8PathBuf, + /// The workspace-level metadata object. Null if non-existent. + #[serde(rename = "metadata", default, skip_serializing_if = "is_null")] + pub workspace_metadata: serde_json::Value, + /// The metadata format version + version: usize, +} + +impl Metadata { + /// Get the root package of this metadata instance. + pub fn root_package(&self) -> Option<&Package> { + let root = self.resolve.as_ref()?.root.as_ref()?; + self.packages.iter().find(|pkg| &pkg.id == root) + } +} + +impl<'a> std::ops::Index<&'a PackageId> for Metadata { + type Output = Package; + + fn index(&self, idx: &'a PackageId) -> &Package { + self.packages + .iter() + .find(|p| p.id == *idx) + .unwrap_or_else(|| panic!("no package with this id: {:?}", idx)) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency graph +pub struct Resolve { + /// Nodes in a dependencies graph + pub nodes: Vec<Node>, + + /// The crate for which the metadata was read. + pub root: Option<PackageId>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A node in a dependencies graph +pub struct Node { + /// An opaque identifier for a package + pub id: PackageId, + /// Dependencies in a structured format. + /// + /// `deps` handles renamed dependencies whereas `dependencies` does not. + #[serde(default)] + pub deps: Vec<NodeDep>, + + /// List of opaque identifiers for this node's dependencies. + /// It doesn't support renamed dependencies. See `deps`. + pub dependencies: Vec<PackageId>, + + /// Features enabled on the crate + #[serde(default)] + pub features: Vec<String>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// A dependency in a node +pub struct NodeDep { + /// The name of the dependency's library target. + /// If the crate was renamed, it is the new name. + pub name: String, + /// Package ID (opaque unique identifier) + pub pkg: PackageId, + /// The kinds of dependencies. + /// + /// This field was added in Rust 1.41. + #[serde(default)] + pub dep_kinds: Vec<DepKindInfo>, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// Information about a dependency kind. +pub struct DepKindInfo { + /// The kind of dependency. + #[serde(deserialize_with = "dependency::parse_dependency_kind")] + pub kind: DependencyKind, + /// The target platform for the dependency. + /// + /// This is `None` if it is not a target dependency. + /// + /// Use the [`Display`] trait to access the contents. + /// + /// By default all platform dependencies are included in the resolve + /// graph. Use Cargo's `--filter-platform` flag if you only want to + /// include dependencies for a specific platform. + /// + /// [`Display`]: std::fmt::Display + pub target: Option<dependency::Platform>, +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +/// One or more crates described by a single `Cargo.toml` +/// +/// Each [`target`][Package::targets] of a `Package` will be built as a crate. +/// For more information, see <https://doc.rust-lang.org/book/ch07-01-packages-and-crates.html>. +pub struct Package { + /// Name as given in the `Cargo.toml` + pub name: String, + /// Version given in the `Cargo.toml` + pub version: Version, + /// Authors given in the `Cargo.toml` + #[serde(default)] + pub authors: Vec<String>, + /// An opaque identifier for a package + pub id: PackageId, + /// The source of the package, e.g. + /// crates.io or `None` for local projects. + pub source: Option<Source>, + /// Description as given in the `Cargo.toml` + pub description: Option<String>, + /// List of dependencies of this particular package + pub dependencies: Vec<Dependency>, + /// License as given in the `Cargo.toml` + pub license: Option<String>, + /// If the package is using a nonstandard license, this key may be specified instead of + /// `license`, and must point to a file relative to the manifest. + pub license_file: Option<Utf8PathBuf>, + /// Targets provided by the crate (lib, bin, example, test, ...) + pub targets: Vec<Target>, + /// Features provided by the crate, mapped to the features required by that feature. + pub features: HashMap<String, Vec<String>>, + /// Path containing the `Cargo.toml` + pub manifest_path: Utf8PathBuf, + /// Categories as given in the `Cargo.toml` + #[serde(default)] + pub categories: Vec<String>, + /// Keywords as given in the `Cargo.toml` + #[serde(default)] + pub keywords: Vec<String>, + /// Readme as given in the `Cargo.toml` + pub readme: Option<Utf8PathBuf>, + /// Repository as given in the `Cargo.toml` + // can't use `url::Url` because that requires a more recent stable compiler + pub repository: Option<String>, + /// Homepage as given in the `Cargo.toml` + /// + /// On versions of cargo before 1.49, this will always be [`None`]. + pub homepage: Option<String>, + /// Documentation URL as given in the `Cargo.toml` + /// + /// On versions of cargo before 1.49, this will always be [`None`]. + pub documentation: Option<String>, + /// Default Rust edition for the package + /// + /// Beware that individual targets may specify their own edition in + /// [`Target::edition`]. + #[serde(default = "edition_default")] + pub edition: String, + /// Contents of the free form package.metadata section + /// + /// This contents can be serialized to a struct using serde: + /// + /// ```rust + /// use serde::Deserialize; + /// use serde_json::json; + /// + /// #[derive(Debug, Deserialize)] + /// struct SomePackageMetadata { + /// some_value: i32, + /// } + /// + /// fn main() { + /// let value = json!({ + /// "some_value": 42, + /// }); + /// + /// let package_metadata: SomePackageMetadata = serde_json::from_value(value).unwrap(); + /// assert_eq!(package_metadata.some_value, 42); + /// } + /// + /// ``` + #[serde(default, skip_serializing_if = "is_null")] + pub metadata: serde_json::Value, + /// The name of a native library the package is linking to. + pub links: Option<String>, + /// List of registries to which this package may be published. + /// + /// Publishing is unrestricted if `None`, and forbidden if the `Vec` is empty. + /// + /// This is always `None` if running with a version of Cargo older than 1.39. + pub publish: Option<Vec<String>>, + /// The default binary to run by `cargo run`. + /// + /// This is always `None` if running with a version of Cargo older than 1.55. + pub default_run: Option<String>, + /// The minimum supported Rust version of this package. + /// + /// This is always `None` if running with a version of Cargo older than 1.58. + pub rust_version: Option<VersionReq>, +} + +impl Package { + /// Full path to the license file if one is present in the manifest + pub fn license_file(&self) -> Option<Utf8PathBuf> { + self.license_file.as_ref().map(|file| { + self.manifest_path + .parent() + .unwrap_or(&self.manifest_path) + .join(file) + }) + } + + /// Full path to the readme file if one is present in the manifest + pub fn readme(&self) -> Option<Utf8PathBuf> { + self.readme + .as_ref() + .map(|file| self.manifest_path.join(file)) + } +} + +/// The source of a package such as crates.io. +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(transparent)] +pub struct Source { + /// The underlying string representation of a source. + pub repr: String, +} + +impl Source { + /// Returns true if the source is crates.io. + pub fn is_crates_io(&self) -> bool { + self.repr == "registry+https://github.com/rust-lang/crates.io-index" + } +} + +impl std::fmt::Display for Source { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.repr, f) + } +} + +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +#[non_exhaustive] +/// A single target (lib, bin, example, ...) provided by a crate +pub struct Target { + /// Name as given in the `Cargo.toml` or generated from the file name + pub name: String, + /// Kind of target ("bin", "example", "test", "bench", "lib") + pub kind: Vec<String>, + /// Almost the same as `kind`, except when an example is a library instead of an executable. + /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example` + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + pub crate_types: Vec<String>, + + #[serde(default)] + #[cfg_attr(feature = "builder", builder(default))] + #[serde(rename = "required-features")] + /// This target is built only if these features are enabled. + /// It doesn't apply to `lib` targets. + pub required_features: Vec<String>, + /// Path to the main source file of the target + pub src_path: Utf8PathBuf, + /// Rust edition for this target + #[serde(default = "edition_default")] + #[cfg_attr(feature = "builder", builder(default = "edition_default()"))] + pub edition: String, + /// Whether or not this target has doc tests enabled, and the target is + /// compatible with doc testing. + /// + /// This is always `true` if running with a version of Cargo older than 1.37. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub doctest: bool, + /// Whether or not this target is tested by default by `cargo test`. + /// + /// This is always `true` if running with a version of Cargo older than 1.47. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub test: bool, + /// Whether or not this target is documented by `cargo doc`. + /// + /// This is always `true` if running with a version of Cargo older than 1.50. + #[serde(default = "default_true")] + #[cfg_attr(feature = "builder", builder(default = "true"))] + pub doc: bool, +} + +fn default_true() -> bool { + true +} + +fn edition_default() -> String { + "2015".to_string() +} + +/// Cargo features flags +#[derive(Debug, Clone)] +pub enum CargoOpt { + /// Run cargo with `--features-all` + AllFeatures, + /// Run cargo with `--no-default-features` + NoDefaultFeatures, + /// Run cargo with `--features <FEATURES>` + SomeFeatures(Vec<String>), +} + +/// A builder for configurating `cargo metadata` invocation. +#[derive(Debug, Clone, Default)] +pub struct MetadataCommand { + /// Path to `cargo` executable. If not set, this will use the + /// the `$CARGO` environment variable, and if that is not set, will + /// simply be `cargo`. + cargo_path: Option<PathBuf>, + /// Path to `Cargo.toml` + manifest_path: Option<PathBuf>, + /// Current directory of the `cargo metadata` process. + current_dir: Option<PathBuf>, + /// Output information only about the root package and don't fetch dependencies. + no_deps: bool, + /// Collections of `CargoOpt::SomeFeatures(..)` + features: Vec<String>, + /// Latched `CargoOpt::AllFeatures` + all_features: bool, + /// Latched `CargoOpt::NoDefaultFeatures` + no_default_features: bool, + /// Arbitrary command line flags to pass to `cargo`. These will be added + /// to the end of the command line invocation. + other_options: Vec<String>, +} + +impl MetadataCommand { + /// Creates a default `cargo metadata` command, which will look for + /// `Cargo.toml` in the ancestors of the current directory. + pub fn new() -> MetadataCommand { + MetadataCommand::default() + } + /// Path to `cargo` executable. If not set, this will use the + /// the `$CARGO` environment variable, and if that is not set, will + /// simply be `cargo`. + pub fn cargo_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand { + self.cargo_path = Some(path.into()); + self + } + /// Path to `Cargo.toml` + pub fn manifest_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand { + self.manifest_path = Some(path.into()); + self + } + /// Current directory of the `cargo metadata` process. + pub fn current_dir(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand { + self.current_dir = Some(path.into()); + self + } + /// Output information only about the root package and don't fetch dependencies. + pub fn no_deps(&mut self) -> &mut MetadataCommand { + self.no_deps = true; + self + } + /// Which features to include. + /// + /// Call this multiple times to specify advanced feature configurations: + /// + /// ```no_run + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::NoDefaultFeatures) + /// .features(CargoOpt::SomeFeatures(vec!["feat1".into(), "feat2".into()])) + /// .features(CargoOpt::SomeFeatures(vec!["feat3".into()])) + /// // ... + /// # ; + /// ``` + /// + /// # Panics + /// + /// `cargo metadata` rejects multiple `--no-default-features` flags. Similarly, the `features()` + /// method panics when specifying multiple `CargoOpt::NoDefaultFeatures`: + /// + /// ```should_panic + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::NoDefaultFeatures) + /// .features(CargoOpt::NoDefaultFeatures) // <-- panic! + /// // ... + /// # ; + /// ``` + /// + /// The method also panics for multiple `CargoOpt::AllFeatures` arguments: + /// + /// ```should_panic + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .features(CargoOpt::AllFeatures) + /// .features(CargoOpt::AllFeatures) // <-- panic! + /// // ... + /// # ; + /// ``` + pub fn features(&mut self, features: CargoOpt) -> &mut MetadataCommand { + match features { + CargoOpt::SomeFeatures(features) => self.features.extend(features), + CargoOpt::NoDefaultFeatures => { + assert!( + !self.no_default_features, + "Do not supply CargoOpt::NoDefaultFeatures more than once!" + ); + self.no_default_features = true; + } + CargoOpt::AllFeatures => { + assert!( + !self.all_features, + "Do not supply CargoOpt::AllFeatures more than once!" + ); + self.all_features = true; + } + } + self + } + /// Arbitrary command line flags to pass to `cargo`. These will be added + /// to the end of the command line invocation. + pub fn other_options(&mut self, options: impl Into<Vec<String>>) -> &mut MetadataCommand { + self.other_options = options.into(); + self + } + + /// Builds a command for `cargo metadata`. This is the first + /// part of the work of `exec`. + pub fn cargo_command(&self) -> Command { + let cargo = self + .cargo_path + .clone() + .or_else(|| env::var("CARGO").map(PathBuf::from).ok()) + .unwrap_or_else(|| PathBuf::from("cargo")); + let mut cmd = Command::new(cargo); + cmd.args(&["metadata", "--format-version", "1"]); + + if self.no_deps { + cmd.arg("--no-deps"); + } + + if let Some(path) = self.current_dir.as_ref() { + cmd.current_dir(path); + } + + if !self.features.is_empty() { + cmd.arg("--features").arg(self.features.join(",")); + } + if self.all_features { + cmd.arg("--all-features"); + } + if self.no_default_features { + cmd.arg("--no-default-features"); + } + + if let Some(manifest_path) = &self.manifest_path { + cmd.arg("--manifest-path").arg(manifest_path.as_os_str()); + } + cmd.args(&self.other_options); + + cmd + } + + /// Parses `cargo metadata` output. `data` must have been + /// produced by a command built with `cargo_command`. + pub fn parse<T: AsRef<str>>(data: T) -> Result<Metadata> { + let meta = serde_json::from_str(data.as_ref())?; + Ok(meta) + } + + /// Runs configured `cargo metadata` and returns parsed `Metadata`. + pub fn exec(&self) -> Result<Metadata> { + let output = self.cargo_command().output()?; + if !output.status.success() { + return Err(Error::CargoMetadata { + stderr: String::from_utf8(output.stderr)?, + }); + } + let stdout = from_utf8(&output.stdout)? + .lines() + .find(|line| line.starts_with('{')) + .ok_or_else(|| Error::NoJson)?; + Self::parse(stdout) + } +}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/messages.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/messages.rs new file mode 100644 index 0000000..a52cde1 --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/src/messages.rs
@@ -0,0 +1,165 @@ +use super::{Diagnostic, PackageId, Target}; +use camino::Utf8PathBuf; +#[cfg(feature = "builder")] +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; +use std::fmt; +use std::io::{self, BufRead, Lines, Read}; + +/// Profile settings used to determine which compiler flags to use for a +/// target. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct ArtifactProfile { + /// Optimization level. Possible values are 0-3, s or z. + pub opt_level: String, + /// The amount of debug info. 0 for none, 1 for limited, 2 for full + pub debuginfo: Option<u32>, + /// State of the `cfg(debug_assertions)` directive, enabling macros like + /// `debug_assert!` + pub debug_assertions: bool, + /// State of the overflow checks. + pub overflow_checks: bool, + /// Whether this profile is a test + pub test: bool, +} + +/// A compiler-generated file. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct Artifact { + /// The package this artifact belongs to + pub package_id: PackageId, + /// The target this artifact was compiled for + pub target: Target, + /// The profile this artifact was compiled with + pub profile: ArtifactProfile, + /// The enabled features for this artifact + pub features: Vec<String>, + /// The full paths to the generated artifacts + /// (e.g. binary file and separate debug info) + pub filenames: Vec<Utf8PathBuf>, + /// Path to the executable file + pub executable: Option<Utf8PathBuf>, + /// If true, then the files were already generated + pub fresh: bool, +} + +/// Message left by the compiler +// TODO: Better name. This one comes from machine_message.rs +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct CompilerMessage { + /// The package this message belongs to + pub package_id: PackageId, + /// The target this message is aimed at + pub target: Target, + /// The message the compiler sent. + pub message: Diagnostic, +} + +/// Output of a build script execution. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct BuildScript { + /// The package this build script execution belongs to + pub package_id: PackageId, + /// The libs to link + pub linked_libs: Vec<Utf8PathBuf>, + /// The paths to search when resolving libs + pub linked_paths: Vec<Utf8PathBuf>, + /// Various `--cfg` flags to pass to the compiler + pub cfgs: Vec<String>, + /// The environment variables to add to the compilation + pub env: Vec<(String, String)>, + /// The `OUT_DIR` environment variable where this script places its output + /// + /// Added in Rust 1.41. + #[serde(default)] + pub out_dir: Utf8PathBuf, +} + +/// Final result of a build. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "builder", derive(Builder))] +#[non_exhaustive] +#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))] +pub struct BuildFinished { + /// Whether or not the build finished successfully. + pub success: bool, +} + +/// A cargo message +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[non_exhaustive] +#[serde(tag = "reason", rename_all = "kebab-case")] +pub enum Message { + /// The compiler generated an artifact + CompilerArtifact(Artifact), + /// The compiler wants to display a message + CompilerMessage(CompilerMessage), + /// A build script successfully executed. + BuildScriptExecuted(BuildScript), + /// The build has finished. + /// + /// This is emitted at the end of the build as the last message. + /// Added in Rust 1.44. + BuildFinished(BuildFinished), + /// A line of text which isn't a cargo or compiler message. + /// Line separator is not included + #[serde(skip)] + TextLine(String), +} + +impl Message { + /// Creates an iterator of Message from a Read outputting a stream of JSON + /// messages. For usage information, look at the top-level documentation. + pub fn parse_stream<R: BufRead>(input: R) -> MessageIter<R> { + MessageIter { + lines: input.lines(), + } + } +} + +impl fmt::Display for CompilerMessage { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.message) + } +} + +/// An iterator of Messages. +pub struct MessageIter<R> { + lines: Lines<R>, +} + +impl<R: BufRead> Iterator for MessageIter<R> { + type Item = io::Result<Message>; + fn next(&mut self) -> Option<Self::Item> { + let line = self.lines.next()?; + let message = line.map(|it| { + let mut deserializer = serde_json::Deserializer::from_str(&it); + deserializer.disable_recursion_limit(); + Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(it)) + }); + Some(message) + } +} + +/// An iterator of Message. +type MessageIterator<R> = + serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>; + +/// Creates an iterator of Message from a Read outputting a stream of JSON +/// messages. For usage information, look at the top-level documentation. +#[deprecated(note = "Use Message::parse_stream instead")] +pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> { + serde_json::Deserializer::from_reader(input).into_iter::<Message>() +}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/tests/selftest.rs b/third_party/rust/cargo_metadata/v0_14/crate/tests/selftest.rs new file mode 100644 index 0000000..70b131b --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/tests/selftest.rs
@@ -0,0 +1,159 @@ +use std::env::current_dir; +use std::path::PathBuf; + +use semver::Version; + +use cargo_metadata::{CargoOpt, Error, MetadataCommand}; +use serde::Deserialize; + +#[derive(Debug, PartialEq, Eq, Deserialize)] +struct TestPackageMetadata { + some_field: bool, + other_field: String, +} + +#[test] +fn metadata() { + let metadata = MetadataCommand::new().no_deps().exec().unwrap(); + + let this = &metadata.packages[0]; + assert_eq!(this.name, "cargo_metadata"); + assert_eq!(this.targets.len(), 3); + + let lib = this + .targets + .iter() + .find(|t| t.name == "cargo_metadata") + .unwrap(); + assert_eq!(lib.kind[0], "lib"); + assert_eq!(lib.crate_types[0], "lib"); + + let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap(); + assert_eq!(selftest.name, "selftest"); + assert_eq!(selftest.kind[0], "test"); + assert_eq!(selftest.crate_types[0], "bin"); + + let package_metadata = &metadata.packages[0] + .metadata + .as_object() + .expect("package.metadata must be a table."); + assert_eq!(package_metadata.len(), 1); + + let value = package_metadata.get("cargo_metadata_test").unwrap(); + let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone()).unwrap(); + assert_eq!( + test_package_metadata, + TestPackageMetadata { + some_field: true, + other_field: "foo".into(), + } + ); +} + +#[test] +fn builder_interface() { + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path(String::from("Cargo.toml")) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path(PathBuf::from("Cargo.toml")) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .no_deps() + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .features(CargoOpt::AllFeatures) + .exec() + .unwrap(); + let _ = MetadataCommand::new() + .manifest_path("Cargo.toml") + .current_dir(current_dir().unwrap()) + .exec() + .unwrap(); +} + +#[test] +fn error1() { + match MetadataCommand::new().manifest_path("foo").exec() { + Err(Error::CargoMetadata { stderr }) => assert_eq!( + stderr.trim(), + "error: the manifest-path must be a path to a Cargo.toml file" + ), + _ => unreachable!(), + } +} + +#[test] +fn error2() { + match MetadataCommand::new() + .manifest_path("foo/Cargo.toml") + .exec() + { + Err(Error::CargoMetadata { stderr }) => assert_eq!( + stderr.trim(), + "error: manifest path `foo/Cargo.toml` does not exist" + ), + _ => unreachable!(), + } +} + +#[test] +fn cargo_path() { + match MetadataCommand::new() + .cargo_path("this does not exist") + .exec() + { + Err(Error::Io(e)) => assert_eq!(e.kind(), std::io::ErrorKind::NotFound), + _ => unreachable!(), + } +} + +#[test] +fn metadata_deps() { + std::env::set_var("CARGO_PROFILE", "3"); + let metadata = MetadataCommand::new() + .manifest_path("Cargo.toml") + .exec() + .unwrap(); + let this_id = metadata + .workspace_members + .first() + .expect("Did not find ourselves"); + let this = &metadata[this_id]; + + assert_eq!(this.name, "cargo_metadata"); + + let lib = this + .targets + .iter() + .find(|t| t.name == "cargo_metadata") + .unwrap(); + assert_eq!(lib.kind[0], "lib"); + assert_eq!(lib.crate_types[0], "lib"); + + let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap(); + assert_eq!(selftest.name, "selftest"); + assert_eq!(selftest.kind[0], "test"); + assert_eq!(selftest.crate_types[0], "bin"); + + let dependencies = &this.dependencies; + + let serde = dependencies + .iter() + .find(|dep| dep.name == "serde") + .expect("Did not find serde dependency"); + + assert_eq!(serde.kind, cargo_metadata::DependencyKind::Normal); + assert!(!serde.req.matches(&Version::parse("1.0.0").unwrap())); + assert!(serde.req.matches(&Version::parse("1.99.99").unwrap())); + assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap())); +}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/tests/test_samples.rs b/third_party/rust/cargo_metadata/v0_14/crate/tests/test_samples.rs new file mode 100644 index 0000000..f899e6d --- /dev/null +++ b/third_party/rust/cargo_metadata/v0_14/crate/tests/test_samples.rs
@@ -0,0 +1,624 @@ +extern crate cargo_metadata; +extern crate semver; +#[macro_use] +extern crate serde_json; + +use camino::Utf8PathBuf; +use cargo_metadata::{CargoOpt, DependencyKind, Metadata, MetadataCommand}; + +#[test] +fn old_minimal() { + // Output from oldest supported version (1.24). + // This intentionally has as many null fields as possible. + // 1.8 is when metadata was introduced. + // Older versions not supported because the following are required: + // - `workspace_members` added in 1.13 + // - `target_directory` added in 1.19 + // - `workspace_root` added in 1.24 + let json = r#" +{ + "packages": [ + { + "name": "foo", + "version": "0.1.0", + "id": "foo 0.1.0 (path+file:///foo)", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "somedep", + "source": null, + "req": "^1.0", + "kind": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null + } + ], + "targets": [ + { + "kind": [ + "bin" + ], + "crate_types": [ + "bin" + ], + "name": "foo", + "src_path": "/foo/src/main.rs" + } + ], + "features": {}, + "manifest_path": "/foo/Cargo.toml" + } + ], + "workspace_members": [ + "foo 0.1.0 (path+file:///foo)" + ], + "resolve": null, + "target_directory": "/foo/target", + "version": 1, + "workspace_root": "/foo" +} +"#; + let meta: Metadata = serde_json::from_str(json).unwrap(); + assert_eq!(meta.packages.len(), 1); + let pkg = &meta.packages[0]; + assert_eq!(pkg.name, "foo"); + assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap()); + assert_eq!(pkg.authors.len(), 0); + assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)"); + assert_eq!(pkg.description, None); + assert_eq!(pkg.license, None); + assert_eq!(pkg.license_file, None); + assert_eq!(pkg.default_run, None); + assert_eq!(pkg.rust_version, None); + assert_eq!(pkg.dependencies.len(), 1); + let dep = &pkg.dependencies[0]; + assert_eq!(dep.name, "somedep"); + assert_eq!(dep.source, None); + assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap()); + assert_eq!(dep.kind, DependencyKind::Normal); + assert_eq!(dep.optional, false); + assert_eq!(dep.uses_default_features, true); + assert_eq!(dep.features.len(), 0); + assert!(dep.target.is_none()); + assert_eq!(dep.rename, None); + assert_eq!(dep.registry, None); + assert_eq!(pkg.targets.len(), 1); + let target = &pkg.targets[0]; + assert_eq!(target.name, "foo"); + assert_eq!(target.kind, vec!["bin"]); + assert_eq!(target.crate_types, vec!["bin"]); + assert_eq!(target.required_features.len(), 0); + assert_eq!(target.src_path, "/foo/src/main.rs"); + assert_eq!(target.edition, "2015"); + assert_eq!(target.doctest, true); + assert_eq!(target.test, true); + assert_eq!(target.doc, true); + assert_eq!(pkg.features.len(), 0); + assert_eq!(pkg.manifest_path, "/foo/Cargo.toml"); + assert_eq!(pkg.categories.len(), 0); + assert_eq!(pkg.keywords.len(), 0); + assert_eq!(pkg.readme, None); + assert_eq!(pkg.repository, None); + assert_eq!(pkg.homepage, None); + assert_eq!(pkg.documentation, None); + assert_eq!(pkg.edition, "2015"); + assert_eq!(pkg.metadata, serde_json::Value::Null); + assert_eq!(pkg.links, None); + assert_eq!(pkg.publish, None); + assert_eq!(meta.workspace_members.len(), 1); + assert_eq!( + meta.workspace_members[0].to_string(), + "foo 0.1.0 (path+file:///foo)" + ); + assert!(meta.resolve.is_none()); + assert_eq!(meta.workspace_root, "/foo"); + assert_eq!(meta.workspace_metadata, serde_json::Value::Null); + assert_eq!(meta.target_directory, "/foo/target"); +} + +macro_rules! sorted { + ($e:expr) => {{ + let mut v = $e.clone(); + v.sort(); + v + }}; +} + +fn cargo_version() -> semver::Version { + let output = std::process::Command::new("cargo") + .arg("-V") + .output() + .expect("Failed to exec cargo."); + let out = std::str::from_utf8(&output.stdout) + .expect("invalid utf8") + .trim(); + let split: Vec<&str> = out.split_whitespace().collect(); + assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out); + let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed"); + // Don't care about metadata, it is awkward to compare. + ver.pre = semver::Prerelease::EMPTY; + ver.build = semver::BuildMetadata::EMPTY; + ver +} + +#[derive(serde::Deserialize, PartialEq, Eq, Debug)] +struct WorkspaceMetadata { + testobject: TestObject, +} + +#[derive(serde::Deserialize, PartialEq, Eq, Debug)] +struct TestObject { + myvalue: String, +} + +#[test] +fn all_the_fields() { + // All the fields currently generated as of 1.60. This tries to exercise as + // much as possible. + let ver = cargo_version(); + let minimum = semver::Version::parse("1.56.0").unwrap(); + if ver < minimum { + // edition added in 1.30 + // rename added in 1.31 + // links added in 1.33 + // doctest added in 1.37 + // publish added in 1.39 + // dep_kinds added in 1.41 + // test added in 1.47 + // homepage added in 1.49 + // documentation added in 1.49 + // doc added in 1.50 + // path added in 1.51 + // default_run added in 1.55 + // rust_version added in 1.58 + eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver); + return; + } + let meta = MetadataCommand::new() + .manifest_path("tests/all/Cargo.toml") + .exec() + .unwrap(); + assert_eq!(meta.workspace_root.file_name().unwrap(), "all"); + assert_eq!( + serde_json::from_value::<WorkspaceMetadata>(meta.workspace_metadata).unwrap(), + WorkspaceMetadata { + testobject: TestObject { + myvalue: "abc".to_string() + } + } + ); + assert_eq!(meta.workspace_members.len(), 1); + assert!(meta.workspace_members[0].to_string().starts_with("all")); + + assert_eq!(meta.packages.len(), 9); + let all = meta.packages.iter().find(|p| p.name == "all").unwrap(); + assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap()); + assert_eq!(all.authors, vec!["Jane Doe <user@example.com>"]); + assert!(all.id.to_string().starts_with("all")); + assert_eq!(all.description, Some("Package description.".to_string())); + assert_eq!(all.license, Some("MIT/Apache-2.0".to_string())); + assert_eq!(all.license_file, Some(Utf8PathBuf::from("LICENSE"))); + assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE")); + assert_eq!(all.publish, Some(vec![])); + assert_eq!(all.links, Some("foo".to_string())); + assert_eq!(all.default_run, Some("otherbin".to_string())); + if ver >= semver::Version::parse("1.58.0").unwrap() { + assert_eq!( + all.rust_version, + Some(semver::VersionReq::parse("1.56").unwrap()) + ); + } + + assert_eq!(all.dependencies.len(), 8); + let bitflags = all + .dependencies + .iter() + .find(|d| d.name == "bitflags") + .unwrap(); + assert_eq!( + bitflags.source, + Some("registry+https://github.com/rust-lang/crates.io-index".to_string()) + ); + assert_eq!(bitflags.optional, true); + assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap()); + + let path_dep = all + .dependencies + .iter() + .find(|d| d.name == "path-dep") + .unwrap(); + assert_eq!(path_dep.source, None); + assert_eq!(path_dep.kind, DependencyKind::Normal); + assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap()); + assert_eq!( + path_dep.path.as_ref().map(|p| p.ends_with("path-dep")), + Some(true), + ); + + all.dependencies + .iter() + .find(|d| d.name == "namedep") + .unwrap(); + + let featdep = all + .dependencies + .iter() + .find(|d| d.name == "featdep") + .unwrap(); + assert_eq!(featdep.features, vec!["i128"]); + assert_eq!(featdep.uses_default_features, false); + + let renamed = all + .dependencies + .iter() + .find(|d| d.name == "oldname") + .unwrap(); + assert_eq!(renamed.rename, Some("newname".to_string())); + + let devdep = all + .dependencies + .iter() + .find(|d| d.name == "devdep") + .unwrap(); + assert_eq!(devdep.kind, DependencyKind::Development); + + let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap(); + assert_eq!(bdep.kind, DependencyKind::Build); + + let windep = all + .dependencies + .iter() + .find(|d| d.name == "windep") + .unwrap(); + assert_eq!( + windep.target.as_ref().map(|x| x.to_string()), + Some("cfg(windows)".to_string()) + ); + + macro_rules! get_file_name { + ($v:expr) => { + all.targets + .iter() + .find(|t| t.src_path.file_name().unwrap() == $v) + .unwrap() + }; + } + assert_eq!(all.targets.len(), 8); + let lib = get_file_name!("lib.rs"); + assert_eq!(lib.name, "all"); + assert_eq!(sorted!(lib.kind), vec!["cdylib", "rlib", "staticlib"]); + assert_eq!( + sorted!(lib.crate_types), + vec!["cdylib", "rlib", "staticlib"] + ); + assert_eq!(lib.required_features.len(), 0); + assert_eq!(lib.edition, "2018"); + assert_eq!(lib.doctest, true); + assert_eq!(lib.test, true); + assert_eq!(lib.doc, true); + + let main = get_file_name!("main.rs"); + assert_eq!(main.crate_types, vec!["bin"]); + assert_eq!(main.kind, vec!["bin"]); + assert_eq!(main.doctest, false); + assert_eq!(main.test, true); + assert_eq!(main.doc, true); + + let otherbin = get_file_name!("otherbin.rs"); + assert_eq!(otherbin.edition, "2015"); + assert_eq!(otherbin.doc, false); + + let reqfeat = get_file_name!("reqfeat.rs"); + assert_eq!(reqfeat.required_features, vec!["feat2"]); + + let ex1 = get_file_name!("ex1.rs"); + assert_eq!(ex1.kind, vec!["example"]); + assert_eq!(ex1.test, false); + + let t1 = get_file_name!("t1.rs"); + assert_eq!(t1.kind, vec!["test"]); + + let b1 = get_file_name!("b1.rs"); + assert_eq!(b1.kind, vec!["bench"]); + + let build = get_file_name!("build.rs"); + assert_eq!(build.kind, vec!["custom-build"]); + + if ver >= semver::Version::parse("1.60.0").unwrap() { + // 1.60 now reports optional dependencies within the features table + assert_eq!(all.features.len(), 4); + assert_eq!(all.features["bitflags"], vec!["dep:bitflags"]); + } else { + assert_eq!(all.features.len(), 3); + } + assert_eq!(all.features["feat1"].len(), 0); + assert_eq!(all.features["feat2"].len(), 0); + assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]); + + assert!(all.manifest_path.ends_with("all/Cargo.toml")); + assert_eq!(all.categories, vec!["command-line-utilities"]); + assert_eq!(all.keywords, vec!["cli"]); + assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md"))); + assert_eq!( + all.repository, + Some("https://github.com/oli-obk/cargo_metadata/".to_string()) + ); + assert_eq!( + all.homepage, + Some("https://github.com/oli-obk/cargo_metadata/".to_string()) + ); + assert_eq!( + all.documentation, + Some("https://docs.rs/cargo_metadata/".to_string()) + ); + assert_eq!(all.edition, "2018"); + assert_eq!( + all.metadata, + json!({ + "docs": { + "rs": { + "all-features": true, + "default-target": "x86_64-unknown-linux-gnu", + "rustc-args": ["--example-rustc-arg"] + } + } + }) + ); + + let resolve = meta.resolve.as_ref().unwrap(); + assert!(resolve + .root + .as_ref() + .unwrap() + .to_string() + .starts_with("all")); + + assert_eq!(resolve.nodes.len(), 9); + let path_dep = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("path-dep")) + .unwrap(); + assert_eq!(path_dep.deps.len(), 0); + assert_eq!(path_dep.dependencies.len(), 0); + assert_eq!(path_dep.features.len(), 0); + + let bitflags = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("bitflags")) + .unwrap(); + assert_eq!(bitflags.features, vec!["default"]); + + let featdep = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("featdep")) + .unwrap(); + assert_eq!(featdep.features, vec!["i128"]); + + let all = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("all")) + .unwrap(); + assert_eq!(all.dependencies.len(), 8); + assert_eq!(all.deps.len(), 8); + let newname = all.deps.iter().find(|d| d.name == "newname").unwrap(); + assert!(newname.pkg.to_string().starts_with("oldname")); + // Note the underscore here. + let path_dep = all.deps.iter().find(|d| d.name == "path_dep").unwrap(); + assert!(path_dep.pkg.to_string().starts_with("path-dep")); + assert_eq!(path_dep.dep_kinds.len(), 1); + let kind = &path_dep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Normal); + assert!(kind.target.is_none()); + + let namedep = all + .deps + .iter() + .find(|d| d.name == "different_name") + .unwrap(); + assert!(namedep.pkg.to_string().starts_with("namedep")); + assert_eq!(sorted!(all.features), vec!["bitflags", "default", "feat1"]); + + let bdep = all.deps.iter().find(|d| d.name == "bdep").unwrap(); + assert_eq!(bdep.dep_kinds.len(), 1); + let kind = &bdep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Build); + assert!(kind.target.is_none()); + + let devdep = all.deps.iter().find(|d| d.name == "devdep").unwrap(); + assert_eq!(devdep.dep_kinds.len(), 1); + let kind = &devdep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Development); + assert!(kind.target.is_none()); + + let windep = all.deps.iter().find(|d| d.name == "windep").unwrap(); + assert_eq!(windep.dep_kinds.len(), 1); + let kind = &windep.dep_kinds[0]; + assert_eq!(kind.kind, DependencyKind::Normal); + assert_eq!( + kind.target.as_ref().map(|x| x.to_string()), + Some("cfg(windows)".to_string()) + ); +} + +#[test] +fn alt_registry() { + // This is difficult to test (would need to set up a custom index). + // Just manually check the JSON is handled. + let json = r#" +{ + "packages": [ + { + "name": "alt", + "version": "0.1.0", + "id": "alt 0.1.0 (path+file:///alt)", + "source": null, + "dependencies": [ + { + "name": "alt2", + "source": "registry+https://example.com", + "req": "^0.1", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": "https://example.com" + } + ], + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "name": "alt", + "src_path": "/alt/src/lib.rs", + "edition": "2018" + } + ], + "features": {}, + "manifest_path": "/alt/Cargo.toml", + "metadata": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "edition": "2018", + "links": null + } + ], + "workspace_members": [ + "alt 0.1.0 (path+file:///alt)" + ], + "resolve": null, + "target_directory": "/alt/target", + "version": 1, + "workspace_root": "/alt" +} +"#; + let meta: Metadata = serde_json::from_str(json).unwrap(); + assert_eq!(meta.packages.len(), 1); + let alt = &meta.packages[0]; + let deps = &alt.dependencies; + assert_eq!(deps.len(), 1); + let dep = &deps[0]; + assert_eq!(dep.registry, Some("https://example.com".to_string())); +} + +#[test] +fn current_dir() { + let meta = MetadataCommand::new() + .current_dir("tests/all/namedep") + .exec() + .unwrap(); + let namedep = meta.packages.iter().find(|p| p.name == "namedep").unwrap(); + assert!(namedep.name.starts_with("namedep")); +} + +#[test] +fn parse_stream_is_robust() { + // Proc macros can print stuff to stdout, which naturally breaks JSON messages. + // Let's check that we don't die horribly in this case, and report an error. + let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false} +Evil proc macro was here! +{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false} +"##; + let mut n_messages = 0; + let mut text = String::new(); + for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) { + let message = message.unwrap(); + match message { + cargo_metadata::Message::TextLine(line) => text = line, + _ => n_messages += 1, + } + } + assert_eq!(n_messages, 2); + assert_eq!(text, "Evil proc macro was here!"); +} + +#[test] +fn advanced_feature_configuration() { + fn build_features<F: FnOnce(&mut MetadataCommand) -> &mut MetadataCommand>( + func: F, + ) -> Vec<String> { + let mut meta = MetadataCommand::new(); + let meta = meta.manifest_path("tests/all/Cargo.toml"); + + let meta = func(meta); + let meta = meta.exec().unwrap(); + + let resolve = meta.resolve.as_ref().unwrap(); + + let all = resolve + .nodes + .iter() + .find(|n| n.id.to_string().starts_with("all")) + .unwrap(); + + all.features.clone() + } + + // Default behavior; tested above + let default_features = build_features(|meta| meta); + assert_eq!( + sorted!(default_features), + vec!["bitflags", "default", "feat1"] + ); + + // Manually specify the same default features + let manual_features = build_features(|meta| { + meta.features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::SomeFeatures(vec![ + "feat1".into(), + "bitflags".into(), + ])) + }); + assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]); + + // Multiple SomeFeatures is same as one longer SomeFeatures + let manual_features = build_features(|meta| { + meta.features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::SomeFeatures(vec!["feat1".into()])) + .features(CargoOpt::SomeFeatures(vec!["feat2".into()])) + }); + assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]); + + // No features + All features == All features + let all_features = build_features(|meta| { + meta.features(CargoOpt::AllFeatures) + .features(CargoOpt::NoDefaultFeatures) + }); + assert_eq!( + sorted!(all_features), + vec!["bitflags", "default", "feat1", "feat2"] + ); + + // The '--all-features' flag supersedes other feature flags + let all_flag_variants = build_features(|meta| { + meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()])) + .features(CargoOpt::NoDefaultFeatures) + .features(CargoOpt::AllFeatures) + }); + assert_eq!(sorted!(all_flag_variants), sorted!(all_features)); +} + +#[test] +fn depkind_to_string() { + assert_eq!(DependencyKind::Normal.to_string(), "normal"); + assert_eq!(DependencyKind::Development.to_string(), "dev"); + assert_eq!(DependencyKind::Build.to_string(), "build"); + assert_eq!(DependencyKind::Unknown.to_string(), "Unknown"); +}
diff --git a/third_party/rust/cargo_platform/v0_1/BUILD.gn b/third_party/rust/cargo_platform/v0_1/BUILD.gn new file mode 100644 index 0000000..3194458 --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/BUILD.gn
@@ -0,0 +1,26 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/rust/cargo_crate.gni") + +cargo_crate("lib") { + crate_name = "cargo_platform" + epoch = "0.1" + crate_type = "rlib" + + # Only for usage from third-party crates. Add the crate to + # third_party.toml to use it from first-party code. + visibility = [ "//third_party/rust/*" ] + crate_root = "crate/src/lib.rs" + + # Unit tests skipped. Generate with --with-tests to include them. + build_native_rust_unit_tests = false + sources = [ "crate/src/lib.rs" ] + edition = "2018" + cargo_pkg_version = "0.1.2" + cargo_pkg_authors = "The Cargo Project Developers" + cargo_pkg_name = "cargo-platform" + cargo_pkg_description = "Cargo's representation of a target platform." + deps = [ "//third_party/rust/serde/v1:lib" ] +}
diff --git a/third_party/rust/cargo_platform/v0_1/README.chromium b/third_party/rust/cargo_platform/v0_1/README.chromium new file mode 100644 index 0000000..2f362f59 --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/README.chromium
@@ -0,0 +1,6 @@ +Name: cargo-platform +URL: https://crates.io/crates/cargo-platform +Description: Cargo's representation of a target platform. +Version: 0.1.2 +Security Critical: no +License: Apache 2.0
diff --git a/third_party/rust/cargo_platform/v0_1/crate/.cargo_vcs_info.json b/third_party/rust/cargo_platform/v0_1/crate/.cargo_vcs_info.json new file mode 100644 index 0000000..5f45bec --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/.cargo_vcs_info.json
@@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "981508778c4fac545eda4d517b9d6ddf48ed6636" + } +}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/Cargo.lock b/third_party/rust/cargo_platform/v0_1/crate/Cargo.lock new file mode 100644 index 0000000..059f730 --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/Cargo.lock
@@ -0,0 +1,65 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cargo-platform" +version = "0.1.2" +dependencies = [ + "serde", +] + +[[package]] +name = "proc-macro2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
diff --git a/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml new file mode 100644 index 0000000..ebf12c85 --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml
@@ -0,0 +1,24 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "cargo-platform" +version = "0.1.2" +authors = ["The Cargo Project Developers"] +description = "Cargo's representation of a target platform." +homepage = "https://github.com/rust-lang/cargo" +documentation = "https://docs.rs/cargo-platform" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/cargo" +[dependencies.serde] +version = "1.0.82" +features = ["derive"]
diff --git a/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml.orig b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml.orig new file mode 100644 index 0000000..2b5e86e --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml.orig
@@ -0,0 +1,13 @@ +[package] +name = "cargo-platform" +version = "0.1.2" +authors = ["The Cargo Project Developers"] +edition = "2018" +license = "MIT OR Apache-2.0" +homepage = "https://github.com/rust-lang/cargo" +repository = "https://github.com/rust-lang/cargo" +documentation = "https://docs.rs/cargo-platform" +description = "Cargo's representation of a target platform." + +[dependencies] +serde = { version = "1.0.82", features = ['derive'] }
diff --git a/third_party/rust/cargo_platform/v0_1/crate/LICENSE-APACHE b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-APACHE new file mode 100644 index 0000000..c98d27d --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-APACHE
@@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.
diff --git a/third_party/rust/cargo_platform/v0_1/crate/LICENSE-MIT b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-MIT new file mode 100644 index 0000000..31aa7938 --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-MIT
@@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/cargo_platform/v0_1/crate/examples/matches.rs b/third_party/rust/cargo_platform/v0_1/crate/examples/matches.rs new file mode 100644 index 0000000..9ad5d10d --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/examples/matches.rs
@@ -0,0 +1,55 @@ +//! This example demonstrates how to filter a Platform based on the current +//! host target. + +use cargo_platform::{Cfg, Platform}; +use std::process::Command; +use std::str::FromStr; + +static EXAMPLES: &[&str] = &[ + "cfg(windows)", + "cfg(unix)", + "cfg(target_os=\"macos\")", + "cfg(target_os=\"linux\")", + "cfg(any(target_arch=\"x86\", target_arch=\"x86_64\"))", +]; + +fn main() { + let target = get_target(); + let cfgs = get_cfgs(); + println!("host target={} cfgs:", target); + for cfg in &cfgs { + println!(" {}", cfg); + } + let mut examples: Vec<&str> = EXAMPLES.iter().copied().collect(); + examples.push(target.as_str()); + for example in examples { + let p = Platform::from_str(example).unwrap(); + println!("{:?} matches: {:?}", example, p.matches(&target, &cfgs)); + } +} + +fn get_target() -> String { + let output = Command::new("rustc") + .arg("-Vv") + .output() + .expect("rustc failed to run"); + let stdout = String::from_utf8(output.stdout).unwrap(); + for line in stdout.lines() { + if line.starts_with("host: ") { + return String::from(&line[6..]); + } + } + panic!("Failed to find host: {}", stdout); +} + +fn get_cfgs() -> Vec<Cfg> { + let output = Command::new("rustc") + .arg("--print=cfg") + .output() + .expect("rustc failed to run"); + let stdout = String::from_utf8(output.stdout).unwrap(); + stdout + .lines() + .map(|line| Cfg::from_str(line).unwrap()) + .collect() +}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/src/cfg.rs b/third_party/rust/cargo_platform/v0_1/crate/src/cfg.rs new file mode 100644 index 0000000..c3ddb69bc --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/src/cfg.rs
@@ -0,0 +1,319 @@ +use crate::error::{ParseError, ParseErrorKind::*}; +use std::fmt; +use std::iter; +use std::str::{self, FromStr}; + +/// A cfg expression. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum CfgExpr { + Not(Box<CfgExpr>), + All(Vec<CfgExpr>), + Any(Vec<CfgExpr>), + Value(Cfg), +} + +/// A cfg value. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum Cfg { + /// A named cfg value, like `unix`. + Name(String), + /// A key/value cfg pair, like `target_os = "linux"`. + KeyPair(String, String), +} + +#[derive(PartialEq)] +enum Token<'a> { + LeftParen, + RightParen, + Ident(&'a str), + Comma, + Equals, + String(&'a str), +} + +#[derive(Clone)] +struct Tokenizer<'a> { + s: iter::Peekable<str::CharIndices<'a>>, + orig: &'a str, +} + +struct Parser<'a> { + t: Tokenizer<'a>, +} + +impl FromStr for Cfg { + type Err = ParseError; + + fn from_str(s: &str) -> Result<Cfg, Self::Err> { + let mut p = Parser::new(s); + let e = p.cfg()?; + if let Some(rest) = p.rest() { + return Err(ParseError::new( + p.t.orig, + UnterminatedExpression(rest.to_string()), + )); + } + Ok(e) + } +} + +impl fmt::Display for Cfg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Cfg::Name(ref s) => s.fmt(f), + Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v), + } + } +} + +impl CfgExpr { + /// Utility function to check if the key, "cfg(..)" matches the `target_cfg` + pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool { + if key.starts_with("cfg(") && key.ends_with(')') { + let cfg = &key[4..key.len() - 1]; + + CfgExpr::from_str(cfg) + .ok() + .map(|ce| ce.matches(target_cfg)) + .unwrap_or(false) + } else { + false + } + } + + pub fn matches(&self, cfg: &[Cfg]) -> bool { + match *self { + CfgExpr::Not(ref e) => !e.matches(cfg), + CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)), + CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)), + CfgExpr::Value(ref e) => cfg.contains(e), + } + } +} + +impl FromStr for CfgExpr { + type Err = ParseError; + + fn from_str(s: &str) -> Result<CfgExpr, Self::Err> { + let mut p = Parser::new(s); + let e = p.expr()?; + if let Some(rest) = p.rest() { + return Err(ParseError::new( + p.t.orig, + UnterminatedExpression(rest.to_string()), + )); + } + Ok(e) + } +} + +impl fmt::Display for CfgExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + CfgExpr::Not(ref e) => write!(f, "not({})", e), + CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)), + CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)), + CfgExpr::Value(ref e) => write!(f, "{}", e), + } + } +} + +struct CommaSep<'a, T>(&'a [T]); + +impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, v) in self.0.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + write!(f, "{}", v)?; + } + Ok(()) + } +} + +impl<'a> Parser<'a> { + fn new(s: &'a str) -> Parser<'a> { + Parser { + t: Tokenizer { + s: s.char_indices().peekable(), + orig: s, + }, + } + } + + fn expr(&mut self) -> Result<CfgExpr, ParseError> { + match self.peek() { + Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => { + self.t.next(); + let mut e = Vec::new(); + self.eat(&Token::LeftParen)?; + while !self.r#try(&Token::RightParen) { + e.push(self.expr()?); + if !self.r#try(&Token::Comma) { + self.eat(&Token::RightParen)?; + break; + } + } + if op == "all" { + Ok(CfgExpr::All(e)) + } else { + Ok(CfgExpr::Any(e)) + } + } + Some(Ok(Token::Ident("not"))) => { + self.t.next(); + self.eat(&Token::LeftParen)?; + let e = self.expr()?; + self.eat(&Token::RightParen)?; + Ok(CfgExpr::Not(Box::new(e))) + } + Some(Ok(..)) => self.cfg().map(CfgExpr::Value), + Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()), + None => Err(ParseError::new( + self.t.orig, + IncompleteExpr("start of a cfg expression"), + )), + } + } + + fn cfg(&mut self) -> Result<Cfg, ParseError> { + match self.t.next() { + Some(Ok(Token::Ident(name))) => { + let e = if self.r#try(&Token::Equals) { + let val = match self.t.next() { + Some(Ok(Token::String(s))) => s, + Some(Ok(t)) => { + return Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: "a string", + found: t.classify(), + }, + )) + } + Some(Err(e)) => return Err(e), + None => { + return Err(ParseError::new(self.t.orig, IncompleteExpr("a string"))) + } + }; + Cfg::KeyPair(name.to_string(), val.to_string()) + } else { + Cfg::Name(name.to_string()) + }; + Ok(e) + } + Some(Ok(t)) => Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: "identifier", + found: t.classify(), + }, + )), + Some(Err(e)) => Err(e), + None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))), + } + } + + fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> { + self.t.clone().next() + } + + fn r#try(&mut self, token: &Token<'a>) -> bool { + match self.peek() { + Some(Ok(ref t)) if token == t => {} + _ => return false, + } + self.t.next(); + true + } + + fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> { + match self.t.next() { + Some(Ok(ref t)) if token == t => Ok(()), + Some(Ok(t)) => Err(ParseError::new( + self.t.orig, + UnexpectedToken { + expected: token.classify(), + found: t.classify(), + }, + )), + Some(Err(e)) => Err(e), + None => Err(ParseError::new( + self.t.orig, + IncompleteExpr(token.classify()), + )), + } + } + + /// Returns the rest of the input from the current location. + fn rest(&self) -> Option<&str> { + let mut s = self.t.s.clone(); + loop { + match s.next() { + Some((_, ' ')) => {} + Some((start, _ch)) => return Some(&self.t.orig[start..]), + None => return None, + } + } + } +} + +impl<'a> Iterator for Tokenizer<'a> { + type Item = Result<Token<'a>, ParseError>; + + fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> { + loop { + match self.s.next() { + Some((_, ' ')) => {} + Some((_, '(')) => return Some(Ok(Token::LeftParen)), + Some((_, ')')) => return Some(Ok(Token::RightParen)), + Some((_, ',')) => return Some(Ok(Token::Comma)), + Some((_, '=')) => return Some(Ok(Token::Equals)), + Some((start, '"')) => { + while let Some((end, ch)) = self.s.next() { + if ch == '"' { + return Some(Ok(Token::String(&self.orig[start + 1..end]))); + } + } + return Some(Err(ParseError::new(self.orig, UnterminatedString))); + } + Some((start, ch)) if is_ident_start(ch) => { + while let Some(&(end, ch)) = self.s.peek() { + if !is_ident_rest(ch) { + return Some(Ok(Token::Ident(&self.orig[start..end]))); + } else { + self.s.next(); + } + } + return Some(Ok(Token::Ident(&self.orig[start..]))); + } + Some((_, ch)) => { + return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch)))); + } + None => return None, + } + } + } +} + +fn is_ident_start(ch: char) -> bool { + ch == '_' || ch.is_ascii_alphabetic() +} + +fn is_ident_rest(ch: char) -> bool { + is_ident_start(ch) || ch.is_ascii_digit() +} + +impl<'a> Token<'a> { + fn classify(&self) -> &'static str { + match *self { + Token::LeftParen => "`(`", + Token::RightParen => "`)`", + Token::Ident(..) => "an identifier", + Token::Comma => "`,`", + Token::Equals => "`=`", + Token::String(..) => "a string", + } + } +}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/src/error.rs b/third_party/rust/cargo_platform/v0_1/crate/src/error.rs new file mode 100644 index 0000000..bf4b35f --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/src/error.rs
@@ -0,0 +1,67 @@ +use std::fmt; + +#[derive(Debug)] +pub struct ParseError { + kind: ParseErrorKind, + orig: String, +} + +#[non_exhaustive] +#[derive(Debug)] +pub enum ParseErrorKind { + UnterminatedString, + UnexpectedChar(char), + UnexpectedToken { + expected: &'static str, + found: &'static str, + }, + IncompleteExpr(&'static str), + UnterminatedExpression(String), + InvalidTarget(String), +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "failed to parse `{}` as a cfg expression: {}", + self.orig, self.kind + ) + } +} + +impl fmt::Display for ParseErrorKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ParseErrorKind::*; + match self { + UnterminatedString => write!(f, "unterminated string in cfg"), + UnexpectedChar(ch) => write!( + f, + "unexpected character `{}` in cfg, expected parens, a comma, \ + an identifier, or a string", + ch + ), + UnexpectedToken { expected, found } => { + write!(f, "expected {}, found {}", expected, found) + } + IncompleteExpr(expected) => { + write!(f, "expected {}, but cfg expression ended", expected) + } + UnterminatedExpression(s) => { + write!(f, "unexpected content `{}` found after cfg expression", s) + } + InvalidTarget(s) => write!(f, "invalid target specifier: {}", s), + } + } +} + +impl std::error::Error for ParseError {} + +impl ParseError { + pub fn new(orig: &str, kind: ParseErrorKind) -> ParseError { + ParseError { + kind, + orig: orig.to_string(), + } + } +}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/src/lib.rs b/third_party/rust/cargo_platform/v0_1/crate/src/lib.rs new file mode 100644 index 0000000..0a3dcf1 --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/src/lib.rs
@@ -0,0 +1,146 @@ +//! Platform definition used by Cargo. +//! +//! This defines a [`Platform`] type which is used in Cargo to specify a target platform. +//! There are two kinds, a named target like `x86_64-apple-darwin`, and a "cfg expression" +//! like `cfg(any(target_os = "macos", target_os = "ios"))`. +//! +//! See `examples/matches.rs` for an example of how to match against a `Platform`. +//! +//! [`Platform`]: enum.Platform.html + +use std::fmt; +use std::str::FromStr; + +mod cfg; +mod error; + +pub use cfg::{Cfg, CfgExpr}; +pub use error::{ParseError, ParseErrorKind}; + +/// Platform definition. +#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)] +pub enum Platform { + /// A named platform, like `x86_64-apple-darwin`. + Name(String), + /// A cfg expression, like `cfg(windows)`. + Cfg(CfgExpr), +} + +impl Platform { + /// Returns whether the Platform matches the given target and cfg. + /// + /// The named target and cfg values should be obtained from `rustc`. + pub fn matches(&self, name: &str, cfg: &[Cfg]) -> bool { + match *self { + Platform::Name(ref p) => p == name, + Platform::Cfg(ref p) => p.matches(cfg), + } + } + + fn validate_named_platform(name: &str) -> Result<(), ParseError> { + if let Some(ch) = name + .chars() + .find(|&c| !(c.is_alphanumeric() || c == '_' || c == '-' || c == '.')) + { + if name.chars().any(|c| c == '(') { + return Err(ParseError::new( + name, + ParseErrorKind::InvalidTarget( + "unexpected `(` character, cfg expressions must start with `cfg(`" + .to_string(), + ), + )); + } + return Err(ParseError::new( + name, + ParseErrorKind::InvalidTarget(format!( + "unexpected character {} in target name", + ch + )), + )); + } + Ok(()) + } + + pub fn check_cfg_attributes(&self, warnings: &mut Vec<String>) { + fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec<String>) { + match *expr { + CfgExpr::Not(ref e) => check_cfg_expr(e, warnings), + CfgExpr::All(ref e) | CfgExpr::Any(ref e) => { + for e in e { + check_cfg_expr(e, warnings); + } + } + CfgExpr::Value(ref e) => match e { + Cfg::Name(name) => match name.as_str() { + "test" | "debug_assertions" | "proc_macro" => + warnings.push(format!( + "Found `{}` in `target.'cfg(...)'.dependencies`. \ + This value is not supported for selecting dependencies \ + and will not work as expected. \ + To learn more visit \ + https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies", + name + )), + _ => (), + }, + Cfg::KeyPair(name, _) => if name.as_str() == "feature" { + warnings.push(String::from( + "Found `feature = ...` in `target.'cfg(...)'.dependencies`. \ + This key is not supported for selecting dependencies \ + and will not work as expected. \ + Use the [features] section instead: \ + https://doc.rust-lang.org/cargo/reference/features.html" + )) + }, + } + } + } + + if let Platform::Cfg(cfg) = self { + check_cfg_expr(cfg, warnings); + } + } +} + +impl serde::Serialize for Platform { + fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + self.to_string().serialize(s) + } +} + +impl<'de> serde::Deserialize<'de> for Platform { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + FromStr::from_str(&s).map_err(serde::de::Error::custom) + } +} + +impl FromStr for Platform { + type Err = ParseError; + + fn from_str(s: &str) -> Result<Platform, ParseError> { + if s.starts_with("cfg(") && s.ends_with(')') { + let s = &s[4..s.len() - 1]; + s.parse().map(Platform::Cfg) + } else { + Platform::validate_named_platform(s)?; + Ok(Platform::Name(s.to_string())) + } + } +} + +impl fmt::Display for Platform { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Platform::Name(ref n) => n.fmt(f), + Platform::Cfg(ref e) => write!(f, "cfg({})", e), + } + } +}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/tests/test_cfg.rs b/third_party/rust/cargo_platform/v0_1/crate/tests/test_cfg.rs new file mode 100644 index 0000000..dd99d9a --- /dev/null +++ b/third_party/rust/cargo_platform/v0_1/crate/tests/test_cfg.rs
@@ -0,0 +1,251 @@ +use cargo_platform::{Cfg, CfgExpr, Platform}; +use std::fmt; +use std::str::FromStr; + +macro_rules! c { + ($a:ident) => { + Cfg::Name(stringify!($a).to_string()) + }; + ($a:ident = $e:expr) => { + Cfg::KeyPair(stringify!($a).to_string(), $e.to_string()) + }; +} + +macro_rules! e { + (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*])); + (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*])); + (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*)))); + (($($t:tt)*)) => (e!($($t)*)); + ($($t:tt)*) => (CfgExpr::Value(c!($($t)*))); +} + +fn good<T>(s: &str, expected: T) +where + T: FromStr + PartialEq + fmt::Debug, + T::Err: fmt::Display, +{ + let c = match T::from_str(s) { + Ok(c) => c, + Err(e) => panic!("failed to parse `{}`: {}", s, e), + }; + assert_eq!(c, expected); +} + +fn bad<T>(s: &str, err: &str) +where + T: FromStr + fmt::Display, + T::Err: fmt::Display, +{ + let e = match T::from_str(s) { + Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg), + Err(e) => e.to_string(), + }; + assert!( + e.contains(err), + "when parsing `{}`,\n\"{}\" not contained \ + inside: {}", + s, + err, + e + ); +} + +#[test] +fn cfg_syntax() { + good("foo", c!(foo)); + good("_bar", c!(_bar)); + good(" foo", c!(foo)); + good(" foo ", c!(foo)); + good(" foo = \"bar\"", c!(foo = "bar")); + good("foo=\"\"", c!(foo = "")); + good(" foo=\"3\" ", c!(foo = "3")); + good("foo = \"3 e\"", c!(foo = "3 e")); +} + +#[test] +fn cfg_syntax_bad() { + bad::<Cfg>("", "but cfg expression ended"); + bad::<Cfg>(" ", "but cfg expression ended"); + bad::<Cfg>("\t", "unexpected character"); + bad::<Cfg>("7", "unexpected character"); + bad::<Cfg>("=", "expected identifier"); + bad::<Cfg>(",", "expected identifier"); + bad::<Cfg>("(", "expected identifier"); + bad::<Cfg>("foo (", "unexpected content `(` found after cfg expression"); + bad::<Cfg>("bar =", "expected a string"); + bad::<Cfg>("bar = \"", "unterminated string"); + bad::<Cfg>( + "foo, bar", + "unexpected content `, bar` found after cfg expression", + ); +} + +#[test] +fn cfg_expr() { + good("foo", e!(foo)); + good("_bar", e!(_bar)); + good(" foo", e!(foo)); + good(" foo ", e!(foo)); + good(" foo = \"bar\"", e!(foo = "bar")); + good("foo=\"\"", e!(foo = "")); + good(" foo=\"3\" ", e!(foo = "3")); + good("foo = \"3 e\"", e!(foo = "3 e")); + + good("all()", e!(all())); + good("all(a)", e!(all(a))); + good("all(a, b)", e!(all(a, b))); + good("all(a, )", e!(all(a))); + good("not(a = \"b\")", e!(not(a = "b"))); + good("not(all(a))", e!(not(all(a)))); +} + +#[test] +fn cfg_expr_bad() { + bad::<CfgExpr>(" ", "but cfg expression ended"); + bad::<CfgExpr>(" all", "expected `(`"); + bad::<CfgExpr>("all(a", "expected `)`"); + bad::<CfgExpr>("not", "expected `(`"); + bad::<CfgExpr>("not(a", "expected `)`"); + bad::<CfgExpr>("a = ", "expected a string"); + bad::<CfgExpr>("all(not())", "expected identifier"); + bad::<CfgExpr>( + "foo(a)", + "unexpected content `(a)` found after cfg expression", + ); +} + +#[test] +fn cfg_matches() { + assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)])); + assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)])); + assert!(e!(any(foo, bar)).matches(&[c!(bar)])); + assert!(e!(any(foo, bar)).matches(&[c!(foo)])); + assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)])); + assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)])); + assert!(e!(not(foo)).matches(&[c!(bar)])); + assert!(e!(not(foo)).matches(&[])); + assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)])); + assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)])); + + assert!(!e!(foo).matches(&[])); + assert!(!e!(foo).matches(&[c!(bar)])); + assert!(!e!(foo).matches(&[c!(fo)])); + assert!(!e!(any(foo)).matches(&[])); + assert!(!e!(any(foo)).matches(&[c!(bar)])); + assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)])); + assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)])); + assert!(!e!(all(foo, bar)).matches(&[c!(bar)])); + assert!(!e!(all(foo, bar)).matches(&[c!(foo)])); + assert!(!e!(all(foo, bar)).matches(&[])); + assert!(!e!(not(bar)).matches(&[c!(bar)])); + assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)])); + assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)])); +} + +#[test] +fn bad_target_name() { + bad::<Platform>( + "any(cfg(unix), cfg(windows))", + "failed to parse `any(cfg(unix), cfg(windows))` as a cfg expression: \ + invalid target specifier: unexpected `(` character, \ + cfg expressions must start with `cfg(`", + ); + bad::<Platform>( + "!foo", + "failed to parse `!foo` as a cfg expression: \ + invalid target specifier: unexpected character ! in target name", + ); +} + +#[test] +fn round_trip_platform() { + fn rt(s: &str) { + let p = Platform::from_str(s).unwrap(); + let s2 = p.to_string(); + let p2 = Platform::from_str(&s2).unwrap(); + assert_eq!(p, p2); + } + rt("x86_64-apple-darwin"); + rt("foo"); + rt("cfg(windows)"); + rt("cfg(target_os = \"windows\")"); + rt( + "cfg(any(all(any(target_os = \"android\", target_os = \"linux\"), \ + any(target_arch = \"aarch64\", target_arch = \"arm\", target_arch = \"powerpc64\", \ + target_arch = \"x86\", target_arch = \"x86_64\")), \ + all(target_os = \"freebsd\", target_arch = \"x86_64\")))", + ); +} + +#[test] +fn check_cfg_attributes() { + fn ok(s: &str) { + let p = Platform::Cfg(s.parse().unwrap()); + let mut warnings = Vec::new(); + p.check_cfg_attributes(&mut warnings); + assert!( + warnings.is_empty(), + "Expected no warnings but got: {:?}", + warnings, + ); + } + + fn warn(s: &str, names: &[&str]) { + let p = Platform::Cfg(s.parse().unwrap()); + let mut warnings = Vec::new(); + p.check_cfg_attributes(&mut warnings); + assert_eq!( + warnings.len(), + names.len(), + "Expecter warnings about {:?} but got {:?}", + names, + warnings, + ); + for (name, warning) in names.iter().zip(warnings.iter()) { + assert!( + warning.contains(name), + "Expected warning about '{}' but got: {}", + name, + warning, + ); + } + } + + ok("unix"); + ok("windows"); + ok("any(not(unix), windows)"); + ok("foo"); + + ok("target_arch = \"abc\""); + ok("target_feature = \"abc\""); + ok("target_os = \"abc\""); + ok("target_family = \"abc\""); + ok("target_env = \"abc\""); + ok("target_endian = \"abc\""); + ok("target_pointer_width = \"abc\""); + ok("target_vendor = \"abc\""); + ok("bar = \"def\""); + + warn("test", &["test"]); + warn("debug_assertions", &["debug_assertions"]); + warn("proc_macro", &["proc_macro"]); + warn("feature = \"abc\"", &["feature"]); + + warn("any(not(debug_assertions), windows)", &["debug_assertions"]); + warn( + "any(not(feature = \"def\"), target_arch = \"abc\")", + &["feature"], + ); + warn( + "any(not(target_os = \"windows\"), proc_macro)", + &["proc_macro"], + ); + warn( + "any(not(feature = \"windows\"), proc_macro)", + &["feature", "proc_macro"], + ); + warn( + "all(not(debug_assertions), any(windows, proc_macro))", + &["debug_assertions", "proc_macro"], + ); +}
diff --git a/third_party/rust/semver/v1/BUILD.gn b/third_party/rust/semver/v1/BUILD.gn index 1c1dec8..c2b1c20 100644 --- a/third_party/rust/semver/v1/BUILD.gn +++ b/third_party/rust/semver/v1/BUILD.gn
@@ -23,7 +23,11 @@ cargo_pkg_name = "semver" cargo_pkg_description = "Parser and evaluator for Cargo's flavor of Semantic Versioning" - features = [ "std" ] + deps = [ "//third_party/rust/serde/v1:lib" ] + features = [ + "serde", + "std", + ] build_root = "crate/build.rs" build_sources = [ "crate/build.rs" ] }
diff --git a/third_party/rust/serde_json/v1/BUILD.gn b/third_party/rust/serde_json/v1/BUILD.gn index 5a005a1..89e19b2a 100644 --- a/third_party/rust/serde_json/v1/BUILD.gn +++ b/third_party/rust/serde_json/v1/BUILD.gn
@@ -27,7 +27,10 @@ "//third_party/rust/ryu/v1:lib", "//third_party/rust/serde/v1:lib", ] - features = [ "std" ] + features = [ + "std", + "unbounded_depth", + ] build_root = "crate/build.rs" build_sources = [ "crate/build.rs" ] }
diff --git a/third_party/rust/third_party.toml b/third_party/rust/third_party.toml index f15c4a8b..270dc03 100644 --- a/third_party/rust/third_party.toml +++ b/third_party/rust/third_party.toml
@@ -77,4 +77,5 @@ syn = {version = "1", features = ["full"]} # Used in Rust tool for BUILD.gn generation. +cargo_metadata = "0.14" toml = "0.5"
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index 0dfb991..32a79a5 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -437,10 +437,14 @@ # Check that all non-glob wanted files exist on disk. want = [w.replace('$V', RELEASE_VERSION) for w in want] + found_all_wanted_files = True for w in want: if '*' in w: continue if os.path.exists(os.path.join(LLVM_RELEASE_DIR, w)): continue print('wanted file "%s" but it did not exist' % w, file=sys.stderr) + found_all_wanted_files = False + + if not found_all_wanted_files: return 1 # Check that all reclient inputs are in the package.
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 3a8b94d..f4da766 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -388,7 +388,7 @@ 'ios15-sdk-device': 'ios_device_release_static_bot_xctest', 'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest', - 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_no_lld_treat_warnings_as_errors', 'lacros-amd64-generic-rel (goma cache silo)': 'chromeos_amd64-generic_lacros_rel', 'lacros-amd64-generic-rel (reclient)': 'chromeos_amd64-generic-vm_lacros_rel_reclient', 'lacros-amd64-generic-rel-fyi': 'chromeos_amd64-generic_lacros_rel_reclient', @@ -673,6 +673,8 @@ }, 'chromium.updater': { + 'mac-updater-builder-arm64-dbg': 'updater_debug_bot_arm64', + 'mac-updater-builder-arm64-rel': 'updater_release_bot_arm64', 'mac-updater-builder-dbg': 'updater_debug_bot', 'mac-updater-builder-rel': 'updater_release_bot', 'win-updater-builder-dbg': 'updater_debug_bot_reclient', @@ -819,7 +821,6 @@ 'mac12.0.arm64-blink-rel': 'release_bot_blink_arm64_minimal_symbols', 'win10.20h2-blink-rel': 'release_bot_blink_x86_minimal_symbols', 'win11-blink-rel': 'release_bot_blink_x64_minimal_symbols', - 'win7-blink-rel': 'release_bot_blink_x86_minimal_symbols', }, 'tryserver.chrome': { @@ -1169,7 +1170,7 @@ 'ios15-beta-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest', - 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_no_lld_treat_warnings_as_errors', 'mac-arm64-on-arm64-rel': 'mac_arm64_release_trybot', 'mac-builder-next-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl', 'mac-clang-tidy-rel': 'release_trybot', @@ -2793,6 +2794,10 @@ 'debug_static_bot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest', 'ios_disable_xcode_project_generation', 'no_lld', ], + 'ios_simulator_debug_static_bot_xctest_no_lld_treat_warnings_as_errors': [ + 'debug_static_bot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest', 'ios_disable_xcode_project_generation', 'no_lld', 'treat_warnings_as_errors' + ], + 'ios_simulator_debug_static_bot_xctest_reclient': [ 'debug_static_bot_reclient', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest', 'ios_disable_xcode_project_generation', ], @@ -3407,6 +3412,10 @@ 'updater_on_win_mac', 'debug_static_bot', ], + 'updater_debug_bot_arm64': [ + 'arm64', 'updater_on_win_mac', 'debug_static_bot', + ], + 'updater_debug_bot_reclient': [ 'updater_on_win_mac', 'debug_static_bot_reclient', ], @@ -3419,6 +3428,10 @@ 'updater_on_win_mac', 'release_bot', ], + 'updater_release_bot_arm64': [ + 'arm64', 'updater_on_win_mac', 'release_bot', + ], + 'updater_release_bot_reclient': [ 'updater_on_win_mac', 'release_bot_reclient', ], @@ -4348,6 +4361,10 @@ 'gn_args': 'use_thin_lto=true thin_lto_enable_optimizations=true', }, + 'treat_warnings_as_errors': { + 'gn_args': 'treat_warnings_as_errors=false', + }, + 'tsan': { 'gn_args': 'is_tsan=true', },
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json index 1c62ba2..37f808ae 100644 --- a/tools/mb/mb_config_expectations/chromium.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -906,7 +906,9 @@ "target_cpu": "x64", "target_environment": "simulator", "target_os": "ios", - "use_goma": true + "treat_warnings_as_errors": false, + "use_goma": true, + "use_lld": false } }, "lacros-amd64-generic-rel (goma cache silo)": {
diff --git a/tools/mb/mb_config_expectations/chromium.updater.json b/tools/mb/mb_config_expectations/chromium.updater.json index ee66ff07..478b25d 100644 --- a/tools/mb/mb_config_expectations/chromium.updater.json +++ b/tools/mb/mb_config_expectations/chromium.updater.json
@@ -1,4 +1,24 @@ { + "mac-updater-builder-arm64-dbg": { + "gn_args": { + "enable_chromium_updater": true, + "is_component_build": false, + "is_debug": true, + "symbol_level": 1, + "target_cpu": "arm64", + "use_goma": true + } + }, + "mac-updater-builder-arm64-rel": { + "gn_args": { + "dcheck_always_on": false, + "enable_chromium_updater": true, + "is_component_build": false, + "is_debug": false, + "target_cpu": "arm64", + "use_goma": true + } + }, "mac-updater-builder-dbg": { "gn_args": { "enable_chromium_updater": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.blink.json b/tools/mb/mb_config_expectations/tryserver.blink.json index f9c412f..c24b3c1c 100644 --- a/tools/mb/mb_config_expectations/tryserver.blink.json +++ b/tools/mb/mb_config_expectations/tryserver.blink.json
@@ -128,17 +128,5 @@ "target_cpu": "x64", "use_goma": true } - }, - "win7-blink-rel": { - "gn_args": { - "dcheck_always_on": false, - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "symbol_level": 1, - "target_cpu": "x86", - "use_goma": true - } } } \ No newline at end of file
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json index 8bb4c9a1..a72e72b 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -461,7 +461,9 @@ "target_cpu": "x64", "target_environment": "simulator", "target_os": "ios", - "use_goma": true + "treat_warnings_as_errors": false, + "use_goma": true, + "use_lld": false } }, "mac-arm64-on-arm64-rel": {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b7047a3..4a93fa5 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -21150,6 +21150,7 @@ <int value="18" label="DELETE_PREV_SENT"/> <int value="19" label="NAV_NEXT_WORD"/> <int value="20" label="NAV_PREV_WORD"/> + <int value="21" label="SMART_DELETE_PHRASE"/> </enum> <enum name="CrosDictationToggleDictationMethod"> @@ -34541,7 +34542,7 @@ <int value="1559" label="WMDESKSPRIVATE_UPDATEDESKTEMPLATE"/> <int value="1560" label="WMDESKSPRIVATE_GETSAVEDDESKTEMPLATES"/> <int value="1561" label="WMDESKSPRIVATE_DELETEDESKTEMPLATE"/> - <int value="1562" label="WMDESKSPRIVATE_LAUNCHDESKTEMPLATE"/> + <int value="1562" label="WMDESKSPRIVATE_LAUNCHDESK"/> <int value="1563" label="AUTOTESTPRIVATE_SETSHELFICONPIN"/> <int value="1564" label="SCRIPTING_GETREGISTEREDCONTENTSCRIPTS"/> <int value="1565" label="OS_TELEMETRY_GETVPDINFO"/> @@ -34639,7 +34640,7 @@ <int value="1656" label="ACCESSIBILITY_PRIVATE_INSTALLPUMPKINFORDICTATION"/> <int value="1657" label="BOOKMARKMANAGERPRIVATE_OPENINNEWTAB"/> <int value="1658" label="BOOKMARKMANAGERPRIVATE_OPENINNEWWINDOW"/> - <int value="1659" label="WMDESKSPRIVATE_REMOVEDESKANDCLOSEWINDOWS"/> + <int value="1659" label="WMDESKSPRIVATE_REMOVEDESK"/> <int value="1660" label="SHAREDSTORAGEPRIVATE_GET"/> <int value="1661" label="SHAREDSTORAGEPRIVATE_SET"/> <int value="1662" label="SHAREDSTORAGEPRIVATE_REMOVE"/> @@ -58397,6 +58398,7 @@ <int value="301536977" label="DetailedLanguageSettings:enabled"/> <int value="301630312" label="ForcedColors:disabled"/> <int value="301869874" label="NTPPhysicalWebPageSuggestions:disabled"/> + <int value="302725573" label="NewInstanceFromDraggedLink:enabled"/> <int value="302754902" label="MicMuteNotifications:disabled"/> <int value="303058039" label="AccountConsistency:disabled"/> <int value="303252119" label="AutofillExpandedPopupViews:disabled"/> @@ -59406,6 +59408,7 @@ <int value="966134219" label="CrostiniEnableDlc:disabled"/> <int value="966352185" label="PrivacyAdvisor:disabled"/> <int value="966415988" label="SyncPseudoUSSPasswords:enabled"/> + <int value="966626581" label="NewInstanceFromDraggedLink:disabled"/> <int value="966958557" label="CryptAuthV2DedupDeviceLastActivityTime:enabled"/> <int value="967706865" label="ForceEnablePasswordDomainCapabilities:enabled"/>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml index 257e04a7..2f142d5 100644 --- a/tools/metrics/histograms/metadata/power/histograms.xml +++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -134,19 +134,19 @@ but there was in the last 2 minutes"/> </variants> -<histogram name="PerformanceMonitor.AverageCPU4.Total{UsageScenario}" +<histogram name="PerformanceMonitor.AverageCPU5.Total{UsageScenario}" units="1/100 %" expires_after="2022-11-30"> <owner>fdoray@chromium.org</owner> <owner>pmonette@chromium.org</owner> <owner>catan-team@chromium.org</owner> <summary> - See definition of PerformanceClass.AverageCPU4.ProcessName. This is recorded + See definition of PerformanceClass.AverageCPU5.ProcessName. This is recorded for {UsageScenario} (see go/chrome_power_use_per_scenario). </summary> <token key="UsageScenario" variants="UsageScenario"/> </histogram> -<histogram name="PerformanceMonitor.AverageCPU4.{ProcessName}" units="1/100 %" +<histogram name="PerformanceMonitor.AverageCPU5.{ProcessName}" units="1/100 %" expires_after="2022-11-30"> <owner>fdoray@chromium.org</owner> <owner>pmonette@chromium.org</owner> @@ -166,6 +166,9 @@ we know that short-lived processes are very common (see Renderer.ProcessLifetime). A future version of this metric will address this limitation. + + ANOTHER NOTE: On Windows, this is not recorded on CPUs that do not support + constant rate TSC. </summary> <token key="ProcessName" variants="ProcessName"/> </histogram> @@ -203,6 +206,19 @@ <token key="ProcessName" variants="ProcessName"/> </histogram> +<histogram name="PerformanceMonitor.HasPreciseCPUUsage" enum="Boolean" + expires_after="2022-09-30"> + <owner>pmonette@chromium.org</owner> + <owner>catan-team@chromium.org</owner> + <summary> + Records whether or not the CPU supports constant rate TSC, which allows a + more precise calculation of the CPU usage of a process. Recorded during + startup when the ProcessMonitor is instantiated. + + Only Recorded on Windows. + </summary> +</histogram> + <histogram name="PerformanceMonitor.IdleWakeups2.Total{UsageScenario}" units="WakeupsPerSecond" expires_after="2022-11-30"> <owner>olivierli@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index acc0926..af9c16b 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -13057,7 +13057,8 @@ </event> <event name="PageLoad" singular="True"> - <owner>bmcquade@chromium.org</owner> + <owner>sullivan@chromium.org</owner> + <owner>chrome-metrics-team@google.com</owner> <summary> Core metrics associated with web page loads. </summary> @@ -14701,7 +14702,7 @@ </event> <event name="PageLoad.FromGoogleSearch" singular="True"> - <owner>bmcquade@chromium.org</owner> + <owner>sullivan@chromium.org</owner> <owner>mushan@chromium.org</owner> <summary> Recorded for page loads that were navigated to via Google Search. @@ -18487,7 +18488,6 @@ </event> <event name="SubresourceFilter" singular="True"> - <owner>bmcquade@chromium.org</owner> <owner>csharrison@chromium.org</owner> <summary> Recorded for page loads where subresource filtering policy was evaluated.
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index bd17757..c066a60 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,16 +5,16 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "80e7be4b409112767087a1c92fd17d95537e561b", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/8ad5ba6c8bd3d01daecd0df5c4cf33d70f5f7710/trace_processor_shell.exe" + "hash": "929c4fd292208274ef28469051c43c60ab7006da", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/7479a87c2032ebc3504fb6bedbb688827a66bb4a/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "f6d69cc6cddb6a1ddfa0cc0fae2b98b6adb38677", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/2e22f4e894ed9800027ff05dc0c7fe2217b033d6/trace_processor_shell" + "hash": "a91d33c8f0282a876c3481bbb24bc2463f7d4a97", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/31772328c517b725c81994e4b9b99aac18319e40/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", @@ -22,7 +22,7 @@ }, "linux": { "hash": "2ae07fc516b89c8ac44f70798f402c8f3e80bca4", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/8ad5ba6c8bd3d01daecd0df5c4cf33d70f5f7710/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/7479a87c2032ebc3504fb6bedbb688827a66bb4a/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h index 457757a..3029706 100644 --- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h +++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -8,11 +8,12 @@ #include <IOSurface/IOSurface.h> #include <QuartzCore/QuartzCore.h> +#include <list> #include <memory> -#include <vector> #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h" #include "ui/gfx/geometry/rect.h" @@ -84,8 +85,9 @@ class RootLayer { public: - RootLayer(); + RootLayer(CARendererLayerTree* tree); + RootLayer(RootLayer&&) = delete; RootLayer(const RootLayer&) = delete; RootLayer& operator=(const RootLayer&) = delete; @@ -109,25 +111,28 @@ // to nil, so that its destructor will not remove an active CALayer. void CommitToCA(CALayer* superlayer, RootLayer* old_layer, - const gfx::Size& pixel_size, - float scale_factor); + const gfx::Size& pixel_size); // Return true if the CALayer tree is just a video layer on a black or // transparent background, false otherwise. bool WantsFullcreenLowPowerBackdrop() const; - std::vector<ClipAndSortingLayer> clip_and_sorting_layers_; + // Tree that owns `this`. + const raw_ptr<CARendererLayerTree> tree_; + + std::list<ClipAndSortingLayer> clip_and_sorting_layers_; base::scoped_nsobject<CALayer> ca_layer_; }; class ClipAndSortingLayer { public: - ClipAndSortingLayer(bool is_clipped, + ClipAndSortingLayer(RootLayer* root_layer, + bool is_clipped, gfx::Rect clip_rect, gfx::RRectF rounded_corner_bounds, unsigned sorting_context_id, bool is_singleton_sorting_context); - ClipAndSortingLayer(ClipAndSortingLayer&& layer); + ClipAndSortingLayer(ClipAndSortingLayer&& layer) = delete; ClipAndSortingLayer(const ClipAndSortingLayer&) = delete; ClipAndSortingLayer& operator=(const ClipAndSortingLayer&) = delete; @@ -136,11 +141,13 @@ ~ClipAndSortingLayer(); void AddContentLayer(CARendererLayerTree* tree, const CARendererLayerParams& params); - void CommitToCA(CALayer* superlayer, - ClipAndSortingLayer* old_layer, - float scale_factor); + void CommitToCA(ClipAndSortingLayer* old_layer); + CARendererLayerTree* tree() { return parent_layer_->tree_; } - std::vector<TransformLayer> transform_layers_; + // Parent layer that owns `this`, and child layers that `this` owns. + const raw_ptr<RootLayer> parent_layer_; + std::list<TransformLayer> transform_layers_; + bool is_clipped_ = false; gfx::Rect clip_rect_; gfx::RRectF rounded_corner_bounds_; @@ -151,9 +158,10 @@ }; class TransformLayer { public: - TransformLayer(const gfx::Transform& transform); - TransformLayer(TransformLayer&& layer); + TransformLayer(ClipAndSortingLayer* parent_layer, + const gfx::Transform& transform); + TransformLayer(TransformLayer&& layer) = delete; TransformLayer(const TransformLayer&) = delete; TransformLayer& operator=(const TransformLayer&) = delete; @@ -162,17 +170,19 @@ ~TransformLayer(); void AddContentLayer(CARendererLayerTree* tree, const CARendererLayerParams& params); - void CommitToCA(CALayer* superlayer, - TransformLayer* old_layer, - float scale_factor); + void CommitToCA(TransformLayer* old_layer); + CARendererLayerTree* tree() { return parent_layer_->tree(); } + + // Parent layer that owns `this`, and child layers that `this` owns. + const raw_ptr<ClipAndSortingLayer> parent_layer_; + std::list<ContentLayer> content_layers_; gfx::Transform transform_; - std::vector<ContentLayer> content_layers_; base::scoped_nsobject<CALayer> ca_layer_; }; class ContentLayer { public: - ContentLayer(CARendererLayerTree* tree, + ContentLayer(TransformLayer* parent_layer, base::ScopedCFTypeRef<IOSurfaceRef> io_surface, base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer, const gfx::RectF& contents_rect, @@ -183,17 +193,19 @@ float opacity, unsigned filter, gfx::ProtectedVideoType protected_video_type); - ContentLayer(ContentLayer&& layer); + ContentLayer(ContentLayer&& layer) = delete; ContentLayer(const ContentLayer&) = delete; ContentLayer& operator=(const ContentLayer&) = delete; // See the behavior of RootLayer for the effects of these functions on the // |ca_layer| member and |old_layer| argument. ~ContentLayer(); - void CommitToCA(CALayer* parent, - ContentLayer* old_layer, - float scale_factor); + void CommitToCA(ContentLayer* old_layer); + CARendererLayerTree* tree() { return parent_layer_->tree(); } + + // Parent layer that owns `this`. + const raw_ptr<TransformLayer> parent_layer_; // Ensure that the IOSurface be marked as in-use as soon as it is received. // When they are committed to the window server, that will also increment @@ -234,7 +246,7 @@ base::scoped_nsobject<CALayer> update_indicator_layer_; }; - RootLayer root_layer_; + RootLayer root_layer_{this}; float scale_factor_ = 1; bool has_committed_ = false; const bool allow_av_sample_buffer_display_layer_ = true;
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm index 523f6bd8..21c075a 100644 --- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm +++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -278,13 +278,13 @@ if (old_tree->scale_factor_ == scale_factor) old_root_layer = &old_tree->root_layer_; } + scale_factor_ = scale_factor; - root_layer_.CommitToCA(superlayer, old_root_layer, pixel_size, scale_factor); + root_layer_.CommitToCA(superlayer, old_root_layer, pixel_size); // If there are any extra CALayers in |old_tree| that were not stolen by this // tree, they will be removed from the CALayer tree in this deallocation. old_tree.reset(); has_committed_ = true; - scale_factor_ = scale_factor; } bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() const { @@ -345,25 +345,26 @@ return nullptr; } const ClipAndSortingLayer& clip_and_sorting = - root_layer_.clip_and_sorting_layers_[0]; + root_layer_.clip_and_sorting_layers_.front(); size_t transform_count = clip_and_sorting.transform_layers_.size(); if (transform_count != 1) { DLOG(ERROR) << "Can only return contents IOSurface when there is 1 " << "TransformLayer, there are " << transform_count << "."; return nullptr; } - const TransformLayer& transform = clip_and_sorting.transform_layers_[0]; + const TransformLayer& transform = clip_and_sorting.transform_layers_.front(); size_t content_count = transform.content_layers_.size(); if (content_count != 1) { DLOG(ERROR) << "Can only return contents IOSurface when there is 1 " << "ContentLayer, there are " << transform_count << "."; return nullptr; } - const ContentLayer& content = transform.content_layers_[0]; + const ContentLayer& content = transform.content_layers_.front(); return content.io_surface_.get(); } -CARendererLayerTree::RootLayer::RootLayer() {} +CARendererLayerTree::RootLayer::RootLayer(CARendererLayerTree* tree) + : tree_(tree) {} // Note that for all destructors, the the CALayer will have been reset to nil if // another layer has taken it. @@ -372,57 +373,35 @@ } CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer( + RootLayer* parent_layer, bool is_clipped, gfx::Rect clip_rect, gfx::RRectF rounded_corner_bounds_arg, unsigned sorting_context_id, bool is_singleton_sorting_context) - : is_clipped_(is_clipped), + : parent_layer_(parent_layer), + is_clipped_(is_clipped), clip_rect_(clip_rect), rounded_corner_bounds_(rounded_corner_bounds_arg), sorting_context_id_(sorting_context_id), is_singleton_sorting_context_(is_singleton_sorting_context) {} -CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer( - ClipAndSortingLayer&& layer) - : transform_layers_(std::move(layer.transform_layers_)), - is_clipped_(layer.is_clipped_), - clip_rect_(layer.clip_rect_), - rounded_corner_bounds_(layer.rounded_corner_bounds_), - sorting_context_id_(layer.sorting_context_id_), - is_singleton_sorting_context_(layer.is_singleton_sorting_context_), - clipping_ca_layer_(layer.clipping_ca_layer_), - rounded_corner_ca_layer_(layer.rounded_corner_ca_layer_) { - // Ensure that the ca_layer be reset, so that when the destructor is called, - // the layer hierarchy is unaffected. - // TODO(ccameron): Add a move constructor for scoped_nsobject to do this - // automatically. - layer.clipping_ca_layer_.reset(); - layer.rounded_corner_ca_layer_.reset(); -} - CARendererLayerTree::ClipAndSortingLayer::~ClipAndSortingLayer() { [clipping_ca_layer_ removeFromSuperlayer]; [rounded_corner_ca_layer_ removeFromSuperlayer]; } CARendererLayerTree::TransformLayer::TransformLayer( + ClipAndSortingLayer* parent_layer, const gfx::Transform& transform) - : transform_(transform) {} - -CARendererLayerTree::TransformLayer::TransformLayer(TransformLayer&& layer) - : transform_(layer.transform_), - content_layers_(std::move(layer.content_layers_)), - ca_layer_(layer.ca_layer_) { - layer.ca_layer_.reset(); -} + : parent_layer_(parent_layer), transform_(transform) {} CARendererLayerTree::TransformLayer::~TransformLayer() { [ca_layer_ removeFromSuperlayer]; } CARendererLayerTree::ContentLayer::ContentLayer( - CARendererLayerTree* tree, + TransformLayer* parent_layer, base::ScopedCFTypeRef<IOSurfaceRef> io_surface, base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer, const gfx::RectF& contents_rect, @@ -433,7 +412,8 @@ float opacity, unsigned filter, gfx::ProtectedVideoType protected_video_type) - : io_surface_(io_surface), + : parent_layer_(parent_layer), + io_surface_(io_surface), cv_pixel_buffer_(cv_pixel_buffer), contents_rect_(contents_rect), rect_(rect), @@ -453,7 +433,7 @@ // transparent layers must use real colors to be eligible for low power // detachment in fullscreen. // https://crbug.com/633805 - if (!io_surface && !tree->allow_solid_color_layers_ && + if (!io_surface && !tree()->allow_solid_color_layers_ && background_color_ != SK_ColorBLACK && background_color_ != SK_ColorTRANSPARENT) { solid_color_contents_ = SolidColorContents::Get(background_color); @@ -490,7 +470,7 @@ } else if (io_surface) { // Only allow 4:2:0 frames which fill the layer's contents or protected // video to be promoted to AV layers. - if (tree->allow_av_sample_buffer_display_layer_) { + if (tree()->allow_av_sample_buffer_display_layer_) { if (contents_rect == gfx::RectF(0, 0, 1, 1)) { switch (IOSurfaceGetPixelFormat(io_surface)) { case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: @@ -544,28 +524,6 @@ } } -CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer) - : io_surface_(layer.io_surface_), - cv_pixel_buffer_(layer.cv_pixel_buffer_), - solid_color_contents_(layer.solid_color_contents_), - contents_rect_(layer.contents_rect_), - rect_(layer.rect_), - background_color_(layer.background_color_), - io_surface_color_space_(layer.io_surface_color_space_), - ca_edge_aa_mask_(layer.ca_edge_aa_mask_), - opacity_(layer.opacity_), - ca_filter_(layer.ca_filter_), - type_(layer.type_), - video_type_can_downgrade_(layer.video_type_can_downgrade_), - protected_video_type_(layer.protected_video_type_), - ca_layer_(std::move(layer.ca_layer_)), - av_layer_(std::move(layer.av_layer_)), - update_indicator_layer_(std::move(layer.update_indicator_layer_)) { - DCHECK(!layer.ca_layer_); - DCHECK(!layer.av_layer_); - DCHECK(!update_indicator_layer_); -} - CARendererLayerTree::ContentLayer::~ContentLayer() { [ca_layer_ removeFromSuperlayer]; [update_indicator_layer_ removeFromSuperlayer]; @@ -606,9 +564,9 @@ } } if (needs_new_clip_and_sorting_layer) { - clip_and_sorting_layers_.push_back(ClipAndSortingLayer( - params.is_clipped, params.clip_rect, params.rounded_corner_bounds, - params.sorting_context_id, is_singleton_sorting_context)); + clip_and_sorting_layers_.emplace_back( + this, params.is_clipped, params.clip_rect, params.rounded_corner_bounds, + params.sorting_context_id, is_singleton_sorting_context); } clip_and_sorting_layers_.back().AddContentLayer(tree, params); return true; @@ -624,7 +582,7 @@ needs_new_transform_layer = false; } if (needs_new_transform_layer) - transform_layers_.push_back(TransformLayer(params.transform)); + transform_layers_.emplace_back(this, params.transform); transform_layers_.back().AddContentLayer(tree, params); } @@ -649,16 +607,15 @@ // cv_pixel_buffer = io_surface_image->cv_pixel_buffer(); io_surface_color_space = params.image->color_space(); } - content_layers_.push_back(ContentLayer( - tree, io_surface, cv_pixel_buffer, params.contents_rect, params.rect, + content_layers_.emplace_back( + this, io_surface, cv_pixel_buffer, params.contents_rect, params.rect, params.background_color, io_surface_color_space, params.edge_aa_mask, - params.opacity, params.filter, params.protected_video_type)); + params.opacity, params.filter, params.protected_video_type); } void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer, RootLayer* old_layer, - const gfx::Size& pixel_size, - float scale_factor) { + const gfx::Size& pixel_size) { if (old_layer) { DCHECK(old_layer->ca_layer_); std::swap(ca_layer_, old_layer->ca_layer_); @@ -677,7 +634,7 @@ // In fullscreen low power mode there exists a single video layer on a // solid black background. const gfx::RectF bg_rect( - ScaleSize(gfx::SizeF(pixel_size), 1 / scale_factor)); + ScaleSize(gfx::SizeF(pixel_size), 1 / tree_->scale_factor_)); if (gfx::RectF([ca_layer_ frame]) != bg_rect) [ca_layer_ setFrame:bg_rect.ToCGRect()]; if (![ca_layer_ backgroundColor]) @@ -699,20 +656,28 @@ DowngradeAVLayersToCALayers(); } - for (size_t i = 0; i < clip_and_sorting_layers_.size(); ++i) { - ClipAndSortingLayer* old_clip_and_sorting_layer = nullptr; - if (old_layer && i < old_layer->clip_and_sorting_layers_.size()) { - old_clip_and_sorting_layer = &old_layer->clip_and_sorting_layers_[i]; + auto children_it = clip_and_sorting_layers_.begin(); + auto old_layer_children_it = old_layer + ? old_layer->clip_and_sorting_layers_.begin() + : std::list<ClipAndSortingLayer>::iterator(); + while (children_it != clip_and_sorting_layers_.end()) { + auto& child_layer = *children_it; + children_it++; + + ClipAndSortingLayer* old_child_layer = nullptr; + if (old_layer && + old_layer_children_it != old_layer->clip_and_sorting_layers_.end()) { + old_child_layer = &(*old_layer_children_it); + old_layer_children_it++; } - clip_and_sorting_layers_[i].CommitToCA( - ca_layer_.get(), old_clip_and_sorting_layer, scale_factor); + + child_layer.CommitToCA(old_child_layer); } } void CARendererLayerTree::ClipAndSortingLayer::CommitToCA( - CALayer* superlayer, - ClipAndSortingLayer* old_layer, - float scale_factor) { + ClipAndSortingLayer* old_layer) { + CALayer* superlayer = parent_layer_->ca_layer_.get(); bool update_is_clipped = true; bool update_clip_rect = true; if (old_layer) { @@ -736,7 +701,7 @@ old_layer->rounded_corner_bounds_ != rounded_corner_bounds_) { gfx::RectF dip_rounded_corner_bounds = gfx::RectF(rounded_corner_bounds_.rect()); - dip_rounded_corner_bounds.Scale(1 / scale_factor); + dip_rounded_corner_bounds.Scale(1 / tree()->scale_factor_); [rounded_corner_ca_layer_ setMasksToBounds:true]; @@ -753,7 +718,7 @@ [rounded_corner_ca_layer_ setCornerRadius:rounded_corner_bounds_.GetSimpleRadius() / - scale_factor]; + tree()->scale_factor_]; } } else { [rounded_corner_ca_layer_ setMasksToBounds:false]; @@ -772,7 +737,7 @@ if (update_clip_rect) { if (is_clipped_) { gfx::RectF dip_clip_rect = gfx::RectF(clip_rect_); - dip_clip_rect.Scale(1 / scale_factor); + dip_clip_rect.Scale(1 / tree()->scale_factor_); [clipping_ca_layer_ setPosition:CGPointMake(dip_clip_rect.x(), dip_clip_rect.y())]; [clipping_ca_layer_ setBounds:CGRectMake(0, 0, dip_clip_rect.width(), @@ -787,18 +752,28 @@ } } - for (size_t i = 0; i < transform_layers_.size(); ++i) { - TransformLayer* old_transform_layer = nullptr; - if (old_layer && i < old_layer->transform_layers_.size()) - old_transform_layer = &old_layer->transform_layers_[i]; - transform_layers_[i].CommitToCA(rounded_corner_ca_layer_, - old_transform_layer, scale_factor); + auto children_it = transform_layers_.begin(); + auto old_layer_children_it = old_layer + ? old_layer->transform_layers_.begin() + : std::list<TransformLayer>::iterator(); + while (children_it != transform_layers_.end()) { + auto& child_layer = *children_it; + children_it++; + + TransformLayer* old_child_layer = nullptr; + if (old_layer && + old_layer_children_it != old_layer->transform_layers_.end()) { + old_child_layer = &(*old_layer_children_it); + old_layer_children_it++; + } + + child_layer.CommitToCA(old_child_layer); } } -void CARendererLayerTree::TransformLayer::CommitToCA(CALayer* superlayer, - TransformLayer* old_layer, - float scale_factor) { +void CARendererLayerTree::TransformLayer::CommitToCA( + TransformLayer* old_layer) { + CALayer* superlayer = parent_layer_->rounded_corner_ca_layer_.get(); bool update_transform = true; if (old_layer) { DCHECK(old_layer->ca_layer_); @@ -813,8 +788,8 @@ if (update_transform) { gfx::Transform pre_scale; gfx::Transform post_scale; - pre_scale.Scale(1 / scale_factor, 1 / scale_factor); - post_scale.Scale(scale_factor, scale_factor); + pre_scale.Scale(1 / tree()->scale_factor_, 1 / tree()->scale_factor_); + post_scale.Scale(tree()->scale_factor_, tree()->scale_factor_); gfx::Transform conjugated_transform = pre_scale * transform_ * post_scale; CATransform3D ca_transform = @@ -822,18 +797,26 @@ [ca_layer_ setTransform:ca_transform]; } - for (size_t i = 0; i < content_layers_.size(); ++i) { - ContentLayer* old_content_layer = nullptr; - if (old_layer && i < old_layer->content_layers_.size()) - old_content_layer = &old_layer->content_layers_[i]; - content_layers_[i].CommitToCA(ca_layer_.get(), old_content_layer, - scale_factor); + auto children_it = content_layers_.begin(); + auto old_layer_children_it = old_layer ? old_layer->content_layers_.begin() + : std::list<ContentLayer>::iterator(); + while (children_it != content_layers_.end()) { + ContentLayer& child_layer = *children_it; + children_it++; + + ContentLayer* old_child_layer = nullptr; + if (old_layer && + old_layer_children_it != old_layer->content_layers_.end()) { + old_child_layer = &(*old_layer_children_it); + old_layer_children_it++; + } + + child_layer.CommitToCA(old_child_layer); } } -void CARendererLayerTree::ContentLayer::CommitToCA(CALayer* superlayer, - ContentLayer* old_layer, - float scale_factor) { +void CARendererLayerTree::ContentLayer::CommitToCA(ContentLayer* old_layer) { + CALayer* superlayer = parent_layer_->ca_layer_.get(); bool update_contents = true; bool update_contents_rect = true; bool update_rect = true; @@ -924,7 +907,7 @@ [ca_layer_ setContents:nil]; } if ([ca_layer_ respondsToSelector:(@selector(setContentsScale:))]) - [ca_layer_ setContentsScale:scale_factor]; + [ca_layer_ setContentsScale:tree()->scale_factor_]; } break; } @@ -935,7 +918,7 @@ } if (update_rect) { gfx::RectF dip_rect = gfx::RectF(rect_); - dip_rect.Scale(1 / scale_factor); + dip_rect.Scale(1 / tree()->scale_factor_); [ca_layer_ setPosition:CGPointMake(dip_rect.x(), dip_rect.y())]; [ca_layer_ setBounds:CGRectMake(0, 0, dip_rect.width(), dip_rect.height())]; }
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java index a53e79ee1..c8cc0a4 100644 --- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java +++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java
@@ -4,6 +4,7 @@ package org.chromium.ui.dragdrop; +import android.content.Intent; import android.view.DragAndDropPermissions; import android.view.DragEvent; @@ -16,4 +17,7 @@ /** Request DragAndDropPermissions. */ DragAndDropPermissions getDragAndDropPermissions(DragEvent dropEvent); + + /** Create an intent from a dragged text link. */ + Intent createLinkIntent(String urlString); }
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java index 762c981..0315ca0e 100644 --- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java +++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java
@@ -8,7 +8,7 @@ import android.view.View; /** - * Delegate to perform drag and drop operations, for example re-routing the call to {@link + * Delegate to facilitate Drag and Drop operations, for example re-routing the call to {@link * #startDragAndDrop(Bitmap, DropDataAndroid).} */ public interface DragAndDropDelegate { @@ -16,7 +16,8 @@ boolean startDragAndDrop(View containerView, Bitmap shadowImage, DropDataAndroid dropData); /** - * Set the {@link DragAndDropBrowserDelegate} that will be used to get DragAndDropPermissions. + * Set the {@link DragAndDropBrowserDelegate} that will be used to facilitate browser related + * tasks required for Drag and Drop. * @param delegate The {@link DragAndDropBrowserDelegate} that will be used by this class. */ default void setDragAndDropBrowserDelegate(DragAndDropBrowserDelegate delegate) {}
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java index a787c31..83972dab 100644 --- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java +++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
@@ -6,7 +6,9 @@ import android.content.ClipData; import android.content.ClipData.Item; +import android.content.ClipDescription; import android.content.Context; +import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; @@ -72,7 +74,6 @@ private int mShadowWidth; private int mShadowHeight; private boolean mIsDragStarted; - private boolean mDropInChrome; /** Whether the current drop has happened on top of the view this object tracks. */ private boolean mIsDropOnView; @@ -202,6 +203,16 @@ } return clipData; case DragTargetType.LINK: + if (mDragAndDropBrowserDelegate != null) { + Intent intent = + mDragAndDropBrowserDelegate.createLinkIntent(dropData.gurl.getSpec()); + if (intent != null) { + return new ClipData(null, + new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN, + ClipDescription.MIMETYPE_TEXT_INTENT}, + new Item(getTextForLinkData(dropData), intent, null)); + } + } return ClipData.newPlainText(null, getTextForLinkData(dropData)); case DragTargetType.INVALID: return null;
diff --git a/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java b/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java index cfadb6d..d22c0de 100644 --- a/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java +++ b/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
@@ -7,11 +7,14 @@ import static org.mockito.Mockito.doReturn; import android.content.ClipData; +import android.content.ClipDescription; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.VectorDrawable; import android.os.Build.VERSION_CODES; import android.util.Pair; +import android.view.DragAndDropPermissions; import android.view.DragEvent; import android.view.View; import android.view.View.DragShadowBuilder; @@ -339,6 +342,37 @@ clipData.getItemAt(1).getText()); } + @Test + public void testClipData_TextLink() { + final DropDataAndroid dropData = DropDataAndroid.create( + "", JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL), null, null, null); + mDragAndDropDelegateImpl.setDragAndDropBrowserDelegate(new DragAndDropBrowserDelegate() { + @Override + public boolean getSupportDropInChrome() { + return false; + } + + @Override + public DragAndDropPermissions getDragAndDropPermissions(DragEvent dropEvent) { + return null; + } + + @Override + public Intent createLinkIntent(String urlString) { + return new Intent(); + } + }); + ClipData clipData = mDragAndDropDelegateImpl.buildClipData(dropData); + Assert.assertTrue("Link ClipData should include plaintext MIME type.", + clipData.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)); + Assert.assertTrue("Link ClipData should include intent MIME type.", + clipData.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT)); + Assert.assertEquals("Dragged link text should match.", JUnitTestGURLs.EXAMPLE_URL, + clipData.getItemAt(0).getText()); + Assert.assertNotNull( + "ClipData intent should not be null.", clipData.getItemAt(0).getIntent()); + } + private void doTestResizeShadowImage( String testcase, int width, int height, int expectedWidth, int expectedHeight) { Pair<Integer, Integer> widthHeight =
diff --git a/ui/display/fake/fake_display_delegate.h b/ui/display/fake/fake_display_delegate.h index f04def70..d1e6998b 100644 --- a/ui/display/fake/fake_display_delegate.h +++ b/ui/display/fake/fake_display_delegate.h
@@ -31,14 +31,14 @@ // native_mode[#other_modes][^dpi][/options] // // native_mode: the native display mode, with format: -// HxW[%R] -// H: display height in pixels [int] +// WxH[%R] // W: display width in pixels [int] +// H: display height in pixels [int] // R: display refresh rate [float] // // other_modes: list of other of display modes, with format: -// #HxW[%R][:HxW[%R]] -// H,W,R: same meaning as in native_mode. +// #WxH[%R][:WxH[%R]] +// W,H,R: same meaning as in native_mode. // Note: The first mode is delimited with '#' and any subsequent modes are // delimited with ':'. //
diff --git a/ui/qt/qt_interface.h b/ui/qt/qt_interface.h index 5115ed6..df4f1d546 100644 --- a/ui/qt/qt_interface.h +++ b/ui/qt/qt_interface.h
@@ -59,9 +59,27 @@ kFull, }; -enum class ColorRole { +enum class ColorType { kWindowBg, kWindowFg, + kHighlightBg, + kHighlightFg, + kEntryBg, + kEntryFg, + kButtonBg, + kButtonFg, + + kLight, + kMidlight, + kDark, + kMidground, + kShadow, +}; + +enum class ColorState { + kNormal, + kDisabled, + kInactive, }; struct FontRenderParams { @@ -105,7 +123,7 @@ virtual FontDescription GetFontDescription() const = 0; virtual Image GetIconForContentType(const String& content_type, int size) const = 0; - virtual SkColor GetColor(ColorRole role) const = 0; + virtual SkColor GetColor(ColorType role, ColorState state) const = 0; }; } // namespace qt
diff --git a/ui/qt/qt_shim.cc b/ui/qt/qt_shim.cc index abe4ba4..0cb5e4f6 100644 --- a/ui/qt/qt_shim.cc +++ b/ui/qt/qt_shim.cc
@@ -146,6 +146,48 @@ } } +QPalette::ColorRole ColorTypeToColorRole(ColorType type) { + switch (type) { + case ColorType::kWindowBg: + return QPalette::Window; + case ColorType::kWindowFg: + return QPalette::WindowText; + case ColorType::kHighlightBg: + return QPalette::Highlight; + case ColorType::kHighlightFg: + return QPalette::HighlightedText; + case ColorType::kEntryBg: + return QPalette::Base; + case ColorType::kEntryFg: + return QPalette::Text; + case ColorType::kButtonBg: + return QPalette::Button; + case ColorType::kButtonFg: + return QPalette::ButtonText; + case ColorType::kLight: + return QPalette::Light; + case ColorType::kMidlight: + return QPalette::Midlight; + case ColorType::kMidground: + return QPalette::Mid; + case ColorType::kDark: + return QPalette::Dark; + case ColorType::kShadow: + return QPalette::Shadow; + } +} + +QPalette::ColorGroup ColorStateToColorGroup(ColorState state) { + switch (state) { + case ColorState::kNormal: + return QPalette::Normal; + case ColorState::kDisabled: + return QPalette::Disabled; + case ColorState::kInactive: + return QPalette::Inactive; + } +} + } // namespace QtShim::QtShim(QtInterface::Delegate* delegate, int* argc, char** argv) @@ -202,14 +244,9 @@ return {}; } -SkColor QtShim::GetColor(ColorRole role) const { - auto palette = app_.palette(); - switch (role) { - case ColorRole::kWindowBg: - return BrushColor(palette.brush(QPalette::ColorRole::Window)); - case ColorRole::kWindowFg: - return BrushColor(palette.brush(QPalette::ColorRole::WindowText)); - } +SkColor QtShim::GetColor(ColorType role, ColorState state) const { + return BrushColor(app_.palette().brush(ColorStateToColorGroup(state), + ColorTypeToColorRole(role))); } void QtShim::FontChanged(const QFont& font) {
diff --git a/ui/qt/qt_shim.h b/ui/qt/qt_shim.h index ef680d22..8b707b81 100644 --- a/ui/qt/qt_shim.h +++ b/ui/qt/qt_shim.h
@@ -28,7 +28,7 @@ FontDescription GetFontDescription() const override; Image GetIconForContentType(const String& content_type, int size) const override; - SkColor GetColor(ColorRole role) const override; + SkColor GetColor(ColorType role, ColorState state) const override; private slots: void FontChanged(const QFont& font);
diff --git a/ui/qt/qt_ui.cc b/ui/qt/qt_ui.cc index f751d0a..35bc486 100644 --- a/ui/qt/qt_ui.cc +++ b/ui/qt/qt_ui.cc
@@ -333,23 +333,48 @@ // These color constants are required by native_chrome_color_mixer_linux.cc struct { ui::ColorId id; - SkColor color; + ColorType role; + ColorState state = ColorState::kNormal; } const kMaps[] = { - {ui::kColorNativeButtonBorder, gfx::kPlaceholderColor}, - {ui::kColorNativeHeaderButtonBorderActive, gfx::kPlaceholderColor}, - {ui::kColorNativeHeaderButtonBorderInactive, gfx::kPlaceholderColor}, - {ui::kColorNativeHeaderSeparatorBorderActive, gfx::kPlaceholderColor}, - {ui::kColorNativeHeaderSeparatorBorderInactive, gfx::kPlaceholderColor}, - {ui::kColorNativeLabelForeground, shim_->GetColor(ColorRole::kWindowFg)}, - {ui::kColorNativeTabForegroundInactiveFrameActive, - gfx::kPlaceholderColor}, - {ui::kColorNativeTabForegroundInactiveFrameInactive, - gfx::kPlaceholderColor}, - {ui::kColorNativeTextfieldBorderUnfocused, gfx::kPlaceholderColor}, - {ui::kColorNativeToolbarBackground, gfx::kPlaceholderColor}, + // Core colors + {ui::kColorAccent, ColorType::kHighlightBg}, + {ui::kColorDisabledForeground, ColorType::kWindowFg, + ColorState::kDisabled}, + {ui::kColorEndpointBackground, ColorType::kEntryBg}, + {ui::kColorEndpointForeground, ColorType::kEntryFg}, + {ui::kColorItemHighlight, ColorType::kHighlightBg}, + {ui::kColorItemSelectionBackground, ColorType::kHighlightBg}, + {ui::kColorMenuSelectionBackground, ColorType::kHighlightBg}, + {ui::kColorMidground, ColorType::kMidground}, + {ui::kColorPrimaryBackground, ColorType::kWindowBg}, + {ui::kColorPrimaryForeground, ColorType::kWindowFg}, + {ui::kColorSecondaryForeground, ColorType::kWindowFg, + ColorState::kDisabled}, + {ui::kColorSubtleAccent, ColorType::kHighlightBg, ColorState::kInactive}, + {ui::kColorSubtleEmphasisBackground, ColorType::kWindowBg}, + {ui::kColorTextSelectionBackground, ColorType::kHighlightBg}, + {ui::kColorTextSelectionForeground, ColorType::kHighlightFg}, + + // Platform-specific UI elements + {ui::kColorNativeButtonBorder, + // For flat-styled buttons, QT uses the text color as the button border. + ColorType::kWindowFg}, + {ui::kColorNativeHeaderButtonBorderActive, ColorType::kWindowFg}, + {ui::kColorNativeHeaderButtonBorderInactive, ColorType::kWindowFg, + ColorState::kInactive}, + {ui::kColorNativeHeaderSeparatorBorderActive, ColorType::kWindowFg}, + {ui::kColorNativeHeaderSeparatorBorderInactive, ColorType::kWindowFg, + ColorState::kInactive}, + {ui::kColorNativeLabelForeground, ColorType::kWindowFg}, + {ui::kColorNativeTabForegroundInactiveFrameActive, ColorType::kButtonFg}, + {ui::kColorNativeTabForegroundInactiveFrameInactive, ColorType::kButtonFg, + ColorState::kInactive}, + {ui::kColorNativeTextfieldBorderUnfocused, ColorType::kWindowFg, + ColorState::kInactive}, + {ui::kColorNativeToolbarBackground, ColorType::kButtonBg}, }; for (const auto& map : kMaps) - mixer[map.id] = {map.color}; + mixer[map.id] = {shim_->GetColor(map.role, map.state)}; } std::unique_ptr<views::LinuxUI> CreateQtUi() {
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index b91e6b0b..8c979f96 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -14,7 +14,7 @@ grd_prefix = "webui_generated" out_grd = "$target_gen_dir/${grd_prefix}_resources.grd" - deps = [ + public_deps = [ ":build_ts_grdp", "cr_components/color_change_listener:build_grdp", "css:build_grdp", @@ -50,7 +50,7 @@ } if (include_polymer) { - deps += [ + public_deps += [ "cr_components:build_grdp", "cr_components/app_management:build_grdp", "cr_components/customize_themes:build_grdp", @@ -70,27 +70,27 @@ ] if (use_nss_certs) { - deps += [ "cr_components/certificate_manager:build_grdp" ] + public_deps += [ "cr_components/certificate_manager:build_grdp" ] grdp_files += [ "$target_gen_dir/cr_components/certificate_manager/resources.grdp" ] } # TODO(crbug.com/1184053): Fully remove once no longer used by CrOS. if (is_chromeos_ash) { - deps += [ "//third_party/polymer/v1_0:build_grdp" ] + public_deps += [ "//third_party/polymer/v1_0:build_grdp" ] grdp_files += [ "$root_gen_dir/third_party/polymer/v1_0/polymer_1_0_resources.grdp", ] } if (!is_android) { - deps += [ "cr_components/history_clusters:build_grdp" ] + public_deps += [ "cr_components/history_clusters:build_grdp" ] grdp_files += [ "$root_gen_dir/ui/webui/resources/cr_components/history_clusters/resources.grdp" ] } } if (is_chromeos_ash) { - deps += [ + public_deps += [ ":build_cros_styles_grdp", "//ash/webui/common/resources:build_grdp", "//chromeos/ash/components/cros_elements:build_grdp", @@ -107,7 +107,7 @@ } if (!is_android && !is_ios) { - deps += [ "//third_party/lottie:build_grdp" ] + public_deps += [ "//third_party/lottie:build_grdp" ] grdp_files += [ "$root_gen_dir/third_party/lottie/resources.grdp" ] } } @@ -116,7 +116,7 @@ generate_grd("build_cros_styles_grdp") { grd_prefix = "webui" out_grd = "$target_gen_dir/cros_styles_resources.grdp" - deps = [ "//ui/chromeos/styles:cros_styles_css" ] + public_deps = [ "//ui/chromeos/styles:cros_styles_css" ] input_files_base_dir = rebase_path("$root_gen_dir/", root_build_dir) input_files = [ "ui/chromeos/styles/cros_styles.css" ] resource_path_rewrites = @@ -157,7 +157,7 @@ generate_grd("build_ts_grdp") { grd_prefix = "webui" out_grd = "$target_gen_dir/resources_ts.grdp" - deps = [ ":library" ] + public_deps = [ ":library" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] }
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn index e8fdf4b..04d8c49 100644 --- a/ui/webui/resources/cr_components/BUILD.gn +++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -22,7 +22,7 @@ generate_grd("build_grdp") { grd_prefix = "cr_components" out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp" - deps = [ ":preprocess" ] + public_deps = [ ":preprocess" ] if (is_chromeos_ash) { input_files_base_dir = rebase_path(".", "//") input_files = [
diff --git a/ui/webui/resources/cr_components/app_management/BUILD.gn b/ui/webui/resources/cr_components/app_management/BUILD.gn index 69436d0..4855a2e 100644 --- a/ui/webui/resources/cr_components/app_management/BUILD.gn +++ b/ui/webui/resources/cr_components/app_management/BUILD.gn
@@ -139,7 +139,7 @@ generate_grd("build_grdp") { grd_prefix = "cr_components_app_management" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "cr_components/app_management" }
diff --git a/ui/webui/resources/cr_components/certificate_manager/BUILD.gn b/ui/webui/resources/cr_components/certificate_manager/BUILD.gn index f1995f9..33d7ddec 100644 --- a/ui/webui/resources/cr_components/certificate_manager/BUILD.gn +++ b/ui/webui/resources/cr_components/certificate_manager/BUILD.gn
@@ -63,7 +63,7 @@ generate_grd("build_grdp") { grd_prefix = "cr_components_certificate_manager" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "cr_components/certificate_manager" }
diff --git a/ui/webui/resources/cr_components/color_change_listener/BUILD.gn b/ui/webui/resources/cr_components/color_change_listener/BUILD.gn index a5d0fc36..97fa197 100644 --- a/ui/webui/resources/cr_components/color_change_listener/BUILD.gn +++ b/ui/webui/resources/cr_components/color_change_listener/BUILD.gn
@@ -48,7 +48,7 @@ generate_grd("build_grdp") { grd_prefix = "cr_components_color_change_listener" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "cr_components/color_change_listener" }
diff --git a/ui/webui/resources/cr_components/customize_themes/BUILD.gn b/ui/webui/resources/cr_components/customize_themes/BUILD.gn index 4e8b44d..060c24d 100644 --- a/ui/webui/resources/cr_components/customize_themes/BUILD.gn +++ b/ui/webui/resources/cr_components/customize_themes/BUILD.gn
@@ -78,7 +78,7 @@ "colorize.svg", "brush.svg", ] - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "cr_components/customize_themes" }
diff --git a/ui/webui/resources/cr_components/history_clusters/BUILD.gn b/ui/webui/resources/cr_components/history_clusters/BUILD.gn index a0f8a489..cc3758de 100644 --- a/ui/webui/resources/cr_components/history_clusters/BUILD.gn +++ b/ui/webui/resources/cr_components/history_clusters/BUILD.gn
@@ -44,7 +44,7 @@ generate_grd("build_grdp") { grd_prefix = "cr_components_history_clusters" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "cr_components/history_clusters" }
diff --git a/ui/webui/resources/cr_components/most_visited/BUILD.gn b/ui/webui/resources/cr_components/most_visited/BUILD.gn index b89c7b3..f2568f6 100644 --- a/ui/webui/resources/cr_components/most_visited/BUILD.gn +++ b/ui/webui/resources/cr_components/most_visited/BUILD.gn
@@ -42,7 +42,7 @@ grd_prefix = "cr_components_most_visited" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "cr_components/most_visited" }
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn index 25d422e..9a0313f6 100644 --- a/ui/webui/resources/cr_elements/BUILD.gn +++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -26,7 +26,7 @@ generate_grd("build_grdp") { grd_prefix = "cr_elements" out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp" - deps = [ ":preprocess" ] + public_deps = [ ":preprocess" ] manifest_files = [ "$target_gen_dir/$preprocess_gen_manifest" ] if (is_chromeos_ash) {
diff --git a/ui/webui/resources/css/BUILD.gn b/ui/webui/resources/css/BUILD.gn index 45073e77..3801cb7 100644 --- a/ui/webui/resources/css/BUILD.gn +++ b/ui/webui/resources/css/BUILD.gn
@@ -13,7 +13,7 @@ generate_grd("build_grdp") { grd_prefix = "webui_css" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":preprocess_src" ] + public_deps = [ ":preprocess_src" ] manifest_files = [ "$target_gen_dir/$preprocess_src_manifest" ] resource_path_prefix = "css" }
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index c5b5f7a..40229e5 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -18,7 +18,7 @@ generate_grd("build_grdp") { grd_prefix = "webui_js" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":preprocess" ] + public_deps = [ ":preprocess" ] manifest_files = [ "$target_gen_dir/$preprocess_gen_manifest", "$target_gen_dir/$preprocess_src_manifest",
diff --git a/ui/webui/resources/js/browser_command/BUILD.gn b/ui/webui/resources/js/browser_command/BUILD.gn index cc43070..a8210ca 100644 --- a/ui/webui/resources/js/browser_command/BUILD.gn +++ b/ui/webui/resources/js/browser_command/BUILD.gn
@@ -51,7 +51,7 @@ generate_grd("build_grdp") { grd_prefix = "webui_js_browser_command" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "js/browser_command" }
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn index f3c4597..2743543 100644 --- a/ui/webui/resources/js/cr/ui/BUILD.gn +++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -16,7 +16,7 @@ generate_grd("build_grdp") { grd_prefix = "webui_js_cr_ui" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":preprocess" ] + public_deps = [ ":preprocess" ] manifest_files = [ "$target_gen_dir/$preprocess_gen_manifest", "$target_gen_dir/$preprocess_src_manifest",
diff --git a/ui/webui/resources/js/metrics_reporter/BUILD.gn b/ui/webui/resources/js/metrics_reporter/BUILD.gn index d13ee52..497ec96 100644 --- a/ui/webui/resources/js/metrics_reporter/BUILD.gn +++ b/ui/webui/resources/js/metrics_reporter/BUILD.gn
@@ -47,7 +47,7 @@ generate_grd("build_grdp") { grd_prefix = "webui_js_metrics_reporter" out_grd = "$target_gen_dir/resources.grdp" - deps = [ ":build_ts" ] + public_deps = [ ":build_ts" ] manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] resource_path_prefix = "js/metrics_reporter" }
diff --git a/ui/webui/resources/tools/generate_grd.gni b/ui/webui/resources/tools/generate_grd.gni index 56464f3..7a99fc8 100644 --- a/ui/webui/resources/tools/generate_grd.gni +++ b/ui/webui/resources/tools/generate_grd.gni
@@ -6,9 +6,11 @@ action(target_name) { script = "//ui/webui/resources/tools/generate_grd.py" - if (defined(invoker.deps)) { - deps = invoker.deps - } + forward_variables_from(invoker, + [ + "deps", + "public_deps", + ]) inputs = [] outputs = [ invoker.out_grd ]