diff --git a/BUILD.gn b/BUILD.gn index 34e680b..6c7e311 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -12,6 +12,7 @@ import("//build/config/features.gni") import("//build/config/sanitizers/sanitizers.gni") import("//build/config/ui.gni") +import("//build/gn_logs.gni") import("//build/util/generate_wrapper.gni") import("//chrome/browser/buildflags.gni") import("//chrome/browser/media/router/features.gni") @@ -757,8 +758,8 @@ } } - if (((is_linux || is_chromeos) && !is_chromecast) || (is_win && use_libfuzzer) || - (use_libfuzzer && is_mac)) { + if (((is_linux || is_chromeos) && !is_chromecast) || + (is_win && use_libfuzzer) || (use_libfuzzer && is_mac)) { deps += [ "//chrome/services/ipp_parser/public/cpp:fuzzers", "//testing/libfuzzer/fuzzers", @@ -1398,3 +1399,15 @@ "*\bwin/*", ]) != [], "Do not use a platform name in your output directory (found \"$root_build_dir\"). http://crbug.com/548283") + +# Write debug logs to gn_logs.txt. +_lines = [ + "Generated during 'gn gen' by //BUILD.gn.", + "", + ] + build_gn_logs + +# GN evaluates each .gn file once per toolchain, so restricting to default +# toolchain will ensure write_file() is called only once. +assert(current_toolchain == default_toolchain) + +write_file("$root_build_dir/gn_logs.txt", _lines)
diff --git a/DEPS b/DEPS index cbad80f0..99ebb56 100644 --- a/DEPS +++ b/DEPS
@@ -195,7 +195,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '3b08f35fd150a16440d8c9737a3fe4244217e3d6', + 'skia_revision': '3e8fae71935893adc69e2b8caee922ec60aa0f59', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -207,7 +207,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': 'fb03de53854802fabc7363c00e863922e7bdb393', + 'angle_revision': '3a3d419df7526518c2ece77f7f7a4cd72d10130b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -266,7 +266,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': '69a10924bc979146d9e4482f0c3e893ff41050a5', + 'devtools_frontend_revision': 'ce00f903c2688e2877dba5f27f63d8916961a107', # 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. @@ -368,7 +368,7 @@ # revisions. # GN CIPD package version. - 'gn_version': 'git_revision:3028c6a426a4aaf6da91c4ebafe716ae370225fe', + 'gn_version': 'git_revision:e327ffdc503815916db2543ec000226a8df45163', # Also, if you change these, update buildtools/DEPS too. Also update the # libc++ svn_revision in //buildtools/deps_revisions.gni. @@ -875,7 +875,7 @@ # Build tools for Chrome OS. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '889f00501aaa0c8b032c400caf09791924d709f5', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fb57bbd19358a5c2f1bb50e8417bd478f83588f9', 'condition': 'checkout_chromeos', }, @@ -1248,7 +1248,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '56f14dabfe991afdf09f35a56418657dbcb81791', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a4cba6578f09d606d32fe32bb0a0c6283ea6d198', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1326,7 +1326,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'xa2xI0A-kKlMVwMtJRzexwWWPSwHynmUpB0Z6C9Y7wkC' + 'version': '8dGfq6t5VMN4pg6qI6Y4F2ljKubFBrpo9AS6NSZbHeYC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1465,7 +1465,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '5184219b6ff46b8bdb432c9fe307ec762ec2119b', + Var('webrtc_git') + '/src.git' + '@' + '4c2f9c90f42591f0935b496d61ee256ebf53198f', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'),
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 9f61883..be1c69e 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -101,6 +101,24 @@ 'third_party/robolectric/local/', ), ), + ( + 'android.support.test.rule.UiThreadTestRule;', + ( + 'Do not use UiThreadTestRule, just use ' + '@org.chromium.base.test.UiThreadTest on test methods that should run on ' + 'the UI thread. See https://crbug.com/1111893.', + ), + (), + ), + ( + 'android.support.test.annotation.UiThreadTest;', + ( + 'Do not use android.support.test.annotation.UiThreadTest, use ' + 'org.chromium.base.test.UiThreadTest instead. See ' + 'https://crbug.com/1111893.', + ), + () + ) ) # Format: Sequence of tuples containing:
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc index bedb16b..4b98241 100644 --- a/android_webview/browser/aw_permission_manager.cc +++ b/android_webview/browser/aw_permission_manager.cc
@@ -341,6 +341,7 @@ case PermissionType::STORAGE_ACCESS_GRANT: case PermissionType::CAMERA_PAN_TILT_ZOOM: case PermissionType::WINDOW_PLACEMENT: + case PermissionType::FONT_ACCESS: NOTIMPLEMENTED() << "RequestPermissions is not implemented for " << static_cast<int>(permissions[i]); pending_request_raw->SetPermissionStatus(permissions[i], @@ -548,6 +549,7 @@ case PermissionType::STORAGE_ACCESS_GRANT: case PermissionType::CAMERA_PAN_TILT_ZOOM: case PermissionType::WINDOW_PLACEMENT: + case PermissionType::FONT_ACCESS: NOTIMPLEMENTED() << "CancelPermission not implemented for " << static_cast<int>(permission); break;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index c436cfd2..948d988 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1910,6 +1910,7 @@ "shelf/login_shelf_gesture_controller_unittest.cc", "shelf/login_shelf_view_unittest.cc", "shelf/scrollable_shelf_view_unittest.cc", + "shelf/shelf_app_button_unittest.cc", "shelf/shelf_application_menu_model_unittest.cc", "shelf/shelf_background_animator_unittest.cc", "shelf/shelf_button_pressed_metric_tracker_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc index 55c6563..8eda728 100644 --- a/ash/accelerators/accelerator_controller_impl.cc +++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -16,6 +16,7 @@ #include "ash/ambient/ambient_controller.h" #include "ash/app_list/app_list_controller_impl.h" #include "ash/assistant/model/assistant_ui_model.h" +#include "ash/capture_mode/capture_mode_controller.h" #include "ash/debug.h" #include "ash/display/display_configuration_controller.h" #include "ash/display/display_move_window_util.h" @@ -743,15 +744,42 @@ NewWindowDelegate::GetInstance()->ShowKeyboardShortcutViewer(); } +bool CanHandleScreenshot() { + // The old screenshot code will handle the different sessions in its own code. + if (!features::IsCaptureModeEnabled()) + return true; + + return !Shell::Get()->session_controller()->IsUserSessionBlocked(); +} + +// Tries to enter capture mode image type with |source|. Returns false if +// unsuccessful (capture mode disabled). +bool MaybeEnterImageCaptureMode(CaptureModeSource source) { + if (!features::IsCaptureModeEnabled()) + return false; + + auto* capture_mode_controller = CaptureModeController::Get(); + capture_mode_controller->SetSource(source); + capture_mode_controller->SetType(CaptureModeType::kImage); + capture_mode_controller->Start(); + return true; +} + void HandleTakeWindowScreenshot() { base::RecordAction(UserMetricsAction("Accel_Take_Window_Screenshot")); + if (MaybeEnterImageCaptureMode(CaptureModeSource::kWindow)) + return; + Shell::Get()->screenshot_controller()->StartWindowScreenshotSession(); } void HandleTakePartialScreenshot() { base::RecordAction(UserMetricsAction("Accel_Take_Partial_Screenshot")); + if (MaybeEnterImageCaptureMode(CaptureModeSource::kRegion)) + return; + Shell::Get()->screenshot_controller()->StartPartialScreenshotSession( - true /* draw_overlay_immediately */); + /*draw_overlay_immediately=*/true); } void HandleTakeScreenshot() { @@ -1938,6 +1966,10 @@ return !!FindPipWidget(); case MINIMIZE_TOP_WINDOW_ON_BACK: return window_util::ShouldMinimizeTopWindowOnBack(); + case TAKE_PARTIAL_SCREENSHOT: + case TAKE_SCREENSHOT: + case TAKE_WINDOW_SCREENSHOT: + return CanHandleScreenshot(); // The following are always enabled. case BRIGHTNESS_DOWN: @@ -1982,9 +2014,6 @@ case SHOW_SHORTCUT_VIEWER: case SHOW_TASK_MANAGER: case SUSPEND: - case TAKE_PARTIAL_SCREENSHOT: - case TAKE_SCREENSHOT: - case TAKE_WINDOW_SCREENSHOT: case TOGGLE_FULLSCREEN: case TOGGLE_HIGH_CONTRAST: case TOGGLE_MAXIMIZED:
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index d1e44781..3819d954 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -1899,7 +1899,9 @@ // when a modal window is open // // Screenshot - { + // TODO(sammiequon): Add some basic tests once capture mode is more fleshed + // out. + if (!features::IsCaptureModeEnabled()) { TestScreenshotDelegate* delegate = GetScreenshotDelegate(); delegate->set_can_take_screenshot(false); EXPECT_TRUE(ProcessInController(
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc index a8c0baa..ce1a979 100644 --- a/ash/frame/header_view.cc +++ b/ash/frame/header_view.cc
@@ -325,4 +325,8 @@ caption_button_container_->SetVisible(should_paint_); } +BEGIN_METADATA(HeaderView) +METADATA_PARENT_CLASS(View) +END_METADATA() + } // namespace ash
diff --git a/ash/frame/header_view.h b/ash/frame/header_view.h index 7ca011e..a4e89fd 100644 --- a/ash/frame/header_view.h +++ b/ash/frame/header_view.h
@@ -51,6 +51,8 @@ explicit HeaderView(views::Widget* target_widget); ~HeaderView() override; + METADATA_HEADER(HeaderView); + void set_immersive_mode_changed_callback(base::RepeatingClosure callback) { immersive_mode_changed_callback_ = std::move(callback); }
diff --git a/ash/frame/wide_frame_view.cc b/ash/frame/wide_frame_view.cc index ef88453a1..8c7481a 100644 --- a/ash/frame/wide_frame_view.cc +++ b/ash/frame/wide_frame_view.cc
@@ -100,7 +100,9 @@ params.name = "WideFrameView"; params.parent = target->GetNativeWindow(); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; + // Setup Opacity Control. + // WideFrame should be used only when the rounded corner is not necessary. + params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque; widget_->Init(std::move(params));
diff --git a/ash/shelf/OWNERS b/ash/shelf/OWNERS index c704b5d..b013bce 100644 --- a/ash/shelf/OWNERS +++ b/ash/shelf/OWNERS
@@ -4,4 +4,6 @@ tbarzic@chromium.org xiyuan@chromium.org +per-file *login*=file://ash/login/OWNERS + # COMPONENT: UI>Shell>Shelf
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index 29a10179..90fcde59 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -251,7 +251,8 @@ bool DialogStateGuestAllowed(OobeDialogState state) { return state == OobeDialogState::GAIA_SIGNIN || - state == OobeDialogState::ERROR || state == OobeDialogState::HIDDEN; + state == OobeDialogState::ERROR || state == OobeDialogState::HIDDEN || + state == OobeDialogState::USER_CREATION; } bool ShutdownButtonHidden(OobeDialogState state) { @@ -861,7 +862,8 @@ if (session_state != SessionState::LOGIN_PRIMARY) return false; - if (dialog_state_ == OobeDialogState::GAIA_SIGNIN) + if (dialog_state_ == OobeDialogState::USER_CREATION || + dialog_state_ == OobeDialogState::GAIA_SIGNIN) return !login_screen_has_users_ && allow_guest_in_oobe_; return true;
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc index f1c2fdb0..fc8e84be 100644 --- a/ash/shelf/shelf_app_button.cc +++ b/ash/shelf/shelf_app_button.cc
@@ -28,6 +28,7 @@ #include "ui/gfx/animation/animation_delegate.h" #include "ui/gfx/animation/throb_animation.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/color_analysis.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/scoped_canvas.h" @@ -48,10 +49,10 @@ constexpr int kStatusIndicatorRunningSize = 4; constexpr int kStatusIndicatorThickness = 2; constexpr int kNotificationIndicatorRadiusDip = 7; -constexpr SkColor kIndicatorColor = SK_ColorWHITE; +constexpr SkColor kDefaultIndicatorColor = SK_ColorWHITE; // Slightly different colors and alpha in the new UI. -constexpr SkColor kIndicatorColorActive = kIndicatorColor; +constexpr SkColor kIndicatorColorActive = kDefaultIndicatorColor; constexpr SkColor kIndicatorColorRunning = SkColorSetA(SK_ColorWHITE, 0x7F); // The time threshold before an item can be dragged. @@ -66,6 +67,30 @@ // The drag and drop app icon scaling up or down animation transition duration. constexpr int kDragDropAppIconScaleTransitionMs = 200; +// Uses the icon image to calculate the light vibrant color to be used for +// the notification indicator. +base::Optional<SkColor> CalculateNotificationColor(gfx::ImageSkia image) { + const SkBitmap* source = image.bitmap(); + if (!source || source->empty() || source->isNull()) + return base::nullopt; + + std::vector<color_utils::ColorProfile> color_profiles; + color_profiles.push_back(color_utils::ColorProfile( + color_utils::LumaRange::LIGHT, color_utils::SaturationRange::VIBRANT)); + + std::vector<color_utils::Swatch> best_swatches = + color_utils::CalculateProminentColorsOfBitmap( + *source, color_profiles, nullptr /* bitmap region */, + color_utils::ColorSwatchFilter()); + + // If the best swatch color is transparent, then + // CalculateProminentColorsOfBitmap() failed to find a suitable color. + if (best_swatches.empty() || best_swatches[0].color == SK_ColorTRANSPARENT) + return base::nullopt; + + return best_swatches[0].color; +} + // Simple AnimationDelegate that owns a single ThrobAnimation instance to // keep all Draw Attention animations in sync. class ShelfAppButtonAnimation : public gfx::AnimationDelegate { @@ -177,8 +202,15 @@ flags); } + void SetColor(SkColor new_color) { + indicator_color_ = new_color; + SchedulePaint(); + } + + SkColor GetColorForTest() { return indicator_color_; } + private: - const SkColor indicator_color_; + SkColor indicator_color_; DISALLOW_COPY_AND_ASSIGN(AppNotificationIndicatorView); }; @@ -343,7 +375,8 @@ AddChildView(indicator_); AddChildView(icon_view_); if (is_notification_indicator_enabled_) { - notification_indicator_ = new AppNotificationIndicatorView(kIndicatorColor); + notification_indicator_ = + new AppNotificationIndicatorView(kDefaultIndicatorColor); notification_indicator_->SetPaintToLayer(); notification_indicator_->layer()->SetFillsBoundsOpaquely(false); notification_indicator_->SetVisible(false); @@ -383,6 +416,13 @@ } icon_image_ = image; + if (is_notification_indicator_enabled_) { + base::Optional<SkColor> notification_color = + CalculateNotificationColor(icon_image_); + notification_indicator_->SetColor( + notification_color.value_or(kDefaultIndicatorColor)); + } + const int icon_size = shelf_view_->GetButtonIconSize() * icon_scale_; // Resize the image maintaining our aspect ratio. @@ -918,4 +958,8 @@ } } +SkColor ShelfAppButton::GetNotificationIndicatorColorForTest() { + return notification_indicator_->GetColorForTest(); +} + } // namespace ash
diff --git a/ash/shelf/shelf_app_button.h b/ash/shelf/shelf_app_button.h index 2a47d56a..246d794 100644 --- a/ash/shelf/shelf_app_button.h +++ b/ash/shelf/shelf_app_button.h
@@ -118,6 +118,9 @@ // Return the bounds in the local coordinates enclosing the small ripple area. gfx::Rect CalculateSmallRippleArea() const; + // Gets the color of the |notification_indicator_| for test usage. + SkColor GetNotificationIndicatorColorForTest(); + protected: // ui::EventHandler: void OnGestureEvent(ui::GestureEvent* event) override;
diff --git a/ash/shelf/shelf_app_button_unittest.cc b/ash/shelf/shelf_app_button_unittest.cc new file mode 100644 index 0000000..060e5c7a --- /dev/null +++ b/ash/shelf/shelf_app_button_unittest.cc
@@ -0,0 +1,87 @@ +// Copyright 2020 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/shelf/shelf_app_button.h" + +#include "ash/shelf/shelf_test_util.h" +#include "ash/shelf/shelf_view.h" +#include "ash/shelf/shelf_view_test_api.h" +#include "ash/test/ash_test_base.h" +#include "base/test/scoped_feature_list.h" +#include "ui/base/ui_base_features.h" +#include "ui/gfx/color_palette.h" + +namespace ash { + +class ShelfAppButtonTest : public AshTestBase { + public: + ShelfAppButtonTest() { + scoped_feature_list_.InitWithFeatures({features::kNotificationIndicator}, + {}); + } + ~ShelfAppButtonTest() override = default; + + // AshTestBase: + void SetUp() override { + AshTestBase::SetUp(); + + test_api_.reset( + new ShelfViewTestAPI(GetPrimaryShelf()->GetShelfViewForTesting())); + } + + void TearDown() override { + test_api_.reset(); + AshTestBase::TearDown(); + } + + ShelfViewTestAPI* test_api() { return test_api_.get(); } + + void SetImageForButton(int button_num, gfx::ImageSkia image) { + test_api()->GetButton(button_num)->SetImage(image); + } + + SkColor GetNotificationColorForButton(int button_num) { + return test_api() + ->GetButton(button_num) + ->GetNotificationIndicatorColorForTest(); + } + + private: + std::unique_ptr<ShelfViewTestAPI> test_api_; + + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Test that the notification indicator has a color which is calculated +// correctly when an image is set for the ShelfAppButton. +TEST_F(ShelfAppButtonTest, NotificatonBadgeColor) { + ShelfTestUtil::AddAppShortcut("app_id", TYPE_PINNED_APP); + + const int width = 64; + const int height = 64; + + SkBitmap all_black_icon; + all_black_icon.allocN32Pixels(width, height); + all_black_icon.eraseColor(SK_ColorBLACK); + + SetImageForButton(0, gfx::ImageSkia::CreateFrom1xBitmap(all_black_icon)); + + // For an all black icon, a white notification badge is expected, since there + // is no other light vibrant color to get from the icon. + EXPECT_EQ(SK_ColorWHITE, GetNotificationColorForButton(0)); + + // Create an icon that is half kGoogleRed300 and half kGoogleRed600. + SkBitmap red_icon; + red_icon.allocN32Pixels(width, height); + red_icon.eraseColor(gfx::kGoogleRed300); + red_icon.erase(gfx::kGoogleRed600, {0, 0, width, height / 2}); + + SetImageForButton(0, gfx::ImageSkia::CreateFrom1xBitmap(red_icon)); + + // For the red icon, the notification badge should calculate and use the + // kGoogleRed300 color as the light vibrant color taken from the icon. + EXPECT_EQ(gfx::kGoogleRed300, GetNotificationColorForButton(0)); +} + +} // namespace ash
diff --git a/ash/wm/overview/overview_constants.h b/ash/wm/overview/overview_constants.h index 89245c2..2d8b500 100644 --- a/ash/wm/overview/overview_constants.h +++ b/ash/wm/overview/overview_constants.h
@@ -19,11 +19,6 @@ // closest distance between adjacent windows will be twice this amount. constexpr int kWindowMargin = 5; -// Cover the transformed window including the gaps between the windows with a -// transparent shield to block the input events from reaching the transformed -// window while in overview. -ASH_EXPORT constexpr int kOverviewMargin = kWindowMargin * 2; - // Height of an item header. constexpr int kHeaderHeightDp = WindowMiniView::kHeaderHeightDp;
diff --git a/ash/wm/overview/overview_controller_unittest.cc b/ash/wm/overview/overview_controller_unittest.cc index 4ebfe21..9ee63bb 100644 --- a/ash/wm/overview/overview_controller_unittest.cc +++ b/ash/wm/overview/overview_controller_unittest.cc
@@ -698,6 +698,9 @@ EXPECT_CALL(observer, OnThrottlingStarted(testing::UnorderedElementsAreArray(windows))); controller->StartOverview(); + + EXPECT_CALL(observer, OnThrottlingStarted(::testing::_)) + .Times(::testing::AnyNumber()); EXPECT_CALL(observer, OnThrottlingEnded()); controller->EndOverview(); frame_throttling_controller->RemoveObserver(&observer);
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 5b45c8c..0674eef 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -9,6 +9,7 @@ #include <memory> #include <utility> +#include "ash/frame_throttler/frame_throttling_controller.h" #include "ash/metrics/histogram_macros.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/metrics_util.h" @@ -547,6 +548,8 @@ window_list_.insert( window_list_.begin() + index, std::make_unique<OverviewItem>(window, overview_session_, this)); + + UpdateFrameThrottling(); auto* item = window_list_[index].get(); item->PrepareForOverview(); @@ -610,6 +613,8 @@ window_list_.erase(std::next(iter).base()); tmp.reset(); + UpdateFrameThrottling(); + if (!item_destroying) return; @@ -1528,7 +1533,7 @@ target_size = ::ash::GetTargetBoundsInScreen(dragged_window).size(); target_size.SetToMin(gfx::SizeF(work_area_size)); } - const gfx::SizeF inset_size(0, height - 2 * kWindowMargin); + const gfx::SizeF inset_size(0, height); scale = ScopedOverviewTransformWindow::GetItemScale( target_size, inset_size, dragged_window->GetProperty(aura::client::kTopViewInset), @@ -1536,8 +1541,7 @@ } } - int width = std::max( - 1, base::ClampFloor(target_size.width() * scale) + 2 * kWindowMargin); + int width = std::max(1, base::ClampFloor(target_size.width() * scale)); switch (grid_fill_mode) { case OverviewGridWindowFillMode::kLetterBoxed: width = kExtremeWindowRatioThreshold * height; @@ -1567,15 +1571,14 @@ const float target_aspect_ratio = split_view_bounds->width() / split_view_bounds->height(); const bool clip_horizontally = aspect_ratio > target_aspect_ratio; - const int window_height = height - 2 * kWindowMargin - kHeaderHeightDp; + const int window_height = height - kHeaderHeightDp; gfx::Size unclipped_size; if (clip_horizontally) { - unclipped_size.set_width(width - 2 * kWindowMargin); - unclipped_size.set_height(height - 2 * kWindowMargin); + unclipped_size.set_width(width); + unclipped_size.set_height(height); // For horizontal clipping, shrink |width| so that the aspect ratio matches // that of |split_view_bounds|. - width = std::max(1, base::ClampFloor(target_aspect_ratio * window_height) + - 2 * kWindowMargin); + width = std::max(1, base::ClampFloor(target_aspect_ratio * window_height)); } else { // For vertical clipping, we want |height| to stay the same, so calculate // what the unclipped height would be based on |split_view_bounds|. @@ -1591,9 +1594,6 @@ width * target_size.height() / target_size.width(); unclipped_size.set_width(width); unclipped_size.set_height(unclipped_height + kHeaderHeightDp); - - // Add some space between this item and the next one (if it exists). - width += (2 * kWindowMargin); } DCHECK(!unclipped_size.IsEmpty()); @@ -1690,8 +1690,8 @@ gfx::Rect overview_mode_bounds(total_bounds); overview_mode_bounds.set_width(right_bound - total_bounds.x()); bool windows_fit = FitWindowRectsInBounds( - overview_mode_bounds, std::min(kMaxHeight + 2 * kWindowMargin, height), - ignored_items, &rects, &max_bottom, &min_right, &max_right); + overview_mode_bounds, std::min(kMaxHeight, height), ignored_items, + &rects, &max_bottom, &min_right, &max_right); if (height_fixed) { if (!windows_fit) { @@ -1736,9 +1736,9 @@ if (make_last_adjustment) { gfx::Rect overview_mode_bounds(total_bounds); overview_mode_bounds.set_width(right_bound - total_bounds.x()); - FitWindowRectsInBounds( - overview_mode_bounds, std::min(kMaxHeight + 2 * kWindowMargin, height), - ignored_items, &rects, &max_bottom, &min_right, &max_right); + FitWindowRectsInBounds(overview_mode_bounds, std::min(kMaxHeight, height), + ignored_items, &rects, &max_bottom, &min_right, + &max_right); } gfx::Vector2dF offset(0, (total_bounds.bottom() - max_bottom) / 2.f); @@ -1844,8 +1844,9 @@ if (ShouldExcludeItemFromGridLayout(window_list_[i].get(), ignored_items)) continue; - int width = - CalculateWidthAndMaybeSetUnclippedBounds(window_list_[i].get(), height); + int width = CalculateWidthAndMaybeSetUnclippedBounds(window_list_[i].get(), + height) + + 2 * kWindowMargin; if (left + width > bounds.right()) { // Move to the next row if possible. @@ -1865,7 +1866,7 @@ } // Position the current rect. - (*out_rects)[i] = gfx::RectF(left, top, width, height); + (*out_rects)[i] = gfx::RectF(left, top, width, height + 2 * kWindowMargin); // Increment horizontal position using sanitized positive |width|. left += width; @@ -1966,4 +1967,12 @@ overview_mode_item->UpdateCannotSnapWarningVisibility(); } +void OverviewGrid::UpdateFrameThrottling() { + std::vector<aura::Window*> windows_to_throttle(window_list_.size(), nullptr); + std::transform( + window_list_.begin(), window_list_.end(), windows_to_throttle.begin(), + [](std::unique_ptr<OverviewItem>& item) { return item->GetWindow(); }); + Shell::Get()->frame_throttling_controller()->StartThrottling( + windows_to_throttle); +} } // namespace ash
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index 8ed3aa6..d94cd80 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -444,6 +444,9 @@ void UpdateCannotSnapWarningVisibility(); + // Updates frame throttling on overview item windows. + void UpdateFrameThrottling(); + // Root window the grid is in. aura::Window* root_window_;
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index efbcde7f..f16cb13 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -263,7 +263,7 @@ } float OverviewItem::GetItemScale(const gfx::Size& size) { - gfx::SizeF inset_size(size.width(), size.height() - 2 * kWindowMargin); + gfx::SizeF inset_size(size.width(), size.height()); return ScopedOverviewTransformWindow::GetItemScale( GetTargetBoundsInScreen().size(), inset_size, transform_window_.GetTopInset(), kHeaderHeightDp); @@ -306,7 +306,6 @@ item_widget_->GetNativeWindow()->layer()->GetAnimator()->StopAnimating(); gfx::Rect minimized_bounds = ToStableSizeRoundedRect(target_bounds); - minimized_bounds.Inset(-kWindowMargin, -kWindowMargin); OverviewAnimationType minimized_animation_type = is_first_update ? OVERVIEW_ANIMATION_NONE : new_animation_type; SetWidgetBoundsAndMaybeAnimateTransform( @@ -394,7 +393,6 @@ } } else { gfx::RectF inset_bounds(target_bounds); - inset_bounds.Inset(kWindowMargin, kWindowMargin); SetItemBounds(inset_bounds, new_animation_type, is_first_update); UpdateHeaderLayout(is_first_update ? OVERVIEW_ANIMATION_NONE : new_animation_type); @@ -734,7 +732,7 @@ if (!shadow_) return; - if (bounds_in_screen == base::nullopt) { + if (!bounds_in_screen) { shadow_->layer()->SetVisible(false); return; } @@ -742,11 +740,9 @@ shadow_->layer()->SetVisible(true); gfx::Rect bounds_in_item = gfx::Rect(item_widget_->GetNativeWindow()->GetTargetBounds().size()); - bounds_in_item.Inset(kOverviewMargin, kOverviewMargin); bounds_in_item.Inset(0, kHeaderHeightDp, 0, 0); bounds_in_item.ClampToCenteredSize( gfx::ToRoundedSize(bounds_in_screen->size())); - shadow_->SetContentBounds(bounds_in_item); } @@ -779,11 +775,12 @@ ->GetAnimator() ->is_animating(); if (should_show_shadow) { - const gfx::RectF shadow_bounds = - transform_window_.IsMinimized() - ? gfx::RectF( - overview_item_view_->preview_view()->GetBoundsInScreen()) - : transform_window_.GetTransformedBounds(); + // The shadow should match the size of the transformed window or preview + // window if unclipped. If clipped, the shadow should match the size of the + // item minus the border and header. + const gfx::RectF shadow_bounds = unclipped_size_ + ? GetWindowTargetBoundsWithInsets() + : GetUnclippedShadowBounds(); SetShadowBounds(base::make_optional(shadow_bounds)); } else { SetShadowBounds(base::nullopt); @@ -1112,6 +1109,13 @@ return window_target_bounds; } +gfx::RectF OverviewItem::GetUnclippedShadowBounds() const { + return transform_window_.IsMinimized() + ? gfx::RectF( + overview_item_view_->preview_view()->GetBoundsInScreen()) + : transform_window_.GetTransformedBounds(); +} + void OverviewItem::OnWindowCloseAnimationCompleted() { transform_window_.Close(); } @@ -1211,6 +1215,11 @@ const int top_view_inset = transform_window_.GetTopInset(); gfx::RectF transformed_bounds = target_bounds; + + // |target_bounds| are the bounds of the |item_widget|, which include a + // border. + transformed_bounds.Inset(kWindowMargin, kWindowMargin); + // Update |transformed_bounds| to match the unclipped size of the window, so // we transform the window to the correct size. if (unclipped_size_) @@ -1301,7 +1310,6 @@ ::wm::TranslateRectFromScreen(root_window_, &item_bounds); const gfx::Point origin = gfx::ToRoundedPoint(item_bounds.origin()); item_bounds.set_origin(gfx::PointF()); - item_bounds.Inset(-kWindowMargin, -kWindowMargin); widget_window->SetBounds(ToStableSizeRoundedRect(item_bounds)); gfx::Transform label_transform;
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h index b8182a4b..c472d4c8 100644 --- a/ash/wm/overview/overview_item.h +++ b/ash/wm/overview/overview_item.h
@@ -282,6 +282,10 @@ // insets. gfx::RectF GetWindowTargetBoundsWithInsets() const; + // The shadow should match the size of the transformed window or preview + // window if unclipped. + gfx::RectF GetUnclippedShadowBounds() const; + // Functions to be called back when their associated animations complete. void OnWindowCloseAnimationCompleted(); void OnItemSpawnedAnimationCompleted();
diff --git a/ash/wm/overview/overview_item_view.cc b/ash/wm/overview/overview_item_view.cc index 6d2471c..2f365ab 100644 --- a/ash/wm/overview/overview_item_view.cc +++ b/ash/wm/overview/overview_item_view.cc
@@ -191,8 +191,6 @@ current_header_visibility_ = HeaderVisibility::kInvisible; } - border_ptr()->set_extra_margin(kWindowMargin); - UpdateIconView(); // Do not use a layout manager for the header as its elements have shadows @@ -259,10 +257,6 @@ Layout(); } -int OverviewItemView::GetMargin() const { - return kOverviewMargin; -} - gfx::Rect OverviewItemView::GetHeaderBounds() const { // We want to align the edges of the image as shown below in the diagram. The // resource itself contains some padding, which is the distance from the edges @@ -275,7 +269,6 @@ const int close_button_width = close_button_->GetPreferredSize().width(); const int right_padding = (close_button_width - image_width) / 2 + kCloseButtonIconMarginDp; - const int margin = GetMargin(); // Positions the header in a way so that the right aligned close button is // aligned so that the edge of its icon, not the button lines up with the @@ -294,9 +287,9 @@ // the header so that the margin is accounted for, then shift the right bounds // by a bit so that the close button resource lines up with the right edge of // the visible region. - return gfx::Rect(margin, margin, - GetLocalBounds().width() - (2 * margin) + right_padding, - kHeaderHeightDp); + const gfx::Rect contents_bounds(GetContentsBounds()); + return gfx::Rect(contents_bounds.x(), contents_bounds.y(), + contents_bounds.width() + right_padding, kHeaderHeightDp); } gfx::Size OverviewItemView::GetPreviewViewSize() const { @@ -336,7 +329,7 @@ // Layout the header items. The icon, if available should be aligned left, the // close button should be aligned right and the title should take up all the // space in between but the text should be aligned left. - gfx::Rect header_bounds = header_view()->GetLocalBounds(); + gfx::Rect header_bounds = header_view()->bounds(); const int width = header_bounds.width(); const int height = header_bounds.height(); int x = 0; @@ -433,9 +426,8 @@ static ui::EventType press_types[] = {ui::ET_GESTURE_TAP_DOWN, ui::ET_MOUSE_PRESSED}; if (event.IsLocatedEvent() && base::Contains(press_types, event.type())) { - gfx::Rect inset_bounds = GetLocalBounds(); - inset_bounds.Inset(gfx::Insets(kOverviewMargin)); - if (!inset_bounds.Contains(event.AsLocatedEvent()->location())) + const gfx::Rect content_bounds = GetContentsBounds(); + if (!content_bounds.Contains(event.AsLocatedEvent()->location())) accept_events = false; }
diff --git a/ash/wm/overview/overview_item_view.h b/ash/wm/overview/overview_item_view.h index 2438793..6f2516f 100644 --- a/ash/wm/overview/overview_item_view.h +++ b/ash/wm/overview/overview_item_view.h
@@ -62,7 +62,6 @@ void RefreshPreviewView(); // WindowMiniView: - int GetMargin() const override; gfx::Rect GetHeaderBounds() const override; gfx::Size GetPreviewViewSize() const override; gfx::ImageSkia ModifyIcon(gfx::ImageSkia* image) const override;
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 7960f33..c56b55d 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -1639,9 +1639,7 @@ // Labels are located based on target_bounds, not the actual window item // bounds. - gfx::RectF label_bounds = - gfx::RectF(label->GetWidget()->GetWindowBoundsInScreen()); - label_bounds.Inset(kWindowMargin, kWindowMargin); + gfx::RectF label_bounds(label->GetWidget()->GetWindowBoundsInScreen()); EXPECT_EQ(label_bounds, window_item->target_bounds()); } @@ -7151,11 +7149,13 @@ WindowState::Get(window.get())->Maximize(); ToggleOverview(); OverviewItem* item = GetOverviewItemForWindow(window.get()); - // Verify that |item| is letter boxed. + // Verify that |item| is letter boxed. The bounds of |item|, minus the margin + // should have an aspect ratio of 2 : 1. + gfx::RectF item_bounds = item->target_bounds(); + item_bounds.Inset(gfx::InsetsF(kWindowMargin)); EXPECT_EQ(OverviewGridWindowFillMode::kLetterBoxed, item->GetWindowDimensionsType()); - EXPECT_EQ(2.f, - item->target_bounds().width() / item->target_bounds().height()); + EXPECT_EQ(2.f, item_bounds.width() / item_bounds.height()); overview_session()->InitiateDrag(item, item->target_bounds().CenterPoint(), /*is_touch_dragging=*/false); Shell::Get()->cursor_manager()->SetDisplay( @@ -7166,9 +7166,11 @@ ASSERT_TRUE(drop_target); // Verify that |drop_target| is effectively pillar boxed. Avoid calling // |OverviewItem::GetWindowDimensionsType|, because it does not work for drop - // targets (and that is okay). - EXPECT_EQ(0.5f, drop_target->target_bounds().width() / - drop_target->target_bounds().height()); + // targets (and that is okay). The bounds of |drop_target|, minus the margin + // should have an aspect ratio of 1 : 2. + gfx::RectF drop_target_bounds = drop_target->target_bounds(); + drop_target_bounds.Inset(gfx::InsetsF(kWindowMargin)); + EXPECT_EQ(0.5f, drop_target_bounds.width() / drop_target_bounds.height()); } // Verify that the drop target in each overview grid has bounds representing
diff --git a/ash/wm/window_finder_unittest.cc b/ash/wm/window_finder_unittest.cc index 9c6a9a5..a42b8d8 100644 --- a/ash/wm/window_finder_unittest.cc +++ b/ash/wm/window_finder_unittest.cc
@@ -28,7 +28,7 @@ EXPECT_EQ(window1.get(), GetTopmostWindowAtPoint(gfx::Point(10, 10), ignore)); } -TEST_F(WindowFinderTest, ToplevelanBeNotDrawn) { +TEST_F(WindowFinderTest, ToplevelCanBeNotDrawn) { aura::test::TestWindowDelegate delegate; auto window = std::make_unique<aura::Window>(&delegate, aura::client::WINDOW_TYPE_POPUP);
diff --git a/ash/wm/window_mini_view.cc b/ash/wm/window_mini_view.cc index 46ef1c2..67e0974 100644 --- a/ash/wm/window_mini_view.cc +++ b/ash/wm/window_mini_view.cc
@@ -111,10 +111,6 @@ SchedulePaint(); } -int WindowMiniView::GetMargin() const { - return 0; -} - gfx::Rect WindowMiniView::GetHeaderBounds() const { gfx::Rect header_bounds = GetContentsBounds(); header_bounds.set_height(kHeaderHeightDp);
diff --git a/ash/wm/window_mini_view.h b/ash/wm/window_mini_view.h index 05ab596..b2a06042 100644 --- a/ash/wm/window_mini_view.h +++ b/ash/wm/window_mini_view.h
@@ -68,7 +68,6 @@ // Subclasses can override these functions to provide customization for // margins and layouts of certain elements. - virtual int GetMargin() const; virtual gfx::Rect GetHeaderBounds() const; virtual gfx::Size GetPreviewViewSize() const; // Allows subclasses to resize/add shadow to the image that will appear as the @@ -87,7 +86,6 @@ void OnWindowTitleChanged(aura::Window* window) override; aura::Window* source_window() const { return source_window_; } - WmHighlightItemBorder* border_ptr() { return border_ptr_; } private: // The window this class is meant to be a header for. This class also may
diff --git a/ash/wm/wm_highlight_item_border.cc b/ash/wm/wm_highlight_item_border.cc index c9a30ab..907d0c66 100644 --- a/ash/wm/wm_highlight_item_border.cc +++ b/ash/wm/wm_highlight_item_border.cc
@@ -46,19 +46,17 @@ gfx::RectF bounds(view.GetLocalBounds()); // The following inset is needed for the rounded corners of the border to // look correct. Otherwise, the borders will be painted at the edge of the - // view, resulting in this border looking chopped. Also, if there is - // |extra_margin_|, we need to paint it more insetted. - const int inset = kBorderSize / 2 + extra_margin_; - bounds.Inset(inset, inset); + // view, resulting in this border looking chopped. + bounds.Inset(kBorderSize / 2, kBorderSize / 2); canvas->DrawRoundRect(bounds, corner_radius_, flags); } gfx::Insets WmHighlightItemBorder::GetInsets() const { - return gfx::Insets(kBorderSize + kBorderPadding + extra_margin_); + return gfx::Insets(kBorderSize + kBorderPadding); } gfx::Size WmHighlightItemBorder::GetMinimumSize() const { - const int minmum_length = 2 * (kBorderSize + kBorderPadding + extra_margin_); + const int minmum_length = 2 * (kBorderSize + kBorderPadding); return gfx::Size(minmum_length, minmum_length); }
diff --git a/ash/wm/wm_highlight_item_border.h b/ash/wm/wm_highlight_item_border.h index 72c6bad..429f523b 100644 --- a/ash/wm/wm_highlight_item_border.h +++ b/ash/wm/wm_highlight_item_border.h
@@ -22,8 +22,6 @@ explicit WmHighlightItemBorder(int corner_radius); ~WmHighlightItemBorder() override = default; - void set_extra_margin(int extra_margin) { extra_margin_ = extra_margin; } - // This highlight meant to indicate focus. No border will be painted if // |focused| is false. void SetFocused(bool focused); @@ -36,14 +34,6 @@ private: const int corner_radius_; - // Some views which use this border have padding for other UI purposes (ie. - // they paint their contents insetted from |View::GetLocalBounds()|. Such - // views are responsible for letting this class know how much padding is used - // so adjustments can be made accordingly. - // TODO(sammiequon): Change OverviewItemView to not have its own margin, then - // this won't be needed. - int extra_margin_ = 0; - DISALLOW_COPY_AND_ASSIGN(WmHighlightItemBorder); };
diff --git a/base/BUILD.gn b/base/BUILD.gn index a6da3e4..6f7ab0d 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3735,6 +3735,8 @@ "test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java", "test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java", "test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java", + "test/android/javatests/src/org/chromium/base/test/UiThreadStatement.java", + "test/android/javatests/src/org/chromium/base/test/UiThreadTest.java", "test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java", "test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java", "test/android/javatests/src/org/chromium/base/test/params/MethodParamAnnotationRule.java",
diff --git a/base/android/javatests/src/org/chromium/base/util/GarbageCollectionTestUtilsTest.java b/base/android/javatests/src/org/chromium/base/util/GarbageCollectionTestUtilsTest.java index f4eb6a73..5847888a 100644 --- a/base/android/javatests/src/org/chromium/base/util/GarbageCollectionTestUtilsTest.java +++ b/base/android/javatests/src/org/chromium/base/util/GarbageCollectionTestUtilsTest.java
@@ -11,7 +11,6 @@ import static org.chromium.base.GarbageCollectionTestUtils.canBeGarbageCollected; import android.graphics.Bitmap; -import android.support.test.annotation.UiThreadTest; import androidx.test.filters.SmallTest; @@ -20,6 +19,7 @@ import org.chromium.base.GarbageCollectionTestUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import java.lang.ref.WeakReference;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java index 498c2f6e..06acc8f 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
@@ -348,11 +348,23 @@ return false; } - /* + /** * Overriding this method to take screenshot of failure before tear down functions are run. */ @Override protected Statement withAfters(FrameworkMethod method, Object test, Statement base) { return super.withAfters(method, test, new ScreenshotOnFailureStatement(base)); } + + /** + * This function replicates the androidx AndroidJUnit4ClassRunner version of this function. + * We can delete this override when we migrate to androidx. + */ + @Override + protected Statement methodInvoker(FrameworkMethod method, Object test) { + if (UiThreadStatement.shouldRunOnUiThread(method)) { + return new UiThreadStatement(super.methodInvoker(method, test)); + } + return super.methodInvoker(method, test); + } }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/UiThreadStatement.java b/base/test/android/javatests/src/org/chromium/base/test/UiThreadStatement.java new file mode 100644 index 0000000..f996c56 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/UiThreadStatement.java
@@ -0,0 +1,44 @@ +// Copyright 2020 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.base.test; + +import android.support.test.InstrumentationRegistry; + +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; + +import java.util.concurrent.atomic.AtomicReference; + +/** + * junit {@link Statement} that runs a test method on the UI thread. + */ +/* package */ class UiThreadStatement extends Statement { + private final Statement mBase; + + public UiThreadStatement(Statement base) { + mBase = base; + } + + @Override + public void evaluate() throws Throwable { + final AtomicReference<Throwable> exceptionRef = new AtomicReference<>(); + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + try { + mBase.evaluate(); + } catch (Throwable throwable) { + exceptionRef.set(throwable); + } + }); + Throwable throwable = exceptionRef.get(); + if (throwable != null) throw throwable; + } + + /** + * @return True if the method is annotated with {@link UiThreadTest}. + */ + public static boolean shouldRunOnUiThread(FrameworkMethod method) { + return method.getAnnotation(UiThreadTest.class) != null; + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/UiThreadTest.java b/base/test/android/javatests/src/org/chromium/base/test/UiThreadTest.java new file mode 100644 index 0000000..73be56a --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/UiThreadTest.java
@@ -0,0 +1,24 @@ +// Copyright 2020 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.base.test; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that runs a test method on the UI thread. + * + * This is used in place of android.support.test.annotation.UiThreadTest, as ActivityTestRule will + * run on the UI thread if that annotation is present, possibly causing other Rules to unexpectedly + * run on the UI thread as well. + * + * UiThreadTestRule should be avoided altogether, as it causes @Before and @After to run on the UI + * thread, which most test writers do not expect. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface UiThreadTest {}
diff --git a/base/util/ranges/algorithm.h b/base/util/ranges/algorithm.h index 61791b5..4727a9d 100644 --- a/base/util/ranges/algorithm.h +++ b/base/util/ranges/algorithm.h
@@ -3503,7 +3503,161 @@ // [alg.merge] Merge // Reference: https://wg21.link/alg.merge -// TODO(crbug.com/1071094): Implement. +// Let `N` be `(last1 - first1) + (last2 - first2)`. +// +// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted +// with respect to `comp` and `proj1` or `proj2`, respectively. The resulting +// range does not overlap with either of the original ranges. +// +// Effects: Copies all the elements of the two ranges `[first1, last1)` and +// `[first2, last2)` into the range `[result, result_last)`, where `result_last` +// is `result + N`. If an element `a` precedes `b` in an input range, `a` is +// copied into the output range before `b`. If `e1` is an element of +// `[first1, last1)` and `e2` of `[first2, last2)`, `e2` is copied into the +// output range before `e1` if and only if +// `bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))` is `true`. +// +// Returns: `result_last`. +// +// Complexity: At most `N - 1` comparisons and applications of each projection. +// +// Remarks: Stable. +// +// Reference: https://wg21.link/alg.merge#:~:text=ranges::merge(I1 +template <typename InputIterator1, + typename InputIterator2, + typename OutputIterator, + typename Comp = ranges::less, + typename Proj1 = identity, + typename Proj2 = identity, + typename = internal::iterator_category_t<InputIterator1>, + typename = internal::iterator_category_t<InputIterator2>, + typename = internal::iterator_category_t<OutputIterator>, + typename = indirect_result_t<Comp&, + projected<InputIterator1, Proj1>, + projected<InputIterator2, Proj2>>, + typename = indirect_result_t<Comp&, + projected<InputIterator2, Proj2>, + projected<InputIterator1, Proj1>>> +constexpr auto merge(InputIterator1 first1, + InputIterator1 last1, + InputIterator2 first2, + InputIterator2 last2, + OutputIterator result, + Comp comp = {}, + Proj1 proj1 = {}, + Proj2 proj2 = {}) { + // Needs to opt-in to all permutations, since std::merge expects + // comp(proj2(lhs), proj1(rhs)) to compile. + return std::merge( + first1, last1, first2, last2, result, + internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2)); +} + +// Let `N` be `size(range1) + size(range2)`. +// +// Preconditions: The ranges `range1` and `range2` are sorted with respect to +// `comp` and `proj1` or `proj2`, respectively. The resulting range does not +// overlap with either of the original ranges. +// +// Effects: Copies all the elements of the two ranges `range1` and `range2` into +// the range `[result, result_last)`, where `result_last` is `result + N`. If an +// element `a` precedes `b` in an input range, `a` is copied into the output +// range before `b`. If `e1` is an element of `range1` and `e2` of `range2`, +// `e2` is copied into the output range before `e1` if and only if +// `bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))` is `true`. +// +// Returns: `result_last`. +// +// Complexity: At most `N - 1` comparisons and applications of each projection. +// +// Remarks: Stable. +// +// Reference: https://wg21.link/alg.merge#:~:text=ranges::merge(R1 +template <typename Range1, + typename Range2, + typename OutputIterator, + typename Comp = ranges::less, + typename Proj1 = identity, + typename Proj2 = identity, + typename = internal::range_category_t<Range1>, + typename = internal::range_category_t<Range2>, + typename = internal::iterator_category_t<OutputIterator>, + typename = indirect_result_t<Comp&, + projected<iterator_t<Range1>, Proj1>, + projected<iterator_t<Range2>, Proj2>>, + typename = indirect_result_t<Comp&, + projected<iterator_t<Range2>, Proj2>, + projected<iterator_t<Range1>, Proj1>>> +constexpr auto merge(Range1&& range1, + Range2&& range2, + OutputIterator result, + Comp comp = {}, + Proj1 proj1 = {}, + Proj2 proj2 = {}) { + return ranges::merge(ranges::begin(range1), ranges::end(range1), + ranges::begin(range2), ranges::end(range2), result, + std::move(comp), std::move(proj1), std::move(proj2)); +} + +// Preconditions: `[first, middle)` and `[middle, last)` are valid ranges sorted +// with respect to `comp` and `proj`. +// +// Effects: Merges two sorted consecutive ranges `[first, middle)` and +// `[middle, last)`, putting the result of the merge into the range +// `[first, last)`. The resulting range is sorted with respect to `comp` and +// `proj`. +// +// Returns: `last`. +// +// Complexity: Let `N = last - first`: If enough additional memory is available, +// exactly `N - 1` comparisons. Otherwise, `O(N log N)` comparisons. In either +// case, twice as many projections as comparisons. +// +// Remarks: Stable. +// +// Reference: https://wg21.link/alg.merge#:~:text=ranges::inplace_merge(I +template <typename BidirectionalIterator, + typename Comp = ranges::less, + typename Proj = identity, + typename = internal::iterator_category_t<BidirectionalIterator>> +constexpr auto inplace_merge(BidirectionalIterator first, + BidirectionalIterator middle, + BidirectionalIterator last, + Comp comp = {}, + Proj proj = {}) { + std::inplace_merge(first, middle, last, + internal::ProjectedBinaryPredicate(comp, proj, proj)); + return last; +} + +// Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid +// ranges sorted with respect to `comp` and `proj`. +// +// Effects: Merges two sorted consecutive ranges `[begin(range), middle)` and +// `[middle, end(range))`, putting the result of the merge into `range`. The +// resulting range is sorted with respect to `comp` and `proj`. +// +// Returns: `end(range)`. +// +// Complexity: Let `N = size(range)`: If enough additional memory is available, +// exactly `N - 1` comparisons. Otherwise, `O(N log N)` comparisons. In either +// case, twice as many projections as comparisons. +// +// Remarks: Stable. +// +// Reference: https://wg21.link/alg.merge#:~:text=ranges::inplace_merge(R +template <typename Range, + typename Comp = ranges::less, + typename Proj = identity, + typename = internal::range_category_t<Range>> +constexpr auto inplace_merge(Range&& range, + iterator_t<Range> middle, + Comp comp = {}, + Proj proj = {}) { + return ranges::inplace_merge(ranges::begin(range), middle, ranges::end(range), + std::move(comp), std::move(proj)); +} // [alg.set.operations] Set operations on sorted structures // Reference: https://wg21.link/alg.set.operations
diff --git a/base/util/ranges/algorithm_unittest.cc b/base/util/ranges/algorithm_unittest.cc index ec75706..cbd6eca 100644 --- a/base/util/ranges/algorithm_unittest.cc +++ b/base/util/ranges/algorithm_unittest.cc
@@ -1099,4 +1099,37 @@ EXPECT_EQ(ints + 2, ranges::partition_point(ints, lt_2, &Int::value)); } +TEST(RangesTest, Merge) { + int input1[] = {0, 2, 4, 6, 8}; + int input2[] = {1, 3, 5, 7, 9}; + int output[10]; + EXPECT_EQ(output + 10, + ranges::merge(input1, input1 + 5, input2, input2 + 5, output)); + EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + + Int ints1[] = {0, 2, 4, 6, 8}; + Int ints2[] = {1, 3, 5, 7, 9}; + Int outs[10]; + EXPECT_EQ(outs + 10, + ranges::merge(ints1, ints2, outs, {}, &Int::value, &Int::value)); + EXPECT_THAT(outs, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + + EXPECT_EQ(outs + 10, ranges::merge(input1, ints1, outs, {}, {}, &Int::value)); + EXPECT_THAT(outs, ElementsAre(0, 0, 2, 2, 4, 4, 6, 6, 8, 8)); + + EXPECT_EQ(outs + 10, ranges::merge(ints2, input2, outs, {}, &Int::value, {})); + EXPECT_THAT(outs, ElementsAre(1, 1, 3, 3, 5, 5, 7, 7, 9, 9)); +} + +TEST(RangesTest, InplaceMerge) { + int input[] = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9}; + EXPECT_EQ(input + 10, ranges::inplace_merge(input, input + 5, input + 10)); + EXPECT_THAT(input, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); + + Int ints[] = {8, 6, 4, 2, 0, 9, 7, 5, 3, 1}; + EXPECT_EQ(ints + 10, ranges::inplace_merge(ints, ints + 5, ranges::greater(), + &Int::value)); + EXPECT_THAT(ints, ElementsAre(9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); +} + } // namespace util
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index e9eccf26..a3290e1 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/android/build_vars.gni") import("//build/config/android/config.gni") import("//build/config/android/rules.gni") import("//build/config/python.gni") @@ -21,28 +22,6 @@ min_sdk_version = default_min_sdk_version } } - - # Write to a file some GN vars that are useful to scripts that use the output - # directory. Format is chosen as easliy importable by both python and bash. - _lines = [ - "android_sdk_build_tools=" + - rebase_path(android_sdk_build_tools, root_build_dir), - "android_sdk_build_tools_version=$android_sdk_build_tools_version", - "android_sdk_root=" + rebase_path(android_sdk_root, root_build_dir), - "android_sdk_version=$android_sdk_version", - "android_ndk_root=" + rebase_path(android_ndk_root, root_build_dir), - "android_tool_prefix=" + rebase_path(android_tool_prefix, root_build_dir), - "android_configuration_failure_dir=" + - rebase_path(android_configuration_failure_dir, root_build_dir), - "final_android_sdk=$final_android_sdk" - ] - if (defined(android_secondary_abi_cpu)) { - _secondary_label_info = - get_label_info(":foo($android_secondary_abi_toolchain)", "root_out_dir") - _lines += [ "android_secondary_abi_toolchain=" + - rebase_path(_secondary_label_info, root_build_dir) ] - } - write_file(android_build_vars, _lines) } python_library("devil_chromium_py") { @@ -98,7 +77,7 @@ "//third_party/catapult/tracing:convert_chart_json", ] data = [ - android_build_vars, + build_vars_file, android_readelf, ] } @@ -126,3 +105,19 @@ [ "//third_party/android_platform/development/scripts:stack_py" ] } } + +# GN evaluates each .gn file once per toolchain, so restricting to default +# toolchain will ensure write_file() is called only once. +assert(current_toolchain == default_toolchain) + +# NOTE: If other platforms would benefit from exporting variables, we should +# move this to a more top-level place. +# It is currently here (instead of //BUILD.gn) to ensure that the file is +# written even for non-chromium embedders of //build. +_build_vars_json = { + # Underscore prefix so that it appears at the top. + _HEADER = "Generated during 'gn gen' by //build/android/BUILD.gn." + forward_variables_from(android_build_vars_json, "*") +} + +write_file(build_vars_file, _build_vars_json, "json")
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py index 603d130..affa6c64 100755 --- a/build/android/gradle/generate_gradle.py +++ b/build/android/gradle/generate_gradle.py
@@ -29,6 +29,9 @@ from util import build_utils from util import resource_utils +sys.path.append(os.path.dirname(_BUILD_ANDROID)) +import gn_helpers + _DEPOT_TOOLS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'depot_tools') _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( @@ -106,11 +109,6 @@ output_file.write(data) -def _ReadPropertiesFile(path): - with open(path) as f: - return dict(l.rstrip().split('=', 1) for l in f if '=' in l) - - def _RunGnGen(output_dir, args=None): cmd = [os.path.join(_DEPOT_TOOLS_PATH, 'gn'), 'gen', output_dir] if args: @@ -825,10 +823,11 @@ for t in targets_from_args ] # Necessary after "gn clean" - if not os.path.exists(os.path.join(output_dir, 'build_vars.txt')): + if not os.path.exists( + os.path.join(output_dir, gn_helpers.BUILD_VARS_FILENAME)): _RunGnGen(output_dir) - build_vars = _ReadPropertiesFile(os.path.join(output_dir, 'build_vars.txt')) + build_vars = gn_helpers.ReadBuildVars(output_dir) jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) if args.beta: channel = 'beta'
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index 56ec117a..902c9de7 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -83,12 +83,6 @@ return files -def ReadBuildVars(path): - """Parses a build_vars.txt into a dict.""" - with open(path) as f: - return dict(l.rstrip().split('=', 1) for l in f) - - def ParseGnList(value): """Converts a "GN-list" command-line parameter into a list.
diff --git a/build/android/resource_sizes.py b/build/android/resource_sizes.py index cd80694..7f4f7ee 100755 --- a/build/android/resource_sizes.py +++ b/build/android/resource_sizes.py
@@ -35,14 +35,17 @@ _BUILD_UTILS_PATH = os.path.join( host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gyp') +with host_paths.SysPath(os.path.join(host_paths.DIR_SOURCE_ROOT, 'build')): + import gn_helpers # pylint: disable=import-error + with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import perf_tests_results_helper # pylint: disable=import-error + import perf_tests_results_helper # pylint: disable=import-error with host_paths.SysPath(host_paths.TRACING_PATH): - from tracing.value import convert_chart_json # pylint: disable=import-error + from tracing.value import convert_chart_json # pylint: disable=import-error with host_paths.SysPath(_BUILD_UTILS_PATH, 0): - from util import build_utils # pylint: disable=import-error + from util import build_utils # pylint: disable=import-error from util import zipalign # pylint: disable=import-error @@ -573,8 +576,7 @@ out_dir = constants.GetOutDirectory() except Exception: # pylint: disable=broad-except return out_dir, '' - build_vars = build_utils.ReadBuildVars( - os.path.join(out_dir, "build_vars.txt")) + build_vars = gn_helpers.ReadBuildVars(out_dir) tool_prefix = os.path.join(out_dir, build_vars['android_tool_prefix']) return out_dir, tool_prefix
diff --git a/build/config/android/build_vars.gni b/build/config/android/build_vars.gni new file mode 100644 index 0000000..a47607dc --- /dev/null +++ b/build/config/android/build_vars.gni
@@ -0,0 +1,29 @@ +# Copyright 2020 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/config/android/config.gni") + +# Contains useful GN variables that may be used by scripts that take +# --output-directory as an arg. +build_vars_file = "$root_build_dir/build_vars.json" + +android_build_vars_json = { + if (enable_java_templates) { + android_ndk_root = rebase_path(android_ndk_root, root_build_dir) + android_sdk_build_tools = + rebase_path(android_sdk_build_tools, root_build_dir) + android_sdk_build_tools_version = android_sdk_build_tools_version + android_sdk_root = rebase_path(android_sdk_root, root_build_dir) + android_sdk_version = android_sdk_version + android_tool_prefix = rebase_path(android_tool_prefix, root_build_dir) + final_android_sdk = final_android_sdk + + if (defined(android_secondary_abi_cpu)) { + android_secondary_abi_toolchain = + rebase_path(get_label_info(":foo($android_secondary_abi_toolchain)", + "root_out_dir"), + root_build_dir) + } + } +}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 87afc44..9be0dc1 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -84,7 +84,7 @@ public_android_sdk_root = "//third_party/android_sdk/public" if (android_sdk_release == "r") { default_android_sdk_root = public_android_sdk_root - default_android_sdk_version = 30 + default_android_sdk_version = "30" default_android_sdk_build_tools_version = "30.0.1" public_android_sdk = true } @@ -138,9 +138,6 @@ assert(defined(default_android_sdk_root), "SDK release " + android_sdk_release + " not recognized.") - # Where to write failed expectations for bots to read. - android_configuration_failure_dir = "$root_build_dir/failed_expectations" - declare_args() { android_ndk_root = default_android_ndk_root android_ndk_version = default_android_ndk_version @@ -250,9 +247,6 @@ enable_jdk_library_desugaring = false } - # Path to where selected build variables are written to. - android_build_vars = "$root_build_dir/build_vars.txt" - # Host stuff ----------------------------------------------------------------- # Defines the name the Android build gives to the current host CPU
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 12e30c6..24d239c 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -82,6 +82,9 @@ _desugar_jdk_libs_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/desugar_jdk_libs-1.0.5.jar" _desugar_runtime_jar = "$root_build_dir/obj/third_party/bazel/desugar/Desugar_runtime.processed.jar" +# Where to write failed expectations for bots to read. +_expectations_failure_dir = "$root_build_dir/failed_expectations" + _dexdump_path = "$android_sdk_build_tools/dexdump" _dexlayout_path = "//third_party/android_build_tools/art/dexlayout" _profman_path = "//third_party/android_build_tools/art/profman" @@ -1262,7 +1265,7 @@ ] _actual_file = "$target_gen_dir/$target_name.proguard_configs" _failure_file = - "$android_configuration_failure_dir/" + + "$_expectations_failure_dir/" + string_replace(invoker.expected_proguard_config, "/", "_") outputs = [ _actual_file ] args = _args + [ @@ -2641,7 +2644,7 @@ action_with_pydeps(_expectations_target) { _actual_file = "${invoker.android_manifest}.normalized" _failure_file = - "$android_configuration_failure_dir/" + + "$_expectations_failure_dir/" + string_replace(invoker.expected_android_manifest, "/", "_") inputs = [ invoker.android_manifest, @@ -2920,7 +2923,7 @@ action_with_pydeps(_expectations_target) { _actual_file = "$target_gen_dir/$target_name.libs_and_assets" _failure_file = - "$android_configuration_failure_dir/" + + "$_expectations_failure_dir/" + string_replace(invoker.expected_libs_and_assets, "/", "_") inputs = [ invoker.build_config, @@ -4140,7 +4143,7 @@ _expectations_target = "${invoker.top_target_name}_validate_libs_and_assets" action_with_pydeps(_expectations_target) { _actual_file = "$target_gen_dir/$target_name.libs_and_assets" - _failure_file = "$android_configuration_failure_dir/" + + _failure_file = "$_expectations_failure_dir/" + string_replace(invoker.expected_libs_and_assets, "/", "_") inputs = [ invoker.expected_libs_and_assets,
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 2bc56d8..37ef9526 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200807.3.1 +0.20200807.4.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 33a944e..2bc56d8 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200806.3.1 +0.20200807.3.1
diff --git a/build/gn_helpers.py b/build/gn_helpers.py index a240d80..8258658 100644 --- a/build/gn_helpers.py +++ b/build/gn_helpers.py
@@ -20,6 +20,7 @@ file to the build directory. """ +import json import os import re import sys @@ -27,6 +28,7 @@ _CHROMIUM_ROOT = os.path.join(os.path.dirname(__file__), os.pardir) +BUILD_VARS_FILENAME = 'build_vars.json' IMPORT_RE = re.compile(r'^import\("//(\S+)"\)') @@ -496,3 +498,9 @@ self.cur = end return True return False + + +def ReadBuildVars(output_directory): + """Parses $output_directory/build_vars.json into a dict.""" + with open(os.path.join(output_directory, BUILD_VARS_FILENAME)) as f: + return json.load(f)
diff --git a/build/gn_logs.gni b/build/gn_logs.gni new file mode 100644 index 0000000..79a92b9 --- /dev/null +++ b/build/gn_logs.gni
@@ -0,0 +1,8 @@ +# Copyright 2020 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/toolchain/concurrent_links.gni") + +# Log lines for gn_logs.txt that originate from within //build. +build_gn_logs = [ "#### get_concurrent_links.py ####" ] + concurrent_links_logs
diff --git a/build/toolchain/concurrent_links.gni b/build/toolchain/concurrent_links.gni index 258619ee..1f427ee6 100644 --- a/build/toolchain/concurrent_links.gni +++ b/build/toolchain/concurrent_links.gni
@@ -70,5 +70,11 @@ # TODO(crbug.com/617429) Pass more build configuration info to the script # so that we can compute better values. - concurrent_links = exec_script("get_concurrent_links.py", _args, "value") + _command_dict = exec_script("get_concurrent_links.py", _args, "scope") + + concurrent_links = _command_dict.concurrent_links + concurrent_links_logs = _command_dict.explanation +} else { + concurrent_links_logs = + [ "concurrent_links set by GN arg (value=$concurrent_links)" ] }
diff --git a/build/toolchain/get_concurrent_links.py b/build/toolchain/get_concurrent_links.py old mode 100644 new mode 100755 index e5121c77..df94ee9 --- a/build/toolchain/get_concurrent_links.py +++ b/build/toolchain/get_concurrent_links.py
@@ -1,3 +1,4 @@ +#!/usr/bin/env python # Copyright 2014 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. @@ -7,28 +8,32 @@ from __future__ import print_function +import argparse import multiprocessing -import optparse import os import re import subprocess import sys +sys.path.insert(1, os.path.join(os.path.dirname(__file__), '..')) +import gn_helpers + + def _GetTotalMemoryInBytes(): if sys.platform in ('win32', 'cygwin'): import ctypes class MEMORYSTATUSEX(ctypes.Structure): _fields_ = [ - ("dwLength", ctypes.c_ulong), - ("dwMemoryLoad", ctypes.c_ulong), - ("ullTotalPhys", ctypes.c_ulonglong), - ("ullAvailPhys", ctypes.c_ulonglong), - ("ullTotalPageFile", ctypes.c_ulonglong), - ("ullAvailPageFile", ctypes.c_ulonglong), - ("ullTotalVirtual", ctypes.c_ulonglong), - ("ullAvailVirtual", ctypes.c_ulonglong), - ("sullAvailExtendedVirtual", ctypes.c_ulonglong), + ("dwLength", ctypes.c_ulong), + ("dwMemoryLoad", ctypes.c_ulong), + ("ullTotalPhys", ctypes.c_ulonglong), + ("ullAvailPhys", ctypes.c_ulonglong), + ("ullTotalPageFile", ctypes.c_ulonglong), + ("ullAvailPageFile", ctypes.c_ulonglong), + ("ullTotalVirtual", ctypes.c_ulonglong), + ("ullAvailVirtual", ctypes.c_ulonglong), + ("sullAvailExtendedVirtual", ctypes.c_ulonglong), ] stat = MEMORYSTATUSEX(dwLength=ctypes.sizeof(MEMORYSTATUSEX)) @@ -53,34 +58,55 @@ def _GetDefaultConcurrentLinks(mem_per_link_gb, reserve_mem_gb): + explanation = [] + explanation.append('mem_per_link_gb={} reserve_mem_gb={}'.format( + mem_per_link_gb, reserve_mem_gb)) # Inherit the legacy environment variable for people that have set it in GYP. - pool_size = int(os.getenv('GYP_LINK_CONCURRENCY', 0)) - if pool_size: - return pool_size + num_links = int(os.getenv('GYP_LINK_CONCURRENCY', 0)) + if num_links: + reason = 'GYP_LINK_CONCURRENCY' + else: + mem_total_bytes = _GetTotalMemoryInBytes() + mem_total_bytes = max(0, mem_total_bytes - reserve_mem_gb * 2**30) + mem_cap = int(max(1, mem_total_bytes / mem_per_link_gb / 2**30)) + hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32))) - mem_total_bytes = _GetTotalMemoryInBytes() - mem_total_bytes = max(0, mem_total_bytes - reserve_mem_gb * 2**30) - num_concurrent_links = int(max(1, mem_total_bytes / mem_per_link_gb / 2**30)) - hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32))) + try: + cpu_cap = multiprocessing.cpu_count() + except: + cpu_cap = 1 - try: - cpu_cap = multiprocessing.cpu_count() - except: - cpu_cap = 1 + explanation.append('cpu_count={} mem_total_bytes={:.1f}GiB'.format( + cpu_cap, mem_total_bytes / 2**30)) - return min(num_concurrent_links, hard_cap, cpu_cap) + num_links = min(mem_cap, hard_cap, cpu_cap) + if num_links == cpu_cap: + reason = 'cpu_count' + elif num_links == hard_cap: + reason = 'GYP_LINK_CONCURRENCY_MAX' + else: + reason = 'RAM' + + explanation.append('concurrent_links={} (reason: {})'.format( + num_links, reason)) + return num_links, explanation def main(): - parser = optparse.OptionParser() - parser.add_option('--mem_per_link_gb', action="store", type="int", default=8) - parser.add_option('--reserve_mem_gb', action="store", type="int", default=0) - parser.disable_interspersed_args() - options, _ = parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument('--mem_per_link_gb', type=int, default=8) + parser.add_argument('--reserve_mem_gb', type=int, default=0) + options = parser.parse_args() - print(_GetDefaultConcurrentLinks(options.mem_per_link_gb, - options.reserve_mem_gb)) + num_links, explanation = _GetDefaultConcurrentLinks(options.mem_per_link_gb, + options.reserve_mem_gb) + sys.stdout.write( + gn_helpers.ToGNString({ + 'concurrent_links': num_links, + 'explanation': explanation, + })) return 0 + if __name__ == '__main__': sys.exit(main())
diff --git a/buildtools/DEPS b/buildtools/DEPS index 6d944a7..c2d737ba 100644 --- a/buildtools/DEPS +++ b/buildtools/DEPS
@@ -14,7 +14,7 @@ # # GN CIPD package version. - 'gn_version': 'git_revision:3028c6a426a4aaf6da91c4ebafe716ae370225fe', + 'gn_version': 'git_revision:e327ffdc503815916db2543ec000226a8df45163', # When changing these, also update the svn revisions in deps_revisions.gni 'clang_format_revision': '96636aa0e9f047f17447f2d45a094d0b59ed7917',
diff --git a/cc/metrics/compositor_timing_history.cc b/cc/metrics/compositor_timing_history.cc index 99873a01..0dbb826 100644 --- a/cc/metrics/compositor_timing_history.cc +++ b/cc/metrics/compositor_timing_history.cc
@@ -35,9 +35,6 @@ virtual void AddInvalidationToReadyToActivateDuration( base::TimeDelta duration, TreePriority priority) = 0; - virtual void AddReadyToActivateToWillActivateDuration( - base::TimeDelta duration, - bool pending_tree_is_impl_side) = 0; virtual void AddPrepareTilesDuration(base::TimeDelta duration) = 0; virtual void AddActivateDuration(base::TimeDelta duration) = 0; virtual void AddDrawDuration(base::TimeDelta duration) = 0; @@ -333,20 +330,6 @@ priority); } - void AddReadyToActivateToWillActivateDuration( - base::TimeDelta duration, - bool pending_tree_is_impl_side) override { - if (pending_tree_is_impl_side) { - UMA_HISTOGRAM_CUSTOM_TIMES_DURATION_SUFFIX( - "Scheduling.Renderer.ReadyToActivateToActivationDuration", ".Impl", - duration); - } else { - UMA_HISTOGRAM_CUSTOM_TIMES_DURATION_SUFFIX( - "Scheduling.Renderer.ReadyToActivateToActivationDuration", ".Main", - duration); - } - } - void AddPrepareTilesDuration(base::TimeDelta duration) override { UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( "Scheduling.Renderer.PrepareTilesDuration", duration); @@ -403,14 +386,6 @@ priority); } - void AddReadyToActivateToWillActivateDuration( - base::TimeDelta duration, - bool pending_tree_is_impl_side) override { - UMA_HISTOGRAM_CUSTOM_TIMES_DURATION_SUFFIX( - "Scheduling.Browser.ReadyToActivateToActivationDuration", ".Main", - duration); - } - void AddPrepareTilesDuration(base::TimeDelta duration) override { UMA_HISTOGRAM_CUSTOM_TIMES_DURATION( "Scheduling.Browser.PrepareTilesDuration", duration); @@ -442,9 +417,6 @@ void AddInvalidationToReadyToActivateDuration( base::TimeDelta duration, TreePriority priority) override {} - void AddReadyToActivateToWillActivateDuration( - base::TimeDelta duration, - bool pending_tree_is_impl_side) override {} void AddPrepareTilesDuration(base::TimeDelta duration) override {} void AddActivateDuration(base::TimeDelta duration) override {} void AddDrawDuration(base::TimeDelta duration) override {} @@ -802,16 +774,6 @@ compositor_frame_reporting_controller_->WillActivate(); activate_start_time_ = Now(); - // Its possible to activate the pending tree before it is ready for - // activation, for instance in the case of a context loss or visibility - // changes. - if (pending_tree_ready_to_activate_time_ != base::TimeTicks()) { - base::TimeDelta time_since_ready = - activate_start_time_ - pending_tree_ready_to_activate_time_; - uma_reporter_->AddReadyToActivateToWillActivateDuration( - time_since_ready, pending_tree_is_impl_side_); - } - pending_tree_is_impl_side_ = false; pending_tree_creation_time_ = base::TimeTicks(); pending_tree_ready_to_activate_time_ = base::TimeTicks();
diff --git a/cc/metrics/frame_sequence_metrics.cc b/cc/metrics/frame_sequence_metrics.cc index 4b7cc9b..6274d74 100644 --- a/cc/metrics/frame_sequence_metrics.cc +++ b/cc/metrics/frame_sequence_metrics.cc
@@ -313,6 +313,11 @@ const auto sequence_type = metrics->type(); DCHECK_LT(sequence_type, FrameSequenceTrackerType::kMaxType); + // All video frames are compositor thread only. + if (sequence_type == FrameSequenceTrackerType::kVideo && + thread_type == ThreadType::kMain) + return base::nullopt; + STATIC_HISTOGRAM_POINTER_GROUP( GetFrameSequenceLengthHistogramName(sequence_type), static_cast<int>(sequence_type),
diff --git a/cc/metrics/frame_sequence_metrics_unittest.cc b/cc/metrics/frame_sequence_metrics_unittest.cc index 622045b7..e99209a7 100644 --- a/cc/metrics/frame_sequence_metrics_unittest.cc +++ b/cc/metrics/frame_sequence_metrics_unittest.cc
@@ -87,6 +87,19 @@ } #endif // DCHECK_IS_ON() +TEST(FrameSequenceMetricsTest, VideoReportsOnImplOnly) { + base::HistogramTester histograms; + + FrameSequenceMetrics first(FrameSequenceTrackerType::kVideo, nullptr); + first.impl_throughput().frames_expected = 120; + first.impl_throughput().frames_produced = 80; + first.main_throughput().frames_expected = 0; + first.main_throughput().frames_produced = 0; + first.ReportMetrics(); + histograms.ExpectTotalCount("Graphics.Smoothness.FrameSequenceLength.Video", + 1u); +} + TEST(FrameSequenceMetricsTest, AllMetricsReported) { base::HistogramTester histograms;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 6659d1a6..4cc51fd 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -871,6 +871,7 @@ "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java", "//third_party/android_deps:com_googlecode_java_diff_utils_diffutils_java", "//third_party/android_sdk/androidx_browser:androidx_browser_java", + "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", "//third_party/blink/public:blink_headers_java", "//third_party/blink/public/mojom:android_mojo_bindings_java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index d542977..0d8cc73 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -800,6 +800,8 @@ "java/res/drawable/visa_card.xml", "java/res/drawable/zoom_in.xml", "java/res/drawable/zoom_out.xml", + "java/res/font/google_sans.xml", + "java/res/font/google_sans_medium.xml", "java/res/layout-sw360dp/preference_spinner_single_line.xml", "java/res/layout-sw600dp/find_toolbar.xml", "java/res/layout-sw600dp/location_bar.xml", @@ -1071,7 +1073,9 @@ "java/res/values-v21/styles.xml", "java/res/values-v24/styles.xml", "java/res/values-v25/styles.xml", + "java/res/values-v26/preloaded_fonts.xml", "java/res/values-v26/styles.xml", + "java/res/values-v27/preloaded_fonts.xml", "java/res/values-v27/styles.xml", "java/res/values-v28/styles.xml", "java/res/values-xhdpi/dimens.xml", @@ -1084,6 +1088,7 @@ "java/res/values/ic_launcher_alias.xml", "java/res/values/ic_launcher_round_alias.xml", "java/res/values/ids.xml", + "java/res/values/preloaded_fonts.xml", "java/res/values/strings.xml", "java/res/values/styles.xml", "java/res/values/values.xml",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 0cde30b..1b7c8a3 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -18,6 +18,7 @@ "javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java", "javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java", "javatests/src/org/chromium/chrome/browser/InstalledAppTest.java", + "javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java", "javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java", "javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java", "javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java",
diff --git a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected index 8e5197f..cbbdcfc 100644 --- a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected +++ b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
@@ -633,95 +633,6 @@ <category android:name="android.intent.category.DEFAULT"/> </intent-filter> # DIFF-ANCHOR: 9fe4b527 </activity-alias> # DIFF-ANCHOR: 7c349c4f - <activity-alias # DIFF-ANCHOR: 9da0e5b6 - android:exported="true" - android:name="com.google.android.apps.chrome.IntentDispatcher" - android:targetActivity="org.chromium.chrome.browser.document.ChromeLauncherActivity"> - <intent-filter> # DIFF-ANCHOR: a5330430 - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.NOTIFICATION_PREFERENCES"/> - </intent-filter> # DIFF-ANCHOR: a5330430 - <intent-filter> # DIFF-ANCHOR: 436dfef3 - <action android:name="android.intent.action.MEDIA_SEARCH"/> - <category android:name="android.intent.category.DEFAULT"/> - </intent-filter> # DIFF-ANCHOR: 436dfef3 - <intent-filter> # DIFF-ANCHOR: 8f70c92f - <action android:name="android.intent.action.SEARCH"/> - </intent-filter> # DIFF-ANCHOR: 8f70c92f - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:host="*"/> - <data android:mimeType="*/*"/> - <data android:pathPattern="/.*\\.mht"/> - <data android:pathPattern="/.*\\.mhtml"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:host="*"/> - <data android:pathPattern="/.*\\.mht"/> - <data android:pathPattern="/.*\\.mhtml"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="application/xhtml+xml"/> - <data android:mimeType="text/html"/> - <data android:mimeType="text/plain"/> - <data android:scheme="about"/> - <data android:scheme="content"/> - <data android:scheme="googlechrome"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:scheme="javascript"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:scheme="about"/> - <data android:scheme="googlechrome"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:scheme="javascript"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="message/rfc822"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="multipart/related"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 7a3b3be8 - <action android:name="android.nfc.action.NDEF_DISCOVERED"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - </intent-filter> # DIFF-ANCHOR: 7a3b3be8 - <intent-filter> # DIFF-ANCHOR: 2a3a3c3d - <action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/> - <category android:name="android.intent.category.DEFAULT"/> - </intent-filter> # DIFF-ANCHOR: 2a3a3c3d - <intent-filter> # DIFF-ANCHOR: 83919a44 - <action android:name="com.sec.android.airview.HOVER"/> - </intent-filter> # DIFF-ANCHOR: 83919a44 - <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/> - </activity-alias> # DIFF-ANCHOR: 9da0e5b6 <activity-alias # DIFF-ANCHOR: 5042984f android:exported="true" android:name="com.google.android.apps.chrome.Main" @@ -766,6 +677,134 @@ <data android:scheme="file"/> </intent-filter> # DIFF-ANCHOR: 13c9b0a8 </activity-alias> # DIFF-ANCHOR: b4a6221b + <activity-alias # DIFF-ANCHOR: 9da0e5b6 + android:exported="true" + android:name="com.google.android.apps.chrome.IntentDispatcher" + android:targetActivity="org.chromium.chrome.browser.document.ChromeLauncherActivity"> + <intent-filter tools:ignore="AppLinkUrlError"> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="application/xhtml+xml"/> + <data android:mimeType="text/html"/> + <data android:mimeType="text/plain"/> + <data android:scheme="about"/> + <data android:scheme="content"/> + <data android:scheme="googlechrome"/> + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:scheme="javascript"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: a5330430 + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.NOTIFICATION_PREFERENCES"/> + </intent-filter> # DIFF-ANCHOR: a5330430 + <intent-filter> # DIFF-ANCHOR: 436dfef3 + <action android:name="android.intent.action.MEDIA_SEARCH"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> # DIFF-ANCHOR: 436dfef3 + <intent-filter> # DIFF-ANCHOR: 8f70c92f + <action android:name="android.intent.action.SEARCH"/> + </intent-filter> # DIFF-ANCHOR: 8f70c92f + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:host="*"/> + <data android:mimeType="*/*"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\.mht"/> + <data android:pathPattern="/.*\\.mhtml"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:host="*"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\.mht"/> + <data android:pathPattern="/.*\\.mhtml"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="multipart/related"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:scheme="about"/> + <data android:scheme="googlechrome"/> + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:scheme="javascript"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="message/rfc822"/> + <data android:scheme="content"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="multipart/related"/> + <data android:scheme="content"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 7a3b3be8 + <action android:name="android.nfc.action.NDEF_DISCOVERED"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:scheme="http"/> + <data android:scheme="https"/> + </intent-filter> # DIFF-ANCHOR: 7a3b3be8 + <intent-filter> # DIFF-ANCHOR: 2a3a3c3d + <action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> # DIFF-ANCHOR: 2a3a3c3d + <intent-filter> # DIFF-ANCHOR: 83919a44 + <action android:name="com.sec.android.airview.HOVER"/> + </intent-filter> # DIFF-ANCHOR: 83919a44 + <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/> + </activity-alias> # DIFF-ANCHOR: 9da0e5b6 <meta-data android:name="android.allow_multiple_resumed_activities" android:value="true"/> <meta-data android:name="android.content.APP_RESTRICTIONS" android:resource="@xml/app_restrictions"/> <meta-data android:name="com.android.webview.WebViewLibrary" android:value="libmonochrome.so"/> @@ -779,6 +818,7 @@ <meta-data android:name="org.chromium.content.browser.NUM_SANDBOXED_SERVICES" android:value="40"/> <meta-data android:name="org.chromium.content.browser.REMOTE_MEDIA_PLAYERS" android:value="org.chromium.chrome.browser.media.remote.DefaultMediaRouteController"/> <meta-data android:name="org.chromium.content.browser.SMART_CLIP_PROVIDER" android:value="org.chromium.content_public.browser.SmartClipProvider"/> + <meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_google_sans_fonts"/> <provider # DIFF-ANCHOR: 2215b9cd android:authorities="$PACKAGE.ChromeBrowserProvider;$PACKAGE.browser;$PACKAGE" android:exported="true"
diff --git a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected index 06e44d1..e9a5542 100644 --- a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected +++ b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
@@ -590,95 +590,6 @@ <category android:name="android.intent.category.DEFAULT"/> </intent-filter> # DIFF-ANCHOR: 9fe4b527 </activity-alias> # DIFF-ANCHOR: 7c349c4f - <activity-alias # DIFF-ANCHOR: 9da0e5b6 - android:exported="true" - android:name="com.google.android.apps.chrome.IntentDispatcher" - android:targetActivity="org.chromium.chrome.browser.document.ChromeLauncherActivity"> - <intent-filter> # DIFF-ANCHOR: a5330430 - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.NOTIFICATION_PREFERENCES"/> - </intent-filter> # DIFF-ANCHOR: a5330430 - <intent-filter> # DIFF-ANCHOR: 436dfef3 - <action android:name="android.intent.action.MEDIA_SEARCH"/> - <category android:name="android.intent.category.DEFAULT"/> - </intent-filter> # DIFF-ANCHOR: 436dfef3 - <intent-filter> # DIFF-ANCHOR: 8f70c92f - <action android:name="android.intent.action.SEARCH"/> - </intent-filter> # DIFF-ANCHOR: 8f70c92f - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:host="*"/> - <data android:mimeType="*/*"/> - <data android:pathPattern="/.*\\.mht"/> - <data android:pathPattern="/.*\\.mhtml"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:host="*"/> - <data android:pathPattern="/.*\\.mht"/> - <data android:pathPattern="/.*\\.mhtml"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="application/xhtml+xml"/> - <data android:mimeType="text/html"/> - <data android:mimeType="text/plain"/> - <data android:scheme="about"/> - <data android:scheme="content"/> - <data android:scheme="googlechrome"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:scheme="javascript"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.BROWSABLE"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:scheme="about"/> - <data android:scheme="googlechrome"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - <data android:scheme="javascript"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="message/rfc822"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <action android:name="android.intent.action.VIEW"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:mimeType="multipart/related"/> - <data android:scheme="content"/> - <data android:scheme="file"/> - </intent-filter> # DIFF-ANCHOR: 13c9b0a8 - <intent-filter> # DIFF-ANCHOR: 7a3b3be8 - <action android:name="android.nfc.action.NDEF_DISCOVERED"/> - <category android:name="android.intent.category.DEFAULT"/> - <data android:scheme="http"/> - <data android:scheme="https"/> - </intent-filter> # DIFF-ANCHOR: 7a3b3be8 - <intent-filter> # DIFF-ANCHOR: 2a3a3c3d - <action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/> - <category android:name="android.intent.category.DEFAULT"/> - </intent-filter> # DIFF-ANCHOR: 2a3a3c3d - <intent-filter> # DIFF-ANCHOR: 83919a44 - <action android:name="com.sec.android.airview.HOVER"/> - </intent-filter> # DIFF-ANCHOR: 83919a44 - <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/> - </activity-alias> # DIFF-ANCHOR: 9da0e5b6 <activity-alias # DIFF-ANCHOR: 5042984f android:exported="true" android:name="com.google.android.apps.chrome.Main" @@ -723,6 +634,134 @@ <data android:scheme="file"/> </intent-filter> # DIFF-ANCHOR: 13c9b0a8 </activity-alias> # DIFF-ANCHOR: b4a6221b + <activity-alias # DIFF-ANCHOR: 9da0e5b6 + android:exported="true" + android:name="com.google.android.apps.chrome.IntentDispatcher" + android:targetActivity="org.chromium.chrome.browser.document.ChromeLauncherActivity"> + <intent-filter tools:ignore="AppLinkUrlError"> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="application/xhtml+xml"/> + <data android:mimeType="text/html"/> + <data android:mimeType="text/plain"/> + <data android:scheme="about"/> + <data android:scheme="content"/> + <data android:scheme="googlechrome"/> + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:scheme="javascript"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: a5330430 + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.NOTIFICATION_PREFERENCES"/> + </intent-filter> # DIFF-ANCHOR: a5330430 + <intent-filter> # DIFF-ANCHOR: 436dfef3 + <action android:name="android.intent.action.MEDIA_SEARCH"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> # DIFF-ANCHOR: 436dfef3 + <intent-filter> # DIFF-ANCHOR: 8f70c92f + <action android:name="android.intent.action.SEARCH"/> + </intent-filter> # DIFF-ANCHOR: 8f70c92f + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:host="*"/> + <data android:mimeType="*/*"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\.mht"/> + <data android:pathPattern="/.*\\.mhtml"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:host="*"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\..*\\.mht"/> + <data android:pathPattern="/.*\\..*\\.mhtml"/> + <data android:pathPattern="/.*\\.mht"/> + <data android:pathPattern="/.*\\.mhtml"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="multipart/related"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.BROWSABLE"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:scheme="about"/> + <data android:scheme="googlechrome"/> + <data android:scheme="http"/> + <data android:scheme="https"/> + <data android:scheme="javascript"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="message/rfc822"/> + <data android:scheme="content"/> + <data android:scheme="file"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="multipart/related"/> + <data android:scheme="content"/> + </intent-filter> # DIFF-ANCHOR: 13c9b0a8 + <intent-filter> # DIFF-ANCHOR: 7a3b3be8 + <action android:name="android.nfc.action.NDEF_DISCOVERED"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:scheme="http"/> + <data android:scheme="https"/> + </intent-filter> # DIFF-ANCHOR: 7a3b3be8 + <intent-filter> # DIFF-ANCHOR: 2a3a3c3d + <action android:name="android.speech.action.VOICE_SEARCH_RESULTS"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> # DIFF-ANCHOR: 2a3a3c3d + <intent-filter> # DIFF-ANCHOR: 83919a44 + <action android:name="com.sec.android.airview.HOVER"/> + </intent-filter> # DIFF-ANCHOR: 83919a44 + <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/> + </activity-alias> # DIFF-ANCHOR: 9da0e5b6 <meta-data android:name="android.allow_multiple_resumed_activities" android:value="true"/> <meta-data android:name="android.content.APP_RESTRICTIONS" android:resource="@xml/app_restrictions"/> <meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME" android:value="org.chromium.chrome.browser.media.router.caf.CastOptionsProvider"/> @@ -735,6 +774,7 @@ <meta-data android:name="org.chromium.content.browser.NUM_SANDBOXED_SERVICES" android:value="40"/> <meta-data android:name="org.chromium.content.browser.REMOTE_MEDIA_PLAYERS" android:value="org.chromium.chrome.browser.media.remote.DefaultMediaRouteController"/> <meta-data android:name="org.chromium.content.browser.SMART_CLIP_PROVIDER" android:value="org.chromium.content_public.browser.SmartClipProvider"/> + <meta-data android:name="preloaded_fonts" android:resource="@array/preloaded_google_sans_fonts"/> <provider # DIFF-ANCHOR: 2215b9cd android:authorities="$PACKAGE.ChromeBrowserProvider;$PACKAGE.browser;$PACKAGE" android:exported="true"
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java index 42a1752..8b92080 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java
@@ -14,7 +14,6 @@ import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_BOTTOM_BAR_VISIBLE; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -26,6 +25,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.start_surface.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java index 04a7cab..0d164c4 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java
@@ -14,7 +14,6 @@ import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_STACK_TAB_SWITCHER; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_MARGIN; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; @@ -25,6 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index ade54a9..23e316f 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -75,6 +75,7 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.DeferredStartupHandler; import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout; +import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator; import org.chromium.chrome.browser.feed.FeedSurfaceMediator; import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -990,6 +991,11 @@ StartSurfaceConfiguration.getHistogramName( FeedSurfaceMediator.FEED_CONTENT_FIRST_LOADED_TIME_MS_UMA, isInstantStart))); + Assert.assertEquals(expectedRecordCount, + RecordHistogram.getHistogramTotalCountForTesting( + StartSurfaceConfiguration.getHistogramName( + FeedSurfaceCoordinator.FEED_STREAM_CREATED_TIME_MS_UMA, + isInstantStart))); Assert.assertEquals(isInstantReturn() ? 1 : 0, RecordHistogram.getHistogramTotalCountForTesting( StartSurfaceConfiguration.getHistogramName(
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java index 593bb8d..2f2af60 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java
@@ -14,7 +14,6 @@ import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_STACK_TAB_SWITCHER; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_MARGIN; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; @@ -25,6 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java index e96f0de..92ccddd 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java
@@ -18,7 +18,6 @@ import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.TITLE; import android.graphics.drawable.BitmapDrawable; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -30,6 +29,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java index cf8a179e..3053713 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java
@@ -32,7 +32,6 @@ import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; -import android.support.test.annotation.UiThreadTest; import android.text.Editable; import android.text.TextWatcher; import android.view.View; @@ -45,6 +44,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager; import org.chromium.chrome.tab_ui.R;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TrendyTermsViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TrendyTermsViewBinderTest.java index 5b55b3e..5e3bea4 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TrendyTermsViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TrendyTermsViewBinderTest.java
@@ -8,7 +8,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import android.support.test.annotation.UiThreadTest; import android.view.View; import androidx.test.filters.SmallTest; @@ -17,6 +16,7 @@ import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java index 17adffaa..f7d42e9a 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java
@@ -7,7 +7,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import android.support.test.annotation.UiThreadTest; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; @@ -17,6 +16,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java index c601cf0f..504664c 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java
@@ -9,7 +9,6 @@ import android.content.res.ColorStateList; import android.content.res.Configuration; import android.graphics.Color; -import android.support.test.annotation.UiThreadTest; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -25,6 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java index 75f9b981..cced52f 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java
@@ -10,7 +10,6 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Build; -import android.support.test.annotation.UiThreadTest; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -29,6 +28,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.toolbar.ToolbarColors; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiViewBinderTest.java index eada18c..88296a4 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiViewBinderTest.java
@@ -10,7 +10,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import android.support.test.annotation.UiThreadTest; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -19,9 +18,11 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.toolbar.top.ToolbarPhone; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivityTestCase; @@ -43,19 +44,21 @@ public void setUpTest() throws Exception { super.setUpTest(); - mTopAnchorView = new ToolbarPhone(getActivity(), null); - mTopAnchorView.setId(R.id.toolbar); - mBottomAnchorView = new FrameLayout(getActivity()); - mParent = new TabGroupPopupUiParent(getActivity(), mTopAnchorView); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mTopAnchorView = new ToolbarPhone(getActivity(), null); + mTopAnchorView.setId(R.id.toolbar); + mBottomAnchorView = new FrameLayout(getActivity()); + mParent = new TabGroupPopupUiParent(getActivity(), mTopAnchorView); - mModel = new PropertyModel(TabGroupPopupUiProperties.ALL_KEYS); - mMCP = PropertyModelChangeProcessor.create( - mModel, mParent, TabGroupPopupUiViewBinder::bind); + mModel = new PropertyModel(TabGroupPopupUiProperties.ALL_KEYS); + mMCP = PropertyModelChangeProcessor.create( + mModel, mParent, TabGroupPopupUiViewBinder::bind); + }); } @Override public void tearDownTest() throws Exception { - mMCP.destroy(); + TestThreadUtils.runOnUiThreadBlocking(mMCP::destroy); super.tearDownTest(); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java index 6750eb7..1f606b1 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java
@@ -13,7 +13,6 @@ import android.content.res.ColorStateList; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.support.test.annotation.UiThreadTest; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -28,6 +27,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.toolbar.ToolbarColors; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java index acd85b6..9ec79d1 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java
@@ -12,7 +12,6 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.areAnimatorsEnabled; import android.graphics.drawable.ColorDrawable; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; @@ -29,6 +28,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.CommandLine; import org.chromium.base.MathUtils; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.flags.ChromeFeatureList;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java index c46b7e1..5b76d8d 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -13,7 +13,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -29,6 +28,7 @@ import org.junit.runner.RunWith; import org.chromium.base.Callback; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java index de9fe57..ce42fd9e 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java
@@ -9,7 +9,6 @@ import static junit.framework.Assert.assertTrue; import android.graphics.Rect; -import android.support.test.annotation.UiThreadTest; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.Button; @@ -25,6 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java index ed85c8b4..644100a 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -11,6 +11,7 @@ import android.graphics.Canvas; import android.os.Build; import android.os.Handler; +import android.os.SystemClock; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -47,6 +48,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.user_education.UserEducationHelper; +import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool; import org.chromium.components.browser_ui.widget.displaystyle.UiConfig; @@ -63,6 +65,9 @@ * Provides a surface that displays an interest feed rendered list of content suggestions. */ public class FeedSurfaceCoordinator implements FeedSurfaceProvider { + @VisibleForTesting + public static final String FEED_STREAM_CREATED_TIME_MS_UMA = "FeedStreamCreatedTime"; + private final Activity mActivity; private final SnackbarManager mSnackbarManager; @Nullable @@ -81,6 +86,7 @@ private FrameLayout mRootView; private ContextMenuManager mContextMenuManager; private Tracker mTracker; + private long mStreamCreatedTimeMs; // Homepage promo view will be not-null once we have it created, until it is destroyed. private @Nullable View mHomepagePromoView; @@ -311,6 +317,7 @@ } boolean isPlaceholderShownInV1 = mIsPlaceholderShown && !mV2Enabled; + mStreamCreatedTimeMs = SystemClock.elapsedRealtime(); if (mV2Enabled) { mStream = new FeedStream(mActivity, mShowDarkBackground, mSnackbarManager, @@ -501,6 +508,8 @@ public void onOverviewShownAtLaunch(long activityCreationTimeMs) { mMediator.onOverviewShownAtLaunch(activityCreationTimeMs, mIsPlaceholderShown); + StartSurfaceConfiguration.recordHistogram(FEED_STREAM_CREATED_TIME_MS_UMA, + mStreamCreatedTimeMs - activityCreationTimeMs, mIsPlaceholderShown); } Tracker getFeatureEngagementTracker() {
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/drivers/StreamDriver.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/drivers/StreamDriver.java index 9c8f2a54..29f62c4 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/drivers/StreamDriver.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/drivers/StreamDriver.java
@@ -46,7 +46,7 @@ import org.chromium.chrome.browser.feed.library.sharedstream.pendingdismiss.PendingDismissCallback; import org.chromium.chrome.browser.feed.library.sharedstream.removetrackingfactory.StreamRemoveTrackingFactory; import org.chromium.chrome.browser.feed.library.sharedstream.scroll.ScrollLogger; -import org.chromium.chrome.browser.feed.library.sharedstream.scroll.ScrollTracker; +import org.chromium.chrome.browser.feed.shared.ScrollTracker; import org.chromium.chrome.browser.feed.shared.stream.Stream.ContentChangedListener; import org.chromium.components.feed.core.proto.libraries.sharedstream.UiRefreshReasonProto.UiRefreshReason; import org.chromium.components.feed.core.proto.libraries.sharedstream.UiRefreshReasonProto.UiRefreshReason.Reason; @@ -124,8 +124,8 @@ this.mViewLoggingUpdater = viewLoggingUpdater; this.mTooltipApi = tooltipApi; this.mUiRefreshReason = uiRefreshReason; - mScrollTracker = new BasicStreamScrollTracker( - mainThreadRunner, new ScrollLogger(basicLoggingApi), clock, scrollMonitor); + mScrollTracker = + new BasicStreamScrollTracker(new ScrollLogger(basicLoggingApi), scrollMonitor); modelProvider.enableRemoveTracking( new StreamRemoveTrackingFactory(modelProvider, feedKnownContent));
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTracker.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTracker.java index 05e6a39f..9593d70 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTracker.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTracker.java
@@ -7,12 +7,10 @@ import android.view.View; import org.chromium.chrome.browser.feed.library.api.host.logging.ScrollType; -import org.chromium.chrome.browser.feed.library.common.concurrent.MainThreadRunner; -import org.chromium.chrome.browser.feed.library.common.time.Clock; import org.chromium.chrome.browser.feed.library.sharedstream.publicapi.scroll.ScrollObservable; import org.chromium.chrome.browser.feed.library.sharedstream.publicapi.scroll.ScrollObserver; import org.chromium.chrome.browser.feed.library.sharedstream.scroll.ScrollLogger; -import org.chromium.chrome.browser.feed.library.sharedstream.scroll.ScrollTracker; +import org.chromium.chrome.browser.feed.shared.ScrollTracker; /** A @link{ScrollTracker} used by BasicStream */ public class BasicStreamScrollTracker extends ScrollTracker { @@ -20,9 +18,7 @@ private final ScrollObserver mScrollObserver; private final ScrollObservable mScrollObservable; - public BasicStreamScrollTracker(MainThreadRunner mainThreadRunner, ScrollLogger scrollLogger, - Clock clock, ScrollObservable scrollObservable) { - super(mainThreadRunner, clock); + public BasicStreamScrollTracker(ScrollLogger scrollLogger, ScrollObservable scrollObservable) { this.mScrollLogger = scrollLogger; this.mScrollObservable = scrollObservable; this.mScrollObserver = new BasicStreamScrollObserver(); @@ -30,7 +26,7 @@ } @Override - protected void onScrollEvent(int scrollAmount, long timestamp) { + protected void onScrollEvent(int scrollAmount) { mScrollLogger.handleScroll(ScrollType.STREAM_SCROLL, scrollAmount); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTracker.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTracker.java deleted file mode 100644 index 79b599a..0000000 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTracker.java +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2019 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.feed.library.sharedstream.scroll; - -import androidx.annotation.Nullable; - -import org.chromium.chrome.browser.feed.library.common.concurrent.CancelableTask; -import org.chromium.chrome.browser.feed.library.common.concurrent.MainThreadRunner; -import org.chromium.chrome.browser.feed.library.common.time.Clock; - -/** - * Helper which is able to track a Scroll and aggregate them before sending the scroll events - * events. - */ -public abstract class ScrollTracker { - private static final String TAG = "ScrollTracker"; - // onScroll events are very noisy, so we collate them together to avoid over-reporting scrolls. - private static final long SCROLL_EVENT_COLLATE_MILLIS = 200L; - - private final MainThreadRunner mMainThreadRunner; - private final Clock mClock; - - @Nullable - protected ScrollNotifier mScrollNotifier; - @Nullable - protected CancelableTask mTask; - - public ScrollTracker(MainThreadRunner mainThreadRunner, Clock clock) { - this.mMainThreadRunner = mainThreadRunner; - this.mClock = clock; - } - - public void onUnbind() { - ScrollTracker.ScrollNotifier localScrollNotifier = mScrollNotifier; - if (localScrollNotifier != null) { - if (mTask != null) { - mTask.cancel(); - } - localScrollNotifier.run(); - } - } - - protected void trackScroll(int dx, int dy) { - boolean positiveScroll; - int amount; - if (dy == 0) { - return; - } - positiveScroll = dy > 0; - amount = dy; - - int previousTotalScroll = 0; - ScrollNotifier previousScrollNotifier = mScrollNotifier; - if (previousScrollNotifier != null && !(mTask != null && mTask.canceled())) { - if (previousScrollNotifier.mPositiveScroll == positiveScroll) { - // Same direction, so merge the existing scroll with the new one. - previousTotalScroll = previousScrollNotifier.mScrollAmount; - if (mTask != null) { - mTask.cancel(); - } - } - } - - amount += previousTotalScroll; - mScrollNotifier = new ScrollNotifier(positiveScroll, amount, mClock.currentTimeMillis()); - mTask = mMainThreadRunner.executeWithDelay( - TAG, mScrollNotifier, SCROLL_EVENT_COLLATE_MILLIS); - } - - protected abstract void onScrollEvent(int scrollAmount, long timestamp); - - private class ScrollNotifier implements Runnable { - final boolean mPositiveScroll; - final int mScrollAmount; - final long mTimestamp; - - public ScrollNotifier(boolean positiveScroll, int scrollAmount, long timestamp) { - this.mPositiveScroll = positiveScroll; - this.mScrollAmount = scrollAmount; - this.mTimestamp = timestamp; - } - - @Override - public void run() { - onScrollEvent(mScrollAmount, mTimestamp); - if (mScrollNotifier == this) { - mScrollNotifier = null; - if (mTask != null) { - mTask.cancel(); - } - } - } - } -}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/testing/conformance/scheduler/SchedulerConformanceTest.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/testing/conformance/scheduler/SchedulerConformanceTest.java index fbd70c39..615884b 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/testing/conformance/scheduler/SchedulerConformanceTest.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/testing/conformance/scheduler/SchedulerConformanceTest.java
@@ -6,6 +6,7 @@ import org.junit.Test; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.feed.library.api.host.scheduler.SchedulerApi; import org.chromium.chrome.browser.feed.library.api.host.scheduler.SchedulerApi.SessionState; @@ -16,24 +17,28 @@ protected SchedulerApi mScheduler; @Test + @UiThreadTest public void shouldSessionRequestData() { // Should not throw error mScheduler.shouldSessionRequestData(new SessionState(false, 0, false)); } @Test + @UiThreadTest public void onReceiveNewContent() { // Should not throw error mScheduler.onReceiveNewContent(System.currentTimeMillis()); } @Test + @UiThreadTest public void onRequestError_notFound() { // Should not throw error mScheduler.onRequestError(NOT_FOUND); } @Test + @UiThreadTest public void onRequestError_serverError() { // Should not throw error mScheduler.onRequestError(SERVER_ERROR);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ScrollTracker.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ScrollTracker.java new file mode 100644 index 0000000..66fbfdd --- /dev/null +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ScrollTracker.java
@@ -0,0 +1,74 @@ +// Copyright 2019 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.feed.shared; + +import androidx.annotation.Nullable; + +import org.chromium.base.task.PostTask; +import org.chromium.content_public.browser.UiThreadTaskTraits; + +/** + * Helper which is able to track a Scroll and aggregate them before sending the scroll events. + */ +public abstract class ScrollTracker { + // onScroll events are very noisy, so we collate them together to avoid over-reporting scrolls. + private static final long SCROLL_EVENT_COLLATE_MILLIS = 200L; + + @Nullable + private ReportFunction mPostedReportFunction; + + // If |mScrollAmount| is non-zero and should be reported when ReportFunction runs. + private boolean mReadyToReport; + // How much scrolling is currently unreported. May be negative. + private int mScrollAmount; + + public void onUnbind() { + reportAndReset(); + } + + public void trackScroll(int dx, int dy) { + if (dy == 0) { + return; + } + + if (mScrollAmount != 0 && (dy > 0) != (mScrollAmount > 0)) { + // Scroll direction changing, report it now. + reportAndReset(); + } + + mScrollAmount += dy; + if (mPostedReportFunction == null) { + mReadyToReport = true; + mPostedReportFunction = new ReportFunction(); + PostTask.postDelayedTask( + UiThreadTaskTraits.DEFAULT, mPostedReportFunction, SCROLL_EVENT_COLLATE_MILLIS); + } else { + mReadyToReport = false; + } + } + + private void reportAndReset() { + if (mScrollAmount != 0) { + onScrollEvent(mScrollAmount); + mScrollAmount = 0; + } + mReadyToReport = false; + } + + protected abstract void onScrollEvent(int scrollAmount); + + private class ReportFunction implements Runnable { + @Override + public void run() { + if (mReadyToReport) { + reportAndReset(); + mPostedReportFunction = null; + } else if (mScrollAmount != 0) { + mReadyToReport = true; + PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, mPostedReportFunction, + SCROLL_EVENT_COLLATE_MILLIS); + } + } + } +}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java index c239178..e717594 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java
@@ -53,11 +53,16 @@ return FeedServiceBridgeJni.get().getLoadMoreTriggerLookahead(); } + public static void reportOpenVisitComplete(long visitTimeMs) { + FeedServiceBridgeJni.get().reportOpenVisitComplete(visitTimeMs); + } + @NativeMethods interface Natives { boolean isEnabled(); void startup(); int getLoadMoreTriggerLookahead(); String getClientInstanceId(); + void reportOpenVisitComplete(long visitTimeMs); } }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java index 66935e87..7132efd 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
@@ -215,6 +215,7 @@ public void onScrolled(RecyclerView v, int dx, int dy) { super.onScrolled(v, dx, dy); checkScrollingForLoadMore(dy); + mFeedStreamSurface.streamScrolled(dx, dy); for (ScrollListener listener : mScrollListeners) { listener.onScrolled(dx, dy); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java index da2e4f4..58934920 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
@@ -24,6 +24,7 @@ import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.AppHooks; +import org.chromium.chrome.browser.feed.shared.ScrollTracker; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; @@ -32,6 +33,7 @@ import org.chromium.chrome.browser.offlinepages.RequestCoordinatorBridge; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.IdentityServicesProvider; +import org.chromium.chrome.browser.suggestions.NavigationRecorder; import org.chromium.chrome.browser.suggestions.SuggestionsConfig; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -99,6 +101,7 @@ private FeedSliceViewTracker mSliceViewTracker; private final NativePageNavigationDelegate mPageNavigationDelegate; private final HelpAndFeedback mHelpAndFeedback; + private final ScrollReporter mScrollReporter = new ScrollReporter(); private int mHeaderCount; private BottomSheetContent mBottomSheetContent; @@ -597,7 +600,7 @@ FeedStreamSurface.this, getSliceIdFromView(actionSourceView)); NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_SNIPPET); - openUrl(url, WindowOpenDisposition.NEW_FOREGROUND_TAB); + openUrl(url, WindowOpenDisposition.NEW_BACKGROUND_TAB); // Attempts to load more content if needed. maybeLoadMore(); @@ -793,6 +796,7 @@ if (feedCount > 0) { mContentManager.removeContents(mHeaderCount, feedCount); } + mScrollReporter.onUnbind(); untrackSurface(this); if (sStartupCalled) { @@ -815,6 +819,24 @@ mNativeFeedStreamSurface, FeedStreamSurface.this); if (tab != null) { tab.addObserver(new FeedTabNavigationObserver(inNewTab)); + NavigationRecorder.record(tab, + visitData -> FeedServiceBridge.reportOpenVisitComplete(visitData.duration)); + } + } + + // Called when the stream is scrolled. + void streamScrolled(int dx, int dy) { + FeedStreamSurfaceJni.get().reportStreamScrollStart( + mNativeFeedStreamSurface, FeedStreamSurface.this); + mScrollReporter.trackScroll(dx, dy); + } + + // Ingests scroll events and reports scroll completion back to native. + private class ScrollReporter extends ScrollTracker { + @Override + protected void onScrollEvent(int scrollAmount) { + FeedStreamSurfaceJni.get().reportStreamScrolled( + mNativeFeedStreamSurface, FeedStreamSurface.this, scrollAmount); } } @@ -844,10 +866,8 @@ void reportRemoveAction(long nativeFeedStreamSurface, FeedStreamSurface caller); void reportNotInterestedInAction(long nativeFeedStreamSurface, FeedStreamSurface caller); - // TODO(jianli): Call this function at the appropriate time. void reportStreamScrolled( long nativeFeedStreamSurface, FeedStreamSurface caller, int distanceDp); - // TODO(jianli): Call this function at the appropriate time. void reportStreamScrollStart(long nativeFeedStreamSurface, FeedStreamSurface caller); void loadMore( long nativeFeedStreamSurface, FeedStreamSurface caller, Callback<Boolean> callback);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java index 57c8273..b9a1ccb7 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedSchedulerBridgeConformanceTest.java
@@ -4,15 +4,11 @@ package org.chromium.chrome.browser.feed; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.After; import org.junit.Before; import org.junit.Rule; -import org.junit.rules.RuleChain; -import org.junit.runner.Description; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -25,6 +21,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.Arrays; import java.util.List; @@ -46,14 +43,7 @@ new ParameterSet().value(true).name("withRequestManager")); @Rule - public RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule() { - @Override - protected boolean shouldRunOnUiThread(Description description) { - // FeedSchedulerBridge requires the used methods to be called on the UI Thread. - return true; - } - }); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); @Mock private RequestManager mRequestManager; @@ -66,15 +56,17 @@ @Before public void setUp() { // The scheduler is declared and tested in SchedulerConformanceTest. - mScheduler = new FeedSchedulerBridge(Profile.getLastUsedRegularProfile()); - if (mUseRequestManager) { - ((FeedSchedulerBridge) mScheduler).initializeFeedDependencies(mRequestManager); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + mScheduler = new FeedSchedulerBridge(Profile.getLastUsedRegularProfile()); + if (mUseRequestManager) { + ((FeedSchedulerBridge) mScheduler).initializeFeedDependencies(mRequestManager); + } + }); } @After public void tearDown() { - ((FeedSchedulerBridge) mScheduler).destroy(); + TestThreadUtils.runOnUiThreadBlocking(() -> ((FeedSchedulerBridge) mScheduler).destroy()); mScheduler = null; } }
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTrackerTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTrackerTest.java index 8d134f0..0df70b9 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTrackerTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/internal/scroll/BasicStreamScrollTrackerTest.java
@@ -15,8 +15,6 @@ import org.robolectric.annotation.Config; import org.chromium.chrome.browser.feed.library.api.host.logging.ScrollType; -import org.chromium.chrome.browser.feed.library.common.concurrent.testing.FakeMainThreadRunner; -import org.chromium.chrome.browser.feed.library.common.time.testing.FakeClock; import org.chromium.chrome.browser.feed.library.sharedstream.publicapi.scroll.ScrollObservable; import org.chromium.chrome.browser.feed.library.sharedstream.publicapi.scroll.ScrollObserver; import org.chromium.chrome.browser.feed.library.sharedstream.scroll.ScrollLogger; @@ -30,16 +28,13 @@ private ScrollLogger mLogger; @Mock private ScrollObservable mScrollObservable; - private final FakeClock mClock = new FakeClock(); - private final FakeMainThreadRunner mMainThreadRunner = FakeMainThreadRunner.queueAllTasks(); private BasicStreamScrollTracker mScrollTracker; @Before public void setUp() { initMocks(this); - mScrollTracker = - new BasicStreamScrollTracker(mMainThreadRunner, mLogger, mClock, mScrollObservable); + mScrollTracker = new BasicStreamScrollTracker(mLogger, mScrollObservable); verify(mScrollObservable).addScrollObserver(any(ScrollObserver.class)); } @@ -53,7 +48,7 @@ public void onScrollEvent() { int scrollAmount = 10; long timestamp = 10L; - mScrollTracker.onScrollEvent(scrollAmount, timestamp); + mScrollTracker.onScrollEvent(scrollAmount); verify(mLogger).handleScroll(ScrollType.STREAM_SCROLL, scrollAmount); } }
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTrackerTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTrackerTest.java deleted file mode 100644 index a119dc3..0000000 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTrackerTest.java +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2019 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.feed.library.sharedstream.scroll; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.MockitoAnnotations.initMocks; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; - -import org.chromium.chrome.browser.feed.library.common.concurrent.testing.FakeMainThreadRunner; -import org.chromium.chrome.browser.feed.library.common.time.testing.FakeClock; -import org.chromium.testing.local.LocalRobolectricTestRunner; - -import java.util.ArrayList; - -/** Tests for {@link ScrollTracker}. */ -@RunWith(LocalRobolectricTestRunner.class) -@Config(manifest = Config.NONE) -public final class ScrollTrackerTest { - private static final long AGGREGATE_TIME_MS = 200L; - private final FakeClock mClock = new FakeClock(); - private ScrollTrackerForTest mScrollTracker; - private final FakeMainThreadRunner mMainThreadRunner = FakeMainThreadRunner.create(mClock); - - @Before - public void setUp() { - initMocks(this); - mScrollTracker = new ScrollTrackerForTest(mMainThreadRunner, mClock); - } - - @Test - public void testSinglePositiveScroll_scrollWrongDirection() { - mScrollTracker.trackScroll(10, 0); - mClock.advance(AGGREGATE_TIME_MS); - - assertThat(mScrollTracker.scrollAmounts).isEmpty(); - } - - @Test - public void testNoScroll() { - mScrollTracker.trackScroll(0, 0); - mClock.advance(AGGREGATE_TIME_MS); - - assertThat(mScrollTracker.scrollAmounts).isEmpty(); - } - - @Test - public void testSinglePositiveScroll_notEnoughTime() { - mScrollTracker.trackScroll(0, 10); - mClock.advance(AGGREGATE_TIME_MS - 1); - - assertThat(mScrollTracker.scrollAmounts).isEmpty(); - } - - @Test - public void testSinglePositiveScroll() { - mScrollTracker.trackScroll(0, 10); - mClock.advance(AGGREGATE_TIME_MS); - - assertThat(mScrollTracker.scrollAmounts).containsExactly(10); - } - - @Test - public void testDoublePositiveScroll_singleTask() { - mScrollTracker.trackScroll(0, 10); - mScrollTracker.trackScroll(0, 5); - mClock.advance(AGGREGATE_TIME_MS); - - assertThat(mScrollTracker.scrollAmounts).containsExactly(15); - } - - @Test - public void testDoublePositiveScroll_doubleTask() { - mScrollTracker.trackScroll(0, 10); - mClock.advance(AGGREGATE_TIME_MS); - mScrollTracker.trackScroll(0, 5); - mClock.advance(AGGREGATE_TIME_MS); - - assertThat(mScrollTracker.scrollAmounts).containsExactly(10, 5).inOrder(); - } - - @Test - public void testSwitchScroll() { - mScrollTracker.trackScroll(0, 10); - mClock.advance(1L); - mScrollTracker.trackScroll(0, -5); - mClock.advance(AGGREGATE_TIME_MS); - - assertThat(mScrollTracker.scrollAmounts).containsExactly(10, -5).inOrder(); - } - - static class ScrollTrackerForTest extends ScrollTracker { - public ArrayList<Integer> scrollAmounts; - - ScrollTrackerForTest(FakeMainThreadRunner mainThreadRunner, FakeClock clock) { - super(mainThreadRunner, clock); - scrollAmounts = new ArrayList<>(); - } - - @Override - protected void onScrollEvent(int scrollAmount, long timestamp) { - scrollAmounts.add(scrollAmount); - } - } -}
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni index 656c437..7bb4cbb2 100644 --- a/chrome/android/feed/feed_java_sources.gni +++ b/chrome/android/feed/feed_java_sources.gni
@@ -374,9 +374,9 @@ "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollListenerNotifier.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollLogger.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollRestoreHelper.java", - "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTracker.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/FeedSurfaceDelegate.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/FeedSurfaceProvider.java", + "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/ScrollTracker.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/Header.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/NonDismissibleHeader.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/shared/stream/Stream.java", @@ -638,7 +638,6 @@ "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollListenerNotifierTest.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollLoggerTest.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollRestoreHelperTest.java", - "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/sharedstream/scroll/ScrollTrackerTest.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/shared/ui/MaterialSpinnerViewTest.java", "junit/src/org/chromium/chrome/browser/feed/FeedApplicationInfoTest.java", "junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java", @@ -649,6 +648,7 @@ "junit/src/org/chromium/chrome/browser/feed/FutureTaskConsumerTest.java", "junit/src/org/chromium/chrome/browser/feed/NtpStreamLifecycleManagerTest.java", "junit/src/org/chromium/chrome/browser/feed/action/FeedActionHandlerTest.java", + "junit/src/org/chromium/chrome/browser/feed/shared/ScrollTrackerTest.java", "junit/src/org/chromium/chrome/browser/feed/v2/FakeLinearLayoutManager.java", "junit/src/org/chromium/chrome/browser/feed/v2/FeedListContentManagerTest.java", "junit/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTrackerTest.java",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 13a3bea6..a929217 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -210,17 +210,17 @@ {% block common_view_intent_shared_filter_body %} <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> {% if channel in ['stable', 'default'] %}<data android:scheme="googlechrome" />{% endif %} <data android:scheme="http" /> <data android:scheme="https" /> <data android:scheme="about" /> <data android:scheme="javascript" /> {% endblock %} + <category android:name="android.intent.category.BROWSABLE" /> </intent-filter> <!-- Same filter as above but with MIME types. Intents that do not specify a MIME type won't match. --> - <intent-filter> + <intent-filter tools:ignore="AppLinkUrlError"> {{ self.common_view_intent_shared_filter_body() }} <data android:scheme="content" /> <data android:mimeType="text/html"/> @@ -231,7 +231,13 @@ <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="file"/> + <data android:mimeType="multipart/related"/> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="content"/> <data android:mimeType="multipart/related"/> </intent-filter> @@ -248,10 +254,11 @@ <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="file"/> - <data android:scheme="content"/> <data android:host="*" /> - <data android:pathPattern="/.*\\.mhtml"/> - <data android:pathPattern="/.*\\.mht"/> + {% for i in range(10) %} + <data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.mhtml" /> + <data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.mht" /> + {% endfor %} {% endblock %} </intent-filter> <!-- Same filter as above but with mimeType="*/*". Used for @@ -263,21 +270,24 @@ <!-- Web Bundles (.wbn) support --> {% if channel in ['dev', 'canary', 'default'] %} <intent-filter> + {% block wbn_view_intent_shared_filter_body %} <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="file" /> - <data android:scheme="content" /> - <data android:mimeType="*/*" /> <data android:host="*" /> {% for i in range(10) %} <data android:pathPattern="/.*{{ '\\\\..*' * i }}\\.wbn" /> {% endfor %} + {% endblock %} </intent-filter> <intent-filter> + {{ self.wbn_view_intent_shared_filter_body() }} + <data android:mimeType="*/*"/> + </intent-filter> + <intent-filter tools:ignore="AppLinkUrlError"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="content" /> <data android:mimeType="application/webbundle" /> </intent-filter> @@ -1178,6 +1188,10 @@ <meta-data android:name="org.chromium.content.browser.REMOTE_MEDIA_PLAYERS" android:value="org.chromium.chrome.browser.media.remote.DefaultMediaRouteController"/> + <!-- Downloads Google Sans from GMS Core --> + <meta-data android:name="preloaded_fonts" + android:resource="@array/preloaded_google_sans_fonts" /> + {% endblock %} {% block extra_application_definitions_for_test %} {% endblock %}
diff --git a/chrome/android/java/res/font/google_sans.xml b/chrome/android/java/res/font/google_sans.xml new file mode 100644 index 0000000..3728b718 --- /dev/null +++ b/chrome/android/java/res/font/google_sans.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<font-family + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + tools:ignore="FontValidationError,FontValidationWarning,UnusedResources" + android:fontProviderAuthority="com.google.android.gms.fonts" + android:fontProviderCerts="@array/com_google_android_gms_fonts_certs" + android:fontProviderPackage="com.google.android.gms" + android:fontProviderQuery="Google Sans" + app:fontProviderAuthority="com.google.android.gms.fonts" + app:fontProviderCerts="@array/com_google_android_gms_fonts_certs" + app:fontProviderPackage="com.google.android.gms" + app:fontProviderQuery="Google Sans" />
diff --git a/chrome/android/java/res/font/google_sans_medium.xml b/chrome/android/java/res/font/google_sans_medium.xml new file mode 100644 index 0000000..c65671d6 --- /dev/null +++ b/chrome/android/java/res/font/google_sans_medium.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<font-family + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + tools:ignore="FontValidationError,FontValidationWarning,UnusedResources" + android:fontProviderAuthority="com.google.android.gms.fonts" + android:fontProviderCerts="@array/com_google_android_gms_fonts_certs" + android:fontProviderPackage="com.google.android.gms" + android:fontProviderQuery="Google Sans:500" + app:fontProviderAuthority="com.google.android.gms.fonts" + app:fontProviderCerts="@array/com_google_android_gms_fonts_certs" + app:fontProviderPackage="com.google.android.gms" + app:fontProviderQuery="Google Sans:500"/>
diff --git a/chrome/android/java/res/values-v26/preloaded_fonts.xml b/chrome/android/java/res/values-v26/preloaded_fonts.xml new file mode 100644 index 0000000..c6d4a67 --- /dev/null +++ b/chrome/android/java/res/values-v26/preloaded_fonts.xml
@@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources"> + <!-- + Fonts that are specified to be preloaded by AndroidManifest.xml. + + Note: we override this resource in API 26 so that we can provide an empty array to preload on + Android O which will crash when preloading fonts because of a platform bug. + b/67327250 or b/111754038 + --> + <array name="preloaded_google_sans_fonts"/> +</resources>
diff --git a/chrome/android/java/res/values-v27/preloaded_fonts.xml b/chrome/android/java/res/values-v27/preloaded_fonts.xml new file mode 100644 index 0000000..1bfe964c --- /dev/null +++ b/chrome/android/java/res/values-v27/preloaded_fonts.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources"> + <!-- + Fonts that are specified to be preloaded by AndroidManifest.xml. + + Note: we override this resource in API 26 so that we can provide an empty array to preload on + Android O which will crash when preloading fonts because of a platform bug. + b/67327250 or b/111754038 + --> + <array name="preloaded_google_sans_fonts"> + <item>@font/google_sans</item> + <item>@font/google_sans_medium</item> + </array> +</resources>
diff --git a/chrome/android/java/res/values/preloaded_fonts.xml b/chrome/android/java/res/values/preloaded_fonts.xml new file mode 100644 index 0000000..1bfe964c --- /dev/null +++ b/chrome/android/java/res/values/preloaded_fonts.xml
@@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources"> + <!-- + Fonts that are specified to be preloaded by AndroidManifest.xml. + + Note: we override this resource in API 26 so that we can provide an empty array to preload on + Android O which will crash when preloading fonts because of a platform bug. + b/67327250 or b/111754038 + --> + <array name="preloaded_google_sans_fonts"> + <item>@font/google_sans</item> + <item>@font/google_sans_medium</item> + </array> +</resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index 2067734..33776b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -2432,7 +2432,8 @@ @Nullable private PaymentRequestClient getClient() { - return mComponentPaymentRequestImpl.getClient(); + return mComponentPaymentRequestImpl == null ? null + : mComponentPaymentRequestImpl.getClient(); } // Pre-condition: the client is not null.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java new file mode 100644 index 0000000..9c67e1e --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentFilterUnitTest.java
@@ -0,0 +1,137 @@ +// Copyright 2020 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; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; + +import androidx.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; + +/** + * Unit tests for Intent Filters in chrome/android/java/AndroidManifest.xml + */ +@RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.UNIT_TESTS) +public class IntentFilterUnitTest { + private static final Uri HTTPS_URI = Uri.parse("https://www.example.com/index.html"); + private static final Uri CONTENT_URI = Uri.parse("content://package/path/id"); + private static final Uri HTML_URI = Uri.parse("file:///path/filename.html"); + private static final Uri MHTML_URI = Uri.parse("file:///path/to/.file/site.mhtml"); + private static final Uri WBN_URI = Uri.parse("file:///path/to/.file/site.wbn"); + + // Some apps (like ShareIt) specify a file URI along with a mime type. We don't care what + // this mime type is and trust the file extension. + private static final String ANY_MIME = "bad/mime"; + + private Intent mIntent; + private PackageManager mPm; + + @Before + public void setUp() { + mPm = ContextUtils.getApplicationContext().getPackageManager(); + mIntent = new Intent(); + mIntent.setPackage(ContextUtils.getApplicationContext().getPackageName()); + } + + private void verifyIntent(boolean supported) { + ComponentName component = mIntent.resolveActivity(mPm); + if (supported) { + Assert.assertNotNull(component); + } else { + Assert.assertNull(component); + } + } + + @Test + @SmallTest + public void testIgnoredMimeType() { + mIntent.setDataAndType(CONTENT_URI, "application/octet-stream"); + verifyIntent(false); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(false); + } + + @Test + @SmallTest + public void testHttpsUri() { + mIntent.setData(HTTPS_URI); + verifyIntent(true); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(true); + } + + @Test + @SmallTest + public void testHtmlFileUri() { + mIntent.setData(HTML_URI); + verifyIntent(false); + mIntent.setType("text/html"); + verifyIntent(false); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(false); + } + + @Test + @SmallTest + public void testHtmlContentUri() { + mIntent.setDataAndType(CONTENT_URI, "text/html"); + verifyIntent(true); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(false); + } + + @Test + @SmallTest + public void testMhtmlUri() { + mIntent.setData(MHTML_URI); + verifyIntent(true); + // Note that calling setType() would clear the Data... + mIntent.setDataAndType(MHTML_URI, ANY_MIME); + verifyIntent(true); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(true); + } + + @Test + @SmallTest + public void testContentMhtmlUri() { + mIntent.setDataAndType(CONTENT_URI, "multipart/related"); + verifyIntent(true); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(false); + } + + @Test + @SmallTest + public void testWbnUri() { + mIntent.setData(WBN_URI); + verifyIntent(true); + // Note that calling setType() would clear the Data... + mIntent.setDataAndType(WBN_URI, ANY_MIME); + verifyIntent(true); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(true); + } + + @Test + @SmallTest + public void testContentWbnUri() { + mIntent.setDataAndType(CONTENT_URI, "application/webbundle"); + verifyIntent(true); + mIntent.addCategory(Intent.CATEGORY_BROWSABLE); + verifyIntent(false); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java index a641cf56..02d0ab9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java
@@ -16,8 +16,6 @@ import android.provider.Browser; import android.speech.RecognizerResultsIntent; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.browser.customtabs.CustomTabsService; import androidx.browser.customtabs.CustomTabsSessionToken; @@ -33,6 +31,7 @@ import org.chromium.base.CollectionUtil; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.browserservices.OriginVerifier; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; @@ -55,9 +54,8 @@ @RunWith(BaseJUnit4ClassRunner.class) public class IntentHandlerTest { @Rule - public final RuleChain mChain = RuleChain.outerRule(new CommandLineInitRule(null)) - .around(new ChromeBrowserTestRule()) - .around(new UiThreadTestRule()); + public final RuleChain mChain = + RuleChain.outerRule(new CommandLineInitRule(null)).around(new ChromeBrowserTestRule()); private static final String VOICE_SEARCH_QUERY = "VOICE_QUERY"; private static final String VOICE_SEARCH_QUERY_URL = "http://www.google.com/?q=VOICE_QUERY";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java index c49a5307..a499e63 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; @@ -16,10 +14,10 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.task.PostTask; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterProvider; @@ -40,7 +38,6 @@ import org.chromium.net.test.EmbeddedTestServer; import java.util.Arrays; -import java.util.concurrent.Callable; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -60,8 +57,7 @@ } @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private WarmupManager mWarmupManager; private Context mContext; @@ -71,13 +67,9 @@ mContext = InstrumentationRegistry.getInstrumentation() .getTargetContext() .getApplicationContext(); - TestThreadUtils.runOnUiThreadBlocking(new Callable<Void>() { - @Override - public Void call() { - ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); - mWarmupManager = WarmupManager.getInstance(); - return null; - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); + mWarmupManager = WarmupManager.getInstance(); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java index 0f39c5c..413d3062 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
@@ -4,19 +4,16 @@ package org.chromium.chrome.browser.bookmarks; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.profiles.Profile; @@ -36,8 +33,7 @@ @RunWith(BaseJUnit4ClassRunner.class) public class BookmarkBridgeTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private BookmarkBridge mBookmarkBridge; private BookmarkId mMobileNode;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java index 931c522..f36f7bf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java
@@ -4,19 +4,16 @@ package org.chromium.chrome.browser.bookmarks; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.profiles.Profile; @@ -38,8 +35,7 @@ @RunWith(BaseJUnit4ClassRunner.class) public class BookmarkModelTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private static final int TIMEOUT_MS = 5000; private BookmarkModel mBookmarkModel;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java index eefaaf34..fcd5292 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
@@ -6,21 +6,20 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * Tests logic in the OverlayPanelBase. @@ -34,9 +33,6 @@ private static final float MOCK_EXPANDED_HEIGHT = 400.0f; private static final float MOCK_MAXIMIZED_HEIGHT = 600.0f; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - MockOverlayPanel mNoExpandPanel; MockOverlayPanel mExpandPanel; @@ -97,11 +93,13 @@ @Before public void setUp() { - OverlayPanelManager panelManager = new OverlayPanelManager(); - mExpandPanel = - new MockOverlayPanel(InstrumentationRegistry.getTargetContext(), panelManager); - mNoExpandPanel = new NoExpandMockOverlayPanel( - InstrumentationRegistry.getTargetContext(), panelManager); + TestThreadUtils.runOnUiThreadBlocking(() -> { + OverlayPanelManager panelManager = new OverlayPanelManager(); + mExpandPanel = + new MockOverlayPanel(InstrumentationRegistry.getTargetContext(), panelManager); + mNoExpandPanel = new NoExpandMockOverlayPanel( + InstrumentationRegistry.getTargetContext(), panelManager); + }); } // Start OverlayPanelBase test suite.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java index 6d41425..13b9012 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewGroup; @@ -16,13 +14,14 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.compositor.layouts.eventfilter.OverlayPanelEventFilter; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.test.util.TestThreadUtils; /** * Class responsible for testing the OverlayPanelEventFilter. @@ -61,9 +60,6 @@ // OverlayPanelEventFilterWrapper // -------------------------------------------------------------------------------------------- - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - /** * Wrapper around OverlayPanelEventFilter used by tests. */ @@ -213,16 +209,18 @@ mDpToPx = context.getResources().getDisplayMetrics().density; mTouchSlopDp = ViewConfiguration.get(context).getScaledTouchSlop() / mDpToPx; - mPanel = new MockOverlayPanel(context, new OverlayPanelManager()); - mEventFilter = new OverlayPanelEventFilterWrapper(context, mPanel); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mPanel = new MockOverlayPanel(context, new OverlayPanelManager()); + mEventFilter = new OverlayPanelEventFilterWrapper(context, mPanel); - mPanel.setSearchBarHeightForTesting(BAR_HEIGHT_DP); - mPanel.setHeightForTesting(LAYOUT_HEIGHT_DP); - mPanel.setIsFullWidthSizePanelForTesting(true); + mPanel.setSearchBarHeightForTesting(BAR_HEIGHT_DP); + mPanel.setHeightForTesting(LAYOUT_HEIGHT_DP); + mPanel.setIsFullWidthSizePanelForTesting(true); - // NOTE(pedrosimonetti): This should be called after calling the method - // setIsFullWidthSizePanelForTesting(), otherwise it will crash the test. - mPanel.onSizeChanged(LAYOUT_WIDTH_DP, LAYOUT_HEIGHT_DP, 0, 0); + // NOTE(pedrosimonetti): This should be called after calling the method + // setIsFullWidthSizePanelForTesting(), otherwise it will crash the test. + mPanel.onSizeChanged(LAYOUT_WIDTH_DP, LAYOUT_HEIGHT_DP, 0, 0); + }); setContentViewVerticalScroll(0);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java index 29af2c7..d02126ec 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java
@@ -6,18 +6,16 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.ViewGroup; import android.widget.LinearLayout; import androidx.test.filters.SmallTest; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; @@ -34,9 +32,6 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) public class OverlayPanelManagerTest { - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - // -------------------------------------------------------------------------------------------- // MockOverlayPanel // --------------------------------------------------------------------------------------------
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java index bc72e28..dca5f17 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -10,7 +10,6 @@ import android.content.Context; import android.graphics.PointF; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; import android.util.Log; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; @@ -29,6 +28,7 @@ import org.junit.runner.RunWith; import org.chromium.base.MathUtils; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderViewTest.java index 7260aa9..16162e5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderViewTest.java
@@ -12,7 +12,6 @@ import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; -import android.support.test.annotation.UiThreadTest; import android.text.TextUtils; import android.view.View; import android.widget.ImageView; @@ -68,30 +67,30 @@ mImage = mHeaderView.findViewById(R.id.menu_header_image); mCircleBg = mHeaderView.findViewById(R.id.circle_background); mPerformanceInfo = mHeaderView.findViewById(R.id.menu_header_performance_info); + mModel = new PropertyModel.Builder(RevampedContextMenuHeaderProperties.ALL_KEYS) + .with(RevampedContextMenuHeaderProperties.TITLE, "") + .with(RevampedContextMenuHeaderProperties.URL, "") + .with(RevampedContextMenuHeaderProperties.TITLE_AND_URL_CLICK_LISTENER, + null) + .with(RevampedContextMenuHeaderProperties.IMAGE, null) + .with(RevampedContextMenuHeaderProperties.CIRCLE_BG_VISIBLE, false) + .with(RevampedContextMenuHeaderProperties.URL_PERFORMANCE_CLASS, + PerformanceClass.PERFORMANCE_UNKNOWN) + .build(); + + mMCP = PropertyModelChangeProcessor.create( + mModel, mHeaderView, RevampedContextMenuHeaderViewBinder::bind); }); - mModel = new PropertyModel.Builder(RevampedContextMenuHeaderProperties.ALL_KEYS) - .with(RevampedContextMenuHeaderProperties.TITLE, "") - .with(RevampedContextMenuHeaderProperties.URL, "") - .with(RevampedContextMenuHeaderProperties.TITLE_AND_URL_CLICK_LISTENER, - null) - .with(RevampedContextMenuHeaderProperties.IMAGE, null) - .with(RevampedContextMenuHeaderProperties.CIRCLE_BG_VISIBLE, false) - .with(RevampedContextMenuHeaderProperties.URL_PERFORMANCE_CLASS, - PerformanceClass.PERFORMANCE_UNKNOWN) - .build(); - mMCP = PropertyModelChangeProcessor.create( - mModel, mHeaderView, RevampedContextMenuHeaderViewBinder::bind); } @Override public void tearDownTest() throws Exception { - mMCP.destroy(); + TestThreadUtils.runOnUiThreadBlocking(mMCP::destroy); super.tearDownTest(); } @Test @SmallTest - @UiThreadTest public void testTitle() { assertThat( "Incorrect initial title visibility.", mTitle.getVisibility(), equalTo(View.GONE)); @@ -110,7 +109,6 @@ @Test @SmallTest - @UiThreadTest public void testUrl() { assertThat("Incorrect initial URL visibility.", mUrl.getVisibility(), equalTo(View.GONE)); @@ -136,7 +134,6 @@ @Test @SmallTest - @UiThreadTest public void testTitleAndUrlClick() { // Clicking on the title or the URL expands/shrinks both of them. assertFalse("Title and URL have onClickListeners when it shouldn't, yet, have.", @@ -181,7 +178,6 @@ @Test @SmallTest - @UiThreadTest public void testImage() { assertThat("Incorrect initial circle background visibility.", mCircleBg.getVisibility(), equalTo(View.INVISIBLE)); @@ -201,7 +197,6 @@ @Test @SmallTest - @UiThreadTest public void testPerformanceInfo() { assertThat("Incorrect initial performance info visibility.", mPerformanceInfo.getVisibility(), equalTo(View.GONE));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuItemViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuItemViewTest.java index aa27738b..16bdb5ba 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuItemViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuItemViewTest.java
@@ -11,7 +11,6 @@ import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -22,6 +21,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -60,20 +60,20 @@ mShareItemView = getActivity().findViewById(android.R.id.content); mText = mShareItemView.findViewById(R.id.menu_row_text); mIcon = mShareItemView.findViewById(R.id.menu_row_share_icon); + mModel = new PropertyModel.Builder(RevampedContextMenuShareItemProperties.ALL_KEYS) + .with(RevampedContextMenuShareItemProperties.TEXT, "") + .with(RevampedContextMenuShareItemProperties.IMAGE, null) + .with(RevampedContextMenuShareItemProperties.CONTENT_DESC, "") + .with(RevampedContextMenuShareItemProperties.CLICK_LISTENER, null) + .build(); + mMCP = PropertyModelChangeProcessor.create( + mModel, mShareItemView, RevampedContextMenuShareItemViewBinder::bind); }); - mModel = new PropertyModel.Builder(RevampedContextMenuShareItemProperties.ALL_KEYS) - .with(RevampedContextMenuShareItemProperties.TEXT, "") - .with(RevampedContextMenuShareItemProperties.IMAGE, null) - .with(RevampedContextMenuShareItemProperties.CONTENT_DESC, "") - .with(RevampedContextMenuShareItemProperties.CLICK_LISTENER, null) - .build(); - mMCP = PropertyModelChangeProcessor.create( - mModel, mShareItemView, RevampedContextMenuShareItemViewBinder::bind); } @Override public void tearDownTest() throws Exception { - mMCP.destroy(); + TestThreadUtils.runOnUiThreadBlocking(mMCP::destroy); super.tearDownTest(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java index 9d8ff6fb..4d0c6ba 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java
@@ -6,7 +6,6 @@ import android.app.Activity; import android.support.test.InstrumentationRegistry; -import android.support.test.rule.UiThreadTestRule; import androidx.annotation.Nullable; import androidx.test.filters.MediumTest; @@ -16,7 +15,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -29,6 +27,7 @@ import org.chromium.base.task.SequencedTaskRunner; import org.chromium.base.task.TaskRunner; import org.chromium.base.task.TaskTraits; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; @@ -67,13 +66,11 @@ private AdvancedMockContext mAppContext; private SequencedTaskRunner mSequencedTaskRunner = PostTask.createSequencedTaskRunner(TaskTraits.USER_VISIBLE); - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); @Before - public void setUp() { + public void setUp() throws Exception { // CustomTabsConnection needs a true context, not the mock context set below. - CustomTabsConnection.getInstance(); + TestThreadUtils.runOnUiThreadBlocking(() -> CustomTabsConnection.getInstance()); mAppContext = new AdvancedMockContext(InstrumentationRegistry.getInstrumentation() .getTargetContext() @@ -184,48 +181,43 @@ @Test @Feature("TabPersistentStore") @SmallTest + @UiThreadTest public void testGettingTabAndTaskIds() throws Throwable { - mRule.runOnUiThread(new Runnable() { + Set<Integer> tabIds = new HashSet<>(); + Set<Integer> taskIds = new HashSet<>(); + CustomTabTabPersistencePolicy.getAllLiveTabAndTaskIds(tabIds, taskIds); + Assert.assertThat(tabIds, Matchers.emptyIterable()); + Assert.assertThat(taskIds, Matchers.emptyIterable()); + + tabIds.clear(); + taskIds.clear(); + + CustomTabActivity cct1 = buildTestCustomTabActivity(1, new int[] {4, 8, 9}, null); + ApplicationStatus.onStateChangeForTesting(cct1, ActivityState.CREATED); + + CustomTabActivity cct2 = buildTestCustomTabActivity(5, new int[] {458}, new int[] {9878}); + ApplicationStatus.onStateChangeForTesting(cct2, ActivityState.CREATED); + + // Add a tabbed mode activity to ensure that its IDs are not included in the + // returned CCT ID sets. + final TabModelSelectorImpl tabbedSelector = + buildTestTabModelSelector(new int[] {12121212}, new int[] {1515151515}); + ChromeTabbedActivity tabbedActivity = new ChromeTabbedActivity() { @Override - public void run() { - Set<Integer> tabIds = new HashSet<>(); - Set<Integer> taskIds = new HashSet<>(); - CustomTabTabPersistencePolicy.getAllLiveTabAndTaskIds(tabIds, taskIds); - Assert.assertThat(tabIds, Matchers.emptyIterable()); - Assert.assertThat(taskIds, Matchers.emptyIterable()); - - tabIds.clear(); - taskIds.clear(); - - CustomTabActivity cct1 = buildTestCustomTabActivity(1, new int[] {4, 8, 9}, null); - ApplicationStatus.onStateChangeForTesting(cct1, ActivityState.CREATED); - - CustomTabActivity cct2 = - buildTestCustomTabActivity(5, new int[] {458}, new int[] {9878}); - ApplicationStatus.onStateChangeForTesting(cct2, ActivityState.CREATED); - - // Add a tabbed mode activity to ensure that its IDs are not included in the - // returned CCT ID sets. - final TabModelSelectorImpl tabbedSelector = - buildTestTabModelSelector(new int[] {12121212}, new int[] {1515151515}); - ChromeTabbedActivity tabbedActivity = new ChromeTabbedActivity() { - @Override - public int getTaskId() { - return 888; - } - - @Override - public TabModelSelector getTabModelSelector() { - return tabbedSelector; - } - }; - ApplicationStatus.onStateChangeForTesting(tabbedActivity, ActivityState.CREATED); - - CustomTabTabPersistencePolicy.getAllLiveTabAndTaskIds(tabIds, taskIds); - Assert.assertThat(tabIds, Matchers.containsInAnyOrder(4, 8, 9, 458, 9878)); - Assert.assertThat(taskIds, Matchers.containsInAnyOrder(1, 5)); + public int getTaskId() { + return 888; } - }); + + @Override + public TabModelSelector getTabModelSelector() { + return tabbedSelector; + } + }; + ApplicationStatus.onStateChangeForTesting(tabbedActivity, ActivityState.CREATED); + + CustomTabTabPersistencePolicy.getAllLiveTabAndTaskIds(tabIds, taskIds); + Assert.assertThat(tabIds, Matchers.containsInAnyOrder(4, 8, 9, 458, 9878)); + Assert.assertThat(taskIds, Matchers.containsInAnyOrder(1, 5)); } /** @@ -265,12 +257,9 @@ Assert.assertThat(filesToDelete.get(), Matchers.containsInAnyOrder(tab999File.getName())); // Reference the tab state file and ensure it is no longer marked for deletion. - mRule.runOnUiThread(new Runnable() { - @Override - public void run() { - CustomTabActivity cct1 = buildTestCustomTabActivity(1, new int[] {999}, null); - ApplicationStatus.onStateChangeForTesting(cct1, ActivityState.CREATED); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + CustomTabActivity cct1 = buildTestCustomTabActivity(1, new int[] {999}, null); + ApplicationStatus.onStateChangeForTesting(cct1, ActivityState.CREATED); }); policy.cleanupUnusedFiles(filesToDeleteCallback); callbackSignal.waitForCallback(2);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/RequestThrottlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/RequestThrottlerTest.java index fe55eaf..1468857 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/RequestThrottlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/RequestThrottlerTest.java
@@ -6,18 +6,16 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; /** Tests for RequestThrottler. @@ -33,9 +31,6 @@ private Context mContext; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Before public void setUp() { mContext = InstrumentationRegistry.getTargetContext();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/DataReductionPromoUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/DataReductionPromoUtilsTest.java index 9dd06fb..cbe5c06 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/DataReductionPromoUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/DataReductionPromoUtilsTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; @@ -15,12 +13,12 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; import org.chromium.base.FieldTrialList; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; @@ -35,8 +33,7 @@ @RunWith(BaseJUnit4ClassRunner.class) public class DataReductionPromoUtilsTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private static final String SHARED_PREF_DISPLAYED_INFOBAR_PROMO_VERSION = "displayed_data_reduction_infobar_promo_version";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/settings/DataReductionStatsPreferenceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/settings/DataReductionStatsPreferenceTest.java index 7b14bff7..58fba52 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/settings/DataReductionStatsPreferenceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/datareduction/settings/DataReductionStatsPreferenceTest.java
@@ -9,8 +9,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.text.format.DateUtils; import androidx.test.filters.SmallTest; @@ -19,11 +17,11 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; @@ -37,8 +35,7 @@ @RunWith(BaseJUnit4ClassRunner.class) public class DataReductionStatsPreferenceTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); /** * Key used to save the date that the site breakdown should be shown. If the user has historical
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java index 3f2d60b..8cd2c73 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsTest.java
@@ -5,8 +5,6 @@ package org.chromium.chrome.browser.dom_distiller; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; @@ -14,10 +12,10 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeBrowserTestRule; @@ -34,8 +32,7 @@ @RunWith(BaseJUnit4ClassRunner.class) public class DistilledPagePrefsTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private DistilledPagePrefs mDistilledPagePrefs;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java index d6ab76ad..927e522 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadNotificationServiceTest.java
@@ -8,9 +8,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.After; @@ -20,6 +17,7 @@ import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.params.ParameterAnnotations.ClassParameter; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterSet; @@ -34,6 +32,7 @@ import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.components.offline_items_collection.OfflineItem.Progress; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.components.offline_items_collection.OfflineItemProgressUnit; import org.chromium.components.offline_items_collection.PendingState; @@ -66,9 +65,6 @@ @Rule public TestRule mFeaturesProcessor = new Features.JUnitProcessor(); - @Rule - public UiThreadTestRule mUiThreadTestRule = new UiThreadTestRule(); - private MockDownloadNotificationService mDownloadNotificationService; private DownloadForegroundServiceManagerTest .MockDownloadForegroundServiceManager mDownloadForegroundServiceManager; @@ -103,13 +99,15 @@ } else { Features.getInstance().disable(ChromeFeatureList.OFFLINE_PAGES_DESCRIPTIVE_FAIL_STATUS); } - DownloadNotificationService.clearResumptionAttemptLeft(); - mDownloadNotificationService = new MockDownloadNotificationService(); - mDownloadForegroundServiceManager = - new DownloadForegroundServiceManagerTest.MockDownloadForegroundServiceManager(); - mDownloadNotificationService.setDownloadForegroundServiceManager( - mDownloadForegroundServiceManager); - mDownloadSharedPreferenceHelper = DownloadSharedPreferenceHelper.getInstance(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + DownloadNotificationService.clearResumptionAttemptLeft(); + mDownloadNotificationService = new MockDownloadNotificationService(); + mDownloadForegroundServiceManager = + new DownloadForegroundServiceManagerTest.MockDownloadForegroundServiceManager(); + mDownloadNotificationService.setDownloadForegroundServiceManager( + mDownloadForegroundServiceManager); + mDownloadSharedPreferenceHelper = DownloadSharedPreferenceHelper.getInstance(); + }); } @After
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java index 89d3fb4..20a88d79 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelperTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.text.TextUtils; import android.widget.Button; import android.widget.RadioButton; @@ -16,10 +14,10 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.widget.RadioButtonLayout; @@ -105,9 +103,6 @@ } }; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - private final DismissRunnable mDismissRunnable = new DismissRunnable(); private final List<TemplateUrl> mTemplateUrls = new ArrayList<>();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java index 1d703fc..88ed4c9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
@@ -7,7 +7,6 @@ import android.annotation.TargetApi; import android.os.Build; import android.support.test.InstrumentationRegistry; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.MediumTest; @@ -51,8 +50,6 @@ private static final String VIDEO_ID = "video"; @Rule - public UiThreadTestRule mUiThreadTestRule = new UiThreadTestRule(); - @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); private EmbeddedTestServer mTestServer; @@ -212,8 +209,9 @@ } private void triggerAutoPiP() throws Throwable{ - mUiThreadTestRule.runOnUiThread( - () -> InstrumentationRegistry.getInstrumentation().callActivityOnUserLeaving( + TestThreadUtils.runOnUiThreadBlocking( + () + -> InstrumentationRegistry.getInstrumentation().callActivityOnUserLeaving( mActivity)); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizerTest.java index e75b0d8..107daa2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizerTest.java
@@ -6,8 +6,6 @@ import android.content.res.Resources; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.text.Spannable; import android.text.SpannableStringBuilder; @@ -18,10 +16,10 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.profiles.Profile; @@ -44,8 +42,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class OmniboxUrlEmphasizerTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private Profile mProfile; private ChromeAutocompleteSchemeClassifier mChromeAutocompleteSchemeClassifier;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java index 68f38656..6ef73cdcf5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
@@ -16,8 +16,6 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; @@ -36,6 +34,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -46,6 +45,7 @@ import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.test.NativeLibraryTestUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; /** @@ -58,9 +58,6 @@ private static final String TEST_SEARCH_URL = "https://www.test.com"; @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); @Mock @@ -85,24 +82,22 @@ StatusMediator mMediator; Bitmap mBitmap; - public StatusMediatorUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); mContext = ContextUtils.getApplicationContext(); mResources = mContext.getResources(); mModel = new PropertyModel(StatusProperties.ALL_KEYS); - mMediator = - new StatusMediator(mModel, mResources, mContext, mUrlBarEditingTextStateProvider, - /* isTablet */ false, mMockForceModelViewReconciliationRunnable); - mMediator.setToolbarCommonPropertiesModel(mToolbarCommonPropertiesModel); - mMediator.setDelegateForTesting(mDelegate); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + mMediator = new StatusMediator(mModel, mResources, mContext, + mUrlBarEditingTextStateProvider, + /* isTablet */ false, mMockForceModelViewReconciliationRunnable); + mMediator.setToolbarCommonPropertiesModel(mToolbarCommonPropertiesModel); + mMediator.setDelegateForTesting(mDelegate); + }); mBitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); when(mDelegate.isUrlValid(mUrlCaptor.capture()))
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediatorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediatorUnitTest.java index 1450576..ad8c8a8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediatorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediatorUnitTest.java
@@ -19,8 +19,6 @@ import android.os.Handler; import android.os.Message; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.util.SparseArray; import android.view.View; @@ -40,6 +38,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; @@ -68,9 +67,6 @@ private static final int HEADER_MIN_HEIGHT = 15; @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); @Mock @@ -99,15 +95,10 @@ private List<OmniboxSuggestion> mSuggestionsList; private ModelList mSuggestionModels; - public AutocompleteMediatorUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); mSuggestionModels = new ModelList(); mListModel = new PropertyModel(SuggestionListProperties.ALL_KEYS);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java index ec48fe90..c3f3ca2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java
@@ -4,19 +4,18 @@ package org.chromium.chrome.browser.omnibox.suggestions; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.util.SparseArray; import androidx.test.filters.SmallTest; import org.junit.Assert; -import org.junit.Rule; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; @@ -34,12 +33,8 @@ @RunWith(BaseJUnit4ClassRunner.class) @Batch(Batch.UNIT_TESTS) public class CachedZeroSuggestionsManagerUnitTest { - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - public CachedZeroSuggestionsManagerUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. + @Before + public void setUp() { NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java index 0c50576..4d3ceff5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java
@@ -14,8 +14,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.util.Pair; import android.util.SparseArray; @@ -32,6 +30,7 @@ import org.mockito.MockitoAnnotations; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; @@ -53,9 +52,6 @@ @Batch(Batch.UNIT_TESTS) public class DropdownItemViewInfoListBuilderUnitTest { @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); @Mock @@ -66,15 +62,10 @@ DropdownItemViewInfoListBuilder mBuilder; - public DropdownItemViewInfoListBuilderUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); when(mMockSuggestionProcessor.doesProcessSuggestion(any(), anyInt())).thenReturn(true); when(mMockSuggestionProcessor.createModel())
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProviderTest.java index 4c2f7a4..437415e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProviderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProviderTest.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.omnibox.suggestions; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.text.TextUtils; import androidx.test.filters.SmallTest; @@ -13,10 +11,10 @@ import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler.VoiceResult; @@ -32,8 +30,7 @@ @RunWith(BaseJUnit4ClassRunner.class) public class VoiceSuggestionProviderTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); private static List<OmniboxSuggestion> createDummySuggestions(String... texts) { List<OmniboxSuggestion> suggestions = new ArrayList<OmniboxSuggestion>(texts.length);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java index f5cb0843..d0cdb72 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java
@@ -15,15 +15,12 @@ import android.graphics.Bitmap.Config; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.text.Spannable; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -33,6 +30,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.R; import org.chromium.chrome.browser.image_fetcher.ImageFetcher; @@ -66,9 +64,6 @@ AnswerType.FINANCE, AnswerType.KNOWLEDGE_GRAPH, AnswerType.SPORTS, AnswerType.SUNRISE, AnswerType.TRANSLATION, AnswerType.WEATHER, AnswerType.WHEN_IS, AnswerType.CURRENCY}; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Mock SuggestionHost mSuggestionHost;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java index 192edfe..fb1d27d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
@@ -12,8 +12,6 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.drawable.BitmapDrawable; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.collection.ArrayMap; import androidx.test.filters.SmallTest; @@ -30,6 +28,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -97,9 +96,6 @@ }; @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - @Rule public TestRule mFeaturesProcessor = new Features.JUnitProcessor(); @Mock @@ -114,15 +110,10 @@ private OmniboxSuggestion mSuggestion; private PropertyModel mModel; - public BasicSuggestionProcessorUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); doReturn("").when(mUrlBarText).getTextWithoutAutocomplete(); mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8); mProcessor = new BasicSuggestionProcessor(ContextUtils.getApplicationContext(),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorTest.java index cc79916..46c0323 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorTest.java
@@ -12,8 +12,6 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.drawable.BitmapDrawable; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; @@ -22,7 +20,6 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -31,6 +28,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; @@ -59,9 +57,6 @@ private static final GURL TEST_URL = new GURL("http://url"); private static final GURL ARABIC_URL = new GURL("http://site.com/Ù…Ø±ØØ¨Ø§/123"); - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Mock SuggestionHost mSuggestionHost; @Mock @@ -78,15 +73,10 @@ private TextView mContentTextView; private int mLastSetTextDirection = -1; - public ClipboardSuggestionProcessorTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); mBitmap = Bitmap.createBitmap(10, 5, Config.ARGB_8888); mProcessor = new ClipboardSuggestionProcessor( ContextUtils.getApplicationContext(), mSuggestionHost, () -> mIconBridge);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java index 6f875ed..b2c148c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java
@@ -11,8 +11,6 @@ import android.content.ClipData; import android.content.ClipboardManager; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.View; import androidx.test.filters.SmallTest; @@ -30,6 +28,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; @@ -48,6 +47,7 @@ import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.test.NativeLibraryTestUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.base.Clipboard; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; @@ -77,9 +77,6 @@ private PropertyModel mModel; @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - - @Rule public TestRule mFeaturesProcessor = new Features.JUnitProcessor(); @Mock @@ -121,19 +118,12 @@ // The original (real) ClipboardManager to be restored after a test run. private ClipboardManager mOldClipboardManager; - public EditUrlSuggestionUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlService); - mOldClipboardManager = - Clipboard.getInstance().overrideClipboardManagerForTesting(mClipboardManager); doReturn(mTestUrl).when(mTab).getUrl(); doReturn(TEST_TITLE).when(mTab).getTitle(); @@ -149,16 +139,23 @@ doReturn(OmniboxSuggestionType.SEARCH_HISTORY).when(mOtherSuggestion).getType(); - mModel = new PropertyModel.Builder(SuggestionViewProperties.ALL_KEYS).build(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mOldClipboardManager = + Clipboard.getInstance().overrideClipboardManagerForTesting(mClipboardManager); - mProcessor = new EditUrlSuggestionProcessor(ContextUtils.getApplicationContext(), - mSuggestionHost, mUrlBarDelegate, - () -> mIconBridge, () -> mTab, () -> mShareDelegate); + mModel = new PropertyModel.Builder(SuggestionViewProperties.ALL_KEYS).build(); + + mProcessor = new EditUrlSuggestionProcessor(ContextUtils.getApplicationContext(), + mSuggestionHost, mUrlBarDelegate, + () -> mIconBridge, () -> mTab, () -> mShareDelegate); + }); } @After public void tearDown() { - Clipboard.getInstance().overrideClipboardManagerForTesting(mOldClipboardManager); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Clipboard.getInstance().overrideClipboardManagerForTesting(mOldClipboardManager); + }); } /** Test that the suggestion is triggered. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java index c1ac03b6..d714891 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java
@@ -17,14 +17,11 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -35,6 +32,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.R; @@ -63,9 +61,6 @@ private static final int DECORATION_TYPE_COLOR = 1; private static final int DECORATION_TYPE_IMAGE = 2; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Mock SuggestionHost mSuggestionHost; @@ -122,15 +117,10 @@ mProcessor.populateModel(helper.mSuggestion, helper.mModel, 0); } - public EntitySuggestionProcessorUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessorUnitTest.java index 64eec128..ba1cd934 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessorUnitTest.java
@@ -11,14 +11,11 @@ import android.content.Context; import android.content.res.Resources; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -27,6 +24,7 @@ import org.chromium.base.Callback; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.components.query_tiles.QueryTile; @@ -46,9 +44,6 @@ private PropertyModel mModel; private TileSuggestionProcessor mProcessor; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Mock Context mContext; @@ -61,15 +56,11 @@ @Mock OmniboxSuggestion mSuggestion; - public TileSuggestionProcessorUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { MockitoAnnotations.initMocks(this); + NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); + when(mContext.getResources()).thenReturn(mResources); mModel = new PropertyModel();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerNativeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerNativeTest.java index 7b1b3b2e..5ee8d300 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerNativeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerNativeTest.java
@@ -7,18 +7,16 @@ import android.content.Context; import android.content.SharedPreferences; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; @@ -32,8 +30,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class PrivacyPreferencesManagerNativeTest { @Rule - public final RuleChain mChain = - RuleChain.outerRule(new ChromeBrowserTestRule()).around(new UiThreadTestRule()); + public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule(); @Test @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java index 6ce3068..ad26b47 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/WebsitePermissionsFetcherTest.java
@@ -473,7 +473,7 @@ // If the ContentSettingsType.NUM_TYPES value changes *and* a new value has been exposed on // Android, then please update this code block to include a test for your new type. // Otherwise, just update count in the assert. - Assert.assertEquals(64, ContentSettingsType.NUM_TYPES); + Assert.assertEquals(65, ContentSettingsType.NUM_TYPES); websitePreferenceBridge.addContentSettingException( new ContentSettingException(ContentSettingsType.COOKIES, googleOrigin, ContentSettingValues.DEFAULT, preferenceSource));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java index b11b4e9c..67a8bd9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java
@@ -15,7 +15,6 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.support.test.annotation.UiThreadTest; import android.text.TextUtils; import android.view.View; @@ -27,6 +26,7 @@ import org.junit.runner.RunWith; import org.chromium.base.MathUtils; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.widget.ViewResourceFrameLayout; @@ -63,22 +63,23 @@ TestThreadUtils.runOnUiThreadBlocking(() -> { mContainer = getActivity().findViewById(R.id.status_indicator); mStatusTextView = mContainer.findViewById(R.id.status_text); + + mSceneLayer = new MockStatusIndicatorSceneLayer(mContainer); + mModel = new PropertyModel.Builder(StatusIndicatorProperties.ALL_KEYS) + .with(StatusIndicatorProperties.STATUS_TEXT, "") + .with(StatusIndicatorProperties.STATUS_ICON, null) + .with(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY, View.GONE) + .with(StatusIndicatorProperties.COMPOSITED_VIEW_VISIBLE, false) + .build(); + mMCP = PropertyModelChangeProcessor.create(mModel, + new StatusIndicatorViewBinder.ViewHolder(mContainer, mSceneLayer), + StatusIndicatorViewBinder::bind); }); - mSceneLayer = new MockStatusIndicatorSceneLayer(mContainer); - mModel = new PropertyModel.Builder(StatusIndicatorProperties.ALL_KEYS) - .with(StatusIndicatorProperties.STATUS_TEXT, "") - .with(StatusIndicatorProperties.STATUS_ICON, null) - .with(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY, View.GONE) - .with(StatusIndicatorProperties.COMPOSITED_VIEW_VISIBLE, false) - .build(); - mMCP = PropertyModelChangeProcessor.create(mModel, - new StatusIndicatorViewBinder.ViewHolder(mContainer, mSceneLayer), - StatusIndicatorViewBinder::bind); } @Override public void tearDownTest() throws Exception { - mMCP.destroy(); + TestThreadUtils.runOnUiThreadBlocking(mMCP::destroy); super.tearDownTest(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabIdManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabIdManagerTest.java index aefede2..6352b8a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabIdManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabIdManagerTest.java
@@ -6,17 +6,15 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; @@ -27,9 +25,6 @@ public class TabIdManagerTest { Context mContext; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Before public void setUp() { mContext = new AdvancedMockContext(InstrumentationRegistry.getTargetContext());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java index 8af8c30..1601154 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/PersistedTabDataTest.java
@@ -4,18 +4,16 @@ package org.chromium.chrome.browser.tab.state; -import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; -import android.support.test.rule.UiThreadTestRule; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.tab.MockTab; import org.chromium.chrome.browser.tab.Tab; @@ -27,9 +25,6 @@ private static final int INITIAL_VALUE = 42; private static final int CHANGED_VALUE = 51; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java index fffb485..2739aa72 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java
@@ -4,16 +4,13 @@ package org.chromium.chrome.browser.tabmodel; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.LoadUrlParams; @@ -22,9 +19,6 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) public class AsyncTabCreationParamsManagerTest { - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Test @SmallTest @UiThreadTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java index 4c33d36..62cdf0bf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java
@@ -6,19 +6,17 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.ContextUtils; import org.chromium.base.StreamUtil; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; @@ -73,9 +71,6 @@ return maxId; } - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Before public void setUp() { mAppContext = new AdvancedMockContext(InstrumentationRegistry.getInstrumentation()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabModelObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabModelObserverTest.java index a3670444..1136a40 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabModelObserverTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabModelObserverTest.java
@@ -4,19 +4,16 @@ package org.chromium.chrome.browser.tabmodel; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; @@ -32,12 +29,9 @@ */ @RunWith(BaseJUnit4ClassRunner.class) public class TabModelSelectorTabModelObserverTest { - // Do not add @Rule to this, it's already added to RuleChain - private final TabModelSelectorObserverTestRule mTestRule = - new TabModelSelectorObserverTestRule(); - @Rule - public final RuleChain mChain = RuleChain.outerRule(mTestRule).around(new UiThreadTestRule()); + public final TabModelSelectorObserverTestRule mTestRule = + new TabModelSelectorObserverTestRule(); private TabModelSelectorBase mSelector;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java index fcc628e3..7a5aa84 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java
@@ -4,14 +4,11 @@ package org.chromium.chrome.browser.tabmodel; -import android.support.test.rule.UiThreadTestRule; - import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.ObserverList.RewindableIterator; @@ -34,12 +31,9 @@ */ @RunWith(BaseJUnit4ClassRunner.class) public class TabModelSelectorTabObserverTest { - // Do not add @Rule to this, it's already added to RuleChain - private final TabModelSelectorObserverTestRule mTestRule = - new TabModelSelectorObserverTestRule(); - @Rule - public final RuleChain mChain = RuleChain.outerRule(mTestRule).around(new UiThreadTestRule()); + public final TabModelSelectorObserverTestRule mTestRule = + new TabModelSelectorObserverTestRule(); @Test @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java index 6e7f114..b881e73 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java
@@ -5,19 +5,17 @@ package org.chromium.chrome.browser.tabmodel; import android.app.Activity; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; import org.junit.After; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.customtabs.CustomTabActivity; @@ -27,6 +25,7 @@ import org.chromium.chrome.browser.tabmodel.TabWindowManager.TabModelSelectorFactory; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector; +import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; import java.util.List; @@ -69,15 +68,14 @@ @After public void tearDown() { - for (Activity a : mActivities) { - ApplicationStatus.onStateChangeForTesting(a, ActivityState.DESTROYED); - } + TestThreadUtils.runOnUiThreadBlocking(() -> { + for (Activity a : mActivities) { + ApplicationStatus.onStateChangeForTesting(a, ActivityState.DESTROYED); + } + }); mActivities.clear(); } - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - /** * Test that a single {@link Activity} can request a {@link TabModelSelector}. */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/shared/ScrollTrackerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/shared/ScrollTrackerTest.java new file mode 100644 index 0000000..a40ebae2 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/shared/ScrollTrackerTest.java
@@ -0,0 +1,135 @@ +// Copyright 2019 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.feed.shared; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; + +import org.chromium.base.task.test.ShadowPostTask; +import org.chromium.base.test.BaseRobolectricTestRunner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** Tests for {@link ScrollTracker}. */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(shadows = {ShadowPostTask.class}) +public final class ScrollTrackerTest { + // The delay time used when scheduling the report task. + private static final long DELAY_TIME_MS = 200L; + // After this much idle time, we're guaranteed to have all scroll events reported. + private static final long STABLE_TIME_MS = DELAY_TIME_MS * 2; + private ScrollTrackerForTest mScrollTracker; + + @Before + public void setUp() { + mScrollTracker = new ScrollTrackerForTest(); + } + + @Test + public void testSinglePositiveScroll_scrollWrongDirection() { + mScrollTracker.trackScroll(10, 0); + advanceByMs(STABLE_TIME_MS); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList()); + } + + @Test + public void testNoScroll() { + mScrollTracker.trackScroll(0, 0); + advanceByMs(STABLE_TIME_MS); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList()); + } + + @Test + public void testSinglePositiveScroll() { + mScrollTracker.trackScroll(0, 10); + advanceByMs(DELAY_TIME_MS); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(10)); + } + + @Test + public void testUnbindReportsImmediately() { + mScrollTracker.trackScroll(0, 10); + mScrollTracker.onUnbind(); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(10)); + } + + @Test + public void testScrollAfterUnbindWorks() { + mScrollTracker.trackScroll(0, 10); + mScrollTracker.onUnbind(); + mScrollTracker.trackScroll(0, 5); + advanceByMs(STABLE_TIME_MS); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(10, 5)); + } + + @Test + public void testUnbindWithoutScroll() { + mScrollTracker.onUnbind(); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList()); + } + + @Test + public void testDoublePositiveScroll_singleTask() { + mScrollTracker.trackScroll(0, 10); + advanceByMs(DELAY_TIME_MS - 1); + mScrollTracker.trackScroll(0, 5); + advanceByMs(STABLE_TIME_MS); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(15)); + } + + @Test + public void testDoublePositiveScroll_doubleTask() { + mScrollTracker.trackScroll(0, 10); + advanceByMs(STABLE_TIME_MS); + mScrollTracker.trackScroll(0, 5); + advanceByMs(STABLE_TIME_MS); + + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(10, 5)); + } + + @Test + public void testSwitchScrollDirection() { + mScrollTracker.trackScroll(0, 10); + advanceByMs(1L); + mScrollTracker.trackScroll(0, -5); + // Reports 10 immediately. + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(10)); + + // Eventually, -5 is reported as well. + advanceByMs(STABLE_TIME_MS); + assertEquals(mScrollTracker.scrollAmounts, Arrays.asList(10, -5)); + } + + static void advanceByMs(long timeMs) { + Robolectric.getForegroundThreadScheduler().advanceBy(timeMs, TimeUnit.MILLISECONDS); + } + + static class ScrollTrackerForTest extends ScrollTracker { + public ArrayList<Integer> scrollAmounts = new ArrayList<>(); + + ScrollTrackerForTest() { + super(); + } + + @Override + protected void onScrollEvent(int scrollAmount) { + scrollAmounts.add(scrollAmount); + } + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java index 302362d..3a60fc7f 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java
@@ -48,6 +48,7 @@ import org.chromium.base.Callback; import org.chromium.base.metrics.test.ShadowRecordHistogram; +import org.chromium.base.task.test.ShadowPostTask; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.base.test.util.MetricsUtils.HistogramDelta; @@ -72,10 +73,11 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** Unit tests for {@link FeedStreamSeSurface}. */ @RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, shadows = {ShadowRecordHistogram.class}) +@Config(manifest = Config.NONE, shadows = {ShadowPostTask.class, ShadowRecordHistogram.class}) public class FeedStreamSurfaceTest { private static final String TEST_DATA = "test"; private static final String TEST_URL = "https://www.chromium.org"; @@ -423,7 +425,7 @@ when(mPageNavigationDelegate.openUrl(anyInt(), any())).thenReturn(new MockTab(1, false)); mFeedStreamSurface.navigateNewTab(TEST_URL); verify(mPageNavigationDelegate) - .openUrl(ArgumentMatchers.eq(WindowOpenDisposition.NEW_FOREGROUND_TAB), any()); + .openUrl(ArgumentMatchers.eq(WindowOpenDisposition.NEW_BACKGROUND_TAB), any()); assertEquals(1, actionOpenedSnippetDelta.getDelta()); } @@ -757,6 +759,30 @@ .reportOpenAction(anyLong(), any(FeedStreamSurface.class), eq("")); } + @Test + @SmallTest + public void testScrollIsReportedOnIdle() { + mFeedStreamSurface.streamScrolled(0, 100); + Robolectric.getForegroundThreadScheduler().advanceBy(1000, TimeUnit.MILLISECONDS); + + verify(mFeedStreamSurfaceJniMock) + .reportStreamScrollStart(anyLong(), any(FeedStreamSurface.class)); + verify(mFeedStreamSurfaceJniMock) + .reportStreamScrolled(anyLong(), any(FeedStreamSurface.class), eq(100)); + } + + @Test + @SmallTest + public void testScrollIsReportedOnClose() { + mFeedStreamSurface.streamScrolled(0, 100); + mFeedStreamSurface.surfaceClosed(); + + verify(mFeedStreamSurfaceJniMock) + .reportStreamScrollStart(anyLong(), any(FeedStreamSurface.class)); + verify(mFeedStreamSurfaceJniMock) + .reportStreamScrolled(anyLong(), any(FeedStreamSurface.class), eq(100)); + } + private SliceUpdate createSliceUpdateForExistingSlice(String sliceId) { return SliceUpdate.newBuilder().setSliceId(sliceId).build(); }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 4eba640..780cf7a 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4942,6 +4942,11 @@ Manage passwords </message> </if> + <if expr="is_android"> + <message name="IDS_SETTINGS_PASSWORDS_ANDROID_APP" desc="Label for the app a password is for when displaying a credential and the real app display name could not be obtained."> + App (<ph name="ANDROID_PACKAGE_NAME">$1<ex>com.netflix.mediaclient</ex></ph>) + </message> + </if> <!-- Password manager onboarding strings --> <message name="IDS_PASSWORD_MANAGER_ONBOARDING_TITLE_A" desc="The title shown in the password manager onboarding dialog."> Save your passwords? @@ -5690,6 +5695,9 @@ <message name="IDS_TOOLTIP_FIND" desc="The tooltip for the find button"> Find </message> + <message name="IDS_TOOLTIP_TAB_SEARCH" desc="The tooltip for the Tab Search bubble."> + Tab search + </message> <!-- Strings for intent picker --> <if expr="not is_android"> @@ -5772,6 +5780,9 @@ <message name="IDS_ACCNAME_ZOOM_SET_DEFAULT" desc="The accessible description of the Reset button in the Zoom bubble."> Reset to default zoom level </message> + <message name="IDS_ACCNAME_TAB_SEARCH" desc="The accessible name for the Tab Search bubble."> + Tab search + </message> <!-- Clipboard permission --> <message name="IDS_ALLOWED_CLIPBOARD_TITLE" desc="Title of the info bubble shown when a site has been allowed access to read the contents of the system clipboard.">
diff --git a/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SEARCH.png.sha1 b/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SEARCH.png.sha1 new file mode 100644 index 0000000..34681cc --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SEARCH.png.sha1
@@ -0,0 +1 @@ +9abc682eb478c03fa60ce766712a08b9b2c6b29b \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_SETTINGS_PASSWORDS_ANDROID_APP.png.sha1 b/chrome/app/generated_resources_grd/IDS_SETTINGS_PASSWORDS_ANDROID_APP.png.sha1 new file mode 100644 index 0000000..91ea5def --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_SETTINGS_PASSWORDS_ANDROID_APP.png.sha1
@@ -0,0 +1 @@ +56486e2523a8ed588602b35a82b3a448adcfcf60 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TOOLTIP_TAB_SEARCH.png.sha1 b/chrome/app/generated_resources_grd/IDS_TOOLTIP_TAB_SEARCH.png.sha1 new file mode 100644 index 0000000..3beefeb --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_TOOLTIP_TAB_SEARCH.png.sha1
@@ -0,0 +1 @@ +dce6b1b6b24f3a9f580a8753a926666e492c68fd \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index acf940f..d780097 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -475,7 +475,7 @@ Off </message> <message name="IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_TITLE" desc="Label for the radio button group of ambient mode topic source, where the screen contents come from."> - Background + Photo Frame </message> <message name="IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_GOOGLE_PHOTOS" desc="Label for the radio button to choose the topic source from Google Photos. The radio button allows the user to set Google Photos for ambient mode, which shows photos to the user when their device is idle."> Google Photos
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_TITLE.png.sha1 index 3c4fcc9..a1f9b883 100644 --- a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_TITLE.png.sha1 +++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_TITLE.png.sha1
@@ -1 +1 @@ -c8a3be00b8006564c838bae42958dcef728e44c7 \ No newline at end of file +6c9a91e5dcdcdc3cc1ea1b1fe9b5a1f5f76f9179 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b921a5a..b3666fd 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -957,8 +957,6 @@ "optimization_guide/optimization_guide_session_statistic.h", "optimization_guide/optimization_guide_top_host_provider.cc", "optimization_guide/optimization_guide_top_host_provider.h", - "optimization_guide/optimization_guide_util.cc", - "optimization_guide/optimization_guide_util.h", "optimization_guide/optimization_guide_web_contents_observer.cc", "optimization_guide/optimization_guide_web_contents_observer.h", "optimization_guide/prediction/prediction_manager.cc", @@ -1176,6 +1174,8 @@ "policy/messaging_layer/storage/storage_module.h", "policy/messaging_layer/storage/storage_queue.cc", "policy/messaging_layer/storage/storage_queue.h", + "policy/messaging_layer/upload/app_install_report_handler.cc", + "policy/messaging_layer/upload/app_install_report_handler.h", "policy/messaging_layer/upload/dm_server_upload_service.cc", "policy/messaging_layer/upload/dm_server_upload_service.h", "policy/messaging_layer/util/backoff_settings.cc", @@ -3817,6 +3817,7 @@ } if (is_chromeos) { + assert(enable_native_notifications) sources += [ "apps/app_service/arc_activity_adaptive_icon_impl.cc", "apps/app_service/arc_activity_adaptive_icon_impl.h", @@ -3929,6 +3930,9 @@ "notifications/chrome_ash_message_center_client.h", "notifications/extension_notifier_controller.cc", "notifications/extension_notifier_controller.h", + "notifications/notification_platform_bridge_chromeos.cc", + "notifications/notification_platform_bridge_chromeos.h", + "notifications/notification_platform_bridge_delegate.h", "notifications/notifier_controller.h", "notifications/web_page_notifier_controller.cc", "notifications/web_page_notifier_controller.h", @@ -4005,13 +4009,6 @@ "//ui/ozone", ] allow_circular_includes_from += [ "//chrome/browser/chromeos" ] - - if (enable_native_notifications) { - sources += [ - "notifications/notification_platform_bridge_chromeos.cc", - "notifications/notification_platform_bridge_chromeos.h", - ] - } } else { # Non - ChromeOS. sources += [ "fullscreen.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index cdd5f50d..373a5b23 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -351,6 +351,35 @@ data_reduction_proxy::switches::kDataReductionProxyExperiment, data_reduction_proxy::switches::kDataReductionProxyServerAlternative10}}; +const FeatureEntry::Choice kLiteVideoDefaultDownlinkBandwidthKbps[] = { + {flags_ui::kGenericExperimentChoiceDefault, "", ""}, + {"100", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "100"}, + {"150", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "150"}, + {"200", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "200"}, + {"250", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "250"}, + {"300", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "300"}, + {"350", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "350"}, + {"400", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "400"}, + {"450", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "450"}, + {"500", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "500"}, + {"600", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "600"}, + {"700", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "700"}, + {"800", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "800"}, + {"900", lite_video::switches::kLiteVideoDefaultDownlinkBandwidthKbps, + "900"}}; + #if defined(OS_WIN) const FeatureEntry::Choice kUseAngleChoices[] = { {flag_descriptions::kUseAngleDefault, "", ""}, @@ -2462,6 +2491,15 @@ flag_descriptions::kWebUITabStripDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kWebUITabStrip)}, #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) +#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && defined(OS_CHROMEOS) + { + "webui-tab-strip-tab-drag-integration", + flag_descriptions::kWebUITabStripTabDragIntegrationName, + flag_descriptions::kWebUITabStripTabDragIntegrationDescription, + kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kWebUITabStripTabDragIntegration), + }, +#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && defined(OS_CHROMEOS) {"focus-mode", flag_descriptions::kFocusMode, flag_descriptions::kFocusModeDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kFocusMode)}, @@ -6139,6 +6177,11 @@ flag_descriptions::kLiteVideoDescription, kOsAll, FEATURE_VALUE_TYPE(features::kLiteVideo)}, + {"lite-video-default-downlink-bandwidth-kbps", + flag_descriptions::kLiteVideoDownlinkBandwidthKbpsName, + flag_descriptions::kLiteVideoDownlinkBandwidthKbpsDescription, kOsAll, + MULTI_VALUE_TYPE(kLiteVideoDefaultDownlinkBandwidthKbps)}, + {"lite-video-force-override-decision", flag_descriptions::kLiteVideoForceOverrideDecisionName, flag_descriptions::kLiteVideoForceOverrideDecisionDescription, kOsAll,
diff --git a/chrome/browser/android/feed/v2/feed_service_bridge.cc b/chrome/browser/android/feed/v2/feed_service_bridge.cc index ed470e0a..d9f057fc 100644 --- a/chrome/browser/android/feed/v2/feed_service_bridge.cc +++ b/chrome/browser/android/feed/v2/feed_service_bridge.cc
@@ -10,6 +10,7 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/check_op.h" +#include "base/time/time.h" #include "chrome/android/chrome_jni_headers/FeedServiceBridge_jni.h" #include "chrome/browser/android/feed/v2/feed_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -43,6 +44,15 @@ return GetFeedConfig().load_more_trigger_lookahead; } +static void JNI_FeedServiceBridge_ReportOpenVisitComplete(JNIEnv* env, + jlong visitTimeMs) { + FeedService* service = GetFeedService(); + if (!service) + return; + service->GetStream()->ReportOpenVisitComplete( + base::TimeDelta::FromMilliseconds(visitTimeMs)); +} + static base::android::ScopedJavaLocalRef<jstring> JNI_FeedServiceBridge_GetClientInstanceId(JNIEnv* env) { FeedService* service = GetFeedService();
diff --git a/chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_launcher.cc b/chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_launcher.cc index 47724703..212955c4 100644 --- a/chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_launcher.cc
@@ -55,9 +55,8 @@ delegate_->OnAppInstalling(); DCHECK(!is_installed_); install_task_.reset(new web_app::WebAppInstallTask( - profile_, /*shortcut_manager=*/nullptr, - /*os_integration_manager=*/nullptr, /*install_finalizer=*/nullptr, - data_retriever_factory_.Run())); + profile_, /*os_integration_manager=*/nullptr, + /*install_finalizer=*/nullptr, data_retriever_factory_.Run())); install_task_->LoadAndRetrieveWebApplicationInfoWithIcons( WebKioskAppManager::Get()->GetAppByAccountId(account_id_)->install_url(), url_loader_.get(),
diff --git a/chrome/browser/chromeos/login/eula_browsertest.cc b/chrome/browser/chromeos/login/eula_browsertest.cc index 8612dd2a..0863e00f 100644 --- a/chrome/browser/chromeos/login/eula_browsertest.cc +++ b/chrome/browser/chromeos/login/eula_browsertest.cc
@@ -16,9 +16,9 @@ #include "base/task/post_task.h" #include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" -#include "build/branding_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/test/dialog_window_waiter.h" +#include "chrome/browser/chromeos/login/test/fake_eula_mixin.h" #include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" @@ -43,33 +43,15 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" -using net::test_server::BasicHttpResponse; -using net::test_server::HttpRequest; -using net::test_server::HttpResponse; using ::testing::ElementsAre; namespace chromeos { namespace { -constexpr char kFakeOnlineEulaPath[] = "/intl/en-US/chrome/eula_text.html"; -constexpr char kFakeOnlineEula[] = "No obligations at all"; -#if BUILDFLAG(GOOGLE_CHROME_BRANDING) -// See IDS_TERMS_HTML for the complete text. -constexpr char kOfflineEULAWarning[] = - "Google Chrome and Chrome OS Additional Terms of Service"; -#else -// Placeholder text in terms_chromium.html. -constexpr char kOfflineEULAWarning[] = - "In official builds this space will show the terms of service."; -#endif - const test::UIPath kEulaWebview = {"oobe-eula-md", "crosEulaFrame"}; const test::UIPath kAcceptEulaButton = {"oobe-eula-md", "acceptButton"}; const test::UIPath kEulaTPMPassword = {"oobe-eula-md", "eula-password"}; @@ -128,33 +110,12 @@ EulaTest() = default; ~EulaTest() override = default; - // OobeBaseTest: - void SetUpCommandLine(base::CommandLine* command_line) override { - OobeBaseTest::SetUpCommandLine(command_line); - // Retrieve the URL from the embedded test server and override EULA URL. - std::string fake_eula_url = - embedded_test_server()->base_url().Resolve(kFakeOnlineEulaPath).spec(); - command_line->AppendSwitchASCII(switches::kOobeEulaUrlForTests, - fake_eula_url); - } - - // OobeBaseTest: - void RegisterAdditionalRequestHandlers() override { - embedded_test_server()->RegisterRequestHandler( - base::Bind(&EulaTest::HandleRequest, base::Unretained(this))); - } - void ShowEulaScreen() { LoginDisplayHost::default_host()->StartWizard(EulaView::kScreenId); OobeScreenWaiter(EulaView::kScreenId).Wait(); } protected: - // Used for customizing the response handler of the embedded server. - void set_force_http_unavailable(bool force_unavailable) { - force_http_unavailable_ = force_unavailable; - } - content::WebContents* FindEulaContents() { // Tag the Eula webview in use with a unique name. constexpr char kUniqueEulaWebviewName[] = "unique-eula-webview-name"; @@ -239,34 +200,9 @@ return consented; } + FakeEulaMixin fake_eula_{&mixin_host_, embedded_test_server()}; + private: - std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { - GURL request_url = GURL("http://localhost").Resolve(request.relative_url); - const std::string request_path = request_url.path(); - if (!base::EndsWith(request_path, "/eula_text.html", - base::CompareCase::SENSITIVE)) { - return std::unique_ptr<HttpResponse>(); - } - - std::unique_ptr<BasicHttpResponse> http_response = - std::make_unique<BasicHttpResponse>(); - - if (force_http_unavailable_) { - http_response->set_code(net::HTTP_SERVICE_UNAVAILABLE); - } else { - http_response->set_code(net::HTTP_OK); - http_response->set_content_type("text/html"); - http_response->set_content(kFakeOnlineEula); - } - - return std::move(http_response); - } - - // The default behaviour for the embedded server is to service the - // online version properly. Offline tests may change this during construction - // of the class. - bool force_http_unavailable_ = false; - DISALLOW_COPY_AND_ASSIGN(EulaTest); }; @@ -274,7 +210,7 @@ // embedded server have to be handled differently. class EulaOfflineTest : public EulaTest { public: - EulaOfflineTest() { set_force_http_unavailable(true); } + EulaOfflineTest() { fake_eula_.set_force_http_unavailable(true); } ~EulaOfflineTest() override = default; }; @@ -285,20 +221,13 @@ ShowEulaScreen(); WaitForLocalWebviewLoad(); - EXPECT_TRUE( - test::GetWebViewContents(kEulaWebview).find(kOfflineEULAWarning) != - std::string::npos); + EXPECT_TRUE(test::GetWebViewContents(kEulaWebview) + .find(FakeEulaMixin::kOfflineEULAWarning) != + std::string::npos); } -#if defined(OS_CHROMEOS) && \ - (defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER)) -// TODO(http://crbug.com/1041188): flaky on ChromeOS MSAN and LSAN. -#define MAYBE_LoadOnline DISABLED_LoadOnline -#else -#define MAYBE_LoadOnline LoadOnline -#endif // Tests that online version is shown when it is accessible. -IN_PROC_BROWSER_TEST_F(EulaTest, MAYBE_LoadOnline) { +IN_PROC_BROWSER_TEST_F(EulaTest, LoadOnline) { ShowEulaScreen(); // Wait until the webview has finished loading. @@ -310,7 +239,8 @@ chromeos::test::OobeJS().CreateEnabledWaiter(true, kAcceptEulaButton)->Wait(); const std::string webview_contents = test::GetWebViewContents(kEulaWebview); - EXPECT_TRUE(webview_contents.find(kFakeOnlineEula) != std::string::npos); + EXPECT_TRUE(webview_contents.find(FakeEulaMixin::kFakeOnlineEula) != + std::string::npos); } // Tests that clicking on "System security settings" button opens a dialog
diff --git a/chrome/browser/chromeos/login/test/fake_eula_mixin.cc b/chrome/browser/chromeos/login/test/fake_eula_mixin.cc new file mode 100644 index 0000000..5ce22c0 --- /dev/null +++ b/chrome/browser/chromeos/login/test/fake_eula_mixin.cc
@@ -0,0 +1,77 @@ +// Copyright 2020 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/chromeos/login/test/fake_eula_mixin.h" + +#include "base/bind.h" +#include "build/branding_buildflags.h" +#include "build/build_config.h" +#include "chromeos/constants/chromeos_switches.h" +#include "url/gurl.h" + +using net::test_server::BasicHttpResponse; +using net::test_server::HttpRequest; +using net::test_server::HttpResponse; + +namespace chromeos { + +namespace { + +constexpr char kFakeOnlineEulaPath[] = "/intl/en-US/chrome/eula_text.html"; + +} // namespace + +const char* FakeEulaMixin::kFakeOnlineEula = "No obligations at all"; +const char* FakeEulaMixin::kOfflineEULAWarning = +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + // See IDS_TERMS_HTML for the complete text. + "Google Chrome and Chrome OS Additional Terms of Service"; +#else + // Placeholder text in terms_chromium.html. + "In official builds this space will show the terms of service."; +#endif + +FakeEulaMixin::FakeEulaMixin(InProcessBrowserTestMixinHost* host, + net::EmbeddedTestServer* test_server) + : InProcessBrowserTestMixin(host), test_server_(test_server) {} + +FakeEulaMixin::~FakeEulaMixin() = default; + +void FakeEulaMixin::SetUp() { + test_server_->RegisterRequestHandler(base::BindRepeating( + &FakeEulaMixin::HandleRequest, base::Unretained(this))); +} + +void FakeEulaMixin::SetUpCommandLine(base::CommandLine* command_line) { + // Retrieve the URL from the embedded test server and override EULA URL. + std::string fake_eula_url = + test_server_->base_url().Resolve(kFakeOnlineEulaPath).spec(); + command_line->AppendSwitchASCII(switches::kOobeEulaUrlForTests, + fake_eula_url); +} + +std::unique_ptr<HttpResponse> FakeEulaMixin::HandleRequest( + const HttpRequest& request) { + GURL request_url = GURL("http://localhost").Resolve(request.relative_url); + const std::string request_path = request_url.path(); + if (!base::EndsWith(request_path, "/eula_text.html", + base::CompareCase::SENSITIVE)) { + return nullptr; + } + + std::unique_ptr<BasicHttpResponse> http_response = + std::make_unique<BasicHttpResponse>(); + + if (force_http_unavailable_) { + http_response->set_code(net::HTTP_SERVICE_UNAVAILABLE); + } else { + http_response->set_code(net::HTTP_OK); + http_response->set_content_type("text/html"); + http_response->set_content(kFakeOnlineEula); + } + + return std::move(http_response); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/fake_eula_mixin.h b/chrome/browser/chromeos/login/test/fake_eula_mixin.h new file mode 100644 index 0000000..6b0e065 --- /dev/null +++ b/chrome/browser/chromeos/login/test/fake_eula_mixin.h
@@ -0,0 +1,50 @@ +// Copyright 2020 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_CHROMEOS_LOGIN_TEST_FAKE_EULA_MIXIN_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_FAKE_EULA_MIXIN_H_ + +#include "chrome/test/base/mixin_based_in_process_browser_test.h" + +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" + +using net::test_server::HttpRequest; +using net::test_server::HttpResponse; + +namespace chromeos { + +// Mixin that serves fake eula for OOBE. +class FakeEulaMixin : public InProcessBrowserTestMixin { + public: + static const char* kFakeOnlineEula; + static const char* kOfflineEULAWarning; + + FakeEulaMixin(InProcessBrowserTestMixinHost* host, + net::EmbeddedTestServer* test_server); + + void SetUp() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + + ~FakeEulaMixin() override; + + // Used for customizing the response handler of the embedded server. + void set_force_http_unavailable(bool force_unavailable) { + force_http_unavailable_ = force_unavailable; + } + + private: + std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request); + net::EmbeddedTestServer* test_server_; + + // The default behaviour for the embedded server is to service the + // online version properly. Offline tests may change this during construction + // of the class. + bool force_http_unavailable_ = false; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_FAKE_EULA_MIXIN_H_
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc index 2b1e1ea..f363e0e 100644 --- a/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc +++ b/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
@@ -373,8 +373,22 @@ return status; } - if (status == errSecItemNotFound || force_recreate) - return AddRandomPasswordToKeychain(keychain, password); + if (status == errSecItemNotFound || force_recreate) { + if (status != errSecItemNotFound) { + // If the item is present but can't be read. Try to delete it first. + // If any of those steps fail don't try to proceed any further. + item_ref.reset(); + status = keychain.FindGenericPassword( + strlen(kServiceName), kServiceName, strlen(kAccountName), + kAccountName, nullptr, nullptr, item_ref.InitializeInto()); + if (status != noErr) + return status; + status = keychain.ItemDelete(item_ref.get()); + if (status != noErr) + return status; + } + status = AddRandomPasswordToKeychain(keychain, password); + } return status; }
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc b/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc index ec80d6db..529d3bc 100644 --- a/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc +++ b/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc
@@ -17,6 +17,7 @@ #include "base/files/file.h" #include "base/files/file_util.h" #include "base/nix/xdg_util.h" +#include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info.h" @@ -35,6 +36,20 @@ } std::string GetOsVersion() { + base::FilePath os_release_file("/etc/os-release"); + std::string release_info; + base::StringPairs values; + if (base::PathExists(os_release_file) && + base::ReadFileToStringWithMaxSize(os_release_file, &release_info, 8192) && + base::SplitStringIntoKeyValuePairs(release_info, '=', '\n', &values)) { + auto version_id = std::find_if(values.begin(), values.end(), [](auto v) { + return v.first == "VERSION_ID"; + }); + if (version_id != values.end()) { + return base::TrimString(version_id->second, "\"", base::TRIM_ALL) + .as_string(); + } + } return base::SysInfo::OperatingSystemVersion(); }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 4c8093b4..e1d989a9 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2890,6 +2890,11 @@ "expiry_milestone": -1 }, { + "name": "lite-video-default-downlink-bandwidth-kbps", + "owners": [ "//components/data_reduction_proxy/OWNERS" ], + "expiry_milestone": 92 + }, + { "name": "lite-video-force-override-decision", "owners": [ "//components/data_reduction_proxy/OWNERS" ], // This flag is used for debugging and development purposes, allowing users @@ -4464,7 +4469,12 @@ { "name": "webui-tab-strip", "owners": [ "collinbaker", "johntlee" ], - "expiry_milestone": 85 + "expiry_milestone": 89 + }, + { + "name": "webui-tab-strip-tab-drag-integration", + "owners": [ "collinbaker", "johntlee" ], + "expiry_milestone": 89 }, { "name": "webxr-incubations",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 4826e3d..2e3b4cbb 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1316,6 +1316,11 @@ "Enable the LiteVideo optimization to throttle media requests to " "reduce data usage"; +const char kLiteVideoDownlinkBandwidthKbpsName[] = + "Lite Video: Adjust throttling downlink (in Kbps)."; +const char kLiteVideoDownlinkBandwidthKbpsDescription[] = + "Specify the throttling bandwidth to be used"; + const char kLiteVideoForceOverrideDecisionName[] = "Force LiteVideos decision"; const char kLiteVideoForceOverrideDecisionDescription[] = "Force the LiteVideo decision to be allowed on every navigation."; @@ -4467,6 +4472,14 @@ "When enabled makes use of a WebUI-based tab strip."; #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) +#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && defined(OS_CHROMEOS) +const char kWebUITabStripTabDragIntegrationName[] = + "ChromeOS drag-drop extensions for WebUI tab strip"; +const char kWebUITabStripTabDragIntegrationDescription[] = + "Enables special handling in ash for WebUI tab strip tab drags. Allows " + "dragging tabs out to new windows."; +#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && defined(OS_CHROMEOS) + #if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID) const char kAutofillCreditCardUploadName[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 683ad33d..ef65b68 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -774,6 +774,9 @@ extern const char kLiteVideoName[]; extern const char kLiteVideoDescription[]; +extern const char kLiteVideoDownlinkBandwidthKbpsName[]; +extern const char kLiteVideoDownlinkBandwidthKbpsDescription[]; + extern const char kLiteVideoForceOverrideDecisionName[]; extern const char kLiteVideoForceOverrideDecisionDescription[]; @@ -2623,6 +2626,11 @@ extern const char kWebUITabStripDescription[]; #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) +#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && defined(OS_CHROMEOS) +extern const char kWebUITabStripTabDragIntegrationName[]; +extern const char kWebUITabStripTabDragIntegrationDescription[]; +#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) && defined(OS_CHROMEOS) + #if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID) extern const char kAutofillCreditCardUploadName[];
diff --git a/chrome/browser/media/router/mojo/media_router_desktop_unittest.cc b/chrome/browser/media/router/mojo/media_router_desktop_unittest.cc index 14c9ffc..a7d88bda 100644 --- a/chrome/browser/media/router/mojo/media_router_desktop_unittest.cc +++ b/chrome/browser/media/router/mojo/media_router_desktop_unittest.cc
@@ -72,9 +72,11 @@ feature_list_.InitAndDisableFeature(kDialMediaRouteProvider); cast_media_sink_service = std::make_unique<MockCastMediaSinkService>(); cast_media_sink_service_ = cast_media_sink_service.get(); - media_sink_service_ = std::unique_ptr<DualMediaSinkService>( - new DualMediaSinkService(std::move(cast_media_sink_service), - std::make_unique<MockDialMediaSinkService>())); + media_sink_service_ = + std::unique_ptr<DualMediaSinkService>(new DualMediaSinkService( + std::move(cast_media_sink_service), + std::make_unique<MockDialMediaSinkService>(), + std::make_unique<MockCastAppDiscoveryService>())); return std::unique_ptr<MediaRouterDesktop>( new MediaRouterDesktop(profile(), media_sink_service_.get())); }
diff --git a/chrome/browser/media/router/providers/cast/cast_app_discovery_service.cc b/chrome/browser/media/router/providers/cast/cast_app_discovery_service.cc index 3b06c1f..30dc58f1 100644 --- a/chrome/browser/media/router/providers/cast/cast_app_discovery_service.cc +++ b/chrome/browser/media/router/providers/cast/cast_app_discovery_service.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/media/router/providers/cast/cast_app_discovery_service.h" #include "base/bind.h" +#include "base/strings/strcat.h" #include "base/time/tick_clock.h" #include "chrome/browser/media/router/providers/cast/cast_media_route_provider_metrics.h" #include "components/cast_channel/cast_message_handler.h" @@ -15,6 +16,8 @@ namespace { +constexpr char kLoggerComponent[] = "CastAppDiscoveryService"; + // The minimum time that must elapse before an app availability result can be // force refreshed. static constexpr base::TimeDelta kRefreshThreshold = @@ -79,7 +82,15 @@ cast_channel::CastSocket* socket = socket_service_->GetSocket(channel_id); if (!socket) { - DVLOG(1) << "Socket not found for id " << channel_id; + if (logger_.is_bound()) { + logger_->LogError( + mojom::LogCategory::kDiscovery, kLoggerComponent, + base::StringPrintf( + "Socket not found for channel id: %d when starting " + "discovery for source.", + channel_id), + sink.first, source.source_id(), ""); + } continue; } @@ -98,18 +109,36 @@ // being iterated. for (const auto& sink : sinks) { for (const auto& app_id : app_ids) { - int channel_id = sink.second.cast_data().cast_channel_id; - cast_channel::CastSocket* socket = - socket_service_->GetSocket(channel_id); - if (!socket) { - DVLOG(1) << "Socket not found for id " << channel_id; - continue; + int channel_id = sink.second.cast_data().cast_channel_id; + cast_channel::CastSocket* socket = socket_service_->GetSocket(channel_id); + if (!socket) { + if (logger_.is_bound()) { + logger_->LogError( + mojom::LogCategory::kDiscovery, kLoggerComponent, + base::StringPrintf( + "Socket not found for channel id: %d when refreshing " + "the discovery state.", + channel_id), + sink.first, "", ""); } - RequestAppAvailability(socket, app_id, sink.first); + continue; } + RequestAppAvailability(socket, app_id, sink.first); + } } } +void CastAppDiscoveryServiceImpl::BindLogger( + mojo::PendingRemote<mojom::Logger> pending_remote) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + logger_.Bind(std::move(pending_remote)); +} + +scoped_refptr<base::SequencedTaskRunner> +CastAppDiscoveryServiceImpl::task_runner() { + return socket_service_->task_runner(); +} + void CastAppDiscoveryServiceImpl::MaybeRemoveSinkQueryEntry( const CastMediaSource& source) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -174,8 +203,13 @@ if (!media_sink_service_->GetSinkById(sink_id)) return; - DVLOG(1) << "App " << app_id << " on sink " << sink_id << " is " - << ToString(availability); + if (availability != cast_channel::GetAppAvailabilityResult::kAvailable && + logger_.is_bound()) { + logger_->LogInfo( + mojom::LogCategory::kDiscovery, kLoggerComponent, + base::StrCat({"App ", app_id, " on sink is ", ToString(availability)}), + sink_id, "", ""); + } UpdateSinkQueries(availability_tracker_.UpdateAppAvailability( sink_id, app_id, {availability, clock_->NowTicks()}));
diff --git a/chrome/browser/media/router/providers/cast/cast_app_discovery_service.h b/chrome/browser/media/router/providers/cast/cast_app_discovery_service.h index 16a3be56..69ff5950a 100644 --- a/chrome/browser/media/router/providers/cast/cast_app_discovery_service.h +++ b/chrome/browser/media/router/providers/cast/cast_app_discovery_service.h
@@ -20,8 +20,10 @@ #include "chrome/common/media_router/discovery/media_sink_service_base.h" #include "chrome/common/media_router/media_sink.h" #include "chrome/common/media_router/media_source.h" +#include "chrome/common/media_router/mojom/logger.mojom.h" #include "chrome/common/media_router/providers/cast/cast_media_source.h" #include "components/cast_channel/cast_message_util.h" +#include "mojo/public/cpp/bindings/remote.h" namespace base { class TickClock; @@ -58,6 +60,14 @@ // this method when the user initiates a user gesture (such as opening the // Media Router dialog). virtual void Refresh() = 0; + + // Binds |pending_remote| to the Mojo Remote owned by |impl_|. + virtual void BindLogger( + mojo::PendingRemote<mojom::Logger> pending_remote) = 0; + + // Returns the SequencedTaskRunner that should be used to invoke methods on + // this instance. Can be invoked on any thread. + virtual scoped_refptr<base::SequencedTaskRunner> task_runner() = 0; }; // Keeps track of sink queries and listens to CastMediaSinkServiceImpl for sink @@ -82,6 +92,10 @@ // pairs whose status is kUnavailable or kUnknown. void Refresh() override; + void BindLogger(mojo::PendingRemote<mojom::Logger> pending_remote) override; + + scoped_refptr<base::SequencedTaskRunner> task_runner() override; + private: friend class CastAppDiscoveryServiceImplTest; @@ -136,6 +150,10 @@ CastAppAvailabilityTracker availability_tracker_; const base::TickClock* const clock_; + // Mojo Remote to the logger owned by the Media Router. The Remote is not + // bound until |BindLogger()| is called. Always check if |logger_.is_bound()| + // is true before using. + mojo::Remote<mojom::Logger> logger_; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<CastAppDiscoveryServiceImpl> weak_ptr_factory_{this};
diff --git a/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc b/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc index f37ad54..79d5b73 100644 --- a/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc +++ b/chrome/browser/media/router/providers/cast/dual_media_sink_service.cc
@@ -89,9 +89,11 @@ DualMediaSinkService::DualMediaSinkService( std::unique_ptr<CastMediaSinkService> cast_media_sink_service, - std::unique_ptr<DialMediaSinkService> dial_media_sink_service) + std::unique_ptr<DialMediaSinkService> dial_media_sink_service, + std::unique_ptr<CastAppDiscoveryService> cast_app_discovery_service) : dial_media_sink_service_(std::move(dial_media_sink_service)), - cast_media_sink_service_(std::move(cast_media_sink_service)) {} + cast_media_sink_service_(std::move(cast_media_sink_service)), + cast_app_discovery_service_(std::move(cast_app_discovery_service)) {} DualMediaSinkService::~DualMediaSinkService() = default; @@ -116,6 +118,15 @@ mojo::PendingRemote<mojom::Logger> dial_pending_remote; logger_impl->Bind(dial_pending_remote.InitWithNewPipeAndPassReceiver()); dial_media_sink_service_->BindLogger(std::move(dial_pending_remote)); + + mojo::PendingRemote<mojom::Logger> cast_discovery_pending_remote; + logger_impl->Bind( + cast_discovery_pending_remote.InitWithNewPipeAndPassReceiver()); + cast_app_discovery_service_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&CastAppDiscoveryService::BindLogger, + base::Unretained(cast_app_discovery_service_.get()), + std::move(cast_discovery_pending_remote))); } } // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/dual_media_sink_service.h b/chrome/browser/media/router/providers/cast/dual_media_sink_service.h index d539c334..aae31ad 100644 --- a/chrome/browser/media/router/providers/cast/dual_media_sink_service.h +++ b/chrome/browser/media/router/providers/cast/dual_media_sink_service.h
@@ -77,7 +77,8 @@ // |dial_media_sink_service_|. // The binding should be done once and the method is a no-op after the first // call. - void BindLogger(LoggerImpl* logger_impl); + // Marked virtual for testing. + virtual void BindLogger(LoggerImpl* logger_impl); virtual void OnUserGesture(); @@ -89,7 +90,8 @@ // Used by tests. DualMediaSinkService( std::unique_ptr<CastMediaSinkService> cast_media_sink_service, - std::unique_ptr<DialMediaSinkService> dial_media_sink_service); + std::unique_ptr<DialMediaSinkService> dial_media_sink_service, + std::unique_ptr<CastAppDiscoveryService> cast_app_discovery_service); virtual ~DualMediaSinkService(); private:
diff --git a/chrome/browser/media/router/providers/cast/dual_media_sink_service_unittest.cc b/chrome/browser/media/router/providers/cast/dual_media_sink_service_unittest.cc index 731c382..6b8b7496 100644 --- a/chrome/browser/media/router/providers/cast/dual_media_sink_service_unittest.cc +++ b/chrome/browser/media/router/providers/cast/dual_media_sink_service_unittest.cc
@@ -16,11 +16,15 @@ DualMediaSinkServiceTest() { auto cast_media_sink_service = std::make_unique<MockCastMediaSinkService>(); auto dial_media_sink_service = std::make_unique<MockDialMediaSinkService>(); + auto cast_app_discovery_service = + std::make_unique<MockCastAppDiscoveryService>(); cast_media_sink_service_ = cast_media_sink_service.get(); dial_media_sink_service_ = dial_media_sink_service.get(); + cast_app_discovery_service_ = cast_app_discovery_service.get(); dual_media_sink_service_ = std::unique_ptr<DualMediaSinkService>( new DualMediaSinkService(std::move(cast_media_sink_service), - std::move(dial_media_sink_service))); + std::move(dial_media_sink_service), + std::move(cast_app_discovery_service))); } ~DualMediaSinkServiceTest() override = default; @@ -42,6 +46,7 @@ private: MockCastMediaSinkService* cast_media_sink_service_; MockDialMediaSinkService* dial_media_sink_service_; + MockCastAppDiscoveryService* cast_app_discovery_service_; std::unique_ptr<DualMediaSinkService> dual_media_sink_service_; };
diff --git a/chrome/browser/media/router/test/noop_dual_media_sink_service.cc b/chrome/browser/media/router/test/noop_dual_media_sink_service.cc index d4dcd61..d65be7f8 100644 --- a/chrome/browser/media/router/test/noop_dual_media_sink_service.cc +++ b/chrome/browser/media/router/test/noop_dual_media_sink_service.cc
@@ -6,12 +6,14 @@ #include "chrome/browser/media/router/discovery/dial/dial_media_sink_service.h" #include "chrome/browser/media/router/discovery/mdns/cast_media_sink_service.h" +#include "chrome/browser/media/router/providers/cast/cast_app_discovery_service.h" namespace media_router { NoopDualMediaSinkService::NoopDualMediaSinkService() : DualMediaSinkService(std::unique_ptr<CastMediaSinkService>(nullptr), - std::unique_ptr<DialMediaSinkService>(nullptr)) {} + std::unique_ptr<DialMediaSinkService>(nullptr), + std::unique_ptr<CastAppDiscoveryService>(nullptr)) {} NoopDualMediaSinkService::~NoopDualMediaSinkService() = default; } // namespace media_router
diff --git a/chrome/browser/media/router/test/test_helper.cc b/chrome/browser/media/router/test/test_helper.cc index 319eac5..9d9af75d 100644 --- a/chrome/browser/media/router/test/test_helper.cc +++ b/chrome/browser/media/router/test/test_helper.cc
@@ -12,6 +12,8 @@ #if !defined(OS_ANDROID) #include "base/json/json_reader.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "services/network/public/cpp/simple_url_loader.h" #include "url/gurl.h" #endif @@ -38,7 +40,7 @@ MockPresentationConnectionProxy::~MockPresentationConnectionProxy() {} #if !defined(OS_ANDROID) -MockDialMediaSinkService::MockDialMediaSinkService() : DialMediaSinkService() {} +MockDialMediaSinkService::MockDialMediaSinkService() = default; MockDialMediaSinkService::~MockDialMediaSinkService() = default; MockCastMediaSinkService::MockCastMediaSinkService() : CastMediaSinkService() {} @@ -54,6 +56,10 @@ DoStartObservingMediaSinks(source); return callbacks_.Add(callback); } +scoped_refptr<base::SequencedTaskRunner> +MockCastAppDiscoveryService::task_runner() { + return base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}); +} MockDialAppDiscoveryService::MockDialAppDiscoveryService() = default;
diff --git a/chrome/browser/media/router/test/test_helper.h b/chrome/browser/media/router/test/test_helper.h index b4af439f..eccbdc1 100644 --- a/chrome/browser/media/router/test/test_helper.h +++ b/chrome/browser/media/router/test/test_helper.h
@@ -28,6 +28,7 @@ #include "chrome/browser/media/router/providers/dial/dial_activity_manager.h" #include "chrome/browser/media/router/providers/dial/dial_internal_message_util.h" #include "chrome/common/media_router/discovery/media_sink_internal.h" +#include "chrome/common/media_router/mojom/logger.mojom.h" #include "net/base/ip_endpoint.h" #include "services/network/test/test_url_loader_factory.h" #endif // !defined(OS_ANDROID) @@ -117,8 +118,10 @@ Subscription StartObservingMediaSinks( const CastMediaSource& source, const SinkQueryCallback& callback) override; + scoped_refptr<base::SequencedTaskRunner> task_runner() override; MOCK_METHOD1(DoStartObservingMediaSinks, void(const CastMediaSource&)); MOCK_METHOD0(Refresh, void()); + MOCK_METHOD1(BindLogger, void(mojo::PendingRemote<mojom::Logger>)); SinkQueryCallbackList& callbacks() { return callbacks_; }
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connection.cc b/chrome/browser/nearby_sharing/fake_nearby_connection.cc index 2f5a523..b44d3371 100644 --- a/chrome/browser/nearby_sharing/fake_nearby_connection.cc +++ b/chrome/browser/nearby_sharing/fake_nearby_connection.cc
@@ -24,16 +24,17 @@ void FakeNearbyConnection::Close() { DCHECK(!closed_); closed_ = true; + if (disconnect_listener_) + std::move(disconnect_listener_).Run(); + if (callback_) std::move(callback_).Run(base::nullopt); - for (auto& disconnect_listener : disconnect_listeners_) - std::move(disconnect_listener).Run(); } -void FakeNearbyConnection::RegisterForDisconnection( +void FakeNearbyConnection::SetDisconnectionListener( base::OnceClosure listener) { DCHECK(!closed_); - disconnect_listeners_.push_back(std::move(listener)); + disconnect_listener_ = std::move(listener); } void FakeNearbyConnection::AppendReadableData(std::vector<uint8_t> bytes) {
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connection.h b/chrome/browser/nearby_sharing/fake_nearby_connection.h index 0dc9be4..a54578b 100644 --- a/chrome/browser/nearby_sharing/fake_nearby_connection.h +++ b/chrome/browser/nearby_sharing/fake_nearby_connection.h
@@ -19,7 +19,7 @@ void Read(ReadCallback callback) override; void Write(std::vector<uint8_t> bytes) override; void Close() override; - void RegisterForDisconnection(base::OnceClosure listener) override; + void SetDisconnectionListener(base::OnceClosure listener) override; void AppendReadableData(std::vector<uint8_t> bytes); std::vector<uint8_t> GetWrittenData(); @@ -31,7 +31,7 @@ ReadCallback callback_; std::queue<std::vector<uint8_t>> read_data_; std::queue<std::vector<uint8_t>> write_data_; - std::vector<base::OnceClosure> disconnect_listeners_; + base::OnceClosure disconnect_listener_; }; #endif // CHROME_BROWSER_NEARBY_SHARING_FAKE_NEARBY_CONNECTION_H_
diff --git a/chrome/browser/nearby_sharing/incoming_frames_reader.cc b/chrome/browser/nearby_sharing/incoming_frames_reader.cc index 583e674..b3a2d525 100644 --- a/chrome/browser/nearby_sharing/incoming_frames_reader.cc +++ b/chrome/browser/nearby_sharing/incoming_frames_reader.cc
@@ -36,9 +36,6 @@ DCHECK(connection_); nearby_process_observer_.Add(process_manager); - connection->RegisterForDisconnection( - base::BindOnce(&IncomingFramesReader::OnConnectionClosed, - weak_ptr_factory_.GetWeakPtr())); } IncomingFramesReader::~IncomingFramesReader() = default; @@ -180,10 +177,6 @@ } } -void IncomingFramesReader::OnConnectionClosed() { - connection_ = nullptr; -} - base::Optional<sharing::mojom::V1FramePtr> IncomingFramesReader::GetCachedFrame( base::Optional<sharing::mojom::V1Frame::Tag> frame_type) { NS_LOG(VERBOSE) << __func__ << ": Fetching cached frame";
diff --git a/chrome/browser/nearby_sharing/incoming_frames_reader.h b/chrome/browser/nearby_sharing/incoming_frames_reader.h index 5a11497a..1f27a61c 100644 --- a/chrome/browser/nearby_sharing/incoming_frames_reader.h +++ b/chrome/browser/nearby_sharing/incoming_frames_reader.h
@@ -61,7 +61,6 @@ void OnFrameDecoded(sharing::mojom::FramePtr mojo_frame); void OnTimeout(); void Done(base::Optional<sharing::mojom::V1FramePtr> frame); - void OnConnectionClosed(); base::Optional<sharing::mojom::V1FramePtr> GetCachedFrame( base::Optional<sharing::mojom::V1Frame::Tag> frame_type);
diff --git a/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc b/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc index 5b10fa36..0e5f0a6 100644 --- a/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc +++ b/chrome/browser/nearby_sharing/incoming_frames_reader_unittest.cc
@@ -283,15 +283,4 @@ connection().Close(); run_loop_before_close.Run(); - - base::RunLoop run_loop_after_close; - frames_reader().ReadFrame( - sharing::mojom::V1Frame::Tag::INTRODUCTION, - base::BindLambdaForTesting( - [&](base::Optional<sharing::mojom::V1FramePtr> frame) { - EXPECT_FALSE(frame); - run_loop_after_close.Quit(); - }), - kTimeout); - run_loop_after_close.Run(); }
diff --git a/chrome/browser/nearby_sharing/incoming_share_target_info.h b/chrome/browser/nearby_sharing/incoming_share_target_info.h index 22347a4..4bb9559f 100644 --- a/chrome/browser/nearby_sharing/incoming_share_target_info.h +++ b/chrome/browser/nearby_sharing/incoming_share_target_info.h
@@ -5,10 +5,12 @@ #ifndef CHROME_BROWSER_NEARBY_SHARING_INCOMING_SHARE_TARGET_INFO_H_ #define CHROME_BROWSER_NEARBY_SHARING_INCOMING_SHARE_TARGET_INFO_H_ +#include <memory> #include <string> #include "base/optional.h" #include "chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h" +#include "chrome/browser/nearby_sharing/incoming_frames_reader.h" class NearbyConnection; @@ -50,11 +52,18 @@ const base::Optional<std::string>& token() const { return token_; } + IncomingFramesReader* frames_reader() { return frames_reader_.get(); } + + void set_frames_reader(std::unique_ptr<IncomingFramesReader> frames_reader) { + frames_reader_ = std::move(frames_reader); + } + private: base::Optional<std::string> endpoint_id_; base::Optional<NearbyShareDecryptedPublicCertificate> certificate_; NearbyConnection* connection_ = nullptr; base::Optional<std::string> token_; + std::unique_ptr<IncomingFramesReader> frames_reader_; }; #endif // CHROME_BROWSER_NEARBY_SHARING_INCOMING_SHARE_TARGET_INFO_H_
diff --git a/chrome/browser/nearby_sharing/nearby_connection.h b/chrome/browser/nearby_sharing/nearby_connection.h index 645c1b81..1450a0f 100644 --- a/chrome/browser/nearby_sharing/nearby_connection.h +++ b/chrome/browser/nearby_sharing/nearby_connection.h
@@ -32,12 +32,13 @@ virtual void Write(std::vector<uint8_t> bytes) = 0; // Closes the socket and disconnects from the remote device. This object will - // be invalidated after |callback| in RegisterForDisconnection is invoked. + // be invalidated after |callback| in SetDisconnectionListener is invoked. virtual void Close() = 0; // Listens to the socket being closed. Invoke |callback| when the socket is // closed. This object will be invalidated after |listener| is invoked. - virtual void RegisterForDisconnection(base::OnceClosure listener) = 0; + // Previously set listener will be replaced by |listener|. + virtual void SetDisconnectionListener(base::OnceClosure listener) = 0; }; #endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTION_H_
diff --git a/chrome/browser/nearby_sharing/nearby_connection_impl.cc b/chrome/browser/nearby_sharing/nearby_connection_impl.cc index 3670f17f..04676bb 100644 --- a/chrome/browser/nearby_sharing/nearby_connection_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_connection_impl.cc
@@ -15,11 +15,11 @@ NearbyConnectionImpl::~NearbyConnectionImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (disconnect_listener_) + std::move(disconnect_listener_).Run(); + if (read_callback_) std::move(read_callback_).Run(base::nullopt); - - for (auto& disconnect_listener : disconnect_listeners_) - std::move(disconnect_listener).Run(); } void NearbyConnectionImpl::Read(ReadCallback callback) { @@ -53,10 +53,10 @@ nearby_connections_manager_->Disconnect(std::string(endpoint_id_)); } -void NearbyConnectionImpl::RegisterForDisconnection( +void NearbyConnectionImpl::SetDisconnectionListener( base::OnceClosure listener) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - disconnect_listeners_.push_back(std::move(listener)); + disconnect_listener_ = std::move(listener); } void NearbyConnectionImpl::WriteMessage(std::vector<uint8_t> bytes) {
diff --git a/chrome/browser/nearby_sharing/nearby_connection_impl.h b/chrome/browser/nearby_sharing/nearby_connection_impl.h index 42f9e6f..58368c16 100644 --- a/chrome/browser/nearby_sharing/nearby_connection_impl.h +++ b/chrome/browser/nearby_sharing/nearby_connection_impl.h
@@ -24,7 +24,7 @@ void Read(ReadCallback callback) override; void Write(std::vector<uint8_t> bytes) override; void Close() override; - void RegisterForDisconnection(base::OnceClosure listener) override; + void SetDisconnectionListener(base::OnceClosure listener) override; // Add |bytes| to the read queue, notifying ReadCallback. void WriteMessage(std::vector<uint8_t> bytes); @@ -38,7 +38,7 @@ NearbyConnectionsManager* nearby_connections_manager_; std::string endpoint_id_; ReadCallback read_callback_; - std::vector<base::OnceClosure> disconnect_listeners_; + base::OnceClosure disconnect_listener_; // A read queue. The data that we've read from the remote device ends up here // until Read() is called to dequeue it.
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc index 8c6fd80..31d6f3c 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
@@ -389,7 +389,7 @@ // Close should invoke disconnection callback and read callback. base::RunLoop close_run_loop; - nearby_connection->RegisterForDisconnection( + nearby_connection->SetDisconnectionListener( base::BindLambdaForTesting([&]() { close_run_loop.Quit(); })); base::RunLoop read_run_loop_3; nearby_connection->Read(base::BindLambdaForTesting( @@ -427,7 +427,7 @@ // Remote closing should invoke disconnection callback and read callback. base::RunLoop close_run_loop; - nearby_connection->RegisterForDisconnection( + nearby_connection->SetDisconnectionListener( base::BindLambdaForTesting([&]() { close_run_loop.Quit(); })); base::RunLoop read_run_loop; nearby_connection->Read(base::BindLambdaForTesting( @@ -458,7 +458,7 @@ // Remote closing should invoke disconnection callback and read callback. base::RunLoop close_run_loop; - nearby_connection->RegisterForDisconnection( + nearby_connection->SetDisconnectionListener( base::BindLambdaForTesting([&]() { close_run_loop.Quit(); })); base::RunLoop read_run_loop; nearby_connection->Read(base::BindLambdaForTesting(
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 1e89156..057bb77 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -325,7 +325,7 @@ weak_ptr_factory_.GetWeakPtr(), share_target), kIncomingRejectionDelay); - connection->RegisterForDisconnection( + connection->SetDisconnectionListener( base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget, weak_ptr_factory_.GetWeakPtr(), share_target)); @@ -391,7 +391,7 @@ incoming_share_target_info_map_[share_target.id].set_connection(connection); incoming_share_target_info_map_[share_target.id].set_endpoint_id(endpoint_id); - connection->RegisterForDisconnection( + connection->SetDisconnectionListener( base::BindOnce(&NearbySharingServiceImpl::UnregisterShareTarget, weak_ptr_factory_.GetWeakPtr(), share_target)); @@ -832,7 +832,7 @@ return; } - // TODO(himanshujaju) - Create alarm and cancel in RegisterForDisconnection(). + // TODO(himanshujaju) - Create alarm and cancel in SetDisconnectionListener(). // Send response to remote device. sharing::nearby::ConnectionResponseFrame::Status response_status; @@ -889,21 +889,20 @@ return; } - auto frames_reader = std::make_unique<IncomingFramesReader>( - process_manager_, profile_, connection); - - frames_reader->ReadFrame( + auto& share_target_info = GetIncomingShareTargetInfo(share_target); + share_target_info.set_frames_reader(std::make_unique<IncomingFramesReader>( + process_manager_, profile_, connection)); + share_target_info.frames_reader()->ReadFrame( sharing::mojom::V1Frame::Tag::INTRODUCTION, base::BindOnce(&NearbySharingServiceImpl::OnReceivedIntroduction, weak_ptr_factory_.GetWeakPtr(), std::move(share_target), - std::move(token), std::move(frames_reader)), + std::move(token)), kReadFramesTimeout); } void NearbySharingServiceImpl::OnReceivedIntroduction( ShareTarget share_target, base::Optional<std::string> token, - std::unique_ptr<IncomingFramesReader> frames_reader, base::Optional<sharing::mojom::V1FramePtr> frame) { NearbyConnection* connection = GetIncomingConnection(share_target); if (!connection) { @@ -1000,17 +999,25 @@ return; } - connection->RegisterForDisconnection(base::BindOnce( + connection->SetDisconnectionListener(base::BindOnce( &NearbySharingServiceImpl::OnIncomingConnectionDisconnected, weak_ptr_factory_.GetWeakPtr(), share_target)); - frames_reader->ReadFrame(base::BindOnce( - &NearbySharingServiceImpl::OnFrameRead, weak_ptr_factory_.GetWeakPtr(), - std::move(frames_reader), std::move(share_target))); + auto* frames_reader = + GetIncomingShareTargetInfo(share_target).frames_reader(); + if (!frames_reader) { + NS_LOG(WARNING) << __func__ + << ": Stopped reading further frames, due to no connection " + "established."; + return; + } + + frames_reader->ReadFrame( + base::BindOnce(&NearbySharingServiceImpl::OnFrameRead, + weak_ptr_factory_.GetWeakPtr(), std::move(share_target))); } void NearbySharingServiceImpl::OnFrameRead( - std::unique_ptr<IncomingFramesReader> frames_reader, ShareTarget share_target, base::Optional<sharing::mojom::V1FramePtr> frame) { if (!frame) { @@ -1036,9 +1043,18 @@ break; } - frames_reader->ReadFrame(base::BindOnce( - &NearbySharingServiceImpl::OnFrameRead, weak_ptr_factory_.GetWeakPtr(), - std::move(frames_reader), std::move(share_target))); + auto* frames_reader = + GetIncomingShareTargetInfo(share_target).frames_reader(); + if (!frames_reader) { + NS_LOG(WARNING) << __func__ + << ": Stopped reading further frames, due to no connection " + "established."; + return; + } + + frames_reader->ReadFrame( + base::BindOnce(&NearbySharingServiceImpl::OnFrameRead, + weak_ptr_factory_.GetWeakPtr(), std::move(share_target))); } void NearbySharingServiceImpl::HandleCertificateInfoFrame(
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h index 4d5b6aa..5089cd2 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -151,10 +151,8 @@ void OnReceivedIntroduction( ShareTarget share_target, base::Optional<std::string> token, - std::unique_ptr<IncomingFramesReader> frames_reader, base::Optional<sharing::mojom::V1FramePtr> frame); - void OnFrameRead(std::unique_ptr<IncomingFramesReader> frames_reader, - ShareTarget share_target, + void OnFrameRead(ShareTarget share_target, base::Optional<sharing::mojom::V1FramePtr> frame); void HandleCertificateInfoFrame( const sharing::mojom::CertificateInfoFramePtr& certificate_frame);
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index a3e6e4e..026e5af 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -748,6 +748,28 @@ } TEST_F(NearbySharingServiceImplTest, + IncomingConnection_ClosedReadingIntroduction) { + FakeNearbyConnection connection; + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + NiceMock<MockTransferUpdateCallback> callback; + EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)).Times(0); + + NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( + &callback, NearbySharingService::ReceiveSurfaceState::kForeground); + EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); + EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); + + service_->OnIncomingConnection(kEndpointId, {}, &connection); + connection.Close(); + + // Introduction is ignored without any side effect. + + // To avoid UAF in OnIncomingTransferUpdate(). + service_->UnregisterReceiveSurface(&callback); +} + +TEST_F(NearbySharingServiceImplTest, IncomingConnection_EmptyIntroductionFrame) { std::string intro = "introduction_frame"; std::vector<uint8_t> bytes(intro.begin(), intro.end()); @@ -849,6 +871,59 @@ service_->UnregisterReceiveSurface(&callback); } +TEST_F(NearbySharingServiceImplTest, + IncomingConnection_ClosedWaitingLocalConfirmation) { + std::string intro = "introduction_frame"; + std::vector<uint8_t> bytes(intro.begin(), intro.end()); + NiceMock<MockNearbySharingDecoder> mock_decoder; + EXPECT_CALL(mock_decoder, DecodeFrame(testing::Eq(bytes), testing::_)) + .WillOnce(testing::Invoke( + [&](const std::vector<uint8_t>& data, + MockNearbySharingDecoder::DecodeFrameCallback callback) { + std::move(callback).Run(GetValidIntroductionFrame()); + })); + + EXPECT_CALL(mock_nearby_process_manager(), + GetOrStartNearbySharingDecoder(testing::_)) + .WillRepeatedly(testing::Return(&mock_decoder)); + + FakeNearbyConnection connection; + connection.AppendReadableData(bytes); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + NiceMock<MockTransferUpdateCallback> callback; + base::RunLoop run_loop; + EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)) + .WillOnce(testing::Invoke([&run_loop](const ShareTarget& share_target, + TransferMetadata metadata) { + EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, + metadata.status()); + run_loop.Quit(); + })); + + NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( + &callback, NearbySharingService::ReceiveSurfaceState::kForeground); + EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); + EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); + + service_->OnIncomingConnection(kEndpointId, {}, &connection); + run_loop.Run(); + + base::RunLoop run_loop_2; + EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)) + .WillOnce(testing::Invoke([&run_loop_2](const ShareTarget& share_target, + TransferMetadata metadata) { + EXPECT_EQ(TransferMetadata::Status::kFailed, metadata.status()); + run_loop_2.Quit(); + })); + + connection.Close(); + run_loop_2.Run(); + + // To avoid UAF in OnIncomingTransferUpdate(). + service_->UnregisterReceiveSurface(&callback); +} + TEST_F(NearbySharingServiceImplTest, AcceptInvalidShareTarget) { ShareTarget share_target; base::RunLoop run_loop;
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client.h b/chrome/browser/notifications/chrome_ash_message_center_client.h index 7bae2a8..3f385fc 100644 --- a/chrome/browser/notifications/chrome_ash_message_center_client.h +++ b/chrome/browser/notifications/chrome_ash_message_center_client.h
@@ -9,7 +9,7 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "chrome/browser/notifications/notification_platform_bridge.h" -#include "chrome/browser/notifications/notification_platform_bridge_chromeos.h" +#include "chrome/browser/notifications/notification_platform_bridge_delegate.h" #include "chrome/browser/notifications/notifier_controller.h" // This class serves as Chrome's AshMessageCenterClient, as well as the
diff --git a/chrome/browser/notifications/notification_platform_bridge_chromeos.h b/chrome/browser/notifications/notification_platform_bridge_chromeos.h index 46a8e4e..9710bf0 100644 --- a/chrome/browser/notifications/notification_platform_bridge_chromeos.h +++ b/chrome/browser/notifications/notification_platform_bridge_chromeos.h
@@ -11,39 +11,11 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "chrome/browser/notifications/notification_platform_bridge.h" +#include "chrome/browser/notifications/notification_platform_bridge_delegate.h" #include "chrome/browser/notifications/profile_notification.h" class ChromeAshMessageCenterClient; -// The interface that a NotificationPlatformBridge uses to pass back information -// and interactions from the native notification system. TODO(estade): this -// should be hoisted into its own file, implemented by -// NativeNotificationDisplayService, and used by other platforms' -// NotificationPlatformBridge implementations. See http://crbug.com/776443 -class NotificationPlatformBridgeDelegate { - public: - // To be called when a notification is closed. Each notification can be closed - // at most once. - virtual void HandleNotificationClosed(const std::string& id, - bool by_user) = 0; - - // To be called when the body of a notification is clicked. - virtual void HandleNotificationClicked(const std::string& id) = 0; - - // To be called when a button in a notification is clicked. - virtual void HandleNotificationButtonClicked( - const std::string& id, - int button_index, - const base::Optional<base::string16>& reply) = 0; - - // To be called when the settings button in a notification is clicked. - virtual void HandleNotificationSettingsButtonClicked( - const std::string& id) = 0; - - // To be called when a notification (source) should be disabled. - virtual void DisableNotification(const std::string& id) = 0; -}; - // A platform bridge that uses Ash's message center to display notifications. class NotificationPlatformBridgeChromeOs : public NotificationPlatformBridge,
diff --git a/chrome/browser/notifications/notification_platform_bridge_delegate.h b/chrome/browser/notifications/notification_platform_bridge_delegate.h new file mode 100644 index 0000000..ce0688f --- /dev/null +++ b/chrome/browser/notifications/notification_platform_bridge_delegate.h
@@ -0,0 +1,45 @@ +// Copyright 2020 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_NOTIFICATIONS_NOTIFICATION_PLATFORM_BRIDGE_DELEGATE_H_ +#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_PLATFORM_BRIDGE_DELEGATE_H_ + +#include <string> + +#include "base/optional.h" +#include "base/strings/string16.h" + +// The interface that a NotificationPlatformBridge uses to pass back information +// and interactions from the native notification system. +// TODO(estade): This should be implemented by NativeNotificationDisplayService, +// and used by other platforms' NotificationPlatformBridge implementations. See +// http://crbug.com/776443 +class NotificationPlatformBridgeDelegate { + public: + // To be called when a notification is closed. Each notification can be closed + // at most once. + virtual void HandleNotificationClosed(const std::string& id, + bool by_user) = 0; + + // To be called when the body of a notification is clicked. + virtual void HandleNotificationClicked(const std::string& id) = 0; + + // To be called when a button in a notification is clicked. + virtual void HandleNotificationButtonClicked( + const std::string& id, + int button_index, + const base::Optional<base::string16>& reply) = 0; + + // To be called when the settings button in a notification is clicked. + virtual void HandleNotificationSettingsButtonClicked( + const std::string& id) = 0; + + // To be called when a notification (source) should be disabled. + virtual void DisableNotification(const std::string& id) = 0; + + protected: + virtual ~NotificationPlatformBridgeDelegate() = default; +}; + +#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_PLATFORM_BRIDGE_DELEGATE_H_
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc index 5ca56263..15b153f 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -26,7 +26,6 @@ #include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h" #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" #include "chrome/browser/optimization_guide/optimization_guide_permissions_util.h" -#include "chrome/browser/optimization_guide/optimization_guide_util.h" #include "chrome/browser/optimization_guide/optimization_guide_web_contents_observer.h" #include "chrome/browser/profiles/profile.h" #include "components/google/core/common/google_util.h" @@ -44,6 +43,7 @@ #include "components/optimization_guide/optimization_guide_service.h" #include "components/optimization_guide/optimization_guide_store.h" #include "components/optimization_guide/optimization_guide_switches.h" +#include "components/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/optimization_metadata.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/optimization_guide/top_host_provider.h" @@ -985,7 +985,7 @@ optimization_guide::OptimizationMetadata metadata; optimization_guide::OptimizationTypeDecision type_decision = CanApplyOptimization(navigation_url, optimization_type, &metadata); - optimization_guide::OptimizationGuideDecision decision = + optimization_guide::OptimizationGuideDecision decision = optimization_guide:: GetOptimizationGuideDecisionFromOptimizationTypeDecision(type_decision); // It's possible that a hint that applies to |navigation_url| will come in // later, so only run the callback if we are sure we can apply the decision. @@ -1150,7 +1150,9 @@ optimization_guide::OptimizationTypeDecision type_decision = CanApplyOptimization(navigation_url, opt_type, &metadata); optimization_guide::OptimizationGuideDecision decision = - GetOptimizationGuideDecisionFromOptimizationTypeDecision(type_decision); + optimization_guide:: + GetOptimizationGuideDecisionFromOptimizationTypeDecision( + type_decision); for (auto& callback : opt_type_and_callbacks.second) { base::UmaHistogramEnumeration(
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc index 01ae1f8..3746f1c 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" #include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" #include "chrome/browser/optimization_guide/optimization_guide_top_host_provider.h" -#include "chrome/browser/optimization_guide/optimization_guide_util.h" #include "chrome/browser/optimization_guide/prediction/prediction_manager.h" #include "chrome/browser/profiles/profile.h" #include "components/leveldb_proto/public/proto_database_provider.h" @@ -23,6 +22,7 @@ #include "components/optimization_guide/optimization_guide_decider.h" #include "components/optimization_guide/optimization_guide_features.h" #include "components/optimization_guide/optimization_guide_service.h" +#include "components/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/optimization_guide/top_host_provider.h" #include "content/public/browser/browser_context.h" @@ -78,7 +78,8 @@ optimization_target_decision) { base::UmaHistogramExactLinear( "OptimizationGuide.TargetDecision." + - GetStringNameForOptimizationTarget(optimization_target), + optimization_guide::GetStringNameForOptimizationTarget( + optimization_target), static_cast<int>(optimization_target_decision), static_cast<int>( optimization_guide::OptimizationTargetDecision::kMaxValue));
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc index e042c99..7462efa9 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" #include "chrome/browser/optimization_guide/optimization_guide_permissions_util.h" #include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" -#include "chrome/browser/optimization_guide/optimization_guide_util.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h" #include "chrome/browser/optimization_guide/prediction/remote_decision_tree_predictor.h" #include "chrome/browser/profiles/profile.h" @@ -40,6 +39,7 @@ #include "components/optimization_guide/optimization_guide_store.h" #include "components/optimization_guide/optimization_guide_switches.h" #include "components/optimization_guide/optimization_guide_test_util.h" +#include "components/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/prediction_model.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/optimization_guide/store_update_data.h" @@ -106,7 +106,8 @@ base::UmaHistogramEnumeration( "OptimizationGuide.ShouldTargetNavigation.PredictionModelStatus." + - GetStringNameForOptimizationTarget(optimization_target_), + optimization_guide::GetStringNameForOptimizationTarget( + optimization_target_), status_); } @@ -134,7 +135,8 @@ is_valid_); base::UmaHistogramBoolean( "OptimizationGuide.IsPredictionModelValid." + - GetStringNameForOptimizationTarget(optimization_target_), + optimization_guide::GetStringNameForOptimizationTarget( + optimization_target_), is_valid_); // Only record the timing if the model is valid and was able to be @@ -147,7 +149,8 @@ validation_latency); base::UmaHistogramTimes( "OptimizationGuide.PredictionModelValidationLatency." + - GetStringNameForOptimizationTarget(optimization_target_), + optimization_guide::GetStringNameForOptimizationTarget( + optimization_target_), validation_latency); } } @@ -492,7 +495,8 @@ if (target_decision != OptimizationTargetDecision::kUnknown) { UmaHistogramTimes( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget(optimization_target), + optimization_guide::GetStringNameForOptimizationTarget( + optimization_target), base::TimeTicks::Now() - model_evaluation_start_time); } @@ -615,7 +619,8 @@ machine_learning::mojom::DecisionTreePredictionResult::kUnknown) { UmaHistogramTimes( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget(params->optimization_target), + optimization_guide::GetStringNameForOptimizationTarget( + params->optimization_target), base::TimeTicks::Now() - params->model_evaluation_start_time); } @@ -823,10 +828,11 @@ // Storing the model regardless of whether the model is valid or not. Model // will be removed from store if it fails to load. prediction_model_update_data->CopyPredictionModelIntoUpdateData(model); - base::UmaHistogramSparse("OptimizationGuide.PredictionModelUpdateVersion." + - GetStringNameForOptimizationTarget( - model.model_info().optimization_target()), - model.model_info().version()); + base::UmaHistogramSparse( + "OptimizationGuide.PredictionModelUpdateVersion." + + optimization_guide::GetStringNameForOptimizationTarget( + model.model_info().optimization_target()), + model.model_info().version()); OnLoadPredictionModel(std::make_unique<proto::PredictionModel>(model)); } model_and_features_store_->UpdatePredictionModels( @@ -962,10 +968,11 @@ bool success) { SEQUENCE_CHECKER(sequence_checker_); if (success) { - base::UmaHistogramSparse("OptimizationGuide.PredictionModelLoadedVersion." + - GetStringNameForOptimizationTarget( - model->model_info().optimization_target()), - model->model_info().version()); + base::UmaHistogramSparse( + "OptimizationGuide.PredictionModelLoadedVersion." + + optimization_guide::GetStringNameForOptimizationTarget( + model->model_info().optimization_target()), + model->model_info().version()); return; }
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc index 8bfe3553..1573b20 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
@@ -33,6 +33,7 @@ #include "components/optimization_guide/store_update_data.h" #include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h" #include "components/previews/core/previews_switches.h" +#include "components/variations/hashing.h" #include "content/public/browser/service_process_host.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -370,6 +371,11 @@ web_contents); } + void SetExpectedFieldTrialNames( + const base::flat_set<uint32_t>& expected_field_trial_name_hashes) { + expected_field_trial_name_hashes_ = expected_field_trial_name_hashes; + } + bool using_ml_service() const { return using_ml_service_; } GURL https_url_with_content() { return https_url_with_content_; } GURL https_url_without_content() { return https_url_without_content_; } @@ -395,6 +401,21 @@ // POST. EXPECT_EQ(request.method, net::test_server::METHOD_POST); EXPECT_NE(request.headers.end(), request.headers.find("X-Client-Data")); + optimization_guide::proto::GetModelsRequest models_request; + EXPECT_TRUE(models_request.ParseFromString(request.content)); + // Make sure we actually filter field trials appropriately. + EXPECT_EQ(expected_field_trial_name_hashes_.size(), + static_cast<size_t>(models_request.active_field_trials_size())); + base::flat_set<uint32_t> seen_field_trial_name_hashes; + for (const auto& field_trial : models_request.active_field_trials()) { + EXPECT_TRUE( + expected_field_trial_name_hashes_.find(field_trial.name_hash()) != + expected_field_trial_name_hashes_.end()); + seen_field_trial_name_hashes.insert(field_trial.name_hash()); + } + EXPECT_EQ(seen_field_trial_name_hashes.size(), + expected_field_trial_name_hashes_.size()); + response->set_code(net::HTTP_OK); std::unique_ptr<optimization_guide::proto::GetModelsResponse> get_models_response = BuildGetModelsResponse( @@ -411,9 +432,9 @@ response->set_code(net::HTTP_NOT_FOUND); } - std::string serialized_request; - get_models_response->SerializeToString(&serialized_request); - response->set_content(serialized_request); + std::string serialized_response; + get_models_response->SerializeToString(&serialized_response); + response->set_content(serialized_response); return std::move(response); } @@ -425,6 +446,7 @@ PredictionModelsFetcherRemoteResponseType:: kSuccessfulWithModelsAndFeatures; std::unique_ptr<OptimizationGuideConsumerWebContentsObserver> consumer_; + base::flat_set<uint32_t> expected_field_trial_name_hashes_; }; // Parametrized on whether the ML Service path is enabled. @@ -852,14 +874,26 @@ private: void InitializeFeatureList() override { scoped_feature_list_.InitWithFeaturesAndParameters( - {{optimization_guide::features::kOptimizationHints, {}}, - {optimization_guide::features::kRemoteOptimizationGuideFetching, {}}, - {optimization_guide::features::kOptimizationTargetPrediction, - {{"painful_page_load_metrics_only", "true"}}}, - {optimization_guide::features:: - kOptimizationTargetPredictionUsingMLService, - {}}}, + { + {optimization_guide::features::kOptimizationHints, {}}, + {optimization_guide::features::kRemoteOptimizationGuideFetching, + {}}, + {optimization_guide::features::kOptimizationTargetPrediction, + {{"painful_page_load_metrics_only", "true"}}}, + {optimization_guide::features:: + kOptimizationTargetPredictionUsingMLService, + {}}, + {optimization_guide::features::kOptimizationHintsFieldTrials, + {{"allowed_field_trial_names", + "scoped_feature_list_trial_for_OptimizationHints,scoped_feature_" + "list_trial_for_OptimizationHintsFetching"}}}, + }, {}); + SetExpectedFieldTrialNames(base::flat_set<uint32_t>( + {variations::HashName( + "scoped_feature_list_trial_for_OptimizationHints"), + variations::HashName( + "scoped_feature_list_trial_for_OptimizationHintsFetching")})); } };
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc index 14c7275d1..e0a3519 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
@@ -15,7 +15,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" -#include "chrome/browser/optimization_guide/optimization_guide_util.h" #include "chrome/browser/optimization_guide/optimization_guide_web_contents_observer.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h" #include "chrome/browser/optimization_guide/prediction/remote_decision_tree_predictor.h" @@ -28,6 +27,7 @@ #include "components/optimization_guide/optimization_guide_service.h" #include "components/optimization_guide/optimization_guide_store.h" #include "components/optimization_guide/optimization_guide_switches.h" +#include "components/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/prediction_model.h" #include "components/optimization_guide/proto/hint_cache.pb.h" #include "components/optimization_guide/proto/models.pb.h" @@ -667,12 +667,12 @@ .has_value()); histogram_tester.ExpectTotalCount( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_UNKNOWN), 0); histogram_tester.ExpectTotalCount( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), 0); } @@ -729,7 +729,7 @@ histogram_tester.ExpectTotalCount( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), 0); } @@ -789,13 +789,13 @@ histogram_tester.ExpectTotalCount( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), 1); histogram_tester.ExpectUniqueSample( "OptimizationGuide.IsPredictionModelValid." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), true, 1); @@ -804,7 +804,7 @@ histogram_tester.ExpectTotalCount( "OptimizationGuide.PredictionModelValidationLatency." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), 1); histogram_tester.ExpectTotalCount( @@ -1291,7 +1291,7 @@ histogram_tester.ExpectBucketCount( "OptimizationGuide.ShouldTargetNavigation.PredictionModelStatus." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), PredictionManagerModelStatus::kModelAvailable, 1); } @@ -1346,7 +1346,7 @@ histogram_tester.ExpectBucketCount( "OptimizationGuide.ShouldTargetNavigation.PredictionModelStatus." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), PredictionManagerModelStatus::kStoreAvailableNoModelForTarget, 1); } @@ -1400,7 +1400,7 @@ histogram_tester.ExpectBucketCount( "OptimizationGuide.ShouldTargetNavigation.PredictionModelStatus." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), PredictionManagerModelStatus::kStoreAvailableModelNotLoaded, 1); @@ -1454,7 +1454,7 @@ histogram_tester.ExpectBucketCount( "OptimizationGuide.ShouldTargetNavigation.PredictionModelStatus." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), PredictionManagerModelStatus::kStoreUnavailableModelUnknown, 1); } @@ -1633,13 +1633,13 @@ histogram_tester.ExpectTotalCount( "OptimizationGuide.PredictionModelEvaluationLatency." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), 0); histogram_tester.ExpectUniqueSample( "OptimizationGuide.IsPredictionModelValid." + - GetStringNameForOptimizationTarget( + optimization_guide::GetStringNameForOptimizationTarget( optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD), true, 1); }
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc b/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc index 6638a8c..78db071 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc
@@ -12,8 +12,8 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/optimization_guide_features.h" +#include "components/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/variations/net/variations_http_headers.h" #include "content/public/browser/network_service_instance.h" @@ -70,6 +70,9 @@ pending_models_request_->set_request_context(request_context); + *pending_models_request_->mutable_active_field_trials() = + optimization_guide::GetActiveFieldTrialsAllowedForFetch(); + // Limit the number of hosts to fetch features for, the list of hosts // is assumed to be ordered from most to least important by the top // host provider.
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn index f0fea941..05df26b 100644 --- a/chrome/browser/password_check/android/internal/BUILD.gn +++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -73,6 +73,7 @@ "//third_party/android_deps:androidx_recyclerview_recyclerview_java", "//third_party/android_sdk/androidx_browser:androidx_browser_java", "//ui/android:ui_full_java", + "//url:gurl_java", _public_target, ] sources = [
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java index a0f2450..54613d6b 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java
@@ -77,11 +77,12 @@ mPasswordCheckObserver.onPasswordCheckStatusChanged(state); } + @CalledByNative private static void insertCredential(CompromisedCredential[] credentials, int index, - String originUrl, String username, String password, boolean phished, + String displayOrigin, String displayUsername, String password, boolean phished, boolean hasScript) { - credentials[index] = - new CompromisedCredential(originUrl, username, password, phished, hasScript); + credentials[index] = new CompromisedCredential( + displayOrigin, displayUsername, password, phished, hasScript); } /** @@ -99,6 +100,14 @@ } /** + * @return The timestamp of the last completed check. + */ + long getCheckTimestamp() { + // TODO(crbug.com/1102025): Add method to retrieve the timestamp. + return 0L; + } + + /** * This can return 0 if the compromised credentials haven't been fetched from the database yet. * @return The number of compromised credentials found in the last run password check. */
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java index e8d8429..ecfed056 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java
@@ -96,6 +96,11 @@ } @Override + public long getCheckTimestamp() { + return mPasswordCheckBridge.getCheckTimestamp(); + } + + @Override public int getCompromisedCredentialsCount() { return mPasswordCheckBridge.getCompromisedCredentialsCount(); }
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java index 975ab44..3e51f56 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
@@ -103,8 +103,7 @@ Integer compromisedCredentialCount = null; if (status == PasswordCheckUIStatus.IDLE) { compromisedCredentialCount = getPasswordCheck().getCompromisedCredentialsCount(); - // TODO(crbug.com/1109691): Retrieve the timestamp of the last check from the bridge. - checkTimestamp = 0L; + checkTimestamp = getPasswordCheck().getCheckTimestamp(); } header.set(CHECK_TIMESTAMP, checkTimestamp); header.set(COMPROMISED_CREDENTIALS_COUNT, compromisedCredentialCount);
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java index b4db8c0..62c346c6 100644 --- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java +++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java
@@ -71,6 +71,11 @@ void removeObserver(Observer obs); /** + * @return The timestamp of the last completed check. + */ + long getCheckTimestamp(); + + /** * @return The latest available number of compromised passwords. If this is invoked before * {@link Observer#onCompromisedCredentialsFetchCompleted}, the returned value is likely * invalid.
diff --git a/chrome/browser/password_check/android/password_check_bridge.cc b/chrome/browser/password_check/android/password_check_bridge.cc index 4804f05..1d3e7c0 100644 --- a/chrome/browser/password_check/android/password_check_bridge.cc +++ b/chrome/browser/password_check/android/password_check_bridge.cc
@@ -6,7 +6,10 @@ #include <jni.h> +#include "base/android/jni_string.h" #include "chrome/browser/password_check/android/internal/jni_headers/PasswordCheckBridge_jni.h" +#include "components/password_manager/core/browser/ui/compromised_credentials_manager.h" +#include "url/android/gurl_android.h" static jlong JNI_PasswordCheckBridge_Create( JNIEnv* env, @@ -38,8 +41,22 @@ void PasswordCheckBridge::GetCompromisedCredentials( JNIEnv* env, - const base::android::JavaParamRef<jobjectArray>& credentials) { - // TODO(crbug.com/1102025): implement this. + const base::android::JavaParamRef<jobjectArray>& java_credentials) { + std::vector<PasswordCheckManager::CompromisedCredentialForUI> credentials = + check_manager_.GetCompromisedCredentials(); + + for (size_t i = 0; i < credentials.size(); ++i) { + const auto& credential = credentials[i]; + Java_PasswordCheckBridge_insertCredential( + env, java_credentials, i, + base::android::ConvertUTF16ToJavaString(env, credential.display_origin), + base::android::ConvertUTF16ToJavaString(env, + credential.display_username), + base::android::ConvertUTF16ToJavaString(env, credential.password), + (credential.compromise_type == + password_manager::CompromiseTypeFlags::kCredentialPhished), + credential.has_script); + } } void PasswordCheckBridge::RemoveCredential(
diff --git a/chrome/browser/password_check/android/password_check_manager.cc b/chrome/browser/password_check/android/password_check_manager.cc index fb247b2..4e538a4 100644 --- a/chrome/browser/password_check/android/password_check_manager.cc +++ b/chrome/browser/password_check/android/password_check_manager.cc
@@ -4,15 +4,54 @@ #include "chrome/browser/password_check/android/password_check_manager.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/password_check/android/password_check_bridge.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/grit/generated_resources.h" +#include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_util.h" +#include "components/password_manager/core/browser/ui/compromised_credentials_manager.h" +#include "components/strings/grit/components_strings.h" #include "components/sync/driver/profile_sync_service.h" +#include "components/url_formatter/url_formatter.h" +#include "ui/base/l10n/l10n_util.h" +namespace { + +base::string16 GetDisplayUsername(const base::string16& username) { + return username.empty() + ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN) + : username; +} + +} // namespace + +using autofill::PasswordForm; + +using CredentialsView = + password_manager::CompromisedCredentialsManager::CredentialsView; using PasswordCheckUIStatus = password_manager::PasswordCheckUIStatus; using State = password_manager::BulkLeakCheckService::State; using SyncState = password_manager::SyncState; +using CredentialWithPassword = password_manager::CredentialWithPassword; +using CompromisedCredentialForUI = + PasswordCheckManager::CompromisedCredentialForUI; + +CompromisedCredentialForUI::CompromisedCredentialForUI( + const CredentialWithPassword& credential) + : CredentialWithPassword(credential) {} + +CompromisedCredentialForUI::CompromisedCredentialForUI( + const CompromisedCredentialForUI& other) = default; +CompromisedCredentialForUI::CompromisedCredentialForUI( + CompromisedCredentialForUI&& other) = default; +CompromisedCredentialForUI& CompromisedCredentialForUI::operator=( + const CompromisedCredentialForUI& other) = default; +CompromisedCredentialForUI& CompromisedCredentialForUI::operator=( + CompromisedCredentialForUI&& other) = default; +CompromisedCredentialForUI::~CompromisedCredentialForUI() = default; PasswordCheckManager::PasswordCheckManager(Profile* profile, Observer* observer) : observer_(observer), profile_(profile) { @@ -55,6 +94,18 @@ return saved_passwords_presenter_.GetSavedPasswords().size(); } +std::vector<CompromisedCredentialForUI> +PasswordCheckManager::GetCompromisedCredentials() const { + std::vector<CredentialWithPassword> credentials = + compromised_credentials_manager_.GetCompromisedCredentials(); + std::vector<CompromisedCredentialForUI> ui_credentials; + ui_credentials.reserve(credentials.size()); + for (const auto& credential : credentials) { + ui_credentials.push_back(MakeUICredential(credential)); + } + return ui_credentials; +} + void PasswordCheckManager::OnSavedPasswordsChanged( password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords) { if (!is_initialized_) { @@ -90,6 +141,50 @@ // TODO(crbug.com/1102025): implement this. } +CompromisedCredentialForUI PasswordCheckManager::MakeUICredential( + const CredentialWithPassword& credential) const { + CompromisedCredentialForUI ui_credential(credential); + auto facet = password_manager::FacetURI::FromPotentiallyInvalidSpec( + credential.signon_realm); + + ui_credential.display_username = GetDisplayUsername(credential.username); + if (facet.IsValidAndroidFacetURI()) { + const PasswordForm& android_form = + compromised_credentials_manager_.GetSavedPasswordsFor(credential)[0]; + + ui_credential.is_android_credential = true; + ui_credential.package_name = facet.android_package_name(); + + if (android_form.app_display_name.empty()) { + // In case no affiliation information could be obtained show the + // formatted package name to the user. + ui_credential.display_origin = l10n_util::GetStringFUTF16( + IDS_SETTINGS_PASSWORDS_ANDROID_APP, + base::UTF8ToUTF16(facet.android_package_name())); + } else { + ui_credential.display_origin = + base::UTF8ToUTF16(android_form.app_display_name); + } + } else { + ui_credential.is_android_credential = false; + ui_credential.display_origin = url_formatter::FormatUrl( + credential.url.GetOrigin(), + url_formatter::kFormatUrlOmitDefaults | + url_formatter::kFormatUrlOmitHTTPS | + url_formatter::kFormatUrlOmitTrivialSubdomains | + url_formatter::kFormatUrlTrimAfterHost, + net::UnescapeRule::SPACES, nullptr, nullptr, nullptr); + ui_credential.change_password_url = ui_credential.url.GetOrigin().spec(); + } + + return ui_credential; +} + +void PasswordCheckManager::OnBulkCheckServiceShutDown() { + observed_bulk_leak_check_service_.Remove( + BulkLeakCheckServiceFactory::GetForProfile(profile_)); +} + PasswordCheckUIStatus PasswordCheckManager::GetUIStatus(State state) const { switch (state) { case State::kIdle:
diff --git a/chrome/browser/password_check/android/password_check_manager.h b/chrome/browser/password_check/android/password_check_manager.h index d37e391..2ec6e95 100644 --- a/chrome/browser/password_check/android/password_check_manager.h +++ b/chrome/browser/password_check/android/password_check_manager.h
@@ -30,6 +30,25 @@ password_manager::PasswordCheckUIStatus status) = 0; }; + struct CompromisedCredentialForUI : password_manager::CredentialWithPassword { + explicit CompromisedCredentialForUI( + const password_manager::CredentialWithPassword& credential); + + CompromisedCredentialForUI(const CompromisedCredentialForUI& other); + CompromisedCredentialForUI(CompromisedCredentialForUI&& other); + CompromisedCredentialForUI& operator=( + const CompromisedCredentialForUI& other); + CompromisedCredentialForUI& operator=(CompromisedCredentialForUI&& other); + ~CompromisedCredentialForUI(); + + base::string16 display_username; + base::string16 display_origin; + std::string package_name; + std::string change_password_url; + bool is_android_credential = false; + bool has_script = false; + }; + // `observer` must outlive `this`. PasswordCheckManager(Profile* profile, Observer* observer); ~PasswordCheckManager() override; @@ -48,6 +67,9 @@ // If the saved passwords haven't been fetched yet, this will return 0. int GetSavedPasswordsCount() const; + // Called by java to retrieve the compromised credentials. + std::vector<CompromisedCredentialForUI> GetCompromisedCredentials() const; + // Not copyable or movable PasswordCheckManager(const PasswordCheckManager&) = delete; PasswordCheckManager& operator=(const PasswordCheckManager&) = delete; @@ -70,6 +92,13 @@ password_manager::BulkLeakCheckServiceInterface::State state) override; void OnCredentialDone(const password_manager::LeakCheckCredential& credential, password_manager::IsLeaked is_leaked) override; + void OnBulkCheckServiceShutDown() override; + + // Turns a `CredentialWithPassword` into a `CompromisedCredentialForUI`, + // getting suitable strings for all display elements (e.g. url, app name, + // app package, username, etc.). + CompromisedCredentialForUI MakeUICredential( + const password_manager::CredentialWithPassword& credential) const; // Converts the state retrieved from the check service into a state that // can be used by the UI to display appropriate messages.
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index db1a822..650d365 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -179,11 +179,11 @@ extensions::ExtensionApiTest::TearDownOnMainThread(); } - // Serve paths prefixed with _test_resources/ from chrome/test/data/pdf. + // Serve paths prefixed with _test_resources/ from chrome/test/data. base::FilePath GetTestResourcesParentDir() override { base::FilePath test_root_path; base::PathService::Get(chrome::DIR_TEST_DATA, &test_root_path); - return test_root_path.AppendASCII("pdf"); + return test_root_path; } bool PdfIsExpectedToLoad(const std::string& pdf_file) { @@ -783,7 +783,7 @@ constexpr char kModuleLoaderTemplate[] = R"(var s = document.createElement('script'); s.type = 'module'; - s.src = '_test_resources/%s'; + s.src = '_test_resources/pdf/%s'; document.body.appendChild(s);)"; ASSERT_TRUE(content::ExecuteScript( @@ -2643,7 +2643,7 @@ PdfLoadsWithExtensionThatInjectsFrame) { // Load the test extension. const extensions::Extension* test_extension = LoadExtension( - GetTestResourcesParentDir().AppendASCII("extension_injects_iframe")); + GetTestResourcesParentDir().AppendASCII("pdf/extension_injects_iframe")); ASSERT_TRUE(test_extension); // Load the PDF. The call to LoadPdf() will return false if the pdf extension
diff --git a/chrome/browser/permissions/permission_manager_factory.cc b/chrome/browser/permissions/permission_manager_factory.cc index 7013e95d..4617a0d 100644 --- a/chrome/browser/permissions/permission_manager_factory.cc +++ b/chrome/browser/permissions/permission_manager_factory.cc
@@ -31,6 +31,7 @@ #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/permissions/contexts/font_access_permission_context.h" #include "components/permissions/contexts/webxr_permission_context.h" #include "components/permissions/contexts/window_placement_permission_context.h" #include "components/permissions/permission_manager.h" @@ -135,6 +136,8 @@ std::make_unique<CameraPanTiltZoomPermissionContext>(profile); permission_contexts[ContentSettingsType::WINDOW_PLACEMENT] = std::make_unique<WindowPlacementPermissionContext>(profile); + permission_contexts[ContentSettingsType::FONT_ACCESS] = + std::make_unique<FontAccessPermissionContext>(profile); return permission_contexts; } } // namespace
diff --git a/chrome/browser/policy/messaging_layer/upload/app_install_report_handler.cc b/chrome/browser/policy/messaging_layer/upload/app_install_report_handler.cc new file mode 100644 index 0000000..50ab3e8 --- /dev/null +++ b/chrome/browser/policy/messaging_layer/upload/app_install_report_handler.cc
@@ -0,0 +1,179 @@ +// Copyright 2020 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/policy/messaging_layer/upload/app_install_report_handler.h" + +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/containers/queue.h" +#include "base/json/json_reader.h" +#include "base/optional.h" +#include "base/sequenced_task_runner.h" +#include "base/strings/strcat.h" +#include "base/task/post_task.h" +#include "base/task_runner.h" +#include "base/values.h" +#include "chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h" +#include "chrome/browser/policy/messaging_layer/util/status.h" +#include "chrome/browser/policy/messaging_layer/util/status_macros.h" +#include "chrome/browser/policy/messaging_layer/util/statusor.h" +#include "chrome/browser/policy/messaging_layer/util/task_runner_context.h" +#include "components/policy/core/common/cloud/cloud_policy_client.h" +#include "components/policy/proto/record.pb.h" +#include "components/policy/proto/record_constants.pb.h" + +namespace reporting { + +using AppInstallReportUploader = + AppInstallReportHandler::AppInstallReportUploader; + +using UploaderLeaderTracker = AppInstallReportHandler::UploaderLeaderTracker; + +// static +scoped_refptr<UploaderLeaderTracker> UploaderLeaderTracker::Create() { + return base::WrapRefCounted(new UploaderLeaderTracker()); +} + +StatusOr<AppInstallReportHandler::ReleaseLeaderCallback> +UploaderLeaderTracker::RequestLeaderPromotion() { + if (has_promoted_app_install_event_uploader_) { + return Status(error::RESOURCE_EXHAUSTED, + "Only one leader is allowed at a time."); + } + + has_promoted_app_install_event_uploader_ = true; + return base::BindOnce(&UploaderLeaderTracker::ReleaseLeader, + base::Unretained(this)); +} + +void UploaderLeaderTracker::ReleaseLeader() { + has_promoted_app_install_event_uploader_ = false; +} + +AppInstallReportUploader::AppInstallReportUploader( + base::Value report, + scoped_refptr<SharedQueue<base::Value>> report_queue, + scoped_refptr<UploaderLeaderTracker> leader_tracker, + policy::CloudPolicyClient* client, + ClientCallback client_cb, + scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner) + : TaskRunnerContext<bool>(std::move(client_cb), sequenced_task_runner), + report_(std::move(report)), + report_queue_(report_queue), + leader_tracker_(leader_tracker), + client_(client) {} + +AppInstallReportUploader::~AppInstallReportUploader() = default; + +void AppInstallReportUploader::OnStart() { + report_queue_->Push(std::move(report_), + base::BindOnce(&AppInstallReportUploader::OnPushComplete, + base::Unretained(this))); +} + +void AppInstallReportUploader::OnPushComplete() { + Schedule(&AppInstallReportUploader::RequestLeaderPromotion, + base::Unretained(this)); +} + +void AppInstallReportUploader::RequestLeaderPromotion() { + auto promo_result = leader_tracker_->RequestLeaderPromotion(); + if (!promo_result.ok()) { + Complete(); + return; + } + + release_leader_cb_ = std::move(promo_result.ValueOrDie()); + + ScheduleNextPop(); +} + +void AppInstallReportUploader::ScheduleNextPop() { + report_queue_->Pop(base::BindOnce(&AppInstallReportUploader::OnPopResult, + base::Unretained(this))); +} + +void AppInstallReportUploader::OnPopResult(StatusOr<base::Value> pop_result) { + if (!pop_result.ok()) { + // There are no more records to process - exit. + std::move(release_leader_cb_).Run(); + Complete(); + return; + } + + Schedule(&AppInstallReportUploader::StartUpload, base::Unretained(this), + std::move(pop_result.ValueOrDie())); +} + +void AppInstallReportUploader::StartUpload(base::Value record) { + ClientCallback cb = base::BindOnce( + &AppInstallReportUploader::OnUploadComplete, base::Unretained(this)); + client_->UploadAppInstallReport(std::move(record), std::move(cb)); +} + +void AppInstallReportUploader::OnUploadComplete(bool success) { + if (!success) { + LOG(ERROR) << Status(error::DATA_LOSS, "Upload was unsuccessful"); + } + + Schedule(&AppInstallReportUploader::ScheduleNextPop, base::Unretained(this)); +} + +void AppInstallReportUploader::Complete() { + Schedule(&AppInstallReportUploader::Response, base::Unretained(this), true); +} + +AppInstallReportHandler::AppInstallReportHandler( + policy::CloudPolicyClient* client) + : RecordHandler(client), + report_queue_(SharedQueue<base::Value>::Create()), + leader_tracker_(UploaderLeaderTracker::Create()), + sequenced_task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})) {} + +AppInstallReportHandler::~AppInstallReportHandler() = default; + +Status AppInstallReportHandler::HandleRecord(Record record) { + RETURN_IF_ERROR(ValidateClientState()); + ASSIGN_OR_RETURN(base::Value report, ValidateRecord(record)); + + ClientCallback client_cb = base::BindOnce([](bool finished_running) { + VLOG(1) << "Finished Running AppInstallReportUploader"; + }); + + // Start an uploader in case any previous uploader has finished running before + // this record was posted. + Start<AppInstallReportUploader>(std::move(report), report_queue_, + leader_tracker_, GetClient(), + std::move(client_cb), sequenced_task_runner_); + + return Status::StatusOK(); +} + +StatusOr<base::Value> AppInstallReportHandler::ValidateRecord( + const Record& record) const { + if (record.destination() != Destination::APP_INSTALL_EVENT) { + return Status(error::INVALID_ARGUMENT, + base::StrCat({"Record destination mismatch, encountered=", + Destination_Name(record.destination())})); + } + + base::Optional<base::Value> report_result = + base::JSONReader::Read(record.data()); + if (!report_result.has_value()) { + return Status(error::INVALID_ARGUMENT, "Unknown Report Format"); + } + + return std::move(report_result.value()); +} + +Status AppInstallReportHandler::ValidateClientState() { + if (!GetClient()->is_registered()) { + return Status(error::UNAVAILABLE, "DmServer is currently unavailable"); + } + return Status::StatusOK(); +} + +} // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/upload/app_install_report_handler.h b/chrome/browser/policy/messaging_layer/upload/app_install_report_handler.h new file mode 100644 index 0000000..18dc084c --- /dev/null +++ b/chrome/browser/policy/messaging_layer/upload/app_install_report_handler.h
@@ -0,0 +1,151 @@ +// Copyright 2020 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_POLICY_MESSAGING_LAYER_UPLOAD_APP_INSTALL_REPORT_HANDLER_H_ +#define CHROME_BROWSER_POLICY_MESSAGING_LAYER_UPLOAD_APP_INSTALL_REPORT_HANDLER_H_ + +#include <string> +#include <utility> + +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "base/task_runner.h" +#include "base/values.h" +#include "chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h" +#include "chrome/browser/policy/messaging_layer/util/shared_queue.h" +#include "chrome/browser/policy/messaging_layer/util/status.h" +#include "chrome/browser/policy/messaging_layer/util/status_macros.h" +#include "chrome/browser/policy/messaging_layer/util/statusor.h" +#include "chrome/browser/policy/messaging_layer/util/task_runner_context.h" +#include "components/policy/core/common/cloud/cloud_policy_client.h" +#include "components/policy/proto/record.pb.h" + +namespace reporting { + +// |AppInstallReportHandler| handles |AppInstallReportRequests|, sending them to +// the server using |CloudPolicyClient|. Since |CloudPolicyClient| will cancel +// any in progress reports if a new report is added, |AppInstallReportHandler| +// ensures that only one report is ever processed at one time by forming a +// queue. +class AppInstallReportHandler : public DmServerUploadService::RecordHandler { + public: + // The client uses a boolean value for status, where true indicates success + // and false indicates failure. + using ClientCallback = base::OnceCallback<void(bool status)>; + + using ReleaseLeaderCallback = base::OnceCallback<void()>; + using RequestLeaderPromotionCallback = + base::OnceCallback<StatusOr<ReleaseLeaderCallback>()>; + + // Tracking the leader needs to outlive |AppInstallReportHandler| so it needs + // to be wrapped in a scoped_refptr. + class UploaderLeaderTracker + : public base::RefCountedThreadSafe<UploaderLeaderTracker> { + public: + static scoped_refptr<UploaderLeaderTracker> Create(); + + // If there is currently no leader + // (|has_promoted_app_install_event_uploader_| is false), then the StatusOr + // will contain a callback to release leadership. If there is currently a + // leader an error::RESOURCE_EXHAUSTED is returned (which should be the + // common case). This will be called on sequence from inside the + // |AppInstallReportUploader| and so needs no additional protection. + StatusOr<ReleaseLeaderCallback> RequestLeaderPromotion(); + + // Once a AppInstallEventUploader leader drains the queue of reports, it + // will release its leadership and return, allowing a new + // AppInstallEventUploader to take leadership and upload events. + void ReleaseLeader(); + + private: + friend class base::RefCountedThreadSafe<UploaderLeaderTracker>; + virtual ~UploaderLeaderTracker() = default; + + UploaderLeaderTracker() = default; + + // Flag indicates whether a leader has been promoted. + bool has_promoted_app_install_event_uploader_{false}; + }; + + // AppInstallReportUploader handles enqueuing events on the |report_queue_|, + // and uploading those events with the |client_|. + class AppInstallReportUploader : public TaskRunnerContext<bool> { + public: + AppInstallReportUploader( + base::Value report, + scoped_refptr<SharedQueue<base::Value>> report_queue, + scoped_refptr<UploaderLeaderTracker> leader_tracker, + policy::CloudPolicyClient* client, + ClientCallback client_cb, + scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner); + + private: + ~AppInstallReportUploader() override; + + // AppInstallReportUploader follows the this sequence for handling upload: + // OnStart(): Pushes a report onto the |report_queue_| + // OnPushComplete: Called off sequence. Schedules RequestLeaderPromotion on + // sequence + // RequestLeaderPromotion: Called on sequence. requests promotion to leader + // if there isn't already one. + // OnLeaderPromotionResult: Called off sequence - two paths + // 1. A leader already exists - Call Complete() and then Response(). + // 2. Promoted to leader - begin processing records in the queue. + // Schedules |ScheduleNextUpload| on sequence. + // + // ScheduleNextPop: Called on sequence. Calls report_queue_->Pop() with + // |StartUpload|. + // OnPopResult: Called off Sequence, two paths: + // 1. pop_result indicates there are no more records: + // Schedule ReleaseLeaderPromotion on sequence then Complete and + // Response. + // 2. pop_result holds a record: Schedule |UploadRecord|. + // UploadRecord: Called on sequence. Calls client_->UploadAppInstallReport + // with |UploadComplete| as the callback. + // UploadComplete: Called off sequence. Schedule |ScheduleNextPop| on + // sequence. + // + // During the ScheduleNextPop loop other requests can be enqueued from other + // threads while leadership is held. This allows one thread to be busy with + // the process of uploading, while other threads can push reports onto the + // queue and return. This is necessary because |CloudPolicyClient| only + // allows one upload at a time. + void OnStart() override; + void OnPushComplete(); + void RequestLeaderPromotion(); + + void ScheduleNextPop(); + void OnPopResult(StatusOr<base::Value> pop_result); + void StartUpload(base::Value record); + void OnUploadComplete(bool success); + + void Complete(); + + base::Value report_; + scoped_refptr<SharedQueue<base::Value>> report_queue_; + scoped_refptr<UploaderLeaderTracker> leader_tracker_; + ReleaseLeaderCallback release_leader_cb_; + + policy::CloudPolicyClient* const client_; + }; + + explicit AppInstallReportHandler(policy::CloudPolicyClient* client); + ~AppInstallReportHandler() override; + + Status HandleRecord(Record record) override; + + private: + StatusOr<base::Value> ValidateRecord(const Record& record) const; + Status ValidateClientState(); + + scoped_refptr<SharedQueue<base::Value>> report_queue_; + scoped_refptr<UploaderLeaderTracker> leader_tracker_; + scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_; +}; + +} // namespace reporting + +#endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UPLOAD_APP_INSTALL_REPORT_HANDLER_H_
diff --git a/chrome/browser/policy/messaging_layer/upload/app_install_report_handler_unittest.cc b/chrome/browser/policy/messaging_layer/upload/app_install_report_handler_unittest.cc new file mode 100644 index 0000000..09b14dd1 --- /dev/null +++ b/chrome/browser/policy/messaging_layer/upload/app_install_report_handler_unittest.cc
@@ -0,0 +1,203 @@ +// Copyright 2020 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/policy/messaging_layer/upload/app_install_report_handler.h" + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/optional.h" +#include "base/synchronization/waitable_event.h" +#include "base/task/post_task.h" +#include "base/task_runner.h" +#include "base/test/task_environment.h" +#include "base/values.h" +#include "chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.h" +#include "chrome/browser/policy/messaging_layer/util/status.h" +#include "chrome/browser/policy/messaging_layer/util/status_macros.h" +#include "chrome/browser/policy/messaging_layer/util/statusor.h" +#include "chrome/browser/policy/messaging_layer/util/task_runner_context.h" +#include "components/policy/core/common/cloud/cloud_policy_client.h" +#include "components/policy/core/common/cloud/dm_token.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" +#include "components/policy/proto/record.pb.h" +#include "components/policy/proto/record_constants.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace reporting { +namespace { + +using testing::_; +using testing::Invoke; +using testing::Return; +using testing::WithArgs; + +MATCHER_P(MatchValue, expected, "matches base::Value") { + std::string arg_string; + if (!base::JSONWriter::Write(arg, &arg_string)) { + LOG(INFO) << "Unable to serialize the arg"; + return false; + } + + DCHECK(expected); + std::string expected_string; + if (!base::JSONWriter::Write(*expected, &expected_string)) { + LOG(INFO) << "Unable to serialize the expected"; + return false; + } + + return arg_string == expected_string; +} + +class TestCallbackWaiter { + public: + TestCallbackWaiter() + : completed_(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED) {} + + virtual void Signal() { + DCHECK(!completed_.IsSignaled()); + completed_.Signal(); + } + + void Wait() { completed_.Wait(); } + + protected: + base::WaitableEvent completed_; +}; + +class AppInstallReportHandlerTest : public testing::Test { + public: + AppInstallReportHandlerTest() = default; + + void SetUp() override { + client_.SetDMToken( + policy::DMToken::CreateValidTokenForTesting("FAKE_DM_TOKEN").value()); + } + + protected: + base::test::TaskEnvironment task_envrionment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + policy::MockCloudPolicyClient client_; +}; + +class TestRecord : public Record { + public: + explicit TestRecord(base::StringPiece key = "TEST_KEY", + base::StringPiece value = "TEST_VALUE") { + data_.SetKey(key, base::Value(value)); + std::string json_data; + base::JSONWriter::Write(data_, &json_data); + + set_data(json_data); + set_destination(Destination::APP_INSTALL_EVENT); + } + + const base::Value* data() const { return &data_; } + + private: + base::Value data_{base::Value::Type::DICTIONARY}; +}; + +TEST_F(AppInstallReportHandlerTest, AcceptsValidRecord) { + TestCallbackWaiter waiter; + TestRecord test_record; + EXPECT_CALL(client_, + UploadAppInstallReport_(MatchValue(test_record.data()), _)) + .WillOnce(WithArgs<1>( + Invoke([&waiter](AppInstallReportHandler::ClientCallback& callback) { + std::move(callback).Run(true); + waiter.Signal(); + }))); + + AppInstallReportHandler handler(&client_); + Status handle_status = handler.HandleRecord(test_record); + EXPECT_OK(handle_status); + waiter.Wait(); +} + +TEST_F(AppInstallReportHandlerTest, DeniesInvalidDestination) { + EXPECT_CALL(client_, UploadAppInstallReport_(_, _)).Times(0); + AppInstallReportHandler handler(&client_); + + TestRecord test_record; + test_record.set_destination(Destination::UPLOAD_EVENTS); + + Status handle_status = handler.HandleRecord(test_record); + EXPECT_FALSE(handle_status.ok()); + EXPECT_EQ(handle_status.error_code(), error::INVALID_ARGUMENT); +} + +TEST_F(AppInstallReportHandlerTest, DeniesInvalidData) { + EXPECT_CALL(client_, UploadAppInstallReport_(_, _)).Times(0); + AppInstallReportHandler handler(&client_); + + TestRecord test_record; + test_record.set_data("BAD_DATA"); + Status handle_status = handler.HandleRecord(test_record); + EXPECT_FALSE(handle_status.ok()); + EXPECT_EQ(handle_status.error_code(), error::INVALID_ARGUMENT); +} + +TEST_F(AppInstallReportHandlerTest, ReportsUnsuccessfulCall) { + TestCallbackWaiter waiter; + + TestRecord test_record; + EXPECT_CALL(client_, + UploadAppInstallReport_(MatchValue(test_record.data()), _)) + .WillOnce(WithArgs<1>( + Invoke([&waiter](AppInstallReportHandler::ClientCallback& callback) { + std::move(callback).Run(false); + waiter.Signal(); + }))); + + AppInstallReportHandler handler(&client_); + Status handle_status = handler.HandleRecord(test_record); + EXPECT_OK(handle_status); + waiter.Wait(); +} + +class TestCallbackWaiterWithCounter : public TestCallbackWaiter { + public: + explicit TestCallbackWaiterWithCounter(int counter_limit) + : counter_limit_(counter_limit) {} + + void Signal() override { + DCHECK(!completed_.IsSignaled()); + const int new_counter = --counter_limit_; + DCHECK_GE(new_counter, 0); + if (new_counter > 0) { + return; + } + completed_.Signal(); + } + + private: + std::atomic<int> counter_limit_; +}; + +TEST_F(AppInstallReportHandlerTest, AcceptsMultipleValidRecords) { + const int kExpectedCallTimes = 10; + TestCallbackWaiterWithCounter waiter{kExpectedCallTimes}; + + TestRecord test_record; + EXPECT_CALL(client_, + UploadAppInstallReport_(MatchValue(test_record.data()), _)) + .WillRepeatedly(WithArgs<1>( + Invoke([&waiter](AppInstallReportHandler::ClientCallback& callback) { + std::move(callback).Run(true); + waiter.Signal(); + }))); + + AppInstallReportHandler handler(&client_); + + for (int i = 0; i < kExpectedCallTimes; i++) { + Status handle_status = handler.HandleRecord(test_record); + EXPECT_OK(handle_status); + } + waiter.Wait(); +} + +} // namespace +} // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc index 7ceb3f9..e2dcec0 100644 --- a/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc +++ b/chrome/browser/policy/messaging_layer/upload/dm_server_upload_service.cc
@@ -10,6 +10,7 @@ #include "base/task/post_task.h" #include "base/task_runner.h" +#include "chrome/browser/policy/messaging_layer/upload/app_install_report_handler.h" #include "chrome/browser/policy/messaging_layer/util/backoff_settings.h" #include "chrome/browser/policy/messaging_layer/util/status.h" #include "chrome/browser/policy/messaging_layer/util/status_macros.h" @@ -238,6 +239,8 @@ return Status(error::FAILED_PRECONDITION, "Client was null"); } + record_handlers_.push_back(std::make_unique<AppInstallReportHandler>(client)); + return Status::StatusOK(); }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js index 15ead75..ce51005b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js
@@ -2151,7 +2151,7 @@ article: {msgId: 'role_article', inherits: 'abstractItem'}, application: {msgId: 'role_application', inherits: 'abstractContainer'}, banner: {msgId: 'role_banner', inherits: 'abstractContainer'}, - button: {msgId: 'role_button', earconId: 'BUTTON'}, + button: {msgId: 'role_button', earconId: 'BUTTON', inherits: 'button'}, buttonDropDown: {msgId: 'role_button', earconId: 'BUTTON'}, checkBox: {msgId: 'role_checkbox'}, columnHeader: {msgId: 'role_columnheader', inherits: 'cell'}, @@ -2420,6 +2420,10 @@ speak: `$earcon(ALERT_MODAL) $name $nameOrTextContent $description $state $role` }, + button: { + speak: `$name $node(activeDescendant) $state $restriction $role + $description` + }, cell: { enter: { speak: `$cellIndexText $node(tableCellColumnHeaders) $nameFromNode
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js index 159e3a7..b7d90ef 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js
@@ -327,12 +327,11 @@ ['Time control', [{value: 'role', start: 0, end: 12}]], ['Date control', [{value: 'role', start: 0, end: 12}]], [ - 'Choose File|No file chosen|Button', + 'No file chosen, Choose File|Button', [ - {value: 'name', start: 0, end: 11}, - {value: new Output.EarconAction('BUTTON'), start: 0, end: 11}, - {value: 'value', start: 12, end: 26}, - {value: 'role', start: 27, end: 33} + {value: 'name', start: 0, end: 27}, + {value: new Output.EarconAction('BUTTON'), start: 0, end: 27}, + {value: 'role', start: 28, end: 34} ] ], '||Search', '||Edit text' @@ -342,7 +341,7 @@ const expectedBrailleValues = [ ' ed', ' @ed 8dot', ' pwded', ' #ed', {string_: 'spnbtn', spans_: []}, {string_: 'time'}, {string_: 'date'}, - {string_: 'Choose File No file chosen btn'}, ' search', ' ed' + {string_: 'No file chosen, Choose File btn'}, ' search', ' ed' ]; assertEquals(expectedSpeechValues.length, expectedBrailleValues.length);
diff --git a/chrome/browser/resources/feed_internals/feed_internals.html b/chrome/browser/resources/feed_internals/feed_internals.html index 809dbee..7f98977 100644 --- a/chrome/browser/resources/feed_internals/feed_internals.html +++ b/chrome/browser/resources/feed_internals/feed_internals.html
@@ -52,6 +52,10 @@ <td>Feed Fetch URL</td> <td id="feed-fetch-url"></td> </tr> + <tr> + <td>Feed Actions URL</td> + <td id="feed-actions-url"></td> + </tr> </table> <h2>User Classifier</h2> @@ -105,6 +109,18 @@ </tr> </table> + <h2>Last Action Upload</h2> + <table> + <tr> + <td>Status</td> + <td id="last-action-upload-status"></td> + </tr> + <tr> + <td>Last Upload Time</td> + <td id="last-action-upload-time"></td> + </tr> + </table> + <h2>Current Content</h2> <div id="current-content"> <template id="suggestion-template"> @@ -155,5 +171,9 @@ <input id="feed-host-override"> <button id="feed-host-override-apply">Apply</button> + <h2>Actions Endpoint Override (v2 only)</h2> + <input id="actions-endpoint-override"> + <button id="actions-endpoint-override-apply">Apply</button> + </body> </html>
diff --git a/chrome/browser/resources/feed_internals/feed_internals.js b/chrome/browser/resources/feed_internals/feed_internals.js index 03811954..be8efb6 100644 --- a/chrome/browser/resources/feed_internals/feed_internals.js +++ b/chrome/browser/resources/feed_internals/feed_internals.js
@@ -25,6 +25,7 @@ $('is-prefetching-enabled').textContent = properties.isPrefetchingEnabled; $('load-stream-status').textContent = properties.loadStreamStatus; $('feed-fetch-url').textContent = properties.feedFetchUrl.url; + $('feed-actions-url').textContent = properties.feedActionsUrl.url; }); } @@ -54,6 +55,10 @@ $('refresh-suppress-time').textContent = toDateString(properties.refreshSuppressTime); $('last-fetch-bless-nonce').textContent = properties.lastBlessNonce; + $('last-action-upload-status').textContent = + properties.lastActionUploadStatus; + $('last-action-upload-time').textContent = + toDateString(properties.lastActionUploadTime); }); } @@ -145,6 +150,10 @@ $('feed-host-override-apply').addEventListener('click', function() { pageHandler.overrideFeedHost({url: $('feed-host-override').value}); }); + + $('actions-endpoint-override-apply').addEventListener('click', function() { + pageHandler.overrideFeedHost({url: $('actions-endpoint-override').value}); + }); } function updatePage() {
diff --git a/chrome/browser/resources/nearby_internals/contact_tab.js b/chrome/browser/resources/nearby_internals/contact_tab.js index 5e4b298..191bd4f 100644 --- a/chrome/browser/resources/nearby_internals/contact_tab.js +++ b/chrome/browser/resources/nearby_internals/contact_tab.js
@@ -47,7 +47,7 @@ */ attached() { this.addWebUIListener( - 'contacts-updated', contact => this.onContactUpdateAdded_([contact])); + 'contacts-updated', contact => this.onContactUpdateAdded_(contact)); this.browserProxy_.initialize(); }, @@ -81,11 +81,10 @@ /** * Adds contact sent in from WebUI listener to the list of displayed contacts. - * @param {!Array<!ContactUpdate>} contacts + * @param {!ContactUpdate} contact * @private */ - onContactUpdateAdded_(contacts) { - contacts.unshift('contactList_'); - this.unshift.apply(this, contacts); + onContactUpdateAdded_(contact) { + this.contactList_.unshift(contact); }, });
diff --git a/chrome/browser/resources/nearby_internals/http_tab.js b/chrome/browser/resources/nearby_internals/http_tab.js index c40a949b..4a7520f 100644 --- a/chrome/browser/resources/nearby_internals/http_tab.js +++ b/chrome/browser/resources/nearby_internals/http_tab.js
@@ -94,16 +94,6 @@ * @private */ onHttpMessageAdded_(message) { - this.parseAndAddMessages_([message]); - }, - - /** - * Parses an array of HTTP messages and adds to the javascript list. - * @param {!Array<!HttpMessage>} messages - * @private - */ - parseAndAddMessages_(messages) { - messages.unshift('httpMessageList_'); - this.unshift.apply(this, messages); + this.httpMessageList_.unshift(message); }, });
diff --git a/chrome/browser/resources/nearby_internals/log_object.html b/chrome/browser/resources/nearby_internals/log_object.html index 48485db..0a3154b 100644 --- a/chrome/browser/resources/nearby_internals/log_object.html +++ b/chrome/browser/resources/nearby_internals/log_object.html
@@ -7,11 +7,18 @@ background-color: rgb(255, 241, 241); } + .verbose-log { + background-color: rgb(235, 235, 235); + } + + .default-log { + background-color: rgb(255, 255, 255); + } + #item-metadata { color: #888; display: flex; font-size: 10px; - margin-bottom: 4px; padding: 6px; }
diff --git a/chrome/browser/resources/nearby_internals/log_object.js b/chrome/browser/resources/nearby_internals/log_object.js index 281c4d9..39d28e2 100644 --- a/chrome/browser/resources/nearby_internals/log_object.js +++ b/chrome/browser/resources/nearby_internals/log_object.js
@@ -29,12 +29,16 @@ itemChanged_() { switch (this.item.severity) { case Severity.WARNING: - this.$['item'].classList.add('warning-log'); + this.$['item'].className = 'warning-log'; break; case Severity.ERROR: - this.$['item'].classList.add('error-log'); + this.$['item'].className = 'error-log'; + break; + case Severity.VERBOSE: + this.$['item'].className = 'verbose-log'; break; default: + this.$['item'].className = 'default-log'; break; } },
diff --git a/chrome/browser/resources/nearby_internals/logging_tab.js b/chrome/browser/resources/nearby_internals/logging_tab.js index 52e5d75..47ecc9a 100644 --- a/chrome/browser/resources/nearby_internals/logging_tab.js +++ b/chrome/browser/resources/nearby_internals/logging_tab.js
@@ -7,6 +7,7 @@ import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import './log_object.js'; import './shared_style.js'; + import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {NearbyLogsBrowserProxy} from './nearby_logs_browser_proxy.js'; @@ -83,7 +84,7 @@ this.addWebUIListener( 'log-buffer-cleared', () => this.onWebUILogBufferCleared_()); this.browserProxy_.getLogMessages().then( - logs => this.parseAndAddLogs_(logs)); + logs => this.onGetLogMessages_(logs)); }, /** @@ -132,7 +133,7 @@ * @private */ onLogMessageAdded_(log) { - this.parseAndAddLogs_([log]); + this.logList_.unshift(log); }, /** @@ -144,13 +145,13 @@ }, /** - * Parses an array of log messages and adds to the javascript list. + * Parses an array of log messages and adds to the javascript list sent in + * from the initial page load. * @param {!Array<!LogMessage>} logs * @private */ - parseAndAddLogs_(logs) { - logs.unshift('logList_'); - this.push.apply(this, logs); + onGetLogMessages_(logs) { + this.logList_ = logs.reverse().concat(this.logList_); }, /**
diff --git a/chrome/browser/resources/nearby_internals/types.js b/chrome/browser/resources/nearby_internals/types.js index 384e10e..d2cad83 100644 --- a/chrome/browser/resources/nearby_internals/types.js +++ b/chrome/browser/resources/nearby_internals/types.js
@@ -8,10 +8,10 @@ * @enum {number} */ export const Severity = { + VERBOSE: -1, INFO: 0, WARNING: 1, ERROR: 2, - VERBOSE: 3 }; /**
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.html b/chrome/browser/resources/settings/safety_check_page/safety_check_page.html index cb53810..e50d4f0 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.html +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.html
@@ -20,7 +20,7 @@ restamp> <div class="separator"></div> <cr-button id="safetyCheckParentButton" class="action-button" - on-click="onRunSafetyCheckClick_" no-search + on-click="onRunSafetyCheckClick_" aria-label="$i18n{safetyCheckParentButtonAriaLabel}"> $i18n{safetyCheckParentButton} </cr-button>
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc index b3d3602..b9cdfa5 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc
@@ -70,10 +70,12 @@ // Enable every deep scanning features. if (use_legacy_policies_) { scoped_feature_list_.InitWithFeatures( - {kContentComplianceEnabled, kMalwareScanEnabled}, {}); + {kContentComplianceEnabled, kMalwareScanEnabled}, + {enterprise_connectors::kEnterpriseConnectorsEnabled}); } else { scoped_feature_list_.InitWithFeatures( - {enterprise_connectors::kEnterpriseConnectorsEnabled}, {}); + {enterprise_connectors::kEnterpriseConnectorsEnabled}, + {kContentComplianceEnabled, kMalwareScanEnabled}); } // Change the time values of the upload UI to smaller ones to make tests
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java index 2b971cde..54f095548 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.share.screenshot; -import android.support.test.annotation.UiThreadTest; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -18,6 +17,7 @@ import org.junit.runner.RunWith; import org.chromium.base.Callback; +import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.R;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 719b870..980076e 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3874,8 +3874,6 @@ "views/toolbar/reload_button.h", "views/toolbar/sharesheet_button.cc", "views/toolbar/sharesheet_button.h", - "views/toolbar/tab_search_button.cc", - "views/toolbar/tab_search_button.h", "views/toolbar/toolbar_account_icon_container_view.cc", "views/toolbar/toolbar_account_icon_container_view.h", "views/toolbar/toolbar_action_view.cc",
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc index afcaefe..37a3ec2 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -501,6 +501,13 @@ GURL url( embedded_test_server()->GetURL("/popup_blocker/popup-on-unload.html")); ui_test_utils::NavigateToURL(browser(), url); + // Make sure the same-site navigation below will not create a new + // RenderFrameHost, otherwise the unload handler of the old RenderFrameHost + // will run after the new RenderFrameHost gets rendered. + // TODO(crbug.com/1110744): Support running unload handlers before the new + // RenderFrameHost renders on same-site cross-RenderFrameHost navigations. + DisableProactiveBrowsingInstanceSwapFor( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); NavigateAndCheckPopupShown(embedded_test_server()->GetURL("/popup_blocker/"), kExpectPopup);
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java index 79ccd83..cfe3579 100644 --- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java +++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
@@ -205,7 +205,8 @@ * the mMessageView content description is read aloud if accessibility is enabled. */ public void announceforAccessibility() { - mMessageView.announceForAccessibility(mMessageView.getContentDescription() + " " + mMessageView.announceForAccessibility(mMessageView.getContentDescription() + ". " + + mActionButtonView.getContentDescription() + ". " + mContainerView.getResources().getString(R.string.bottom_bar_screen_position)); } @@ -274,7 +275,6 @@ mMessageView.setMaxLines(snackbar.getSingleLine() ? 1 : MAX_LINES); mMessageView.setTemplate(snackbar.getTemplateText()); setViewText(mMessageView, snackbar.getText(), animate); - String actionText = snackbar.getActionText(); ApiCompatibilityUtils.setTextAppearance(mMessageView, getTextAppearance(snackbar)); ApiCompatibilityUtils.setTextAppearance( @@ -291,8 +291,9 @@ mSnackbarView.setBackgroundColor(backgroundColor); } - if (actionText != null) { + if (snackbar.getActionText() != null) { mActionButtonView.setVisibility(View.VISIBLE); + mActionButtonView.setContentDescription(snackbar.getActionText()); setViewText(mActionButtonView, snackbar.getActionText(), animate); } else { mActionButtonView.setVisibility(View.GONE);
diff --git a/chrome/browser/ui/views/frame/dbus_appmenu.cc b/chrome/browser/ui/views/frame/dbus_appmenu.cc index 66ba9ae4..513a284 100644 --- a/chrome/browser/ui/views/frame/dbus_appmenu.cc +++ b/chrome/browser/ui/views/frame/dbus_appmenu.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/ui/views/frame/dbus_appmenu.h" #include <dlfcn.h> -#include <glib-object.h> #include <stddef.h> #include <limits>
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index d2903e5e..3f8ce78 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -316,13 +316,18 @@ int unelided_left_bound = simplified_domain_bounds_.x() + current_offset_; int unelided_right_bound = unelided_left_bound + simplified_domain_bounds_.width(); + // GetSubstringBounds rounds up when calculating unelided_left_bound and + // unelided_right_bound, we subtract 1 pixel from the gradient widths to make + // sure they never overlap with the always visible part of the URL. + // gfx::Rect() switches negative values to 0, so this doesn't affect + // rectangles that were originally size 0. int left_gradient_width = kSmoothingGradientMaxWidth < unelided_left_bound - ? kSmoothingGradientMaxWidth - : unelided_left_bound; + ? kSmoothingGradientMaxWidth - 1 + : unelided_left_bound - 1; int right_gradient_width = shifted_bounds.right() - kSmoothingGradientMaxWidth > unelided_right_bound - ? kSmoothingGradientMaxWidth - : shifted_bounds.right() - unelided_right_bound; + ? kSmoothingGradientMaxWidth - 1 + : shifted_bounds.right() - unelided_right_bound - 1; view_->elide_animation_smoothing_rect_left_ = gfx::Rect( old_bounds.x(), old_bounds.y(), left_gradient_width, old_bounds.height()); @@ -2446,8 +2451,12 @@ elide_after_web_contents_interaction_animation_.reset(); hover_elide_or_unelide_animation_ = std::make_unique<OmniboxViewViews::ElideAnimation>(this, GetRenderText()); - if (IsURLEligibleForSimplifiedDomainEliding()) + if (IsURLEligibleForSimplifiedDomainEliding()) { ShowFullURLWithoutSchemeAndTrivialSubdomain(); + } else { + GetRenderText()->SetElideBehavior(gfx::ELIDE_TAIL); + FitToLocalBounds(); + } } void OmniboxViewViews::OnShouldPreventElisionChanged() {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index a8a466a..26460020 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -220,6 +220,9 @@ FRIEND_TEST_ALL_PREFIXES( OmniboxViewViewsRevealOnHoverAndMaybeHideOnInteractionTest, UnsetAlwaysShowFullURLs); + FRIEND_TEST_ALL_PREFIXES( + OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, + TabChangeWhenNotEligibleForEliding); FRIEND_TEST_ALL_PREFIXES(OmniboxPopupContentsViewTest, EmitAccessibilityEvents); // TODO(tommycli): Remove the rest of these friends after porting these
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index e14a598..3eb6806f 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -2290,6 +2290,51 @@ EXPECT_TRUE(elide_animation->IsAnimating()); } +// Tests that in the hide-on-interaction field trial, the omnibox is reset to +// the local bounds on tab change when the new text is not eligible for +// simplified domain elision. +TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, + TabChangeWhenNotEligibleForEliding) { + SetUpSimplifiedDomainTest(); + + content::MockNavigationHandle navigation; + navigation.set_is_same_document(false); + omnibox_view()->DidFinishNavigation(&navigation); + ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain( + omnibox_view()->GetRenderText(), + gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(), + kSimplifiedDomainDisplayUrl.size()))); + + // Simulate a user interaction and advance through the animation to elide the + // URL. + omnibox_view()->DidGetUserInteraction(blink::WebKeyboardEvent()); + OmniboxViewViews::ElideAnimation* elide_animation = + omnibox_view()->GetElideAfterInteractionAnimationForTesting(); + gfx::AnimationContainerElement* elide_as_element = + elide_animation->GetAnimationForTesting(); + elide_as_element->SetStartTime(base::TimeTicks()); + elide_as_element->Step(base::TimeTicks() + base::TimeDelta::FromSeconds(1)); + ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( + omnibox_view(), kSimplifiedDomainDisplayUrlScheme, + kSimplifiedDomainDisplayUrlSubdomain, + kSimplifiedDomainDisplayUrlHostnameAndScheme, + kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain())); + + // Change the tab and set state such that the current text is not eligible for + // simplified domain eliding. The omnibox should take up the full local bounds + // and be reset to tail-eliding behavior, just as if the above simplified + // domain elision had not happened. + omnibox_view()->model()->SetInputInProgress(true); + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents(profile(), nullptr); + omnibox_view()->SaveStateToTab(web_contents.get()); + omnibox_view()->OnTabChanged(web_contents.get()); + + EXPECT_EQ(gfx::ELIDE_TAIL, omnibox_view()->GetRenderText()->elide_behavior()); + EXPECT_EQ(kSimplifiedDomainDisplayUrl, + omnibox_view()->GetRenderText()->GetDisplayText()); +} + // Tests that in the hide-on-interaction field trial, when the path changes // while being elided, the animation is stopped. TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, @@ -2633,7 +2678,7 @@ elide_animation->GetAnimationForTesting(); elide_as_element->SetStartTime(base::TimeTicks()); uint32_t step = 1; - int max_gradient_width = OmniboxViewViews::kSmoothingGradientMaxWidth; + int max_gradient_width = OmniboxViewViews::kSmoothingGradientMaxWidth - 1; while (omnibox_view()->elide_animation_smoothing_rect_right_.width() < max_gradient_width) { elide_as_element->Step(base::TimeTicks() + @@ -2668,13 +2713,15 @@ int offset = elide_animation->GetCurrentOffsetForTesting(); gfx::Rect display_rect = render_text->display_rect(); // Check the expected size and positions for both gradients. - EXPECT_EQ(omnibox_view()->elide_animation_smoothing_rect_left_.width(), - simplified_rect.x() + offset); + EXPECT_TRUE(omnibox_view()->elide_animation_smoothing_rect_left_.width() == + simplified_rect.x() + offset - 1 || + omnibox_view()->elide_animation_smoothing_rect_left_.width() == + 0); EXPECT_EQ(omnibox_view()->elide_animation_smoothing_rect_left_.x(), display_rect.x()); EXPECT_EQ(omnibox_view()->elide_animation_smoothing_rect_right_.width(), - display_rect.right() - (simplified_rect.right() + offset)); - EXPECT_EQ(omnibox_view()->elide_animation_smoothing_rect_right_.x(), + display_rect.right() - (simplified_rect.right() + offset) - 1); + EXPECT_EQ(omnibox_view()->elide_animation_smoothing_rect_right_.x() - 1, simplified_rect.right() + offset); }
diff --git a/chrome/browser/ui/views/tab_search/tab_search_bubble_view_browsertest.cc b/chrome/browser/ui/views/tab_search/tab_search_bubble_view_browsertest.cc index a68937c..88cfccf 100644 --- a/chrome/browser/ui/views/tab_search/tab_search_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/tab_search/tab_search_bubble_view_browsertest.cc
@@ -12,9 +12,7 @@ #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/toolbar/tab_search_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" -#include "chrome/browser/ui/webui/tab_search/tab_search_ui.h" #include "chrome/common/webui_url_constants.h" #include "content/public/test/browser_test.h" @@ -32,7 +30,7 @@ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); DCHECK(browser_view); - views::View* anchor_view = browser_view->toolbar()->tab_search_button(); + views::View* anchor_view = browser_view->toolbar(); TabSearchBubbleView::CreateTabSearchBubble(browser()->profile(), anchor_view); }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 460b2537..edbc7bd 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -83,12 +83,14 @@ #include "ui/gfx/skia_util.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/controls/image_view.h" +#include "ui/views/layout/flex_layout.h" #include "ui/views/masked_targeter_delegate.h" #include "ui/views/mouse_watcher_view_host.h" #include "ui/views/rect_based_targeting_utils.h" #include "ui/views/view_model_utils.h" #include "ui/views/view_observer.h" #include "ui/views/view_targeter.h" +#include "ui/views/view_targeter_delegate.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" #include "ui/views/window/non_client_view.h" @@ -104,6 +106,11 @@ #include "ui/aura/window.h" #endif +#if BUILDFLAG(ENABLE_TAB_SEARCH) +#include "chrome/browser/ui/ui_features.h" +#include "chrome/browser/ui/views/tab_search/tab_search_bubble_view.h" +#endif + namespace { // Distance from the next/previous stacked before before we consider the tab @@ -291,6 +298,33 @@ (ui::TouchUiController::Get()->touch_ui() ? 136 : 102); } +// |TabControlsContainer| is as a container class for control views that live +// in the tab strip. +class TabControlsContainer : public views::View, + public views::ViewTargeterDelegate { + public: + TabControlsContainer() { + SetEventTargeter(std::make_unique<views::ViewTargeter>(this)); + SetLayoutManager(std::make_unique<views::FlexLayout>()); + } + + ~TabControlsContainer() override = default; + + // views::ViewTargeterDelegate: + bool DoesIntersectRect(const View* target, + const gfx::Rect& rect) const override { + DCHECK_EQ(this, target); + const auto& children = target->children(); + const auto hits_child = [target, rect](const views::View* child) { + gfx::RectF child_rect(rect); + views::View::ConvertRectToTarget(target, child, &child_rect); + return child->GetVisible() && + child->HitTestRect(gfx::ToEnclosingRect(child_rect)); + }; + return std::any_of(children.cbegin(), children.cend(), hits_child); + } +}; + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -506,7 +540,7 @@ } void DestroyDragController() override { - SetNewTabButtonVisible(true); + SetTabControlsVisible(true); drag_controller_.reset(); } @@ -688,7 +722,7 @@ // Hide the new tab button immediately if we didn't originate the drag. if (!drag_controller_) - SetNewTabButtonVisible(false); + SetTabControlsVisible(false); // Reset dragging state of existing tabs. for (int i = 0; i < GetTabCount(); ++i) @@ -722,7 +756,7 @@ // Let the controller know that the user is not dragging this tabstrip's // tabs anymore. tab_strip_->controller_->OnStoppedDragging(); - SetNewTabButtonVisible(true); + SetTabControlsVisible(true); } void StoppedDragging(const std::vector<TabSlotView*>& views, @@ -732,7 +766,7 @@ // Let the controller know that the user stopped dragging tabs. tab_strip_->controller_->OnStoppedDragging(); - SetNewTabButtonVisible(true); + SetTabControlsVisible(true); if (move_only && tab_strip_->touch_layout_) { if (completed) tab_strip_->touch_layout_->SizeToFit(); @@ -751,7 +785,7 @@ // Immediately hide the new tab button if the last tab is being dragged. const Tab* last_visible_tab = tab_strip_->GetLastVisibleTab(); if (last_visible_tab && last_visible_tab->dragging()) - SetNewTabButtonVisible(false); + SetTabControlsVisible(false); std::vector<gfx::Rect> bounds = CalculateBoundsForDraggedViews(views); DCHECK_EQ(views.size(), bounds.size()); @@ -791,8 +825,8 @@ return tab_strip_->ideal_bounds(group); } - void SetNewTabButtonVisible(bool visible) { - tab_strip_->new_tab_button_->SetVisible(visible); + void SetTabControlsVisible(bool visible) { + tab_strip_->tab_controls_container_->SetVisible(visible); } // Used by GetInsertionIndexForDraggedBounds() when the tabstrip is stacked. @@ -1017,6 +1051,8 @@ RemoveMessageLoopObserver(); new_tab_button_->RemoveObserver(this); + if (tab_search_button_) + tab_search_button_->RemoveObserver(this); hover_card_observer_.RemoveAll(); @@ -1058,6 +1094,8 @@ for (int i = 0; i < tab_count(); ++i) tab_at(i)->FrameColorsChanged(); new_tab_button_->FrameColorsChanged(); + if (tab_search_button_) + tab_search_button_->FrameColorsChanged(); UpdateContrastRatioValues(); SchedulePaint(); } @@ -1096,22 +1134,26 @@ tab_drag_handle.Intersects(rect); } - // Similarly, a hit in the new tab button is considered to be in the caption - // if it's in this thin strip. - gfx::Rect new_tab_button_drag_handle = new_tab_button_->GetMirroredBounds(); - new_tab_button_drag_handle.set_height(drag_handle_extension); - if (extend_drag_handle && new_tab_button_drag_handle.Intersects(rect)) + // Similarly, a hit in the tab controls container is considered to be in the + // caption if it's in this thin strip. + gfx::Rect tab_controls_drag_handle = + tab_controls_container_->GetMirroredBounds(); + tab_controls_drag_handle.set_height(drag_handle_extension); + if (extend_drag_handle && tab_controls_drag_handle.Intersects(rect)) return true; - // Check to see if the rect intersects the non-button parts of the new tab - // button. The button has a non-rectangular shape, so if it's not in the - // visual portions of the button we treat it as a click to the caption. - gfx::RectF rect_in_new_tab_coords_f(rect); - View::ConvertRectToTarget(this, new_tab_button_, &rect_in_new_tab_coords_f); - gfx::Rect rect_in_new_tab_coords = - gfx::ToEnclosingRect(rect_in_new_tab_coords_f); - return new_tab_button_->GetLocalBounds().Intersects(rect_in_new_tab_coords) && - !new_tab_button_->HitTestRect(rect_in_new_tab_coords); + // Check to see if the rect intersects the non-button parts of the tab + // controls container. The enclosed buttons have a non-rectangular shape, so + // if it's not in the visual portions of the buttons we treat it as a click to + // the caption. + gfx::RectF rect_in_tab_controls_coords_f(rect); + View::ConvertRectToTarget(this, tab_controls_container_, + &rect_in_tab_controls_coords_f); + gfx::Rect rect_in_tab_controls_coords = + gfx::ToEnclosingRect(rect_in_tab_controls_coords_f); + return tab_controls_container_->GetLocalBounds().Intersects( + rect_in_tab_controls_coords) && + !tab_controls_container_->HitTestRect(rect_in_tab_controls_coords); } bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) { @@ -1259,7 +1301,7 @@ StartMoveTabAnimation(); if (TabDragController::IsAttachedTo(GetDragContext()) && (last_tab != GetLastVisibleTab() || last_tab->dragging())) { - new_tab_button_->SetVisible(false); + tab_controls_container_->SetVisible(false); } SwapLayoutIfNecessary(); @@ -1828,8 +1870,11 @@ } bool TabStrip::IsFocusInTabs() const { + // Focus is in tabs if the currently focused view is contained in the TabStrip + // and not in the |tab_controls_container_|. return GetFocusManager() && Contains(GetFocusManager()->GetFocusedView()) && - GetFocusManager()->GetFocusedView() != new_tab_button_; + !tab_controls_container_->Contains( + GetFocusManager()->GetFocusedView()); } void TabStrip::MaybeStartDrag( @@ -2235,9 +2280,8 @@ if (active_tab && !is_dragging) active_tab->Paint(paint_info); - // Paint the New Tab button, unless it's being painted onto its own Layer. - if (!new_tab_button_->layer()) - new_tab_button_->Paint(paint_info); + // Paint the tab controls. + tab_controls_container_->Paint(paint_info); // If dragging a group, paint the group highlight and header above all // non-dragging tabs and groups. @@ -2314,9 +2358,9 @@ if (tab) return tab; } else { - if (new_tab_button_->GetVisible()) { - views::View* view = - ConvertPointToViewAndGetTooltipHandler(this, new_tab_button_, point); + if (tab_controls_container_->GetVisible()) { + views::View* view = ConvertPointToViewAndGetTooltipHandler( + this, tab_controls_container_, point); if (view) return view; } @@ -2388,19 +2432,45 @@ // So we get enter/exit on children to switch stacked layout on and off. set_notify_enter_exit_on_child(true); - new_tab_button_ = new NewTabButton(this, this); - new_tab_button_->SetTooltipText( + tab_controls_container_ = + AddChildView(std::make_unique<TabControlsContainer>()); + + auto new_tab_button = std::make_unique<NewTabButton>(this, this); + new_tab_button->SetTooltipText( l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB)); - new_tab_button_->SetAccessibleName( + new_tab_button->SetAccessibleName( l10n_util::GetStringUTF16(IDS_ACCNAME_NEWTAB)); - new_tab_button_->SetImageVerticalAlignment(views::ImageButton::ALIGN_BOTTOM); - new_tab_button_->SetEventTargeter( - std::make_unique<views::ViewTargeter>(new_tab_button_)); - AddChildView(new_tab_button_); - new_tab_button_->AddObserver(this); + new_tab_button->SetImageVerticalAlignment(views::ImageButton::ALIGN_BOTTOM); + new_tab_button->SetEventTargeter( + std::make_unique<views::ViewTargeter>(new_tab_button.get())); + new_tab_button->AddObserver(this); + + new_tab_button_ = + tab_controls_container_->AddChildView(std::move(new_tab_button)); + +#if BUILDFLAG(ENABLE_TAB_SEARCH) + if (base::FeatureList::IsEnabled(features::kTabSearch)) { + // TODO(tluk): Replace the use of the NewTabButton with an appropriate class + // for the tab search button. Current usage is temporary. + auto tab_search_button = std::make_unique<NewTabButton>(this, this); + tab_search_button->SetTooltipText( + l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_SEARCH)); + tab_search_button->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_TAB_SEARCH)); + tab_search_button->SetImageVerticalAlignment( + views::ImageButton::ALIGN_BOTTOM); + tab_search_button->SetEventTargeter( + std::make_unique<views::ViewTargeter>(tab_search_button.get())); + tab_search_button->AddObserver(this); + + tab_search_button_ = + tab_controls_container_->AddChildView(std::move(tab_search_button)); + } +#endif UpdateNewTabButtonBorder(); - new_tab_button_ideal_bounds_.set_size(new_tab_button_->GetPreferredSize()); + tab_controls_container_ideal_bounds_.set_size( + tab_controls_container_->GetPreferredSize()); if (g_drop_indicator_width == 0) { // Direction doesn't matter, both images are the same size. @@ -2538,11 +2608,12 @@ // sense to me. Why is each condition justified? if ((touch_layout_ || !in_tab_close_ || model_index == GetModelCount()) && TabDragController::IsAttachedTo(GetDragContext())) { - // Don't animate the new tab button when dragging tabs. Otherwise it looks - // like the new tab button magically appears from beyond the end of the tab + // Don't animate the tab controls container when dragging tabs. Otherwise it + // looks like the controls magically appear from beyond the end of the tab // strip. - bounds_animator_.StopAnimatingView(new_tab_button_); - new_tab_button_->SetBoundsRect(new_tab_button_ideal_bounds_); + bounds_animator_.StopAnimatingView(tab_controls_container_); + tab_controls_container_->SetBoundsRect( + tab_controls_container_ideal_bounds_); } } @@ -2598,10 +2669,10 @@ base::Unretained(this)))); } - if (bounds_animator_.GetTargetBounds(new_tab_button_) != - new_tab_button_ideal_bounds_) { - bounds_animator_.AnimateViewTo(new_tab_button_, - new_tab_button_ideal_bounds_); + if (bounds_animator_.GetTargetBounds(tab_controls_container_) != + tab_controls_container_ideal_bounds_) { + bounds_animator_.AnimateViewTo(tab_controls_container_, + tab_controls_container_ideal_bounds_); } } @@ -2615,7 +2686,7 @@ header_pair.second->UpdateBounds(); } - new_tab_button_->SetBoundsRect(new_tab_button_ideal_bounds_); + tab_controls_container_->SetBoundsRect(tab_controls_container_ideal_bounds_); } void TabStrip::ExitTabClosingMode() { @@ -2638,7 +2709,7 @@ // The grab area is adjacent to the new tab button. Treat the padding in the // new tab button as part of the grab area. constexpr int kApparentWidth = 50; - return kApparentWidth - new_tab_button_->GetInsets().right(); + return kApparentWidth - tab_controls_container_->GetInsets().right(); } bool TabStrip::TitlebarBackgroundIsTransparent() const { @@ -2710,8 +2781,8 @@ } int TabStrip::GetRightSideReservedWidth() const { - return new_tab_button_ideal_bounds_.width() + TabToNewTabButtonSpacing() + - FrameGrabWidth(); + return tab_controls_container_ideal_bounds_.width() + + TabToNewTabButtonSpacing() + FrameGrabWidth(); } const Tab* TabStrip::GetLastVisibleTab() const { @@ -3291,7 +3362,7 @@ if (touch_layout_) { const int trailing_x = tabs_.ideal_bounds(tab_count() - 1).right(); - new_tab_button_ideal_bounds_.set_origin( + tab_controls_container_ideal_bounds_.set_origin( gfx::Point(trailing_x + TabToNewTabButtonSpacing(), 0)); } else { const int available_width_for_tabs = CalculateAvailableWidthForTabs(); @@ -3303,7 +3374,7 @@ ? trailing_x : std::min(available_width_for_tabs, trailing_x); - new_tab_button_ideal_bounds_.set_origin( + tab_controls_container_ideal_bounds_.set_origin( gfx::Point(ntb_x_offset + TabToNewTabButtonSpacing(), 0)); } } @@ -3471,12 +3542,15 @@ } void TabStrip::UpdateNewTabButtonBorder() { - // The button is placed vertically exactly in the center of the tabstrip. + // The controls container is placed vertically exactly in the center of the + // tabstrip. const int extra_vertical_space = GetLayoutConstant(TAB_HEIGHT) - GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP) - NewTabButton::kButtonSize.height(); constexpr int kHorizontalInset = 8; - new_tab_button_->SetBorder(views::CreateEmptyBorder(gfx::Insets( + // TODO(tluk): Investigate whether this should apply to the |new_tab_button_| + // or the |tab_controls_container_|. + tab_controls_container_->SetBorder(views::CreateEmptyBorder(gfx::Insets( extra_vertical_space / 2, kHorizontalInset, 0, kHorizontalInset))); } @@ -3524,6 +3598,12 @@ if (event.type() == ui::ET_GESTURE_TAP) TouchUMA::RecordGestureAction(TouchUMA::kGestureNewTabTap); } +#if BUILDFLAG(ENABLE_TAB_SEARCH) + if (sender == tab_search_button_) { + TabSearchBubbleView::CreateTabSearchBubble(controller()->GetProfile(), + tab_search_button_); + } +#endif } // Overridden to support automation. See automation_proxy_uitest.cc. @@ -3659,9 +3739,9 @@ if (tab) return tab; } else { - if (new_tab_button_->GetVisible()) { - views::View* view = - ConvertPointToViewAndGetEventHandler(this, new_tab_button_, point); + if (tab_controls_container_->GetVisible()) { + views::View* view = ConvertPointToViewAndGetEventHandler( + this, tab_controls_container_, point); if (view) return view; } @@ -3694,8 +3774,9 @@ void TabStrip::OnTouchUiChanged() { UpdateNewTabButtonBorder(); - new_tab_button_ideal_bounds_.set_size(new_tab_button_->GetPreferredSize()); - new_tab_button_->SetBoundsRect(new_tab_button_ideal_bounds_); + tab_controls_container_ideal_bounds_.set_size( + tab_controls_container_->GetPreferredSize()); + tab_controls_container_->SetBoundsRect(tab_controls_container_ideal_bounds_); StopAnimating(true); PreferredSizeChanged(); }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 3a3e51a..5d24742 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -147,9 +147,9 @@ // Sets |stacked_layout_| and animates if necessary. void SetStackedLayout(bool stacked_layout); - // Returns the ideal bounds of the new tab button. - gfx::Rect new_tab_button_ideal_bounds() const { - return new_tab_button_ideal_bounds_; + // Returns the ideal bounds of the tab controls container. + gfx::Rect tab_controls_container_ideal_bounds() const { + return tab_controls_container_ideal_bounds_; } // Adds a tab at the specified index. @@ -688,11 +688,16 @@ // Responsible for animating tabs in response to model changes. views::BoundsAnimator bounds_animator_{this}; - // The "New Tab" button. + // Container that holds the |new_tab_button_| and the |tab_search_button_|. + views::View* tab_controls_container_ = nullptr; NewTabButton* new_tab_button_ = nullptr; + // |tab_search_button_| will be null if features::kTabSearch is disabled. + // TODO(tluk): Subclass NewTabButton and set the appropriate icon for + // |tab_search_button_|. + NewTabButton* tab_search_button_ = nullptr; - // Ideal bounds of the new tab button. - gfx::Rect new_tab_button_ideal_bounds_; + // Ideal bounds of container holding the tab controls. + gfx::Rect tab_controls_container_ideal_bounds_; // If this value is defined, it is used as the width to lay out tabs // (instead of GetTabAreaWidth()). It is defined when closing tabs with the
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 44e3b6f..5002832 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -866,7 +866,8 @@ CompleteAnimationAndLayout(); - EXPECT_LE(tab_strip_->new_tab_button_ideal_bounds().right(), kTabStripWidth); + EXPECT_LE(tab_strip_->tab_controls_container_ideal_bounds().right(), + kTabStripWidth); } TEST_P(TabStripTest, NewTabButtonRightOfTabs) { @@ -877,7 +878,7 @@ AnimateToIdealBounds(); - EXPECT_EQ(tab_strip_->new_tab_button_ideal_bounds().x(), + EXPECT_EQ(tab_strip_->tab_controls_container_ideal_bounds().x(), tab_strip_->ideal_bounds(0).right() + TabToNewTabButtonSpacing()); }
diff --git a/chrome/browser/ui/views/toolbar/tab_search_button.cc b/chrome/browser/ui/views/toolbar/tab_search_button.cc deleted file mode 100644 index 72b6c0474..0000000 --- a/chrome/browser/ui/views/toolbar/tab_search_button.cc +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2020 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/ui/views/toolbar/tab_search_button.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/views/tab_search/tab_search_bubble_view.h" -#include "chrome/grit/generated_resources.h" -#include "components/vector_icons/vector_icons.h" -#include "ui/base/l10n/l10n_util.h" - -// TODO(crbug.com/1099917): This is a WIP. Implement more detail when design is -// final -TabSearchButton::TabSearchButton(Browser* browser) - : ToolbarButton(this), browser_(browser) { - SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_FIND)); -} - -void TabSearchButton::UpdateIcon() { - UpdateIconsWithStandardColors(vector_icons::kFolderIcon); -} - -void TabSearchButton::ButtonPressed(views::Button* sender, - const ui::Event& event) { - TabSearchBubbleView::CreateTabSearchBubble(browser_->profile(), this); -}
diff --git a/chrome/browser/ui/views/toolbar/tab_search_button.h b/chrome/browser/ui/views/toolbar/tab_search_button.h deleted file mode 100644 index 2af92bf..0000000 --- a/chrome/browser/ui/views/toolbar/tab_search_button.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2020 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_UI_VIEWS_TOOLBAR_TAB_SEARCH_BUTTON_H_ -#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TAB_SEARCH_BUTTON_H_ - -#include "chrome/browser/ui/views/toolbar/toolbar_button.h" -#include "ui/views/controls/button/button.h" - -class Browser; - -class TabSearchButton : public ToolbarButton, public views::ButtonListener { - public: - explicit TabSearchButton(Browser* browser); - TabSearchButton(const TabSearchButton&) = delete; - TabSearchButton& operator=(const TabSearchButton&) = delete; - ~TabSearchButton() override = default; - - // ToolbarButton: - void UpdateIcon() override; - - // views::ButtonListener: - void ButtonPressed(views::Button* sender, const ui::Event& event) override; - - private: - Browser* const browser_; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TAB_SEARCH_BUTTON_H_
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 3c75135..7ccd06a 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -54,7 +54,6 @@ #include "chrome/browser/ui/views/toolbar/home_button.h" #include "chrome/browser/ui/views/toolbar/reload_button.h" #include "chrome/browser/ui/views/toolbar/sharesheet_button.h" -#include "chrome/browser/ui/views/toolbar/tab_search_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_account_icon_container_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_button.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" @@ -268,11 +267,6 @@ if (browser_actions) browser_actions_ = AddChildView(std::move(browser_actions)); - if (base::FeatureList::IsEnabled(features::kTabSearch)) { - tab_search_button_ = - AddChildView(std::make_unique<TabSearchButton>(browser_)); - } - if (extensions_container) extensions_container_ = AddChildView(std::move(extensions_container));
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index b3e4c91..f4af66f 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -50,7 +50,6 @@ class MediaToolbarButtonView; class ReloadButton; class SharesheetButton; -class TabSearchButton; class ToolbarButton; class ToolbarAccountIconContainerView; @@ -153,7 +152,6 @@ } BrowserAppMenuButton* app_menu_button() const { return app_menu_button_; } HomeButton* home_button() const { return home_; } - TabSearchButton* tab_search_button() const { return tab_search_button_; } AppMenuIconController* app_menu_icon_controller() { return &app_menu_icon_controller_; } @@ -278,7 +276,6 @@ SharesheetButton* sharesheet_button_ = nullptr; MediaToolbarButtonView* media_button_ = nullptr; BrowserAppMenuButton* app_menu_button_ = nullptr; - TabSearchButton* tab_search_button_ = nullptr; Browser* const browser_; BrowserView* const browser_view_;
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals.mojom b/chrome/browser/ui/webui/feed_internals/feed_internals.mojom index c063ca5..68266facd 100644 --- a/chrome/browser/ui/webui/feed_internals/feed_internals.mojom +++ b/chrome/browser/ui/webui/feed_internals/feed_internals.mojom
@@ -26,6 +26,9 @@ // Feed fetch URL. url.mojom.Url feed_fetch_url; + + // Feed upload actions URL. + url.mojom.Url feed_actions_url; }; struct UserClassifier { @@ -57,6 +60,12 @@ // For test server authentication. string last_bless_nonce; + + // Last net status for actions upload. + int32 last_action_upload_status; + + // Last action upload time. + mojo_base.mojom.TimeDelta last_action_upload_time; }; // Models a single suggestion in the Feed. @@ -113,4 +122,10 @@ // Empty to clear override. // This allows for testing the Feed against a development server. OverrideFeedHost(url.mojom.Url host); + + // Overrides the URL used to upload actions. + // Empty to clear override. + // This allows for testing the Feed against a development server. + OverrideActionUploadEndpoint(url.mojom.Url endpoint_url); + };
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc index fa27607..cd203793 100644 --- a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
@@ -175,7 +175,11 @@ } void FeedInternalsPageHandler::OverrideFeedHost(const GURL& host) { - return pref_service_->SetString( - feed::prefs::kHostOverrideHost, - host.is_valid() ? host.spec() : std::string()); + pref_service_->SetString(feed::prefs::kHostOverrideHost, + host.is_valid() ? host.spec() : std::string()); +} + +void FeedInternalsPageHandler::OverrideActionUploadEndpoint( + const GURL& endpoint_url) { + // Not implemented for Feed v1. }
diff --git a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h index c854927..6ce68f1 100644 --- a/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h +++ b/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h
@@ -46,6 +46,7 @@ void GetFeedProcessScopeDump(GetFeedProcessScopeDumpCallback) override; void GetFeedHistograms(GetFeedHistogramsCallback) override; void OverrideFeedHost(const GURL& host) override; + void OverrideActionUploadEndpoint(const GURL& endpoint_url) override; private: mojo::Receiver<feed_internals::mojom::PageHandler> receiver_;
diff --git a/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.cc b/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.cc index 89ea3cbb..267a6f4 100644 --- a/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.cc +++ b/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.cc
@@ -58,9 +58,10 @@ properties->is_feed_allowed = IsFeedAllowed(); properties->is_prefetching_enabled = offline_pages::prefetch_prefs::IsEnabled(pref_service_); - if (debug_data.fetch_info) { + if (debug_data.fetch_info) properties->feed_fetch_url = debug_data.fetch_info->base_request_url; - } + if (debug_data.upload_info) + properties->feed_actions_url = debug_data.upload_info->base_request_url; properties->load_stream_status = debug_data.load_stream_status; @@ -80,10 +81,15 @@ feed::DebugStreamData debug_data = feed_stream_->GetDebugStreamData(); if (debug_data.fetch_info) { - const feed::NetworkResponseInfo& fetch_info = *debug_data.fetch_info; - properties->last_fetch_status = fetch_info.status_code; - properties->last_fetch_time = ToJsTimeDelta(fetch_info.fetch_time); - properties->last_bless_nonce = fetch_info.bless_nonce; + const feed::NetworkResponseInfo& net_info = *debug_data.fetch_info; + properties->last_fetch_status = net_info.status_code; + properties->last_fetch_time = ToJsTimeDelta(net_info.fetch_time); + properties->last_bless_nonce = net_info.bless_nonce; + } + if (debug_data.upload_info) { + const feed::NetworkResponseInfo& net_info = *debug_data.upload_info; + properties->last_action_upload_status = net_info.status_code; + properties->last_action_upload_time = ToJsTimeDelta(net_info.fetch_time); } std::move(callback).Run(std::move(properties)); @@ -136,3 +142,9 @@ feed::prefs::kHostOverrideHost, host.is_valid() ? host.spec() : std::string()); } +void FeedV2InternalsPageHandler::OverrideActionUploadEndpoint( + const GURL& endpoint_url) { + return pref_service_->SetString( + feed::prefs::kActionsEndpointOverride, + endpoint_url.is_valid() ? endpoint_url.spec() : std::string()); +}
diff --git a/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.h b/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.h index 9e76e50..b10e495 100644 --- a/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.h +++ b/chrome/browser/ui/webui/feed_internals/feedv2_internals_page_handler.h
@@ -45,6 +45,7 @@ void GetFeedProcessScopeDump(GetFeedProcessScopeDumpCallback) override; void GetFeedHistograms(GetFeedHistogramsCallback) override; void OverrideFeedHost(const GURL& host) override; + void OverrideActionUploadEndpoint(const GURL& endpoint_url) override; private: bool IsFeedAllowed();
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc index 92c7d72b..dcf77b1d 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper.cc +++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -110,6 +110,7 @@ {ContentSettingsType::BLUETOOTH_CHOOSER_DATA, kBluetoothChooserDataGroupType}, {ContentSettingsType::WINDOW_PLACEMENT, "window-placement"}, + {ContentSettingsType::FONT_ACCESS, "font-access"}, // Add new content settings here if a corresponding Javascript string // representation for it is not required. Note some exceptions do have UI in
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc index 373c552d..6a9c074 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -10,6 +10,7 @@ #include <vector> #include "base/base64.h" +#include "base/metrics/histogram_functions.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "chrome/browser/extensions/extension_tab_util.h" @@ -43,7 +44,14 @@ browser_tab_strip_tracker_.Init(); } -TabSearchPageHandler::~TabSearchPageHandler() = default; +TabSearchPageHandler::~TabSearchPageHandler() { + base::UmaHistogramCounts1000("Tabs.TabSearch.NumTabsClosedPerInstance", + num_tabs_closed_); + base::UmaHistogramEnumeration("Tabs.TabSearch.CloseAction", + called_switch_to_tab_ + ? TabSearchCloseAction::kTabSwitch + : TabSearchCloseAction::kNoAction); +} void TabSearchPageHandler::CloseTab(int32_t tab_id) { base::Optional<TabDetails> optional_details = GetTabDetails(tab_id); @@ -53,6 +61,9 @@ const TabDetails& details = optional_details.value(); bool tab_closed = details.tab_strip_model->CloseWebContentsAt( details.index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); + + ++num_tabs_closed_; + if (tab_closed) NotifyTabsChanged(); } @@ -61,9 +72,8 @@ auto profile_tabs = tab_search::mojom::ProfileTabs::New(); Profile* profile = browser_->profile(); for (auto* browser : *BrowserList::GetInstance()) { - if (browser->profile() != profile) { + if (browser->profile() != profile) continue; - } TabStripModel* tab_strip_model = browser->tab_strip_model(); auto window_tabs = tab_search::mojom::WindowTabs::New(); window_tabs->active = (browser == browser_); @@ -74,6 +84,18 @@ profile_tabs->windows.push_back(std::move(window_tabs)); } + // On first run record the number of windows and tabs open for the given + // profile. + if (!sent_initial_payload_) { + sent_initial_payload_ = true; + int tab_count = 0; + for (const auto& window : profile_tabs->windows) + tab_count += window->tabs.size(); + base::UmaHistogramCounts100("Tabs.TabSearch.NumWindowsOnOpen", + profile_tabs->windows.size()); + base::UmaHistogramCounts10000("Tabs.TabSearch.NumTabsOnOpen", tab_count); + } + std::move(callback).Run(std::move(profile_tabs)); } @@ -110,6 +132,8 @@ if (!optional_details) return; + called_switch_to_tab_ = true; + const TabDetails& details = optional_details.value(); details.tab_strip_model->ActivateTabAt(details.index); details.browser->window()->Activate();
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h index 3dc96b1..96c8c9e 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
@@ -21,6 +21,14 @@ class Browser; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class TabSearchCloseAction { + kNoAction = 0, + kTabSwitch = 1, + kMaxValue = kTabSwitch, +}; + class TabSearchPageHandler : public tab_search::mojom::PageHandler, public TabStripModelObserver, public BrowserTabStripTrackerDelegate { @@ -85,6 +93,18 @@ content::WebUI* const web_ui_; BrowserTabStripTracker browser_tab_strip_tracker_{this, this}; std::unique_ptr<base::RetainingOneShotTimer> debounce_timer_; + + // Tracks how many times |CloseTab()| has been evoked for the currently open + // instance of Tab Search for logging in UMA. + int num_tabs_closed_ = 0; + + // Tracks whether or not we have sent the initial payload to the Tab Search + // UI for metric collection purposes. + bool sent_initial_payload_ = false; + + // Tracks whether the user has evoked |SwitchToTab()| for metric collection + // purposes. + bool called_switch_to_tab_ = false; }; #endif // CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index f1e616f6..fa437f77 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -132,8 +132,6 @@ "test/test_app_registrar.h", "test/test_app_registry_controller.cc", "test/test_app_registry_controller.h", - "test/test_app_shortcut_manager.cc", - "test/test_app_shortcut_manager.h", "test/test_data_retriever.cc", "test/test_data_retriever.h", "test/test_file_handler_manager.cc",
diff --git a/chrome/browser/web_applications/components/app_shortcut_manager.cc b/chrome/browser/web_applications/components/app_shortcut_manager.cc index 6f936ed..a6c7b46 100644 --- a/chrome/browser/web_applications/components/app_shortcut_manager.cc +++ b/chrome/browser/web_applications/components/app_shortcut_manager.cc
@@ -39,17 +39,8 @@ registrar_ = registrar; } -void AppShortcutManager::Start() { - DCHECK(registrar_); - app_registrar_observer_.Add(registrar_); -} - -void AppShortcutManager::Shutdown() { - app_registrar_observer_.RemoveAll(); -} - -void AppShortcutManager::OnWebAppManifestUpdated(const AppId& app_id, - base::StringPiece old_name) { +void AppShortcutManager::UpdateShortcuts(const AppId& app_id, + base::StringPiece old_name) { if (!CanCreateShortcuts()) return;
diff --git a/chrome/browser/web_applications/components/app_shortcut_manager.h b/chrome/browser/web_applications/components/app_shortcut_manager.h index 9ae25de..2e3cdafab 100644 --- a/chrome/browser/web_applications/components/app_shortcut_manager.h +++ b/chrome/browser/web_applications/components/app_shortcut_manager.h
@@ -11,10 +11,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "base/scoped_observer.h" #include "chrome/browser/web_applications/components/app_registrar.h" -#include "chrome/browser/web_applications/components/app_registrar_observer.h" #include "chrome/browser/web_applications/components/web_app_id.h" #include "chrome/browser/web_applications/components/web_app_run_on_os_login.h" #include "chrome/browser/web_applications/components/web_app_shortcut.h" @@ -35,30 +32,27 @@ // web_app_extension_shortcut.(h|cc) and // platform_apps/shortcut_manager.(h|cc) to web_app::AppShortcutManager and // its subclasses. -class AppShortcutManager : public AppRegistrarObserver { +class AppShortcutManager { public: explicit AppShortcutManager(Profile* profile); - ~AppShortcutManager() override; + virtual ~AppShortcutManager(); void SetSubsystems(AppIconManager* icon_manager, AppRegistrar* registrar); void Start(); void Shutdown(); - // AppRegistrarObserver: - void OnWebAppManifestUpdated(const web_app::AppId& app_id, - base::StringPiece old_name) override; - // Tells the AppShortcutManager that no shortcuts should actually be written // to the disk. void SuppressShortcutsForTesting(); - // virtual for testing. - virtual bool CanCreateShortcuts() const; - // virtual for testing. - virtual void CreateShortcuts(const AppId& app_id, - bool add_to_desktop, - CreateShortcutsCallback callback); + bool CanCreateShortcuts() const; + void CreateShortcuts(const AppId& app_id, + bool add_to_desktop, + CreateShortcutsCallback callback); + void UpdateShortcuts(const web_app::AppId& app_id, + base::StringPiece old_name); + virtual void RegisterRunOnOsLogin(const AppId& app_id, RegisterRunOnOsLoginCallback callback); @@ -131,9 +125,6 @@ RegisterShortcutsMenuCallback callback, ShortcutsMenuIconsBitmaps shortcuts_menu_icons_bitmaps); - ScopedObserver<AppRegistrar, AppRegistrarObserver> app_registrar_observer_{ - this}; - bool suppress_shortcuts_for_testing_ = false; AppRegistrar* registrar_ = nullptr;
diff --git a/chrome/browser/web_applications/components/file_handler_manager.cc b/chrome/browser/web_applications/components/file_handler_manager.cc index 849e9bb..31c4b752 100644 --- a/chrome/browser/web_applications/components/file_handler_manager.cc +++ b/chrome/browser/web_applications/components/file_handler_manager.cc
@@ -37,8 +37,7 @@ bool FileHandlerManager::disable_automatic_file_handler_cleanup_for_testing_ = false; -FileHandlerManager::FileHandlerManager(Profile* profile) - : profile_(profile), registrar_observer_(this) {} +FileHandlerManager::FileHandlerManager(Profile* profile) : profile_(profile) {} FileHandlerManager::~FileHandlerManager() = default; @@ -49,8 +48,6 @@ void FileHandlerManager::Start() { DCHECK(registrar_); - registrar_observer_.Add(registrar_); - if (!FileHandlerManager:: disable_automatic_file_handler_cleanup_for_testing_) { content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT}) @@ -232,10 +229,6 @@ return cleaned_up_count; } -void FileHandlerManager::OnAppRegistrarDestroyed() { - registrar_observer_.RemoveAll(); -} - const base::Optional<GURL> FileHandlerManager::GetMatchingFileHandlerURL( const AppId& app_id, const std::vector<base::FilePath>& launch_files) {
diff --git a/chrome/browser/web_applications/components/file_handler_manager.h b/chrome/browser/web_applications/components/file_handler_manager.h index 60a2d818..507a42d 100644 --- a/chrome/browser/web_applications/components/file_handler_manager.h +++ b/chrome/browser/web_applications/components/file_handler_manager.h
@@ -10,9 +10,7 @@ #include <vector> #include "base/macros.h" -#include "base/scoped_observer.h" #include "chrome/browser/web_applications/components/app_registrar.h" -#include "chrome/browser/web_applications/components/app_registrar_observer.h" #include "chrome/browser/web_applications/components/app_shortcut_manager.h" #include "chrome/browser/web_applications/components/web_app_id.h" #include "components/services/app_service/public/cpp/file_handler.h" @@ -27,10 +25,10 @@ namespace web_app { -class FileHandlerManager : public AppRegistrarObserver { +class FileHandlerManager { public: explicit FileHandlerManager(Profile* profile); - ~FileHandlerManager() override; + virtual ~FileHandlerManager(); // |registrar| is used to observe OnWebAppInstalled/Uninstalled events. void SetSubsystems(AppRegistrar* registrar); @@ -134,11 +132,6 @@ // handlers unregistered, for use in tests. int CleanupAfterOriginTrials(); - // AppRegistrarObserver: - void OnAppRegistrarDestroyed() override; - - ScopedObserver<AppRegistrar, AppRegistrarObserver> registrar_observer_; - base::WeakPtrFactory<FileHandlerManager> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(FileHandlerManager);
diff --git a/chrome/browser/web_applications/components/install_manager.cc b/chrome/browser/web_applications/components/install_manager.cc index 1e3068cd..8de4fea4 100644 --- a/chrome/browser/web_applications/components/install_manager.cc +++ b/chrome/browser/web_applications/components/install_manager.cc
@@ -19,11 +19,9 @@ InstallManager::~InstallManager() = default; void InstallManager::SetSubsystems(AppRegistrar* registrar, - AppShortcutManager* shortcut_manager, OsIntegrationManager* os_integration_manager, InstallFinalizer* finalizer) { registrar_ = registrar; - shortcut_manager_ = shortcut_manager; os_integration_manager_ = os_integration_manager; finalizer_ = finalizer; }
diff --git a/chrome/browser/web_applications/components/install_manager.h b/chrome/browser/web_applications/components/install_manager.h index 286798e..8f8313c 100644 --- a/chrome/browser/web_applications/components/install_manager.h +++ b/chrome/browser/web_applications/components/install_manager.h
@@ -31,7 +31,6 @@ enum class InstallResultCode; class InstallFinalizer; class AppRegistrar; -class AppShortcutManager; class OsIntegrationManager; // TODO(loyso): Rework this interface. Unify the API and merge similar @@ -161,7 +160,6 @@ virtual ~InstallManager(); void SetSubsystems(AppRegistrar* registrar, - AppShortcutManager* shortcut_manager, OsIntegrationManager* os_integration_manager, InstallFinalizer* finalizer); @@ -182,7 +180,6 @@ protected: Profile* profile() { return profile_; } AppRegistrar* registrar() { return registrar_; } - AppShortcutManager* shortcut_manager() { return shortcut_manager_; } OsIntegrationManager* os_integration_manager() { return os_integration_manager_; } @@ -200,7 +197,6 @@ WebAppUrlLoader url_loader_; AppRegistrar* registrar_ = nullptr; - AppShortcutManager* shortcut_manager_ = nullptr; OsIntegrationManager* os_integration_manager_ = nullptr; InstallFinalizer* finalizer_ = nullptr;
diff --git a/chrome/browser/web_applications/components/pending_app_manager.cc b/chrome/browser/web_applications/components/pending_app_manager.cc index 2f872ce4..a03e7974 100644 --- a/chrome/browser/web_applications/components/pending_app_manager.cc +++ b/chrome/browser/web_applications/components/pending_app_manager.cc
@@ -39,13 +39,11 @@ void PendingAppManager::SetSubsystems( AppRegistrar* registrar, - AppShortcutManager* shortcut_manager, OsIntegrationManager* os_integration_manager, WebAppUiManager* ui_manager, InstallFinalizer* finalizer, InstallManager* install_manager) { registrar_ = registrar; - shortcut_manager_ = shortcut_manager; os_integration_manager_ = os_integration_manager; ui_manager_ = ui_manager; finalizer_ = finalizer;
diff --git a/chrome/browser/web_applications/components/pending_app_manager.h b/chrome/browser/web_applications/components/pending_app_manager.h index 223973d..d8e724dc 100644 --- a/chrome/browser/web_applications/components/pending_app_manager.h +++ b/chrome/browser/web_applications/components/pending_app_manager.h
@@ -24,7 +24,6 @@ enum class InstallResultCode; class AppRegistrar; -class AppShortcutManager; class OsIntegrationManager; class InstallFinalizer; class InstallManager; @@ -58,7 +57,6 @@ virtual ~PendingAppManager(); void SetSubsystems(AppRegistrar* registrar, - AppShortcutManager* shortcut_manager, OsIntegrationManager* os_integration_manager, WebAppUiManager* ui_manager, InstallFinalizer* finalizer, @@ -120,7 +118,6 @@ protected: AppRegistrar* registrar() { return registrar_; } - AppShortcutManager* shortcut_manager() { return shortcut_manager_; } OsIntegrationManager* os_integration_manager() { return os_integration_manager_; } @@ -157,7 +154,6 @@ void OnAppSynchronized(ExternalInstallSource source, const GURL& app_url); AppRegistrar* registrar_ = nullptr; - AppShortcutManager* shortcut_manager_ = nullptr; OsIntegrationManager* os_integration_manager_ = nullptr; WebAppUiManager* ui_manager_ = nullptr; InstallFinalizer* finalizer_ = nullptr;
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc index 20fcea1..2c3fa94 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
@@ -20,10 +20,12 @@ #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_prefs_utils.h" +#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/components/web_app_utils.h" #include "chrome/browser/web_applications/extensions/bookmark_app_finalizer_utils.h" #include "chrome/browser/web_applications/extensions/bookmark_app_registrar.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" +#include "chrome/browser/web_applications/os_integration_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/web_application_info.h" @@ -139,10 +141,11 @@ scoped_refptr<CrxInstaller> crx_installer = crx_installer_factory_.Run(profile_); - crx_installer->set_installer_callback(base::BindOnce( - &BookmarkAppInstallFinalizer::OnExtensionUpdated, - weak_ptr_factory_.GetWeakPtr(), std::move(expected_app_id), - existing_extension->short_name(), std::move(callback), crx_installer)); + crx_installer->set_installer_callback( + base::BindOnce(&BookmarkAppInstallFinalizer::OnExtensionUpdated, + weak_ptr_factory_.GetWeakPtr(), std::move(expected_app_id), + existing_extension->short_name(), web_app_info, + std::move(callback), crx_installer)); crx_installer->InitializeCreationFlagsForUpdate(existing_extension, Extension::NO_FLAGS); crx_installer->set_install_source(existing_extension->location()); @@ -294,6 +297,7 @@ void BookmarkAppInstallFinalizer::OnExtensionUpdated( const web_app::AppId& expected_app_id, const std::string& old_name, + const WebApplicationInfo& web_app_info, InstallFinalizedCallback callback, scoped_refptr<CrxInstaller> crx_installer, const base::Optional<CrxInstallError>& error) { @@ -314,9 +318,12 @@ return; } - if (!is_legacy_finalizer()) + if (!is_legacy_finalizer()) { + web_app::WebAppProviderBase::GetProviderBase(profile_) + ->os_integration_manager() + .UpdateOsHooks(extension->id(), old_name, web_app_info); registrar().NotifyWebAppManifestUpdated(extension->id(), old_name); - + } std::move(callback).Run(extension->id(), web_app::InstallResultCode::kSuccessAlreadyInstalled); }
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h index 54615415..eadc407c 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
@@ -75,6 +75,7 @@ void OnExtensionUpdated(const web_app::AppId& expected_app_id, const std::string& old_name, + const WebApplicationInfo& web_app_info, InstallFinalizedCallback callback, scoped_refptr<CrxInstaller> crx_installer, const base::Optional<CrxInstallError>& error);
diff --git a/chrome/browser/web_applications/os_integration_manager.cc b/chrome/browser/web_applications/os_integration_manager.cc index 4e057f2..170f7a3 100644 --- a/chrome/browser/web_applications/os_integration_manager.cc +++ b/chrome/browser/web_applications/os_integration_manager.cc
@@ -173,6 +173,27 @@ suppress_os_hooks_for_testing_ = true; } +void OsIntegrationManager::UpdateOsHooks( + const AppId& app_id, + base::StringPiece old_name, + const WebApplicationInfo& web_app_info) { + DCHECK(shortcut_manager_); + + // TODO(crbug.com/1079439): Update file handlers. + shortcut_manager_->UpdateShortcuts(app_id, old_name); + if (base::FeatureList::IsEnabled( + features::kDesktopPWAsAppIconShortcutsMenu) && + !web_app_info.shortcut_infos.empty()) { + shortcut_manager_->RegisterShortcutsMenuWithOs( + app_id, web_app_info.shortcut_infos, + web_app_info.shortcuts_menu_icons_bitmaps); + } else { + // Unregister shortcuts menu when feature is disabled or shortcut_infos is + // empty. + shortcut_manager_->UnregisterShortcutsMenuWithOs(app_id); + } +} + void OsIntegrationManager::OnShortcutsCreated( const AppId& app_id, std::unique_ptr<WebApplicationInfo> web_app_info,
diff --git a/chrome/browser/web_applications/os_integration_manager.h b/chrome/browser/web_applications/os_integration_manager.h index aee7dac..19e4afb0 100644 --- a/chrome/browser/web_applications/os_integration_manager.h +++ b/chrome/browser/web_applications/os_integration_manager.h
@@ -73,6 +73,12 @@ virtual void UninstallOsHooks(const AppId& app_id, UninstallOsHooksCallback callback); + // Update all needed OS hooks for the web app. + // virtual for testing + virtual void UpdateOsHooks(const AppId& app_id, + base::StringPiece old_name, + const WebApplicationInfo& web_app_info); + void SuppressOsHooksForTesting(); protected:
diff --git a/chrome/browser/web_applications/system_web_app_manager_unittest.cc b/chrome/browser/web_applications/system_web_app_manager_unittest.cc index b00e125a..3584ced6 100644 --- a/chrome/browser/web_applications/system_web_app_manager_unittest.cc +++ b/chrome/browser/web_applications/system_web_app_manager_unittest.cc
@@ -22,8 +22,6 @@ #include "chrome/browser/web_applications/components/web_app_icon_generator.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/pending_app_manager_impl.h" -#include "chrome/browser/web_applications/system_web_app_manager.h" -#include "chrome/browser/web_applications/test/test_app_shortcut_manager.h" #include "chrome/browser/web_applications/test/test_data_retriever.h" #include "chrome/browser/web_applications/test/test_file_handler_manager.h" #include "chrome/browser/web_applications/test/test_file_utils.h" @@ -198,8 +196,6 @@ install_manager_ = std::make_unique<WebAppInstallManager>(profile()); test_pending_app_manager_impl_ = std::make_unique<TestPendingAppManagerImpl>(profile()); - test_shortcut_manager_ = - std::make_unique<TestAppShortcutManager>(profile()); test_os_integration_manager_ = std::make_unique<TestOsIntegrationManager>(profile()); test_system_web_app_manager_ = @@ -211,17 +207,16 @@ install_manager().SetUrlLoaderForTesting( std::make_unique<TestWebAppUrlLoader>()); - install_manager().SetSubsystems( - &controller().registrar(), &shortcut_manager(), - &os_integration_manager(), &install_finalizer()); + install_manager().SetSubsystems(&controller().registrar(), + &os_integration_manager(), + &install_finalizer()); auto url_loader = std::make_unique<TestWebAppUrlLoader>(); url_loader_ = url_loader.get(); pending_app_manager().SetUrlLoaderForTesting(std::move(url_loader)); pending_app_manager().SetSubsystems( - &controller().registrar(), &shortcut_manager(), - &os_integration_manager(), &ui_manager(), &install_finalizer(), - &install_manager()); + &controller().registrar(), &os_integration_manager(), &ui_manager(), + &install_finalizer(), &install_manager()); system_web_app_manager().SetSubsystems( &pending_app_manager(), &controller().registrar(), @@ -247,7 +242,6 @@ test_ui_manager_.reset(); test_system_web_app_manager_.reset(); test_os_integration_manager_.reset(); - test_shortcut_manager_.reset(); test_pending_app_manager_impl_.reset(); install_manager_.reset(); install_finalizer_.reset(); @@ -280,8 +274,6 @@ return *test_pending_app_manager_impl_; } - TestAppShortcutManager& shortcut_manager() { return *test_shortcut_manager_; } - TestSystemWebAppManager& system_web_app_manager() { return *test_system_web_app_manager_; } @@ -381,7 +373,6 @@ std::unique_ptr<WebAppInstallFinalizer> install_finalizer_; std::unique_ptr<WebAppInstallManager> install_manager_; std::unique_ptr<TestPendingAppManagerImpl> test_pending_app_manager_impl_; - std::unique_ptr<TestAppShortcutManager> test_shortcut_manager_; std::unique_ptr<TestSystemWebAppManager> test_system_web_app_manager_; std::unique_ptr<TestWebAppUiManager> test_ui_manager_; std::unique_ptr<TestOsIntegrationManager> test_os_integration_manager_;
diff --git a/chrome/browser/web_applications/test/test_app_shortcut_manager.cc b/chrome/browser/web_applications/test/test_app_shortcut_manager.cc deleted file mode 100644 index 5a5686c..0000000 --- a/chrome/browser/web_applications/test/test_app_shortcut_manager.cc +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2019 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/web_applications/test/test_app_shortcut_manager.h" - -#include "base/callback.h" -#include "base/threading/thread_task_runner_handle.h" - -namespace web_app { - -TestAppShortcutManager::TestAppShortcutManager(Profile* profile) - : AppShortcutManager(profile) {} - -TestAppShortcutManager::~TestAppShortcutManager() = default; - -void TestAppShortcutManager::SetNextCreateShortcutsResult(const AppId& app_id, - bool success) { - DCHECK(!base::Contains(next_create_shortcut_results_, app_id)); - next_create_shortcut_results_[app_id] = success; -} - -bool TestAppShortcutManager::CanCreateShortcuts() const { - return can_create_shortcuts_; -} - -void TestAppShortcutManager::CreateShortcuts(const AppId& app_id, - bool on_desktop, - CreateShortcutsCallback callback) { - ++num_create_shortcuts_calls_; - did_add_to_desktop_ = on_desktop; - - bool success = true; - - auto it = next_create_shortcut_results_.find(app_id); - if (it != next_create_shortcut_results_.end()) { - success = it->second; - next_create_shortcut_results_.erase(app_id); - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&TestAppShortcutManager::OnShortcutsCreated, - weak_ptr_factory_.GetWeakPtr(), app_id, - std::move(callback), success)); -} - -std::unique_ptr<ShortcutInfo> TestAppShortcutManager::BuildShortcutInfo( - const AppId& app_id) { - NOTIMPLEMENTED(); - return nullptr; -} - -void TestAppShortcutManager::GetShortcutInfoForApp( - const AppId& app_id, - GetShortcutInfoCallback callback) { - NOTIMPLEMENTED(); -} - -void TestAppShortcutManager::RegisterRunOnOsLogin( - const AppId& app_id, - RegisterRunOnOsLoginCallback callback) { - ++num_register_run_on_os_login_calls_; - std::move(callback).Run(true); -} - -} // namespace web_app
diff --git a/chrome/browser/web_applications/test/test_app_shortcut_manager.h b/chrome/browser/web_applications/test/test_app_shortcut_manager.h deleted file mode 100644 index 517fd0c..0000000 --- a/chrome/browser/web_applications/test/test_app_shortcut_manager.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2019 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_WEB_APPLICATIONS_TEST_TEST_APP_SHORTCUT_MANAGER_H_ -#define CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_APP_SHORTCUT_MANAGER_H_ - -#include <map> - -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "chrome/browser/web_applications/components/app_shortcut_manager.h" -#include "chrome/browser/web_applications/components/web_app_id.h" - -class Profile; - -namespace web_app { - -class TestAppShortcutManager : public AppShortcutManager { - public: - explicit TestAppShortcutManager(Profile* profile); - ~TestAppShortcutManager() override; - - size_t num_create_shortcuts_calls() const { - return num_create_shortcuts_calls_; - } - - size_t num_register_run_on_os_login_calls() const { - return num_register_run_on_os_login_calls_; - } - - void set_can_create_shortcuts(bool can_create_shortcuts) { - can_create_shortcuts_ = can_create_shortcuts; - } - - base::Optional<bool> did_add_to_desktop() const { - return did_add_to_desktop_; - } - - void SetNextCreateShortcutsResult(const AppId& app_id, bool success); - void SetNextRegisterRunOnOsLoginResult(const AppId& app_id, bool success); - // AppShortcutManager: - bool CanCreateShortcuts() const override; - void CreateShortcuts(const AppId& app_id, - bool on_desktop, - CreateShortcutsCallback callback) override; - std::unique_ptr<ShortcutInfo> BuildShortcutInfo(const AppId& app_id) override; - void GetShortcutInfoForApp(const AppId& app_id, - GetShortcutInfoCallback callback) override; - void RegisterRunOnOsLogin(const AppId& app_id, - RegisterRunOnOsLoginCallback callback) override; - - private: - size_t num_create_shortcuts_calls_ = 0; - size_t num_register_run_on_os_login_calls_ = 0; - base::Optional<bool> did_add_to_desktop_; - - bool can_create_shortcuts_ = true; - std::map<AppId, bool> next_create_shortcut_results_; - - base::WeakPtrFactory<TestAppShortcutManager> weak_ptr_factory_{this}; -}; - -} // namespace web_app - -#endif // CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_APP_SHORTCUT_MANAGER_H_
diff --git a/chrome/browser/web_applications/test/test_os_integration_manager.cc b/chrome/browser/web_applications/test/test_os_integration_manager.cc index 45bb01d..9e7ea1e 100644 --- a/chrome/browser/web_applications/test/test_os_integration_manager.cc +++ b/chrome/browser/web_applications/test/test_os_integration_manager.cc
@@ -63,4 +63,11 @@ NOTIMPLEMENTED(); } +void TestOsIntegrationManager::UpdateOsHooks( + const AppId& app_id, + base::StringPiece old_name, + const WebApplicationInfo& web_app_info) { + NOTIMPLEMENTED(); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/test/test_os_integration_manager.h b/chrome/browser/web_applications/test/test_os_integration_manager.h index 96b08af..ca71e2ce 100644 --- a/chrome/browser/web_applications/test/test_os_integration_manager.h +++ b/chrome/browser/web_applications/test/test_os_integration_manager.h
@@ -25,6 +25,9 @@ InstallOsHooksOptions options) override; void UninstallOsHooks(const AppId& app_id, UninstallOsHooksCallback callback) override; + void UpdateOsHooks(const AppId& app_id, + base::StringPiece old_name, + const WebApplicationInfo& web_app_info) override; size_t num_create_shortcuts_calls() const { return num_create_shortcuts_calls_;
diff --git a/chrome/browser/web_applications/test/test_pending_app_manager.cc b/chrome/browser/web_applications/test/test_pending_app_manager.cc index d30bed9..71bfc71 100644 --- a/chrome/browser/web_applications/test/test_pending_app_manager.cc +++ b/chrome/browser/web_applications/test/test_pending_app_manager.cc
@@ -24,7 +24,7 @@ deduped_uninstall_count_(0), registrar_(registrar) { // TODO(crbug.com/973324): Wire this up to a TestInstallFinalizer. - SetSubsystems(registrar, nullptr, nullptr, nullptr, nullptr, nullptr); + SetSubsystems(registrar, nullptr, nullptr, nullptr, nullptr); } TestPendingAppManager::~TestPendingAppManager() = default;
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc index 24bf0b0..46805b5 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.cc +++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -357,7 +357,7 @@ CommitCallback commit_callback = base::BindOnce( &WebAppInstallFinalizer::OnDatabaseCommitCompletedForUpdate, weak_ptr_factory_.GetWeakPtr(), std::move(callback), app_id, - existing_web_app->name()); + existing_web_app->name(), web_app_info); SetWebAppManifestFieldsAndWriteData(web_app_info, std::move(web_app), std::move(commit_callback)); @@ -544,6 +544,7 @@ InstallFinalizedCallback callback, AppId app_id, std::string old_name, + const WebApplicationInfo& web_app_info, bool success) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!success) { @@ -551,6 +552,10 @@ return; } + WebAppProviderBase::GetProviderBase(profile_) + ->os_integration_manager() + .UpdateOsHooks(app_id, old_name, web_app_info); + registrar().NotifyWebAppManifestUpdated(app_id, old_name); std::move(callback).Run(app_id, InstallResultCode::kSuccessAlreadyInstalled); }
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h index 98126f4..18af444 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.h +++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -83,10 +83,12 @@ void OnDatabaseCommitCompletedForInstall(InstallFinalizedCallback callback, AppId app_id, bool success); - void OnDatabaseCommitCompletedForUpdate(InstallFinalizedCallback callback, - AppId app_id, - std::string old_name, - bool success); + void OnDatabaseCommitCompletedForUpdate( + InstallFinalizedCallback callback, + AppId app_id, + std::string old_name, + const WebApplicationInfo& web_app_info, + bool success); void OnFallbackInstallFinalized(const AppId& app_in_sync_install_id, InstallFinalizedCallback callback, const AppId& installed_app_id,
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc index 66a2d1c9..80c9ab1f7 100644 --- a/chrome/browser/web_applications/web_app_install_manager.cc +++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -89,7 +89,7 @@ DCHECK(started_); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); task->LoadWebAppAndCheckManifest( @@ -110,7 +110,7 @@ DCHECK(started_); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); task->InstallWebAppFromManifest( contents, bypass_service_worker_check, install_source, @@ -130,7 +130,7 @@ DCHECK(started_); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); task->InstallWebAppFromManifestWithFallback( contents, force_shortcut_app, install_source, std::move(dialog_callback), @@ -148,7 +148,7 @@ DCHECK(started_); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); task->InstallWebAppFromInfo( std::move(web_application_info), for_installable_site, install_source, @@ -166,7 +166,7 @@ DCHECK(started_); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); task->InstallWebAppWithParams( web_contents, install_params, install_source, @@ -221,7 +221,7 @@ GURL launch_url = web_application_info->app_url; auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); task->ExpectAppId(sync_app_id); @@ -266,7 +266,7 @@ DCHECK(started_); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); base::OnceClosure start_task = base::BindOnce( @@ -358,7 +358,7 @@ // Install failed. Do the fallback install from info fetching just icon URLs. auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager(), os_integration_manager(), finalizer(), + profile(), os_integration_manager(), finalizer(), data_retriever_factory_.Run()); InstallFinalizer::FinalizeOptions finalize_options;
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc index f81f9bb..e2bf1bf42 100644 --- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc +++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/web_applications/components/web_app_icon_generator.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/components/web_app_utils.h" -#include "chrome/browser/web_applications/test/test_app_shortcut_manager.h" #include "chrome/browser/web_applications/test/test_data_retriever.h" #include "chrome/browser/web_applications/test/test_file_utils.h" #include "chrome/browser/web_applications/test/test_os_integration_manager.h" @@ -131,7 +130,6 @@ std::unique_ptr<WebAppInstallTask> CreateDummyTask() { return std::make_unique<WebAppInstallTask>( /*profile=*/nullptr, - /*shortcut_manager=*/nullptr, /*os_integration_manager=*/nullptr, /*install_finalizer=*/nullptr, /*data_retriever=*/nullptr); @@ -160,13 +158,11 @@ install_finalizer_ = std::make_unique<WebAppInstallFinalizer>( profile(), icon_manager_.get(), /*legacy_finalizer=*/nullptr); - shortcut_manager_ = std::make_unique<TestAppShortcutManager>(profile()); os_integration_manager_ = std::make_unique<TestOsIntegrationManager>(profile()); install_manager_ = std::make_unique<WebAppInstallManager>(profile()); - install_manager_->SetSubsystems(®istrar(), shortcut_manager_.get(), - os_integration_manager_.get(), + install_manager_->SetSubsystems(®istrar(), os_integration_manager_.get(), install_finalizer_.get()); auto test_url_loader = std::make_unique<TestWebAppUrlLoader>(); @@ -194,7 +190,6 @@ WebAppRegistrar& registrar() { return controller().registrar(); } WebAppInstallManager& install_manager() { return *install_manager_; } - TestAppShortcutManager& shortcut_manager() { return *shortcut_manager_; } TestOsIntegrationManager& os_integration_manager() { return *os_integration_manager_; } @@ -454,7 +449,6 @@ ui_manager_.reset(); install_manager_.reset(); os_integration_manager_.reset(); - shortcut_manager_.reset(); install_finalizer_.reset(); icon_manager_.reset(); test_registry_controller_.reset(); @@ -468,7 +462,6 @@ std::unique_ptr<TestWebAppRegistryController> test_registry_controller_; std::unique_ptr<WebAppIconManager> icon_manager_; - std::unique_ptr<TestAppShortcutManager> shortcut_manager_; std::unique_ptr<TestOsIntegrationManager> os_integration_manager_; std::unique_ptr<WebAppInstallManager> install_manager_; std::unique_ptr<WebAppInstallFinalizer> install_finalizer_;
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc index 59eea1c..4fa7aeb5 100644 --- a/chrome/browser/web_applications/web_app_install_task.cc +++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/security_state_tab_helper.h" -#include "chrome/browser/web_applications/components/app_shortcut_manager.h" #include "chrome/browser/web_applications/components/install_bounce_metric.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_data_retriever.h" @@ -68,12 +67,10 @@ WebAppInstallTask::WebAppInstallTask( Profile* profile, - AppShortcutManager* shortcut_manager, OsIntegrationManager* os_integration_manager, InstallFinalizer* install_finalizer, std::unique_ptr<WebAppDataRetriever> data_retriever) : data_retriever_(std::move(data_retriever)), - shortcut_manager_(shortcut_manager), os_integration_manager_(os_integration_manager), install_finalizer_(install_finalizer), profile_(profile) {} @@ -676,11 +673,8 @@ FilterAndResizeIconsGenerateMissing(web_app_info.get(), &icons_map); install_finalizer_->FinalizeUpdate( - *web_app_info, - base::BindOnce(&WebAppInstallTask::OnUpdateFinalizedRegisterShortcutsMenu, - weak_ptr_factory_.GetWeakPtr(), - web_app_info->shortcut_infos, - web_app_info->shortcuts_menu_icons_bitmaps)); + *web_app_info, base::BindOnce(&WebAppInstallTask::CallInstallCallback, + weak_ptr_factory_.GetWeakPtr())); } void WebAppInstallTask::OnDialogCompleted( @@ -816,33 +810,4 @@ CallInstallCallback(app_id, InstallResultCode::kSuccessNewInstall); } -// TODO(https://crbug.com/1087219): Move RegisterShortcutsMenuWithOs code into -// OsIntegrationManager when that becomes available. -void WebAppInstallTask::OnUpdateFinalizedRegisterShortcutsMenu( - const std::vector<WebApplicationShortcutsMenuItemInfo>& shortcut_infos, - const ShortcutsMenuIconsBitmaps& shortcuts_menu_icons_bitmaps, - const AppId& app_id, - InstallResultCode code) { - if (ShouldStopInstall()) - return; - - if (code != InstallResultCode::kSuccessAlreadyInstalled) { - CallInstallCallback(app_id, code); - return; - } - - if (base::FeatureList::IsEnabled( - features::kDesktopPWAsAppIconShortcutsMenu) && - !shortcut_infos.empty()) { - shortcut_manager_->RegisterShortcutsMenuWithOs( - app_id, shortcut_infos, shortcuts_menu_icons_bitmaps); - } else { - // Unregister shortcuts menu when feature is disabled or shortcut_infos is - // empty. - shortcut_manager_->UnregisterShortcutsMenuWithOs(app_id); - } - - CallInstallCallback(app_id, code); -} - } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h index 944cc61d5..207a5b7 100644 --- a/chrome/browser/web_applications/web_app_install_task.h +++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -37,7 +37,6 @@ namespace web_app { -class AppShortcutManager; class OsIntegrationManager; class InstallFinalizer; class WebAppDataRetriever; @@ -49,7 +48,6 @@ base::OnceCallback<void(std::unique_ptr<WebApplicationInfo>)>; WebAppInstallTask(Profile* profile, - AppShortcutManager* shortcut_manager, OsIntegrationManager* os_integration_manager, InstallFinalizer* install_finalizer, std::unique_ptr<WebAppDataRetriever> data_retriever); @@ -233,11 +231,6 @@ const OsHooksResults os_hooks_results); void OnRegisteredRunOnOsLogin(const AppId& app_id, bool registered_run_on_os_login); - void OnUpdateFinalizedRegisterShortcutsMenu( - const std::vector<WebApplicationShortcutsMenuItemInfo>& shortcut_infos, - const ShortcutsMenuIconsBitmaps& shortcuts_menu_icons_bitmaps, - const AppId& app_id, - InstallResultCode code); // Whether we should just obtain WebApplicationInfo instead of the actual // installation. @@ -260,7 +253,6 @@ std::unique_ptr<WebApplicationInfo> web_application_info_; std::unique_ptr<content::WebContents> web_contents_; - AppShortcutManager* shortcut_manager_; OsIntegrationManager* os_integration_manager_; InstallFinalizer* install_finalizer_; Profile* const profile_;
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc index 07d3657..d2cab3c 100644 --- a/chrome/browser/web_applications/web_app_install_task_unittest.cc +++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -26,7 +26,6 @@ #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_icon_generator.h" #include "chrome/browser/web_applications/components/web_app_utils.h" -#include "chrome/browser/web_applications/test/test_app_shortcut_manager.h" #include "chrome/browser/web_applications/test/test_data_retriever.h" #include "chrome/browser/web_applications/test/test_file_handler_manager.h" #include "chrome/browser/web_applications/test/test_file_utils.h" @@ -99,21 +98,19 @@ install_finalizer_ = std::make_unique<WebAppInstallFinalizer>(profile(), icon_manager_.get(), /*legacy_finalizer=*/nullptr); - shortcut_manager_ = std::make_unique<TestAppShortcutManager>(profile()); os_integration_manager_ = std::make_unique<TestOsIntegrationManager>(profile()); install_finalizer_->SetSubsystems( ®istrar(), ui_manager_.get(), &test_registry_controller_->sync_bridge()); - shortcut_manager_->SetSubsystems(icon_manager_.get(), ®istrar()); auto data_retriever = std::make_unique<TestDataRetriever>(); data_retriever_ = data_retriever.get(); install_task_ = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager_.get(), os_integration_manager_.get(), - install_finalizer_.get(), std::move(data_retriever)); + profile(), os_integration_manager_.get(), install_finalizer_.get(), + std::move(data_retriever)); url_loader_ = std::make_unique<TestWebAppUrlLoader>(); controller().Init(); @@ -149,7 +146,6 @@ install_finalizer_.reset(); ui_manager_.reset(); icon_manager_.reset(); - shortcut_manager_.reset(); test_registry_controller_.reset(); @@ -321,7 +317,6 @@ } WebAppRegistrar& registrar() { return controller().registrar(); } - TestAppShortcutManager& test_shortcut_manager() { return *shortcut_manager_; } TestOsIntegrationManager& test_os_integration_manager() { return *os_integration_manager_; } @@ -335,7 +330,6 @@ std::unique_ptr<WebAppInstallTask> install_task_; std::unique_ptr<TestWebAppUiManager> ui_manager_; std::unique_ptr<InstallFinalizer> install_finalizer_; - std::unique_ptr<TestAppShortcutManager> shortcut_manager_; std::unique_ptr<TestOsIntegrationManager> os_integration_manager_; // Owned by install_task_: @@ -1017,8 +1011,8 @@ /*scope=*/GURL{}); auto install_task = std::make_unique<WebAppInstallTask>( - guest_profile, shortcut_manager_.get(), os_integration_manager_.get(), - install_finalizer_.get(), std::move(data_retriever)); + guest_profile, os_integration_manager_.get(), install_finalizer_.get(), + std::move(data_retriever)); base::RunLoop run_loop; install_task->InstallWebAppWithParams( @@ -1179,8 +1173,8 @@ url_loader().SetNextLoadUrlResult(url, WebAppUrlLoader::Result::kUrlLoaded); auto task = std::make_unique<WebAppInstallTask>( - profile(), shortcut_manager_.get(), os_integration_manager_.get(), - install_finalizer_.get(), std::move(data_retriever)); + profile(), os_integration_manager_.get(), install_finalizer_.get(), + std::move(data_retriever)); std::unique_ptr<WebApplicationInfo> info; task->LoadAndRetrieveWebApplicationInfoWithIcons(
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 793e6f0..196cba6 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -156,7 +156,6 @@ void WebAppProvider::Shutdown() { ui_manager_->Shutdown(); - shortcut_manager_->Shutdown(); pending_app_manager_->Shutdown(); manifest_update_manager_->Shutdown(); system_web_app_manager_->Shutdown(); @@ -257,15 +256,15 @@ install_finalizer_->SetSubsystems(registrar_.get(), ui_manager_.get(), registry_controller_.get()); - install_manager_->SetSubsystems(registrar_.get(), shortcut_manager_.get(), + install_manager_->SetSubsystems(registrar_.get(), os_integration_manager_.get(), install_finalizer_.get()); manifest_update_manager_->SetSubsystems( registrar_.get(), icon_manager_.get(), ui_manager_.get(), install_manager_.get(), system_web_app_manager_.get()); pending_app_manager_->SetSubsystems( - registrar_.get(), shortcut_manager_.get(), os_integration_manager_.get(), - ui_manager_.get(), install_finalizer_.get(), install_manager_.get()); + registrar_.get(), os_integration_manager_.get(), ui_manager_.get(), + install_finalizer_.get(), install_manager_.get()); external_web_app_manager_->SetSubsystems(pending_app_manager_.get()); system_web_app_manager_->SetSubsystems( pending_app_manager_.get(), registrar_.get(), registry_controller_.get(), @@ -297,7 +296,6 @@ web_app_policy_manager_->Start(); system_web_app_manager_->Start(); manifest_update_manager_->Start(); - shortcut_manager_->Start(); file_handler_manager_->Start(); os_integration_manager_->Start(); ui_manager_->Start();
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4eaa8ff3..34dae9b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -758,6 +758,7 @@ data_deps = [ "//chrome:browser_tests_pak", "//chrome/browser/resources/media/mei_preload:component", + "//chrome/test/data/webui:modulize", # TODO(thakis): Why do these need copying in browser_tests? # content_browsertests uses the non-copied files instead. @@ -805,6 +806,7 @@ "//third_party/simplejson/", "//third_party/tlslite/", "//ui/webui/resources/", + "$root_gen_dir/chrome/test/data/webui/test_util.m.js", ] data += js2gtest_js_libraries data += metric_integration_jsdeps @@ -2361,6 +2363,8 @@ "../browser/chromeos/login/test/enrollment_helper_mixin.h", "../browser/chromeos/login/test/enrollment_ui_mixin.cc", "../browser/chromeos/login/test/enrollment_ui_mixin.h", + "../browser/chromeos/login/test/fake_eula_mixin.cc", + "../browser/chromeos/login/test/fake_eula_mixin.h", "../browser/chromeos/login/test/fake_gaia_mixin.cc", "../browser/chromeos/login/test/fake_gaia_mixin.h", "../browser/chromeos/login/test/guest_session_mixin.cc", @@ -3393,6 +3397,7 @@ "../browser/policy/messaging_layer/storage/storage_unittest.cc", "../browser/policy/messaging_layer/storage/test_storage_module.cc", "../browser/policy/messaging_layer/storage/test_storage_module.h", + "../browser/policy/messaging_layer/upload/app_install_report_handler_unittest.cc", "../browser/policy/messaging_layer/upload/dm_server_upload_service_unittest.cc", "../browser/policy/messaging_layer/util/shared_queue_unittest.cc", "../browser/policy/messaging_layer/util/status_macros_unittest.cc",
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn index edf137e..ac9b4a4e 100644 --- a/chrome/test/data/pdf/BUILD.gn +++ b/chrome/test/data/pdf/BUILD.gn
@@ -7,6 +7,7 @@ js_type_check("closure_compile") { is_polymer3 = true closure_flags = default_closure_args + [ + "browser_resolver_prefix_replacements=\"chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/=../../chrome/test/data/\"", "browser_resolver_prefix_replacements=\"chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/=../../chrome/browser/resources/pdf/\"", "js_module_root=../../chrome/test/data/webui/", "js_module_root=./gen/chrome/test/data/webui/", @@ -177,6 +178,7 @@ js_library("viewer_pdf_toolbar_new_test") { deps = [ + "../webui:test_util.m", "//chrome/browser/resources/pdf:constants", "//chrome/browser/resources/pdf/elements:viewer-pdf-toolbar-new", ]
diff --git a/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js b/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js index b260cea..67bc193 100644 --- a/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js +++ b/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {eventToPromise} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/webui/test_util.m.js'; import {FittingType} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/constants.js'; import {ViewerPdfToolbarNewElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/elements/viewer-pdf-toolbar-new.js'; @@ -122,8 +123,9 @@ const rotateButton = getCrIconButtons(toolbar, 'center')[3]; chrome.test.assertEq('pdf:rotate-left', rotateButton.ironIcon); - toolbar.addEventListener('rotate-left', e => chrome.test.succeed()); + const promise = eventToPromise('rotate-left', toolbar); rotateButton.click(); + promise.then(() => chrome.test.succeed()); }, function testZoomField() {
diff --git a/chrome/test/data/webui/i18n_process_test.html b/chrome/test/data/webui/i18n_process_test.html index c503cc1..9700268 100644 --- a/chrome/test/data/webui/i18n_process_test.html +++ b/chrome/test/data/webui/i18n_process_test.html
@@ -67,24 +67,6 @@ assertTrue(document.body.hasAttribute('type')); } -function testI18nProcess_ShadowRoot() { - var a = document.createElement('a'); - var outerShadow = a.createShadowRoot(); - - var b = document.createElement('b'); - outerShadow.appendChild(b); - - var innerShadow = b.createShadowRoot(); - var i = document.createElement('i'); - i.setAttribute('i18n-content', 'content'); - innerShadow.appendChild(i); - - i18nTemplate.process(i, loadTimeData); - - assertTrue(i.hasAttribute('i18n-processed')); - assertNotEqual('', i.textContent); -} - function testI18nProcess_Templates() { var outerDocFrag = document.querySelector('template').content; var innerDocFrag = outerDocFrag.querySelector('template').content;
diff --git a/chrome/test/data/webui/webui_resource_browsertest.cc b/chrome/test/data/webui/webui_resource_browsertest.cc index 73c6bd5a..99a8547a3 100644 --- a/chrome/test/data/webui/webui_resource_browsertest.cc +++ b/chrome/test/data/webui/webui_resource_browsertest.cc
@@ -108,8 +108,6 @@ // See crbug.com/911943 for detail. command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, "HTMLImports"); - command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, - "ShadowDOMV0"); } };
diff --git a/chromecast/browser/cast_web_contents.h b/chromecast/browser/cast_web_contents.h index 5724ada9..b921830d 100644 --- a/chromecast/browser/cast_web_contents.h +++ b/chromecast/browser/cast_web_contents.h
@@ -27,14 +27,15 @@ class AssociatedInterfaceProvider; } // namespace blink -namespace on_load_script_injector { -class OnLoadScriptInjectorHost; -} // namespace on_load_script_injector - namespace content { class WebContents; } // namespace content +namespace on_load_script_injector { +template <typename> +class OnLoadScriptInjectorHost; +} // namespace on_load_script_injector + namespace chromecast { class QueryableDataHost; @@ -338,7 +339,7 @@ // Returns the script injector instance, which injects scripts at page load // time. - virtual on_load_script_injector::OnLoadScriptInjectorHost* + virtual on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>* script_injector() = 0; // Injects on-load scripts into the WebContents' main frame.
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc index 312fa12..00fd4cd 100644 --- a/chromecast/browser/cast_web_contents_impl.cc +++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -327,7 +327,7 @@ } } -on_load_script_injector::OnLoadScriptInjectorHost* +on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>* CastWebContentsImpl::script_injector() { return &script_injector_; }
diff --git a/chromecast/browser/cast_web_contents_impl.h b/chromecast/browser/cast_web_contents_impl.h index d383ff1..696f53c3 100644 --- a/chromecast/browser/cast_web_contents_impl.h +++ b/chromecast/browser/cast_web_contents_impl.h
@@ -70,7 +70,8 @@ void BlockMediaLoading(bool blocked) override; void BlockMediaStarting(bool blocked) override; void EnableBackgroundVideoPlayback(bool enabled) override; - on_load_script_injector::OnLoadScriptInjectorHost* script_injector() override; + on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>* + script_injector() override; void InjectScriptsIntoMainFrame() override; void PostMessageToMainFrame( const std::string& target_origin, @@ -175,7 +176,8 @@ bool notifying_; int last_error_; - on_load_script_injector::OnLoadScriptInjectorHost script_injector_; + on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece> + script_injector_; base::ObserverList<Observer>::Unchecked observer_list_;
diff --git a/chromecast/browser/test/mock_cast_web_view.h b/chromecast/browser/test/mock_cast_web_view.h index 3466cbf..c3df3b2 100644 --- a/chromecast/browser/test/mock_cast_web_view.h +++ b/chromecast/browser/test/mock_cast_web_view.h
@@ -37,10 +37,11 @@ MOCK_METHOD(void, BlockMediaLoading, (bool), (override)); MOCK_METHOD(void, BlockMediaStarting, (bool), (override)); MOCK_METHOD(void, EnableBackgroundVideoPlayback, (bool), (override)); - MOCK_METHOD(on_load_script_injector::OnLoadScriptInjectorHost*, - script_injector, - (), - (override)); + MOCK_METHOD( + on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*, + script_injector, + (), + (override)); MOCK_METHOD(void, InjectScriptsIntoMainFrame, (), (override)); MOCK_METHOD(void, PostMessageToMainFrame,
diff --git a/chromecast/browser/webview/client/webview.cc b/chromecast/browser/webview/client/webview.cc index 30eb16f..4f36171 100644 --- a/chromecast/browser/webview/client/webview.cc +++ b/chromecast/browser/webview/client/webview.cc
@@ -16,7 +16,7 @@ #include "base/time/time.h" #include "chromecast/browser/webview/proto/webview.pb.h" #include "third_party/grpc/src/include/grpcpp/grpcpp.h" -#include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" #include "ui/gl/gl_bindings.h" namespace chromecast {
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java index 4202d9f..0d55897 100644 --- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java +++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java
@@ -94,6 +94,9 @@ // Returns the current volume in dB for the given stream type and volume index. private static float getStreamVolumeDB(int streamType, int idx) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return getAudioManager().getStreamVolumeDb(streamType, idx, DEVICE_TYPE); + } float db = 0; if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1 || Build.VERSION.SDK_INT == Build.VERSION_CODES.N) { @@ -106,10 +109,6 @@ } catch (Exception e) { Log.e(TAG, "Can not call AudioManager.getStreamVolumeDb():", e); } - // TODO(ckuiper): when Android P becomes available add something like this to call the - // AudioManager.getStreamVolumeDb() directly as it is public in P. - // } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - // db = sAudioManager.getStreamVolumeDb(); } else { Log.e(TAG, "Unsupported Android SDK version:" + Build.VERSION.SDK_INT); }
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc index 04dc882..6409cb6 100644 --- a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc +++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
@@ -596,8 +596,7 @@ queued_frames_ += frames; queue_.push_back(std::move(data)); - if (!started_ && queued_frames_ >= start_threshold_frames_ && - mixer_rendering_delay_.timestamp_microseconds != INT64_MIN) { + if (!started_ && queued_frames_ >= start_threshold_frames_) { io_task_runner_->PostTask(FROM_HERE, ready_for_playback_task_); } }
diff --git a/chromeos/printing/ppd_metadata_manager.cc b/chromeos/printing/ppd_metadata_manager.cc index 3335c8a4..b2a655f 100644 --- a/chromeos/printing/ppd_metadata_manager.cc +++ b/chromeos/printing/ppd_metadata_manager.cc
@@ -351,7 +351,7 @@ const std::string metadata_name = PpdMetadataPathInServingRoot(options); if (MapHasValueFresherThan(cached_manufacturers_, metadata_name, - clock_->Now() + age)) { + clock_->Now() - age)) { OnManufacturersAvailable(metadata_name, std::move(cb)); return; } @@ -376,7 +376,7 @@ } if (MapHasValueFresherThan(cached_printers_, metadata_name.value(), - clock_->Now() + age)) { + clock_->Now() - age)) { OnPrintersAvailable(metadata_name.value(), std::move(cb)); return; } @@ -400,7 +400,7 @@ PpdMetadataPathInServingRoot(reverse_index_options); if (MapHasValueFresherThan(cached_reverse_indices_, metadata_name, - clock_->Now() + age)) { + clock_->Now() - age)) { OnReverseIndexAvailable(metadata_name, effective_make_and_model, std::move(cb)); return;
diff --git a/chromeos/printing/ppd_metadata_manager_unittest.cc b/chromeos/printing/ppd_metadata_manager_unittest.cc index d327d37d..c6a4ca3 100644 --- a/chromeos/printing/ppd_metadata_manager_unittest.cc +++ b/chromeos/printing/ppd_metadata_manager_unittest.cc
@@ -400,6 +400,101 @@ PpdProvider::CallbackResultCode::INTERNAL_ERROR); } +// Verifies that the manager fetches manufacturers metadata anew when +// caller asks it for metadata fresher than what it has cached. +TEST_F(PpdMetadataManagerTest, CanGetManufacturersTimeSensitive) { + // Bypasses mandatory call to PpdMetadataManager::GetLocale(). + manager_->SetLocaleForTesting("en"); + + // Known interaction: the manager will fetch manufacturers metadata + // localized in English ("en"). + GetFakeCache()->SetFetchResponseForTesting( + "metadata_v3/manufacturers-en.json", + R"({ "filesMap": { + "It": "Never_Ends-en.json", + "You Are": "Always-en.json", + "Playing": "Yellow_Car-en.json" + } })"); + + base::RunLoop loop; + auto callback = base::BindOnce(&PpdMetadataManagerTest::CatchGetManufacturers, + base::Unretained(this), loop.QuitClosure()); + + // t = 0s: caller requests a list of manufacturers from |manager_|, + // using metadata parsed within the last thirty seconds. |manager_| + // performs a live fetch for the manufacturers metadata. + manager_->GetManufacturers(base::TimeDelta::FromSeconds(30), + std::move(callback)); + loop.Run(); + + ASSERT_EQ(results_.get_manufacturers_code, + PpdProvider::CallbackResultCode::SUCCESS); + + // PpdProvider::ResolveManufacturersCallback specifies that the list + // shall be sorted. + EXPECT_THAT(results_.manufacturers, + ElementsAre(StrEq("It"), StrEq("Playing"), StrEq("You Are"))); + + // Mutates the test data, ensuring that if the metadata manager + // attempts a live fetch from the PrinterConfigCache, it will get + // different data in response. + GetFakeCache()->SetFetchResponseForTesting( + "metadata_v3/manufacturers-en.json", + R"({ "filesMap": { + "It": "Never_Ends-en.json", + "You Are": "Always-en.json" + } })"); + + // Jams the result code to something bad to require that the + // |manager_| positively answer us. + results_.get_manufacturers_code = + PpdProvider::CallbackResultCode::INTERNAL_ERROR; + + base::RunLoop second_loop; + auto second_callback = + base::BindOnce(&PpdMetadataManagerTest::CatchGetManufacturers, + base::Unretained(this), second_loop.QuitClosure()); + + // t = 0s: caller requests a list of manufacturers from |manager_|. + // |manager_| responds using the cached metadata without performing + // a live fetch. + manager_->GetManufacturers(base::TimeDelta::FromSeconds(30), + std::move(second_callback)); + second_loop.Run(); + + // We assert that the results are unchanged from before. + ASSERT_EQ(results_.get_manufacturers_code, + PpdProvider::CallbackResultCode::SUCCESS); + EXPECT_THAT(results_.manufacturers, + ElementsAre(StrEq("It"), StrEq("Playing"), StrEq("You Are"))); + + // t = 31s + clock_.Advance(base::TimeDelta::FromSeconds(31)); + + // Jams the result code to something bad to require that the + // |manager_| positively answer us. + results_.get_manufacturers_code = + PpdProvider::CallbackResultCode::INTERNAL_ERROR; + + base::RunLoop third_loop; + auto third_callback = + base::BindOnce(&PpdMetadataManagerTest::CatchGetManufacturers, + base::Unretained(this), third_loop.QuitClosure()); + + // t = 31s: caller requests a list of manufacturers from |manager_|. + // |manager_| does not have sufficiently fresh metadata, so it + // performs a live fetch. + manager_->GetManufacturers(base::TimeDelta::FromSeconds(30), + std::move(third_callback)); + third_loop.Run(); + + // We assert that the results have changed. + ASSERT_EQ(results_.get_manufacturers_code, + PpdProvider::CallbackResultCode::SUCCESS); + EXPECT_THAT(results_.manufacturers, + ElementsAre(StrEq("It"), StrEq("You Are"))); +} + // Verifies that the manager can fetch, parse, and return a map of // printers metadata from the Chrome OS Printing serving root. TEST_F(PpdMetadataManagerTest, CanGetPrinters) { @@ -524,6 +619,114 @@ EXPECT_FALSE(results_.get_printers_succeeded); } +// Verifies that the manager fetches printers metadata anew when caller +// asks it for metadata fresher than what it has cached. +TEST_F(PpdMetadataManagerTest, CanGetPrintersTimeSensitive) { + // Bypasses mandatory call to PpdMetadataManager::GetLocale(). + manager_->SetLocaleForTesting("en"); + + // Bypasses prerequisite call to PpdMetadataManager::GetManufacturers(). + ASSERT_TRUE(manager_->SetManufacturersForTesting(R"( + { + "filesMap": { + "Manufacturer A": "Manufacturer_A-en.json", + "Manufacturer B": "Manufacturer_B-en.json" + } + } + )")); + + // Known interaction: the manager will fetch printers metadata named + // by the manufacturers map above. + GetFakeCache()->SetFetchResponseForTesting( + "metadata_v3/Manufacturer_A-en.json", R"( + { + "printers": [ { + "emm": "some emm a", + "name": "Some Printer A" + }, { + "emm": "some emm b", + "name": "Some Printer B" + } ] + } + )"); + + // t = 0s: caller requests the printers for "Manufacturer A." + // |manager_| parses and caches the metadata successfully. + base::RunLoop loop; + auto callback = base::BindOnce(&PpdMetadataManagerTest::CatchGetPrinters, + base::Unretained(this), loop.QuitClosure()); + manager_->GetPrinters("Manufacturer A", base::TimeDelta::FromSeconds(30), + std::move(callback)); + loop.Run(); + + ASSERT_TRUE(results_.get_printers_succeeded); + EXPECT_THAT( + results_.printers, + UnorderedElementsAre(ParsedPrinterLike("Some Printer A", "some emm a"), + ParsedPrinterLike("Some Printer B", "some emm b"))); + + // We change the data served by the PrinterConfigCache. + GetFakeCache()->SetFetchResponseForTesting( + "metadata_v3/Manufacturer_A-en.json", R"( + { + "printers": [ { + "emm": "some emm c", + "name": "Some Printer C" + }, { + "emm": "some emm d", + "name": "Some Printer D" + } ] + } + )"); + + // Jams the results to some bad value, requiring that the manager + // answer us positively. + results_.get_printers_succeeded = false; + + base::RunLoop second_loop; + auto second_callback = + base::BindOnce(&PpdMetadataManagerTest::CatchGetPrinters, + base::Unretained(this), second_loop.QuitClosure()); + + // t = 0s: caller requests the printers for "Manufacturer A." + // |manager_| re-uses the cached metadata. + manager_->GetPrinters("Manufacturer A", base::TimeDelta::FromSeconds(30), + std::move(second_callback)); + second_loop.Run(); + + // We assert that the results are unchanged from before. + ASSERT_TRUE(results_.get_printers_succeeded); + EXPECT_THAT( + results_.printers, + UnorderedElementsAre(ParsedPrinterLike("Some Printer A", "some emm a"), + ParsedPrinterLike("Some Printer B", "some emm b"))); + + // t = 31s + clock_.Advance(base::TimeDelta::FromSeconds(31)); + + // Jams the results to some bad value, requiring that the manager + // answer us positively. + results_.get_printers_succeeded = false; + + // t = 31s: caller requests the printers for "Manufacturer A." + // |manager_| does not have sufficiently fresh metadata, so it + // performs a live fetch. + base::RunLoop third_loop; + auto third_callback = + base::BindOnce(&PpdMetadataManagerTest::CatchGetPrinters, + base::Unretained(this), third_loop.QuitClosure()); + manager_->GetPrinters("Manufacturer A", base::TimeDelta::FromSeconds(30), + std::move(third_callback)); + third_loop.Run(); + + // We assert that the results have changed. + ASSERT_TRUE(results_.get_printers_succeeded); + EXPECT_THAT( + results_.printers, + UnorderedElementsAre(ParsedPrinterLike("Some Printer C", "some emm c"), + ParsedPrinterLike("Some Printer D", "some emm d"))); +} + // Verifies that the manager can split an effective-make-and-model // string into its constituent parts (make and model). TEST_F(PpdMetadataManagerTest, CanSplitMakeAndModel) { @@ -618,5 +821,108 @@ PpdProvider::CallbackResultCode::INTERNAL_ERROR); } +// Verifies that the manager fetches reverse index metadata anew when +// caller asks it for metadata fresher than what it has cached. +TEST_F(PpdMetadataManagerTest, CanSplitMakeAndModelTimeSensitive) { + // Bypasses mandatory call to PpdMetadataManager::GetLocale(). + manager_->SetLocaleForTesting("en"); + + // Known interaction: asking the manager to split the string + // "Hello there!" will cause it to fetch the reverse index metadata + // with shard number 2. + GetFakeCache()->SetFetchResponseForTesting( + "metadata_v3/reverse_index-en-02.json", R"( + { + "reverseIndex": { + "Hello there!": { + "manufacturer": "General", + "model": "Kenobi" + } + } + } + )"); + + base::RunLoop loop; + auto callback = + base::BindOnce(&PpdMetadataManagerTest::CatchSplitMakeAndModel, + base::Unretained(this), loop.QuitClosure()); + + // t = 0s: caller requests that |manager_| split the + // effective-make-and-model string "Hello there!" using metadata + // parsed within the last thirty seconds. |manager_| fetches the + // appropriate reverse index metadata. + manager_->SplitMakeAndModel("Hello there!", base::TimeDelta::FromSeconds(30), + std::move(callback)); + loop.Run(); + + ASSERT_EQ(results_.split_make_and_model_code, + PpdProvider::CallbackResultCode::SUCCESS); + EXPECT_THAT(results_.split_make, StrEq("General")); + EXPECT_THAT(results_.split_model, StrEq("Kenobi")); + + // Mutates the reverse index metadata we serve. + GetFakeCache()->SetFetchResponseForTesting( + "metadata_v3/reverse_index-en-02.json", R"( + { + "reverseIndex": { + "Hello there!": { + "manufacturer": "You are", + "model": "a bold one!" + } + } + } + )"); + + // Jams the result to a bad value, requiring that the |manager_| + // answer us positively. + results_.split_make_and_model_code = + PpdProvider::CallbackResultCode::INTERNAL_ERROR; + + base::RunLoop second_loop; + auto second_callback = + base::BindOnce(&PpdMetadataManagerTest::CatchSplitMakeAndModel, + base::Unretained(this), second_loop.QuitClosure()); + + // t = 0s: caller requests that |manager_| split the + // effective-make-and-model string "Hello there!" + // |manager_| re-uses the cached reverse index metadata. + manager_->SplitMakeAndModel("Hello there!", base::TimeDelta::FromSeconds(30), + std::move(second_callback)); + second_loop.Run(); + + // We assert that the results are currently unchanged. + ASSERT_EQ(results_.split_make_and_model_code, + PpdProvider::CallbackResultCode::SUCCESS); + EXPECT_THAT(results_.split_make, StrEq("General")); + EXPECT_THAT(results_.split_model, StrEq("Kenobi")); + + // t = 31s + clock_.Advance(base::TimeDelta::FromSeconds(31)); + + // Jams the result to a bad value, requiring that the |manager_| + // answer us positively. + results_.split_make_and_model_code = + PpdProvider::CallbackResultCode::INTERNAL_ERROR; + + base::RunLoop third_loop; + auto third_callback = + base::BindOnce(&PpdMetadataManagerTest::CatchSplitMakeAndModel, + base::Unretained(this), third_loop.QuitClosure()); + + // t = 31s: caller requests that |manager_| split the + // effective-make-and-model string "Hello there!" + // |manager_| doesn't have sufficiently fresh metadata, so it performs + // a live fetch. + manager_->SplitMakeAndModel("Hello there!", base::TimeDelta::FromSeconds(30), + std::move(third_callback)); + third_loop.Run(); + + // We assert that the live fetch changed the results. + ASSERT_EQ(results_.split_make_and_model_code, + PpdProvider::CallbackResultCode::SUCCESS); + EXPECT_THAT(results_.split_make, StrEq("You are")); + EXPECT_THAT(results_.split_model, StrEq("a bold one!")); +} + } // namespace } // namespace chromeos
diff --git a/components/browser_ui/widget/android/java/res/layout/expand_arrow_with_separator.xml b/components/browser_ui/widget/android/java/res/layout/expand_arrow_with_separator.xml index 79b1f50..8f85522 100644 --- a/components/browser_ui/widget/android/java/res/layout/expand_arrow_with_separator.xml +++ b/components/browser_ui/widget/android/java/res/layout/expand_arrow_with_separator.xml
@@ -17,10 +17,7 @@ android:id="@+id/separator" android:layout_width="1dp" android:layout_height="match_parent" - android:layout_marginStart="@dimen/radio_button_with_description_and_aux_button_spacing" style="@style/VerticalDivider" /> -<!-- TODO(crbug.com/1097310): Follow up with UX to see if the aux button should be highlighted when - the rest of the view is touched. --> <org.chromium.ui.widget.ChromeImageButton android:id="@+id/expand_arrow" android:layout_height="match_parent"
diff --git a/components/browser_ui/widget/android/java/res/layout/radio_button_with_description.xml b/components/browser_ui/widget/android/java/res/layout/radio_button_with_description.xml index 58d679e1..97f6c58 100644 --- a/components/browser_ui/widget/android/java/res/layout/radio_button_with_description.xml +++ b/components/browser_ui/widget/android/java/res/layout/radio_button_with_description.xml
@@ -6,35 +6,41 @@ <!-- RadioButtonWithDescription extends RelativeLayout --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> - - <RadioButton - android:id="@+id/radio_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_centerVertical="true" - android:layout_marginEnd="16dp" - android:clickable="false" - android:focusable="false" - android:background="@null" /> - - <TextView - android:id="@+id/primary" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toEndOf="@id/radio_button" + <RelativeLayout + android:id="@+id/radio_container" android:layout_toStartOf="@id/end_view" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> - - <!-- This TextView is hidden if it has no text, so the initial visibility should be "gone". --> - <TextView - android:id="@+id/description" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignStart="@id/primary" - android:layout_toStartOf="@id/end_view" - android:layout_below="@id/primary" - android:textAppearance="@style/TextAppearance.TextMedium.Secondary" - android:visibility="gone" /> + android:layout_alignParentStart="true" + android:gravity="center_vertical" + android:orientation="horizontal"> + <RadioButton + android:id="@+id/radio_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_marginEnd="16dp" + android:clickable="false" + android:focusable="false" + android:background="@null" /> + + <TextView + android:id="@+id/primary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toEndOf="@id/radio_button" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> + + <!-- This TextView is hidden if it has no text, so the initial visibility should be "gone". --> + <TextView + android:id="@+id/description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignStart="@id/primary" + android:layout_below="@id/primary" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + android:visibility="gone" /> + </RelativeLayout> <!-- A ViewStub placed at the end of the widget that can be replaced by a customized view --> <ViewStub @@ -42,8 +48,8 @@ android:inflatedId="@+id/end_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignTop="@id/primary" - android:layout_alignBottom="@id/description" + android:layout_alignTop="@id/radio_container" + android:layout_alignBottom="@id/radio_container" android:layout_alignParentEnd="true" android:background="@null" /> </merge>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DualControlLayoutTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DualControlLayoutTest.java index 3fb1559..ac7cf29 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DualControlLayoutTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DualControlLayoutTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.LayoutInflater; import android.view.View; import android.view.View.MeasureSpec; @@ -20,11 +18,11 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.components.browser_ui.widget.DualControlLayout.DualControlLayoutAlignment; import org.chromium.components.browser_ui.widget.test.R; @@ -46,9 +44,6 @@ private int mTinyControlWidth; private Context mContext; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Before public void setUp() { mContext = InstrumentationRegistry.getTargetContext();
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonLayoutTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonLayoutTest.java index f80e87b5..6876188 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonLayoutTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonLayoutTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; import android.widget.RadioButton; @@ -16,11 +14,11 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import java.util.ArrayList; import java.util.Arrays; @@ -31,9 +29,6 @@ */ @RunWith(BaseJUnit4ClassRunner.class) public class RadioButtonLayoutTest { - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - private Context mContext; @Before
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescription.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescription.java index 57d867cd..2b4e8ee 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescription.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescription.java
@@ -102,7 +102,19 @@ TypedValue background = new TypedValue(); getContext().getTheme().resolveAttribute( android.R.attr.selectableItemBackground, background, true); - setBackgroundResource(background.resourceId); + if (getEndStubLayoutResourceId() != NO_LAYOUT_ID) { + // If the end view stub is replaced with a custom view, only set background in the + // button container, so the end view is not highlighted when the button is clicked. + View radioContainer = findViewById(R.id.radio_container); + radioContainer.setBackgroundResource(background.resourceId); + // Move the start padding into radio container, so it can be highlighted. + int paddingStart = getPaddingStart(); + radioContainer.setPaddingRelative(paddingStart, radioContainer.getPaddingTop(), + radioContainer.getPaddingEnd(), radioContainer.getPaddingBottom()); + setPaddingRelative(0, getPaddingTop(), getPaddingEnd(), getPaddingBottom()); + } else { + setBackgroundResource(background.resourceId); + } } // We want RadioButtonWithDescription to handle the clicks itself.
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButton.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButton.java index fc2a15a..172221fe5 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButton.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButton.java
@@ -6,6 +6,7 @@ import android.content.Context; import android.util.AttributeSet; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ImageButton; @@ -79,6 +80,16 @@ // Clear any end padding set by default in the parent class, since end padding // is built into the aux button instead. setPaddingRelative(getPaddingStart(), getPaddingTop(), 0, getPaddingBottom()); + + View radioContainer = findViewById(R.id.radio_container); + // Space between the radio container and the separator. The padding is added in the radio + // container instead of the separator, because the padding needs to be highlighted when the + // radio container is clicked. + final int radioContainerEndPadding = getResources().getDimensionPixelSize( + R.dimen.radio_button_with_description_and_aux_button_spacing); + radioContainer.setPaddingRelative(radioContainer.getPaddingStart(), + radioContainer.getPaddingTop(), radioContainerEndPadding, + radioContainer.getPaddingBottom()); } @Override
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButtonTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButtonTest.java index fa437f28..090e8fb4 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButtonTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButtonTest.java
@@ -105,4 +105,24 @@ Assert.assertTrue("Aux Button should be set to enabled.", mRadioButton.getAuxButtonForTests().isEnabled()); } + + @Test + @SmallTest + public void testPaddingAndBackgroundValue() { + View radioContainer = mRadioButton.findViewById(R.id.radio_container); + int lateralPadding = mRadioButton.getResources().getDimensionPixelSize( + R.dimen.radio_button_with_description_lateral_padding); + int auxButtonSpacing = mRadioButton.getResources().getDimensionPixelSize( + R.dimen.radio_button_with_description_and_aux_button_spacing); + Assert.assertEquals("Lateral padding should be set in the radio container.", lateralPadding, + radioContainer.getPaddingStart()); + Assert.assertEquals("Aux button spacing should be set in the radio container.", + auxButtonSpacing, radioContainer.getPaddingEnd()); + Assert.assertEquals("Lateral padding should be set to 0 in the radio button root layout.", + 0, mRadioButton.getPaddingStart()); + Assert.assertNotNull( + "Background should be set in the radio container.", radioContainer.getBackground()); + Assert.assertNull("Background should be null in the radio button root layout", + mRadioButton.getBackground()); + } }
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionLayoutTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionLayoutTest.java index b805db15..dbce9c1d 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionLayoutTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionLayoutTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -19,11 +17,11 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.components.browser_ui.widget.test.R; import java.util.Arrays; @@ -50,9 +48,6 @@ private static final String HINT_MATCH_FROM_XML_ASSERT_MESSAGE = "Hint message set through layout should match the view's hint message."; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - private Context mContext; @Before
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/highlight/ViewHighlighterTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/highlight/ViewHighlighterTest.java index 1413dcc..00db370a 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/highlight/ViewHighlighterTest.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/highlight/ViewHighlighterTest.java
@@ -8,7 +8,6 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.support.test.InstrumentationRegistry; -import android.support.test.rule.UiThreadTestRule; import android.view.View; import android.widget.ImageView; @@ -16,7 +15,6 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,9 +25,6 @@ */ @RunWith(BaseJUnit4ClassRunner.class) public class ViewHighlighterTest { - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - private Context mContext; @Before
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index 2f01102..74d1dab 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -606,6 +606,16 @@ ContentSettingsInfo::INHERIT_IN_INCOGNITO, ContentSettingsInfo::PERSISTENT, ContentSettingsInfo::EXCEPTIONS_ON_SECURE_AND_INSECURE_ORIGINS); + + Register(ContentSettingsType::FONT_ACCESS, "font-access", CONTENT_SETTING_ASK, + WebsiteSettingsInfo::SYNCABLE, WhitelistedSchemes(), + ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, + CONTENT_SETTING_BLOCK), + WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, + WebsiteSettingsRegistry::DESKTOP, + ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE, + ContentSettingsInfo::PERSISTENT, + ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY); } void ContentSettingsRegistry::Register(
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc index 827a8c4..fed84cf 100644 --- a/components/content_settings/core/common/content_settings.cc +++ b/components/content_settings/core/common/content_settings.cc
@@ -91,6 +91,7 @@ {ContentSettingsType::CAMERA_PAN_TILT_ZOOM, 68}, {ContentSettingsType::WINDOW_PLACEMENT, 69}, {ContentSettingsType::INSECURE_PRIVATE_NETWORK, 70}, + {ContentSettingsType::FONT_ACCESS, 71}, }; } // namespace
diff --git a/components/content_settings/core/common/content_settings_types.h b/components/content_settings/core/common/content_settings_types.h index 59650dd9..f89c07d0a 100644 --- a/components/content_settings/core/common/content_settings_types.h +++ b/components/content_settings/core/common/content_settings_types.h
@@ -221,6 +221,10 @@ // Set through enterprise policies only. INSECURE_PRIVATE_NETWORK, + // Content setting which stores whether or not a site can access low-level + // locally installed font data using the Font Access API. + FONT_ACCESS, + NUM_TYPES, };
diff --git a/components/feed/core/common/pref_names.cc b/components/feed/core/common/pref_names.cc index 40c6e8e..c98e194d2 100644 --- a/components/feed/core/common/pref_names.cc +++ b/components/feed/core/common/pref_names.cc
@@ -41,6 +41,7 @@ const char kRequestSchedule[] = "feedv2.request_schedule"; const char kMetricsData[] = "feedv2.metrics_data"; const char kClientInstanceId[] = "feedv2.client_instance_id"; +const char kActionsEndpointOverride[] = "feedv2.actions_endpoint_override"; } // namespace prefs @@ -59,6 +60,7 @@ registry->RegisterDictionaryPref(feed::prefs::kRequestSchedule); registry->RegisterDictionaryPref(feed::prefs::kMetricsData); registry->RegisterStringPref(feed::prefs::kClientInstanceId, ""); + registry->RegisterStringPref(feed::prefs::kActionsEndpointOverride, ""); UserClassifier::RegisterProfilePrefs(registry); }
diff --git a/components/feed/core/common/pref_names.h b/components/feed/core/common/pref_names.h index 74ca44a..2ff1020 100644 --- a/components/feed/core/common/pref_names.h +++ b/components/feed/core/common/pref_names.h
@@ -56,6 +56,8 @@ extern const char kMetricsData[]; // The pref name for storing client instance id. extern const char kClientInstanceId[]; +// The pref name for the Actions endpoint override. +extern const char kActionsEndpointOverride[]; } // namespace prefs
diff --git a/components/feed/core/v2/feed_network_impl.cc b/components/feed/core/v2/feed_network_impl.cc index 9ed2346a..295f6047 100644 --- a/components/feed/core/v2/feed_network_impl.cc +++ b/components/feed/core/v2/feed_network_impl.cc
@@ -151,7 +151,7 @@ network::SharedURLLoaderFactory* loader_factory, const std::string& api_key, const base::TickClock* tick_clock, - PrefService* pref_service) + bool allow_bless_auth) : url_(url), request_type_(request_type), request_body_(std::move(request_body)), @@ -161,22 +161,7 @@ api_key_(api_key), tick_clock_(tick_clock), entire_send_start_ticks_(tick_clock_->NowTicks()), - pref_service_(pref_service) { - // Apply the host override (from snippets-internals). - std::string host_override = - pref_service_->GetString(feed::prefs::kHostOverrideHost); - if (!host_override.empty()) { - GURL override_host_url(host_override); - if (override_host_url.is_valid()) { - GURL::Replacements replacements; - replacements.SetSchemeStr(override_host_url.scheme_piece()); - replacements.SetHostStr(override_host_url.host_piece()); - replacements.SetPortStr(override_host_url.port_piece()); - url_ = url_.ReplaceComponents(replacements); - host_overridden_ = true; - } - } - } + allow_bless_auth_(allow_bless_auth) {} ~NetworkFetch() = default; NetworkFetch(const NetworkFetch&) = delete; NetworkFetch& operator=(const NetworkFetch&) = delete; @@ -270,7 +255,7 @@ // Include credentials ONLY if the user has overridden the feed host through // the internals page. This allows for some authentication workflows we need // for testing. - if (host_overridden_) { + if (allow_bless_auth_) { resource_request->credentials_mode = network::mojom::CredentialsMode::kInclude; resource_request->site_for_cookies = net::SiteForCookies::FromUrl(url); @@ -323,7 +308,7 @@ // If overriding the feed host, try to grab the Bless nonce. This is // strictly informational, and only displayed in snippets-internals. - if (host_overridden_ && simple_loader_->ResponseInfo()) { + if (allow_bless_auth_ && simple_loader_->ResponseInfo()) { size_t iter = 0; std::string value; while (simple_loader_->ResponseInfo()->headers->EnumerateHeader( @@ -398,8 +383,7 @@ // Should be set right before the article fetch, and after the token fetch if // there is one. base::TimeTicks loader_only_start_ticks_; - PrefService* pref_service_; - bool host_overridden_ = false; + bool allow_bless_auth_ = false; }; FeedNetworkImpl::FeedNetworkImpl( @@ -428,15 +412,30 @@ base::Base64UrlEncode( binary_proto, base::Base64UrlEncodePolicy::INCLUDE_PADDING, &base64proto); - // TODO(harringtond): Decide how we want to override these URLs for testing. - // Should probably add a command-line flag. GURL url = GetFeedQueryURL(request.feed_request().feed_query().reason()); if (url.is_empty()) return std::move(callback).Run({}); + // Override url if requested from internals page. + bool host_overridden = false; + std::string host_override = + pref_service_->GetString(feed::prefs::kHostOverrideHost); + if (!host_override.empty()) { + GURL override_host_url(host_override); + if (override_host_url.is_valid()) { + GURL::Replacements replacements; + replacements.SetSchemeStr(override_host_url.scheme_piece()); + replacements.SetHostStr(override_host_url.host_piece()); + replacements.SetPortStr(override_host_url.port_piece()); + url = url.ReplaceComponents(replacements); + host_overridden = true; + } + } + AddMothershipPayloadQueryParams(base64proto, delegate_->GetLanguageTag(), url); Send(url, "GET", /*request_body=*/{}, force_signed_out_request, + /*allow_bless_auth=*/host_overridden, base::BindOnce(&ParseAndForwardResponse<QueryRequestResult, NetworkRequestType::kFeedQuery>, std::move(callback))); @@ -448,8 +447,20 @@ std::string binary_proto; request.SerializeToString(&binary_proto); - Send(GURL(kUploadActionUrl), "POST", std::move(binary_proto), + GURL url(kUploadActionUrl); + + // Override url if requested. + std::string host_override = + pref_service_->GetString(feed::prefs::kActionsEndpointOverride); + if (!host_override.empty()) { + GURL override_url(host_override); + if (override_url.is_valid()) + url = override_url; + } + + Send(url, "POST", std::move(binary_proto), /*force_signed_out_request=*/false, + /*allow_bless_auth=*/false, base::BindOnce( &ParseAndForwardResponse<ActionRequestResult, NetworkRequestType::kUploadActions>, @@ -464,11 +475,12 @@ const std::string& request_type, std::string request_body, bool force_signed_out_request, + bool allow_bless_auth, base::OnceCallback<void(RawResponse)> callback) { auto fetch = std::make_unique<NetworkFetch>( url, request_type, std::move(request_body), force_signed_out_request, identity_manager_, loader_factory_.get(), api_key_, tick_clock_, - pref_service_); + allow_bless_auth); NetworkFetch* fetch_unowned = fetch.get(); pending_requests_.emplace(std::move(fetch));
diff --git a/components/feed/core/v2/feed_network_impl.h b/components/feed/core/v2/feed_network_impl.h index c8d487d..2ed4c907 100644 --- a/components/feed/core/v2/feed_network_impl.h +++ b/components/feed/core/v2/feed_network_impl.h
@@ -73,6 +73,7 @@ const std::string& request_type, std::string request_body, bool force_signed_out_request, + bool host_overridden, base::OnceCallback<void(FeedNetworkImpl::RawResponse)> callback); void SendComplete(NetworkFetch* fetch,
diff --git a/components/feed/core/v2/feed_network_impl_unittest.cc b/components/feed/core/v2/feed_network_impl_unittest.cc index 69d4cce..2df977d 100644 --- a/components/feed/core/v2/feed_network_impl_unittest.cc +++ b/components/feed/core/v2/feed_network_impl_unittest.cc
@@ -143,6 +143,15 @@ return result; } + GURL GetPendingRequestURL() { + task_environment_.RunUntilIdle(); + network::TestURLLoaderFactory::PendingRequest* pending_request = + test_factory()->GetPendingRequest(0); + if (!pending_request) + return GURL(); + return pending_request->request.url; + } + network::ResourceRequest RespondToQueryRequest( const std::string& response_string, net::HttpStatusCode code) { @@ -407,6 +416,8 @@ feed_network()->SendQueryRequest(GetTestFeedRequest(), false, receiver.Bind()); + ASSERT_EQ("www.newhost.com", GetPendingRequestURL().host()); + response_headers_ = base::MakeRefCounted<net::HttpResponseHeaders>( net::HttpUtil::AssembleRawHeaders( "HTTP/1.1 401 Unauthorized\nwww-authenticate: Foo " @@ -463,5 +474,22 @@ EXPECT_EQ(expected_body, sent_body_uncompressed); } +TEST_F(FeedNetworkTest, TestOverrideHostDoesNotAffectActionUpload) { + profile_prefs().SetString(feed::prefs::kHostOverrideHost, + "http://www.newhost.com/"); + feed_network()->SendActionRequest(GetTestActionRequest(), base::DoNothing()); + + EXPECT_EQ(GURL("https://discover-pa.googleapis.com/v1/actions:upload"), + GetPendingRequestURL()); +} + +TEST_F(FeedNetworkTest, TestOverrideActionsEndpoint) { + profile_prefs().SetString(feed::prefs::kActionsEndpointOverride, + "http://www.newhost.com/"); + feed_network()->SendActionRequest(GetTestActionRequest(), base::DoNothing()); + + EXPECT_EQ(GURL("http://www.newhost.com/"), GetPendingRequestURL()); +} + } // namespace } // namespace feed
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc index 68e604b..e40c1ef3 100644 --- a/components/feed/core/v2/feed_stream.cc +++ b/components/feed/core/v2/feed_stream.cc
@@ -42,6 +42,14 @@ namespace feed { namespace { +void UpdateDebugStreamData( + const UploadActionsTask::Result& upload_actions_result, + DebugStreamData& debug_data) { + if (upload_actions_result.last_network_response_info) { + debug_data.upload_info = upload_actions_result.last_network_response_info; + } +} + void PopulateDebugStreamData(const LoadStreamTask::Result& load_result, PrefService& profile_prefs) { DebugStreamData debug_data = ::feed::prefs::GetDebugStreamData(profile_prefs); @@ -49,6 +57,17 @@ ss << "Code: " << load_result.final_status; debug_data.load_stream_status = ss.str(); debug_data.fetch_info = load_result.network_response_info; + if (load_result.upload_actions_result) { + UpdateDebugStreamData(*load_result.upload_actions_result, debug_data); + } + ::feed::prefs::SetDebugStreamData(debug_data, profile_prefs); +} + +void PopulateDebugStreamData( + const UploadActionsTask::Result& upload_actions_result, + PrefService& profile_prefs) { + DebugStreamData debug_data = ::feed::prefs::GetDebugStreamData(profile_prefs); + UpdateDebugStreamData(upload_actions_result, debug_data); ::feed::prefs::SetDebugStreamData(debug_data, profile_prefs); } @@ -339,14 +358,22 @@ if (msg.has_action_payload()) { feedwire::FeedAction action_msg; *action_msg.mutable_action_payload() = std::move(msg.action_payload()); - UploadAction(std::move(action_msg), /*upload_now=*/true, base::DoNothing()); + UploadAction(std::move(action_msg), /*upload_now=*/true, + base::BindOnce(&FeedStream::UploadActionsComplete, + base::Unretained(this))); } } void FeedStream::ProcessViewAction(base::StringPiece data) { feedwire::FeedAction msg; msg.ParseFromArray(data.data(), data.size()); - UploadAction(std::move(msg), /*upload_now=*/false, base::DoNothing()); + UploadAction(std::move(msg), /*upload_now=*/false, + base::BindOnce(&FeedStream::UploadActionsComplete, + base::Unretained(this))); +} + +void FeedStream::UploadActionsComplete(UploadActionsTask::Result result) { + PopulateDebugStreamData(result, *profile_prefs_); } void FeedStream::GetPrefetchSuggestions( @@ -593,6 +620,9 @@ if (index >= 0) metrics_reporter_->OpenAction(index); } +void FeedStream::ReportOpenVisitComplete(base::TimeDelta visit_time) { + metrics_reporter_->OpenVisitComplete(visit_time); +} void FeedStream::ReportOpenInNewTabAction(const std::string& slice_id) { int index = surface_updater_->GetSliceIndexFromSliceId(slice_id); if (index >= 0)
diff --git a/components/feed/core/v2/feed_stream.h b/components/feed/core/v2/feed_stream.h index 19c8f3b..cc9389e 100644 --- a/components/feed/core/v2/feed_stream.h +++ b/components/feed/core/v2/feed_stream.h
@@ -145,6 +145,7 @@ void ReportNavigationStarted() override; void ReportPageLoaded() override; void ReportOpenAction(const std::string& slice_id) override; + void ReportOpenVisitComplete(base::TimeDelta visit_time) override; void ReportOpenInNewTabAction(const std::string& slice_id) override; void ReportOpenInNewIncognitoTabAction() override; void ReportSendFeedbackAction() override; @@ -272,6 +273,7 @@ void InitialStreamLoadComplete(LoadStreamTask::Result result); void LoadMoreComplete(LoadMoreTask::Result result); void BackgroundRefreshComplete(LoadStreamTask::Result result); + void UploadActionsComplete(UploadActionsTask::Result result); void ClearAll();
diff --git a/components/feed/core/v2/metrics_reporter.cc b/components/feed/core/v2/metrics_reporter.cc index 8cea43f..62c3c0af 100644 --- a/components/feed/core/v2/metrics_reporter.cc +++ b/components/feed/core/v2/metrics_reporter.cc
@@ -193,6 +193,11 @@ RecordInteraction(); } +void MetricsReporter::OpenVisitComplete(base::TimeDelta visit_time) { + base::UmaHistogramLongTimes("ContentSuggestions.Feed.VisitDuration", + visit_time); +} + void MetricsReporter::OpenInNewTabAction(int index_in_stream) { CardOpenBegin(); ReportUserActionHistogram(FeedUserActionType::kTappedOpenInNewTab);
diff --git a/components/feed/core/v2/metrics_reporter.h b/components/feed/core/v2/metrics_reporter.h index 27d31a4..3c0b72c 100644 --- a/components/feed/core/v2/metrics_reporter.h +++ b/components/feed/core/v2/metrics_reporter.h
@@ -68,6 +68,7 @@ virtual void ContentSliceViewed(SurfaceId surface_id, int index_in_stream); void OpenAction(int index_in_stream); + void OpenVisitComplete(base::TimeDelta visit_time); void OpenInNewTabAction(int index_in_stream); void OpenInNewIncognitoTabAction(); void SendFeedbackAction();
diff --git a/components/feed/core/v2/public/feed_stream_api.h b/components/feed/core/v2/public/feed_stream_api.h index d6e6a656..2e2fa79 100644 --- a/components/feed/core/v2/public/feed_stream_api.h +++ b/components/feed/core/v2/public/feed_stream_api.h
@@ -11,6 +11,7 @@ #include "base/callback_forward.h" #include "base/observer_list_types.h" #include "base/strings/string_piece_forward.h" +#include "base/time/time.h" #include "components/feed/core/v2/public/types.h" namespace feedui { @@ -109,6 +110,10 @@ virtual void ReportPageLoaded() = 0; // The user triggered the default open action, usually by tapping the card. virtual void ReportOpenAction(const std::string& slice_id) = 0; + // The user triggered an open action, visited a web page, and then navigated + // away or backgrouded the tab. |visit_time| is a measure of how long the + // visited page was foregrounded. + virtual void ReportOpenVisitComplete(base::TimeDelta visit_time) = 0; // The user triggered the 'open in new tab' action. virtual void ReportOpenInNewTabAction(const std::string& slice_id) = 0; // The user triggered the 'open in new incognito tab' action.
diff --git a/components/feed/core/v2/public/types.h b/components/feed/core/v2/public/types.h index cffefa3..3427c0e5 100644 --- a/components/feed/core/v2/public/types.h +++ b/components/feed/core/v2/public/types.h
@@ -59,6 +59,7 @@ DebugStreamData& operator=(const DebugStreamData&); base::Optional<NetworkResponseInfo> fetch_info; + base::Optional<NetworkResponseInfo> upload_info; std::string load_stream_status; };
diff --git a/components/feed/core/v2/tasks/load_stream_task.cc b/components/feed/core/v2/tasks/load_stream_task.cc index df119df..370cd99 100644 --- a/components/feed/core/v2/tasks/load_stream_task.cc +++ b/components/feed/core/v2/tasks/load_stream_task.cc
@@ -115,6 +115,8 @@ } void LoadStreamTask::UploadActionsComplete(UploadActionsTask::Result result) { + upload_actions_result_ = + std::make_unique<UploadActionsTask::Result>(std::move(result)); latencies_->StepComplete(LoadLatencyTimes::kUploadActions); stream_->GetNetwork()->SendQueryRequest( CreateFeedQueryRefreshRequest( @@ -176,6 +178,7 @@ result.network_response_info = network_response_info_; result.loaded_new_content_from_network = loaded_new_content_from_network_; result.latencies = std::move(latencies_); + result.upload_actions_result = std::move(upload_actions_result_); std::move(done_callback_).Run(std::move(result)); TaskComplete(); }
diff --git a/components/feed/core/v2/tasks/load_stream_task.h b/components/feed/core/v2/tasks/load_stream_task.h index 67aef56..dd4c210 100644 --- a/components/feed/core/v2/tasks/load_stream_task.h +++ b/components/feed/core/v2/tasks/load_stream_task.h
@@ -49,10 +49,14 @@ // was attempted. LoadStreamStatus load_from_store_status = LoadStreamStatus::kNoStatus; LoadType load_type; + // Information about the network request, if one was made. base::Optional<NetworkResponseInfo> network_response_info; bool loaded_new_content_from_network = false; std::unique_ptr<LoadLatencyTimes> latencies; + + // Result of the upload actions task. + std::unique_ptr<UploadActionsTask::Result> upload_actions_result; }; LoadStreamTask(LoadType load_type, @@ -87,6 +91,7 @@ base::TimeTicks fetch_start_time_; base::OnceCallback<void(Result)> done_callback_; std::unique_ptr<UploadActionsTask> upload_actions_task_; + std::unique_ptr<UploadActionsTask::Result> upload_actions_result_; base::WeakPtrFactory<LoadStreamTask> weak_ptr_factory_{this}; }; } // namespace feed
diff --git a/components/feed/core/v2/tasks/upload_actions_task.cc b/components/feed/core/v2/tasks/upload_actions_task.cc index 3fce7f1..4663b578 100644 --- a/components/feed/core/v2/tasks/upload_actions_task.cc +++ b/components/feed/core/v2/tasks/upload_actions_task.cc
@@ -40,6 +40,12 @@ } // namespace +UploadActionsTask::Result::Result() = default; +UploadActionsTask::Result::~Result() = default; +UploadActionsTask::Result::Result(UploadActionsTask::Result&&) = default; +UploadActionsTask::Result& UploadActionsTask::Result::operator=(Result&&) = + default; + class UploadActionsTask::Batch { public: Batch() @@ -242,6 +248,8 @@ void UploadActionsTask::OnUploadFinished( std::unique_ptr<UploadActionsTask::Batch> batch, FeedNetwork::ActionRequestResult result) { + last_network_response_info_ = result.response_info; + if (!result.response_body) return BatchComplete(UploadActionsBatchStatus::kFailedToUpload); @@ -284,7 +292,14 @@ void UploadActionsTask::Done(UploadActionsStatus status) { MetricsReporter::OnUploadActions(status); - std::move(callback_).Run({status, upload_attempt_count_, stale_count_}); + Result result; + result.status = status; + result.upload_attempt_count = upload_attempt_count_; + result.stale_count = stale_count_; + result.last_network_response_info = std::move(last_network_response_info_); + LOG(ERROR) << "Upload actions done with netresponse? " + << (result.last_network_response_info ? 1 : 0); + std::move(callback_).Run(std::move(result)); TaskComplete(); }
diff --git a/components/feed/core/v2/tasks/upload_actions_task.h b/components/feed/core/v2/tasks/upload_actions_task.h index 00d37ae..aec1888 100644 --- a/components/feed/core/v2/tasks/upload_actions_task.h +++ b/components/feed/core/v2/tasks/upload_actions_task.h
@@ -39,14 +39,19 @@ class UploadActionsTask : public offline_pages::Task { public: struct Result { + Result(); + ~Result(); + Result(Result&&); + Result& operator=(Result&&); UploadActionsStatus status; - // For testing. Reports the number of actions for which upload was // attempted. size_t upload_attempt_count; // For testing. Reports the number of actions which were erased because of // staleness. size_t stale_count; + // Information about the last network request, if one was attempted. + base::Optional<NetworkResponseInfo> last_network_response_info; }; // Store an action. Use |upload_now|=true to kick off an upload of all pending @@ -109,6 +114,7 @@ size_t upload_attempt_count_ = 0; // Number of stale actions. size_t stale_count_ = 0; + base::Optional<NetworkResponseInfo> last_network_response_info_; base::WeakPtrFactory<UploadActionsTask> weak_ptr_factory_{this}; };
diff --git a/components/feed/core/v2/types.cc b/components/feed/core/v2/types.cc index 797f0fb8..0ca15e3 100644 --- a/components/feed/core/v2/types.cc +++ b/components/feed/core/v2/types.cc
@@ -20,50 +20,78 @@ namespace feed { namespace { -void PickleDebugStreamData(const DebugStreamData& data, base::Pickle* pickle) { - pickle->WriteInt(DebugStreamData::kVersion); - pickle->WriteBool(data.fetch_info.has_value()); - if (data.fetch_info) { - pickle->WriteInt(data.fetch_info->status_code); - pickle->WriteUInt64(data.fetch_info->fetch_duration.InMilliseconds()); - pickle->WriteUInt64((data.fetch_info->fetch_time - base::Time::UnixEpoch()) - .InMilliseconds()); - pickle->WriteString(data.fetch_info->bless_nonce); - pickle->WriteString(data.fetch_info->base_request_url.spec()); - } - pickle->WriteString(data.load_stream_status); +void PickleNetworkResponseInfo(const NetworkResponseInfo& value, + base::Pickle& pickle) { + pickle.WriteInt(value.status_code); + pickle.WriteUInt64(value.fetch_duration.InMilliseconds()); + pickle.WriteUInt64( + (value.fetch_time - base::Time::UnixEpoch()).InMilliseconds()); + pickle.WriteString(value.bless_nonce); + pickle.WriteString(value.base_request_url.spec()); } -base::Optional<DebugStreamData> UnpickleDebugStreamData( - base::PickleIterator iterator) { - DebugStreamData result; - int version; - if (!iterator.ReadInt(&version) || version != DebugStreamData::kVersion) - return base::nullopt; - bool has_fetch_info; - if (!iterator.ReadBool(&has_fetch_info)) - return base::nullopt; - if (has_fetch_info) { - NetworkResponseInfo fetch_info; - uint64_t fetch_duration_ms; - uint64_t fetch_time_ms; - std::string base_request_url; - if (!(iterator.ReadInt(&fetch_info.status_code) && - iterator.ReadUInt64(&fetch_duration_ms) && - iterator.ReadUInt64(&fetch_time_ms) && - iterator.ReadString(&fetch_info.bless_nonce) && - iterator.ReadString(&base_request_url))) - return base::nullopt; - fetch_info.fetch_duration = - base::TimeDelta::FromMilliseconds(fetch_duration_ms); - fetch_info.fetch_time = base::TimeDelta::FromMilliseconds(fetch_time_ms) + - base::Time::UnixEpoch(); - fetch_info.base_request_url = GURL(base_request_url); - result.fetch_info = std::move(fetch_info); +bool UnpickleNetworkResponseInfo(base::PickleIterator& iterator, + NetworkResponseInfo& value) { + uint64_t fetch_duration_ms; + uint64_t fetch_time_ms; + std::string base_request_url; + if (!(iterator.ReadInt(&value.status_code) && + iterator.ReadUInt64(&fetch_duration_ms) && + iterator.ReadUInt64(&fetch_time_ms) && + iterator.ReadString(&value.bless_nonce) && + iterator.ReadString(&base_request_url))) + return false; + value.fetch_duration = base::TimeDelta::FromMilliseconds(fetch_duration_ms); + value.fetch_time = base::TimeDelta::FromMilliseconds(fetch_time_ms) + + base::Time::UnixEpoch(); + value.base_request_url = GURL(base_request_url); + return true; +} + +void PickleOptionalNetworkResponseInfo( + const base::Optional<NetworkResponseInfo>& value, + base::Pickle& pickle) { + if (value.has_value()) { + pickle.WriteBool(true); + PickleNetworkResponseInfo(*value, pickle); + } else { + pickle.WriteBool(false); } - if (!iterator.ReadString(&result.load_stream_status)) - return base::nullopt; - return result; +} + +bool UnpickleOptionalNetworkResponseInfo( + base::PickleIterator& iterator, + base::Optional<NetworkResponseInfo>& value) { + bool has_network_response_info = false; + if (!iterator.ReadBool(&has_network_response_info)) + return false; + + if (has_network_response_info) { + NetworkResponseInfo reponse_info; + if (!UnpickleNetworkResponseInfo(iterator, reponse_info)) + return false; + value = std::move(reponse_info); + } else { + value.reset(); + } + return true; +} + +void PickleDebugStreamData(const DebugStreamData& value, base::Pickle& pickle) { + (void)PickleOptionalNetworkResponseInfo; + pickle.WriteInt(DebugStreamData::kVersion); + PickleOptionalNetworkResponseInfo(value.fetch_info, pickle); + PickleOptionalNetworkResponseInfo(value.upload_info, pickle); + pickle.WriteString(value.load_stream_status); +} + +bool UnpickleDebugStreamData(base::PickleIterator iterator, + DebugStreamData& value) { + int version; + return iterator.ReadInt(&version) && version == DebugStreamData::kVersion && + UnpickleOptionalNetworkResponseInfo(iterator, value.fetch_info) && + UnpickleOptionalNetworkResponseInfo(iterator, value.upload_info) && + iterator.ReadString(&value.load_stream_status); } } // namespace @@ -92,7 +120,7 @@ std::string SerializeDebugStreamData(const DebugStreamData& data) { base::Pickle pickle; - PickleDebugStreamData(data, &pickle); + PickleDebugStreamData(data, pickle); const uint8_t* pickle_data_ptr = static_cast<const uint8_t*>(pickle.data()); return base::Base64Encode( base::span<const uint8_t>(pickle_data_ptr, pickle.size())); @@ -104,7 +132,10 @@ if (!base::Base64Decode(base64_encoded, &binary_data)) return base::nullopt; base::Pickle pickle(binary_data.data(), binary_data.size()); - return UnpickleDebugStreamData(base::PickleIterator(pickle)); + DebugStreamData result; + if (!UnpickleDebugStreamData(base::PickleIterator(pickle), result)) + return base::nullopt; + return result; } DebugStreamData::DebugStreamData() = default;
diff --git a/components/feed/core/v2/types_unittest.cc b/components/feed/core/v2/types_unittest.cc index 95938d4f..f165aad9 100644 --- a/components/feed/core/v2/types_unittest.cc +++ b/components/feed/core/v2/types_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "components/feed/core/v2/types.h" - #include "base/json/json_writer.h" #include "base/strings/string_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,8 +28,16 @@ fetch_info.bless_nonce = "nonce"; fetch_info.base_request_url = GURL("https://www.google.com"); + NetworkResponseInfo upload_info; + upload_info.status_code = 200; + upload_info.fetch_duration = base::TimeDelta::FromSeconds(2); + upload_info.fetch_time = + base::Time::UnixEpoch() + base::TimeDelta::FromMinutes(201); + upload_info.base_request_url = GURL("https://www.upload.com"); + DebugStreamData data; data.fetch_info = fetch_info; + data.upload_info = upload_info; data.load_stream_status = "loaded OK"; return data; } @@ -53,6 +60,18 @@ EXPECT_EQ(test_data.fetch_info->bless_nonce, result->fetch_info->bless_nonce); EXPECT_EQ(test_data.fetch_info->base_request_url, result->fetch_info->base_request_url); + + ASSERT_TRUE(result->upload_info); + EXPECT_EQ(test_data.upload_info->status_code, + result->upload_info->status_code); + EXPECT_EQ(test_data.upload_info->fetch_duration, + result->upload_info->fetch_duration); + EXPECT_EQ(test_data.upload_info->fetch_time, result->upload_info->fetch_time); + EXPECT_EQ(test_data.upload_info->bless_nonce, + result->upload_info->bless_nonce); + EXPECT_EQ(test_data.upload_info->base_request_url, + result->upload_info->base_request_url); + EXPECT_EQ(test_data.load_stream_status, result->load_stream_status); } @@ -68,6 +87,18 @@ EXPECT_EQ(SerializeDebugStreamData(*result), serialized); } +TEST(DebugStreamData, CanSerializeWithoutUploadInfo) { + DebugStreamData input = MakeDebugStreamData(); + input.upload_info = base::nullopt; + + const auto serialized = SerializeDebugStreamData(input); + base::Optional<DebugStreamData> result = + DeserializeDebugStreamData(serialized); + ASSERT_TRUE(result); + + EXPECT_EQ(SerializeDebugStreamData(*result), serialized); +} + TEST(DebugStreamData, FailsDeserializationGracefully) { ASSERT_EQ(base::nullopt, DeserializeDebugStreamData({})); }
diff --git a/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayoutTest.java b/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayoutTest.java index e5925857..6b84021a 100644 --- a/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayoutTest.java +++ b/components/infobars/android/java/src/org/chromium/components/infobars/InfoBarControlLayoutTest.java
@@ -6,8 +6,6 @@ import android.content.Context; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup.LayoutParams; @@ -16,11 +14,11 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.components.infobars.InfoBarControlLayout.ControlLayoutParams; /** @@ -38,9 +36,6 @@ private Context mContext; - @Rule - public UiThreadTestRule mRule = new UiThreadTestRule(); - @Before public void setUp() { mContext = InstrumentationRegistry.getTargetContext();
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index be78719..44b101ad 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -233,8 +233,9 @@ TemplateURLRef::SearchTermsArgs search_terms_args; search_terms_args.page_classification = current_page_classification_; - search_terms_args.omnibox_focus_type = - TemplateURLRef::SearchTermsArgs::OmniboxFocusType::ON_FOCUS; + // TODO(tommycli): Once AutocompleteInput supports tracking OmniboxFocusType, + // copy the value from there. + search_terms_args.focus_type = OmniboxFocusType::ON_FOCUS; GURL suggest_url = RemoteSuggestionsService::EndpointUrl( search_terms_args, client()->GetTemplateURLService()); if (!suggest_url.is_valid())
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc index cb466ae..fed7e12 100644 --- a/components/omnibox/browser/zero_suggest_provider_unittest.cc +++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -166,8 +166,7 @@ metrics::OmniboxEventProto::PageClassification page_classification) { TemplateURLRef::SearchTermsArgs search_terms_args; search_terms_args.page_classification = page_classification; - search_terms_args.omnibox_focus_type = - TemplateURLRef::SearchTermsArgs::OmniboxFocusType::ON_FOCUS; + search_terms_args.focus_type = OmniboxFocusType::ON_FOCUS; return RemoteSuggestionsService::EndpointUrl( search_terms_args, client_->GetTemplateURLService()); }
diff --git a/components/on_load_script_injector/BUILD.gn b/components/on_load_script_injector/BUILD.gn index 3b73edb..d9a71fb 100644 --- a/components/on_load_script_injector/BUILD.gn +++ b/components/on_load_script_injector/BUILD.gn
@@ -9,6 +9,10 @@ public_deps = [ "//mojo/public/mojom/base" ] visibility = [ "./*" ] + + export_define = "ON_LOAD_SCRIPT_INJECTOR_IMPLEMENTATION=1" + export_class_attribute = "ON_LOAD_SCRIPT_INJECTOR_EXPORT" + export_header = "components/on_load_script_injector/export.h" } source_set("export") {
diff --git a/components/on_load_script_injector/browser/on_load_script_injector_host.cc b/components/on_load_script_injector/browser/on_load_script_injector_host.cc index 7a6e56cc..a9c4564f 100644 --- a/components/on_load_script_injector/browser/on_load_script_injector_host.cc +++ b/components/on_load_script_injector/browser/on_load_script_injector_host.cc
@@ -6,121 +6,20 @@ #include <utility> -#include "base/numerics/safe_math.h" -#include "components/on_load_script_injector/on_load_script_injector.mojom.h" -#include "content/public/browser/navigation_handle.h" -#include "mojo/public/cpp/bindings/associated_remote.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" - namespace on_load_script_injector { -OnLoadScriptInjectorHost::OnLoadScriptInjectorHost() = default; +OriginScopedScript::OriginScopedScript() = default; -OnLoadScriptInjectorHost::~OnLoadScriptInjectorHost() = default; - -void OnLoadScriptInjectorHost::AddScript( - ScriptId id, - std::vector<url::Origin> origins_to_inject, - base::StringPiece script) { - // If there is no script with the identifier |id|, then create a place for it - // at the end of the injection sequence. - if (before_load_scripts_.find(id) == before_load_scripts_.end()) - before_load_scripts_order_.push_back(id); - - // Convert script to UTF-16. - base::string16 script_utf16 = base::UTF8ToUTF16(script); - size_t script_utf16_size = - (base::CheckedNumeric<size_t>(script_utf16.size()) * sizeof(base::char16)) - .ValueOrDie(); - base::WritableSharedMemoryRegion script_shared_memory = - base::WritableSharedMemoryRegion::Create(script_utf16_size); - memcpy(script_shared_memory.Map().memory(), script_utf16.data(), - script_utf16_size); - - base::ReadOnlySharedMemoryRegion script_shared_memory_readonly = - base::WritableSharedMemoryRegion::ConvertToReadOnly( - std::move(script_shared_memory)); - CHECK(script_shared_memory_readonly.IsValid()); - - before_load_scripts_[id] = OriginScopedScript( - origins_to_inject, std::move(script_shared_memory_readonly)); -} - -void OnLoadScriptInjectorHost::AddScriptForAllOrigins( - ScriptId id, - base::StringPiece script) { - AddScript(id, {kMatchAllOrigins}, script); -} - -void OnLoadScriptInjectorHost::RemoveScript(ScriptId id) { - before_load_scripts_.erase(id); - - for (auto script_id_iter = before_load_scripts_order_.begin(); - script_id_iter != before_load_scripts_order_.end(); ++script_id_iter) { - if (*script_id_iter == id) { - before_load_scripts_order_.erase(script_id_iter); - return; - } - } - - LOG(WARNING) << "Ignoring attempt to remove unknown OnLoad script: " << id; -} - -void OnLoadScriptInjectorHost::InjectScriptsForURL( - const GURL& url, - content::RenderFrameHost* render_frame_host) { - DCHECK(url.is_valid()); - - mojo::AssociatedRemote<mojom::OnLoadScriptInjector> injector; - render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&injector); - - injector->ClearOnLoadScripts(); - - if (before_load_scripts_.empty()) - return; - - // Provision the renderer's ScriptInjector with the scripts associated with - // |url|. - for (ScriptId script_id : before_load_scripts_order_) { - const OriginScopedScript& script = before_load_scripts_[script_id]; - if (IsUrlMatchedByOriginList(url, script.origins())) - injector->AddOnLoadScript(script.script().Duplicate()); - } -} - -// static -bool OnLoadScriptInjectorHost::IsUrlMatchedByOriginList( - const GURL& url, - const std::vector<url::Origin>& allowed_origins) { - url::Origin url_origin = url::Origin::Create(url); - - for (const url::Origin& allowed_origin : allowed_origins) { - if (allowed_origin == kMatchAllOrigins) - return true; - - DCHECK(!allowed_origin.opaque()); - if (url_origin.IsSameOriginWith(allowed_origin)) - return true; - } - - return false; -} - -OnLoadScriptInjectorHost::OriginScopedScript::OriginScopedScript() = default; - -OnLoadScriptInjectorHost::OriginScopedScript::OriginScopedScript( - std::vector<url::Origin> origins, - base::ReadOnlySharedMemoryRegion script) +OriginScopedScript::OriginScopedScript(std::vector<url::Origin> origins, + base::ReadOnlySharedMemoryRegion script) : origins_(std::move(origins)), script_(std::move(script)) {} -OnLoadScriptInjectorHost::OriginScopedScript& -OnLoadScriptInjectorHost::OriginScopedScript::operator=( - OnLoadScriptInjectorHost::OriginScopedScript&& other) { +OriginScopedScript& OriginScopedScript::operator=(OriginScopedScript&& other) { origins_ = std::move(other.origins_); script_ = std::move(other.script_); return *this; } -OnLoadScriptInjectorHost::OriginScopedScript::~OriginScopedScript() = default; +OriginScopedScript::~OriginScopedScript() = default; } // namespace on_load_script_injector
diff --git a/components/on_load_script_injector/browser/on_load_script_injector_host.h b/components/on_load_script_injector/browser/on_load_script_injector_host.h index f94d675..0c7f552c 100644 --- a/components/on_load_script_injector/browser/on_load_script_injector_host.h +++ b/components/on_load_script_injector/browser/on_load_script_injector_host.h
@@ -10,26 +10,44 @@ #include <vector> #include "base/memory/read_only_shared_memory_region.h" +#include "base/numerics/safe_math.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "components/on_load_script_injector/export.h" +#include "components/on_load_script_injector/on_load_script_injector.mojom.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "url/origin.h" namespace on_load_script_injector { +class ON_LOAD_SCRIPT_INJECTOR_EXPORT OriginScopedScript { + public: + OriginScopedScript(); + OriginScopedScript(std::vector<url::Origin> origins, + base::ReadOnlySharedMemoryRegion script); + OriginScopedScript& operator=(OriginScopedScript&& other); + ~OriginScopedScript(); + + const std::vector<url::Origin>& origins() const { return origins_; } + const base::ReadOnlySharedMemoryRegion& script() const { return script_; } + + private: + std::vector<url::Origin> origins_; + + // A shared memory buffer containing the script, encoded as UTF16. + base::ReadOnlySharedMemoryRegion script_; +}; + // Manages the set of scripts to be injected into document just prior to // document load. -class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost { +template <typename ScriptId> +class OnLoadScriptInjectorHost { public: -#if defined(OS_FUCHSIA) - using ScriptId = uint64_t; -#else - using ScriptId = std::string; -#endif - - OnLoadScriptInjectorHost(); - ~OnLoadScriptInjectorHost(); + OnLoadScriptInjectorHost() = default; + ~OnLoadScriptInjectorHost() = default; OnLoadScriptInjectorHost(const OnLoadScriptInjectorHost&) = delete; OnLoadScriptInjectorHost& operator=(const OnLoadScriptInjectorHost&) = delete; @@ -42,41 +60,92 @@ // All entries of |origins_to_inject| must be valid/not opaque. void AddScript(ScriptId id, std::vector<url::Origin> origins_to_inject, - base::StringPiece script); + base::StringPiece script) { + // If there is no script with the identifier |id|, then create a place for + // it at the end of the injection sequence. + if (before_load_scripts_.find(id) == before_load_scripts_.end()) + before_load_scripts_order_.push_back(id); + + // Convert script to UTF-16. + base::string16 script_utf16 = base::UTF8ToUTF16(script); + size_t script_utf16_size = + (base::CheckedNumeric<size_t>(script_utf16.size()) * + sizeof(base::char16)) + .ValueOrDie(); + base::WritableSharedMemoryRegion script_shared_memory = + base::WritableSharedMemoryRegion::Create(script_utf16_size); + memcpy(script_shared_memory.Map().memory(), script_utf16.data(), + script_utf16_size); + + base::ReadOnlySharedMemoryRegion script_shared_memory_readonly = + base::WritableSharedMemoryRegion::ConvertToReadOnly( + std::move(script_shared_memory)); + CHECK(script_shared_memory_readonly.IsValid()); + + before_load_scripts_[id] = OriginScopedScript( + origins_to_inject, std::move(script_shared_memory_readonly)); + } // Same as AddScript(), except that scripts are injected for all pages. - void AddScriptForAllOrigins(ScriptId id, base::StringPiece script); + void AddScriptForAllOrigins(ScriptId id, base::StringPiece script) { + AddScript(id, {kMatchAllOrigins}, script); + } // Removes the script |id|. - void RemoveScript(ScriptId id); + void RemoveScript(ScriptId id) { + before_load_scripts_.erase(id); + + for (auto script_id_iter = before_load_scripts_order_.begin(); + script_id_iter != before_load_scripts_order_.end(); ++script_id_iter) { + if (*script_id_iter == id) { + before_load_scripts_order_.erase(script_id_iter); + return; + } + } + + LOG(WARNING) << "Ignoring attempt to remove unknown OnLoad script: " << id; + } // Injects the scripts associated with the origin of |url| into the document // hosted by |render_frame_host|. void InjectScriptsForURL(const GURL& url, - content::RenderFrameHost* render_frame_host); + content::RenderFrameHost* render_frame_host) { + DCHECK(url.is_valid()); + + mojo::AssociatedRemote<mojom::OnLoadScriptInjector> injector; + render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&injector); + + injector->ClearOnLoadScripts(); + + if (before_load_scripts_.empty()) + return; + + // Provision the renderer's ScriptInjector with the scripts associated with + // |url|. + for (ScriptId script_id : before_load_scripts_order_) { + const OriginScopedScript& script = before_load_scripts_[script_id]; + if (IsUrlMatchedByOriginList(url, script.origins())) + injector->AddOnLoadScript(script.script().Duplicate()); + } + } private: - class OriginScopedScript { - public: - OriginScopedScript(); - OriginScopedScript(std::vector<url::Origin> origins, - base::ReadOnlySharedMemoryRegion script); - OriginScopedScript& operator=(OriginScopedScript&& other); - ~OriginScopedScript(); - - const std::vector<url::Origin>& origins() const { return origins_; } - const base::ReadOnlySharedMemoryRegion& script() const { return script_; } - - private: - std::vector<url::Origin> origins_; - - // A shared memory buffer containing the script, encoded as UTF16. - base::ReadOnlySharedMemoryRegion script_; - }; - bool IsUrlMatchedByOriginList( const GURL& url, - const std::vector<url::Origin>& allowed_origins); + const std::vector<url::Origin>& allowed_origins) { + url::Origin url_origin = url::Origin::Create(url); + + for (const url::Origin& allowed_origin : allowed_origins) { + if (allowed_origin == kMatchAllOrigins) + return true; + + DCHECK(!allowed_origin.opaque()); + if (url_origin.IsSameOriginWith(allowed_origin)) + return true; + } + + return false; + } // An opaque Origin that, when specified, allows script injection on all URLs // regardless of origin.
diff --git a/components/optimization_guide/BUILD.gn b/components/optimization_guide/BUILD.gn index 92df028..3795364 100644 --- a/components/optimization_guide/BUILD.gn +++ b/components/optimization_guide/BUILD.gn
@@ -48,6 +48,8 @@ "optimization_guide_switches.h", "optimization_guide_test_util.cc", "optimization_guide_test_util.h", + "optimization_guide_util.cc", + "optimization_guide_util.h", "optimization_metadata.cc", "optimization_metadata.h", "prediction_model.cc",
diff --git a/components/optimization_guide/hints_fetcher.cc b/components/optimization_guide/hints_fetcher.cc index 493b8f2..fb56663 100644 --- a/components/optimization_guide/hints_fetcher.cc +++ b/components/optimization_guide/hints_fetcher.cc
@@ -14,10 +14,10 @@ #include "components/optimization_guide/hints_processing_util.h" #include "components/optimization_guide/optimization_guide_features.h" #include "components/optimization_guide/optimization_guide_prefs.h" +#include "components/optimization_guide/optimization_guide_util.h" #include "components/optimization_guide/proto/hints.pb.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" -#include "components/variations/active_field_trials.h" #include "components/variations/net/variations_http_headers.h" #include "content/public/browser/network_service_instance.h" #include "net/base/load_flags.h" @@ -91,8 +91,6 @@ url_loader_factory_ = std::move(url_loader_factory); CHECK(optimization_guide_service_url_.SchemeIs(url::kHttpsScheme)); DCHECK(features::IsRemoteFetchingEnabled()); - allowed_field_trial_name_hashes_ = - features::FieldTrialNameHashesAllowedForFetch(); } HintsFetcher::~HintsFetcher() { @@ -205,29 +203,8 @@ get_hints_request.set_context(request_context_); - if (!allowed_field_trial_name_hashes_.empty()) { - std::vector<variations::ActiveGroupId> active_field_trials; - variations::GetFieldTrialActiveGroupIds(/*suffix=*/"", - &active_field_trials); - for (const auto& active_field_trial : active_field_trials) { - if (static_cast<size_t>(get_hints_request.active_field_trials_size()) == - allowed_field_trial_name_hashes_.size()) { - // We've found all the field trials that we are allowed to send to the - // server. - break; - } - - if (allowed_field_trial_name_hashes_.find(active_field_trial.name) == - allowed_field_trial_name_hashes_.end()) { - // Continue if we are not allowed to send the field trial to the server. - continue; - } - - proto::FieldTrial* ft_proto = get_hints_request.add_active_field_trials(); - ft_proto->set_name_hash(active_field_trial.name); - ft_proto->set_group_hash(active_field_trial.group); - } - } + *get_hints_request.mutable_active_field_trials() = + GetActiveFieldTrialsAllowedForFetch(); for (const auto& url : valid_urls) get_hints_request.add_urls()->set_url(url.spec());
diff --git a/components/optimization_guide/hints_fetcher.h b/components/optimization_guide/hints_fetcher.h index 0b546a3..bc56f79 100644 --- a/components/optimization_guide/hints_fetcher.h +++ b/components/optimization_guide/hints_fetcher.h
@@ -163,10 +163,6 @@ // retrieving hints from the remote Optimization Guide Service. base::TimeTicks hints_fetch_start_time_; - // Field trial name hashes that are allowed to be sent up in the request to - // the remote Optimization Guide Service. - base::flat_set<uint32_t> allowed_field_trial_name_hashes_; - SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(HintsFetcher);
diff --git a/chrome/browser/optimization_guide/optimization_guide_util.cc b/components/optimization_guide/optimization_guide_util.cc similarity index 60% rename from chrome/browser/optimization_guide/optimization_guide_util.cc rename to components/optimization_guide/optimization_guide_util.cc index b345149..89e7df65 100644 --- a/chrome/browser/optimization_guide/optimization_guide_util.cc +++ b/components/optimization_guide/optimization_guide_util.cc
@@ -2,12 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/optimization_guide/optimization_guide_util.h" +#include "components/optimization_guide/optimization_guide_util.h" +#include "base/containers/flat_set.h" #include "base/notreached.h" +#include "components/optimization_guide/optimization_guide_features.h" +#include "components/variations/active_field_trials.h" #include "net/base/url_util.h" #include "url/url_canon.h" +namespace optimization_guide { + std::string GetStringNameForOptimizationTarget( optimization_guide::proto::OptimizationTarget optimization_target) { switch (optimization_target) { @@ -57,3 +62,38 @@ return optimization_guide::OptimizationGuideDecision::kFalse; } } + +google::protobuf::RepeatedPtrField<proto::FieldTrial> +GetActiveFieldTrialsAllowedForFetch() { + google::protobuf::RepeatedPtrField<proto::FieldTrial> + filtered_active_field_trials; + + base::flat_set<uint32_t> allowed_field_trials_for_fetch = + features::FieldTrialNameHashesAllowedForFetch(); + if (allowed_field_trials_for_fetch.empty()) + return filtered_active_field_trials; + + std::vector<variations::ActiveGroupId> active_field_trials; + variations::GetFieldTrialActiveGroupIds(/*suffix=*/"", &active_field_trials); + for (const auto& active_field_trial : active_field_trials) { + if (static_cast<size_t>(filtered_active_field_trials.size()) == + allowed_field_trials_for_fetch.size()) { + // We've found all the field trials that we are allowed to send to the + // server. + break; + } + + if (allowed_field_trials_for_fetch.find(active_field_trial.name) == + allowed_field_trials_for_fetch.end()) { + // Continue if we are not allowed to send the field trial to the server. + continue; + } + + proto::FieldTrial* ft_proto = filtered_active_field_trials.Add(); + ft_proto->set_name_hash(active_field_trial.name); + ft_proto->set_group_hash(active_field_trial.group); + } + return filtered_active_field_trials; +} + +} // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/optimization_guide_util.h b/components/optimization_guide/optimization_guide_util.h similarity index 62% rename from chrome/browser/optimization_guide/optimization_guide_util.h rename to components/optimization_guide/optimization_guide_util.h index f6aa6758..378d45f4 100644 --- a/chrome/browser/optimization_guide/optimization_guide_util.h +++ b/components/optimization_guide/optimization_guide_util.h
@@ -2,21 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_UTIL_H_ -#define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_UTIL_H_ +#ifndef COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_UTIL_H_ +#define COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_UTIL_H_ #include <string> #include "components/optimization_guide/optimization_guide_decider.h" #include "components/optimization_guide/optimization_guide_enums.h" +#include "components/optimization_guide/proto/common_types.pb.h" #include "components/optimization_guide/proto/models.pb.h" +namespace optimization_guide { + // Returns the string than can be used to record histograms for the optimization // target. If adding a histogram to use the string or adding an optimization // target, update the OptimizationGuide.OptimizationTargets histogram suffixes // in histograms.xml. std::string GetStringNameForOptimizationTarget( - optimization_guide::proto::OptimizationTarget optimization_target); + proto::OptimizationTarget optimization_target); // Returns false if the host is an IP address, localhosts, or an invalid // host that is not supported by the remote optimization guide. @@ -25,6 +28,13 @@ // Returns the OptimizationGuideDecision from |optimization_type_decision|. optimization_guide::OptimizationGuideDecision GetOptimizationGuideDecisionFromOptimizationTypeDecision( - optimization_guide::OptimizationTypeDecision optimization_type_decision); + OptimizationTypeDecision optimization_type_decision); -#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_UTIL_H_ +// Returns the set of active field trials that are allowed to be sent to the +// remote Optimization Guide Service. +google::protobuf::RepeatedPtrField<proto::FieldTrial> +GetActiveFieldTrialsAllowedForFetch(); + +} // namespace optimization_guide + +#endif // COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_UTIL_H_
diff --git a/components/optimization_guide/proto/common_types.proto b/components/optimization_guide/proto/common_types.proto index d6c8f55..4716d0f5 100644 --- a/components/optimization_guide/proto/common_types.proto +++ b/components/optimization_guide/proto/common_types.proto
@@ -49,3 +49,10 @@ // Requesting items as part of a batch update. CONTEXT_BATCH_UPDATE = 3; } + +message FieldTrial { + // The hash of a field trial. + optional uint32 name_hash = 1; + // The hash of the active group within the field trial. + optional uint32 group_hash = 2; +}
diff --git a/components/optimization_guide/proto/hints.proto b/components/optimization_guide/proto/hints.proto index f7b20fd..6558fd9 100644 --- a/components/optimization_guide/proto/hints.proto +++ b/components/optimization_guide/proto/hints.proto
@@ -39,13 +39,6 @@ optional string url = 1; } -message FieldTrial { - // The hash of a field trial. - optional uint32 name_hash = 1; - // The hash of the active group within the field trial. - optional uint32 group_hash = 2; -} - // Request to return a set of hints that guide what optimizations to perform // on those hosts. message GetHintsRequest {
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto index a2759cd..a518ebf 100644 --- a/components/optimization_guide/proto/models.proto +++ b/components/optimization_guide/proto/models.proto
@@ -159,6 +159,8 @@ // CONTEXT_PAGE_NAVIGATION), then no model updates will be returned for the // requested models. optional RequestContext request_context = 3; + // The field trials that are currently active when this request is made. + repeated FieldTrial active_field_trials = 4; } // Response to the GetModels request.
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc index 6b6769cc..5c0e5bd 100644 --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -116,6 +116,7 @@ ContentSettingsType::HID_GUARD, ContentSettingsType::SERIAL_GUARD, ContentSettingsType::FILE_SYSTEM_WRITE_GUARD, + ContentSettingsType::FONT_ACCESS, #endif ContentSettingsType::BLUETOOTH_GUARD, ContentSettingsType::BLUETOOTH_SCANNING,
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc index 35b8130e..e1f09ff7 100644 --- a/components/page_info/page_info_ui.cc +++ b/components/page_info/page_info_ui.cc
@@ -184,6 +184,7 @@ IDS_PAGE_INFO_TYPE_CAMERA_PAN_TILT_ZOOM}, {ContentSettingsType::WINDOW_PLACEMENT, IDS_PAGE_INFO_TYPE_WINDOW_PLACEMENT}, + {ContentSettingsType::FONT_ACCESS, IDS_PAGE_INFO_TYPE_FONT_ACCESS}, #if !defined(OS_ANDROID) {ContentSettingsType::HID_GUARD, IDS_PAGE_INFO_TYPE_HID}, #endif @@ -632,6 +633,9 @@ case ContentSettingsType::WINDOW_PLACEMENT: icon = &vector_icons::kWindowPlacementIcon; break; + case ContentSettingsType::FONT_ACCESS: + icon = &vector_icons::kFontDownloadIcon; + break; case ContentSettingsType::HID_GUARD: icon = &vector_icons::kVideogameAssetIcon; break;
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp index 881108a..37d215b 100644 --- a/components/page_info_strings.grdp +++ b/components/page_info_strings.grdp
@@ -311,6 +311,9 @@ <message name="IDS_PAGE_INFO_TYPE_WINDOW_PLACEMENT" desc="The label used for the Window Placement permission controls in the Page Info popup."> Window placement </message> + <message name="IDS_PAGE_INFO_TYPE_FONT_ACCESS" desc="The label used for the Font Access permission controls in the Page Info popup."> + Local font access + </message> <message name="IDS_PAGE_INFO_TYPE_HID" desc="The label used for the HID permission controls in the Page Info popup."> HID devices </message>
diff --git a/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_FONT_ACCESS.png.sha1 b/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_FONT_ACCESS.png.sha1 new file mode 100644 index 0000000..f3e1535 --- /dev/null +++ b/components/page_info_strings_grdp/IDS_PAGE_INFO_TYPE_FONT_ACCESS.png.sha1
@@ -0,0 +1 @@ +f65007ebf343f1b2fcc7aee10525b367c1620fcf \ No newline at end of file
diff --git a/components/password_manager/core/browser/bulk_leak_check_service.cc b/components/password_manager/core/browser/bulk_leak_check_service.cc index 4d29976..c731574 100644 --- a/components/password_manager/core/browser/bulk_leak_check_service.cc +++ b/components/password_manager/core/browser/bulk_leak_check_service.cc
@@ -147,6 +147,8 @@ } void BulkLeakCheckService::Shutdown() { + for (Observer& obs : observers_) + obs.OnBulkCheckServiceShutDown(); observers_.Clear(); metrics_reporter_.reset(); bulk_leak_check_.reset();
diff --git a/components/password_manager/core/browser/bulk_leak_check_service_interface.h b/components/password_manager/core/browser/bulk_leak_check_service_interface.h index f471ef9e0..44751e6 100644 --- a/components/password_manager/core/browser/bulk_leak_check_service_interface.h +++ b/components/password_manager/core/browser/bulk_leak_check_service_interface.h
@@ -54,6 +54,9 @@ // Called when |credential| is analyzed. virtual void OnCredentialDone(const LeakCheckCredential& credential, IsLeaked is_leaked) = 0; + + // Called when the service is shut down. + virtual void OnBulkCheckServiceShutDown() {} }; BulkLeakCheckServiceInterface();
diff --git a/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc b/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc index aa406bb33..d18bb14 100644 --- a/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc +++ b/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc
@@ -146,6 +146,8 @@ EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.BulkCheck"), IsEmpty()); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, Running) { @@ -169,6 +171,8 @@ EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.BulkCheck"), IsEmpty()); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, AppendRunning) { @@ -193,6 +197,8 @@ EXPECT_CALL(*weak_leak_check, GetPendingChecksCount) .WillRepeatedly(Return(20)); EXPECT_EQ(20u, service().GetPendingChecksCount()); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, FailedToCreateCheck) { @@ -208,6 +214,8 @@ EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.BulkCheck"), IsEmpty()); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, FailedToCreateCheckWithError) { @@ -232,6 +240,8 @@ expected_counts); histogram_tester().ExpectUniqueSample("PasswordManager.BulkCheck.Error", LeakDetectionError::kNotSignIn, 1); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, CancelNothing) { @@ -245,6 +255,8 @@ EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.BulkCheck"), IsEmpty()); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, CancelSomething) { @@ -268,6 +280,8 @@ EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.BulkCheck"), ::testing::SizeIs(2)); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, NotifyAboutLeak) { @@ -293,6 +307,8 @@ EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.BulkCheck"), IsEmpty()); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, CheckFinished) { @@ -325,6 +341,8 @@ kMockElapsedTime, 1); histogram_tester().ExpectUniqueSample( "PasswordManager.BulkCheck.TimePerCredential", kMockElapsedTime / 2, 1); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, CheckFinishedWithLeakedCredential) { @@ -361,6 +379,8 @@ kMockElapsedTime, 1); histogram_tester().ExpectUniqueSample( "PasswordManager.BulkCheck.TimePerCredential", kMockElapsedTime / 2, 1); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, TwoChecksAfterEachOther) { @@ -417,6 +437,8 @@ histogram_tester().ExpectUniqueSample( "PasswordManager.BulkCheck.Error", LeakDetectionError::kInvalidServerResponse, 1); + + service().RemoveObserver(&observer); } TEST_F(BulkLeakCheckServiceTest, CheckFinishedWithQuotaLimit) { @@ -443,6 +465,8 @@ expected_counts); histogram_tester().ExpectUniqueSample("PasswordManager.BulkCheck.Error", LeakDetectionError::kQuotaLimit, 1); + + service().RemoveObserver(&observer); } } // namespace
diff --git a/components/password_manager/core/browser/password_scripts_fetcher.h b/components/password_manager/core/browser/password_scripts_fetcher.h index fbf2229..80fecf0 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher.h +++ b/components/password_manager/core/browser/password_scripts_fetcher.h
@@ -21,18 +21,27 @@ // Triggers pre-fetching the list of scripts. Should be called from UI // preceding Bulk Check. virtual void PrewarmCache() = 0; - // Reports metrics about the cache readiness. Should be called right before - // the first call of |GetPasswordScriptAvailability| within a given bulk - // check. - virtual void ReportCacheReadinessMetric() const = 0; + // Triggers fetching if the cache was never set or is stale (but doesn't + // trigger a duplicate request if another request is in-flight). Otherwise, it + // runs the callback immediately (the expected reaction as a call of + // |PrewarmCache| was supposed to fetch the data in advance). In case of + // several calls of the method, the callbacks will be called one after + // another. + virtual void Fetch(base::OnceClosure fetch_finished_callback) = 0; // Returns whether there is a password change script for |origin| via - // |callback|. If the cache was never set or is stale, it triggers a new - // network request (but doesn't trigger a duplicate request if another request - // is in-flight) and enqueues |callback|. Otherwise, it runs the callback - // immediately. In case of an network error, the verdict will default to no - // script being available. - virtual void GetPasswordScriptAvailability(const url::Origin& origin, - ResponseCallback callback) = 0; + // |callback|. If the cache was never set or is stale, it triggers a re-fetch. + // In case of a network error, the verdict will default to no script being + // available. + virtual void FetchScriptAvailability(const url::Origin& origin, + ResponseCallback callback) = 0; + // Immediately returns whether there is a password change script for |origin|. + // The method does NOT trigger any network requests if the cache is not ready + // or stale but reads the current state of the cache. In case of a network + // error while fetching the scripts, the result will always be false. + // TODO(crbug.com/1086114): It is better to deprecate this method and always + // use |FetchScriptAvailability| instead because |IsScriptAvailable| may + // return stale data. + virtual bool IsScriptAvailable(const url::Origin& origin) const = 0; }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_scripts_fetcher_impl.cc b/components/password_manager/core/browser/password_scripts_fetcher_impl.cc index 2334e5e1..fac8f5f8 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher_impl.cc +++ b/components/password_manager/core/browser/password_scripts_fetcher_impl.cc
@@ -36,19 +36,35 @@ StartFetch(); } -void PasswordScriptsFetcherImpl::ReportCacheReadinessMetric() const { +void PasswordScriptsFetcherImpl::Fetch( + base::OnceClosure fetch_finished_callback) { CacheState state = IsCacheStale() ? (url_loader_ ? CacheState::kWaiting : (last_fetch_timestamp_.is_null() ? CacheState::kNeverSet : CacheState::kStale)) : CacheState::kReady; - base::UmaHistogramEnumeration( "PasswordManager.PasswordScriptsFetcher.CacheState", state); + + if (state == CacheState::kReady) + std::move(fetch_finished_callback).Run(); + else + fetch_finished_callbacks_.emplace_back(std::move(fetch_finished_callback)); + + switch (state) { + case CacheState::kReady: + case CacheState::kWaiting: + // No new fetching. + break; + case CacheState::kNeverSet: + case CacheState::kStale: + StartFetch(); + break; + } } -void PasswordScriptsFetcherImpl::GetPasswordScriptAvailability( +void PasswordScriptsFetcherImpl::FetchScriptAvailability( const url::Origin& origin, ResponseCallback callback) { if (IsCacheStale()) { @@ -61,6 +77,12 @@ RunResponseCallback(origin, std::move(callback)); } +bool PasswordScriptsFetcherImpl::IsScriptAvailable( + const url::Origin& origin) const { + return password_change_domains_.find(origin) != + password_change_domains_.end(); +} + void PasswordScriptsFetcherImpl::StartFetch() { static const base::NoDestructor<base::TimeDelta> kFetchTimeout( base::TimeDelta::FromMinutes(kFetchTimeoutInSeconds)); @@ -121,6 +143,8 @@ base::UmaHistogramEnumeration( "PasswordManager.PasswordScriptsFetcher.ParsingResult", parsing_result); + for (auto& callback : std::exchange(fetch_finished_callbacks_, {})) + std::move(callback).Run(); for (auto& callback : std::exchange(pending_callbacks_, {})) RunResponseCallback(std::move(callback.first), std::move(callback.second)); }
diff --git a/components/password_manager/core/browser/password_scripts_fetcher_impl.h b/components/password_manager/core/browser/password_scripts_fetcher_impl.h index f56fc367..159846f 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher_impl.h +++ b/components/password_manager/core/browser/password_scripts_fetcher_impl.h
@@ -64,9 +64,10 @@ // PasswordScriptsFetcher: void PrewarmCache() override; - void ReportCacheReadinessMetric() const override; - void GetPasswordScriptAvailability(const url::Origin& origin, - ResponseCallback callback) override; + void Fetch(base::OnceClosure fetch_finished_callback) override; + void FetchScriptAvailability(const url::Origin& origin, + ResponseCallback callback) override; + bool IsScriptAvailable(const url::Origin& origin) const override; #if defined(UNIT_TEST) void make_cache_stale_for_testing() { @@ -95,6 +96,8 @@ // Timestamp of the last finished request. base::TimeTicks last_fetch_timestamp_; // Stores the callbacks that are waiting for the request to finish. + std::vector<base::OnceClosure> fetch_finished_callbacks_; + // Stores the per-origin callbacks that are waiting for the request to finish. std::vector<std::pair<url::Origin, ResponseCallback>> pending_callbacks_; // URL loader object for the gstatic request. If |url_loader_| is not null, a // request is currently in flight.
diff --git a/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc b/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc index fd62759..9530c96 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc +++ b/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc
@@ -51,7 +51,10 @@ test_shared_loader_factory_); } - void TearDown() override { EXPECT_EQ(0, GetNumberOfPendingRequests()); } + void TearDown() override { + EXPECT_EQ(0, GetNumberOfPendingRequests()); + EXPECT_EQ(0u, pending_fetch_finished_callbacks_); + } void SimulateResponse() { SimulateResponseWithContent(kTestResponseContent); } @@ -67,7 +70,10 @@ } void StartBulkCheck() { - fetcher()->ReportCacheReadinessMetric(); + pending_fetch_finished_callbacks_++; + fetcher()->Fetch( + base::BindOnce(&PasswordScriptsFetcherImplTest::RecordFetchFinished, + base::Unretained(this))); RequestSingleScriptAvailability(GetOriginWithScript1()); RequestSingleScriptAvailability(GetOriginWithScript2()); RequestSingleScriptAvailability(GetOriginWithoutScript()); @@ -85,8 +91,7 @@ private: void RequestSingleScriptAvailability(const url::Origin& origin) { - fetcher_->GetPasswordScriptAvailability(origin, - GenerateResponseCallback(origin)); + fetcher_->FetchScriptAvailability(origin, GenerateResponseCallback(origin)); } void RecordResponse(url::Origin origin, bool has_script) { @@ -99,6 +104,8 @@ } } + void RecordFetchFinished() { pending_fetch_finished_callbacks_--; } + PasswordScriptsFetcher::ResponseCallback GenerateResponseCallback( url::Origin origin) { return base::BindOnce(&PasswordScriptsFetcherImplTest::RecordResponse, @@ -107,6 +114,7 @@ base::test::SingleThreadTaskEnvironment task_environment_; base::flat_map<url::Origin, bool> recorded_responses_; + size_t pending_fetch_finished_callbacks_ = 0; std::unique_ptr<PasswordScriptsFetcherImpl> fetcher_; std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; @@ -246,4 +254,33 @@ net::HttpStatusCode::HTTP_BAD_REQUEST, 1u); } +TEST_F(PasswordScriptsFetcherImplTest, IsScriptAvailable) { + // |IsScriptAvailable| does not trigger any network requests and returns the + // default value (false). + EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithScript1())); + EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithScript2())); + EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithoutScript())); + EXPECT_EQ(0, GetNumberOfPendingRequests()); + + StartBulkCheck(); + EXPECT_EQ(1, GetNumberOfPendingRequests()); + // Bulk check restart doesn't trigger new network request if the cache's state + // is |kWaiting|. + StartBulkCheck(); + EXPECT_EQ(1, GetNumberOfPendingRequests()); + SimulateResponse(); + base::RunLoop().RunUntilIdle(); + // Cache is ready. + EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript1())); + EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript2())); + EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithoutScript())); + + // |IsScriptAvailable| does not trigger refetching and returns stale values. + fetcher()->make_cache_stale_for_testing(); + EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript1())); + EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript2())); + EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithoutScript())); + EXPECT_EQ(0, GetNumberOfPendingRequests()); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/compromised_credentials_manager.cc b/components/password_manager/core/browser/ui/compromised_credentials_manager.cc index b51497ff..506594a6 100644 --- a/components/password_manager/core/browser/ui/compromised_credentials_manager.cc +++ b/components/password_manager/core/browser/ui/compromised_credentials_manager.cc
@@ -15,6 +15,7 @@ #include "components/password_manager/core/browser/compromised_credentials_table.h" #include "components/password_manager/core/browser/ui/credential_utils.h" #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h" +#include "components/password_manager/core/common/password_manager_features.h" namespace password_manager { @@ -70,6 +71,23 @@ SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { CredentialPasswordsMap credentials_to_forms; + bool mark_all_credentials_leaked_for_testing = + base::GetFieldTrialParamByFeatureAsBool( + password_manager::features::kPasswordChangeInSettings, + password_manager::features:: + kPasswordChangeInSettingsWithForcedWarningForEverySite, + false); + if (mark_all_credentials_leaked_for_testing) { + for (const auto& form : saved_passwords) { + CredentialView compromised_credential(form); + auto& credential_to_form = credentials_to_forms[compromised_credential]; + credential_to_form.type = CompromiseTypeFlags::kCredentialLeaked; + credential_to_form.forms.push_back(form); + credential_to_form.latest_time = form.date_created; + } + return credentials_to_forms; + } + // Since a single (signon_realm, username) pair might have multiple // corresponding entries in saved_passwords, we are using a multiset and doing // look-up via equal_range. In most cases the resulting |range| should have a @@ -144,7 +162,7 @@ CredentialView::~CredentialView() = default; CredentialWithPassword::CredentialWithPassword(const CredentialView& credential) - : CredentialView(std::move(credential)) {} + : CredentialView(credential) {} CredentialWithPassword::~CredentialWithPassword() = default; CredentialWithPassword::CredentialWithPassword( const CredentialWithPassword& other) = default;
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn index 055fa84b..6ad5ee7 100644 --- a/components/permissions/BUILD.gn +++ b/components/permissions/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "chooser_context_base.cc", "chooser_context_base.h", + "contexts/font_access_permission_context.cc", + "contexts/font_access_permission_context.h", "contexts/geolocation_permission_context.cc", "contexts/geolocation_permission_context.h", "contexts/webxr_permission_context.cc",
diff --git a/components/permissions/contexts/font_access_permission_context.cc b/components/permissions/contexts/font_access_permission_context.cc new file mode 100644 index 0000000..3b8b0b7 --- /dev/null +++ b/components/permissions/contexts/font_access_permission_context.cc
@@ -0,0 +1,20 @@ +// Copyright 2020 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 "components/permissions/contexts/font_access_permission_context.h" + +#include "components/content_settings/core/common/content_settings_types.h" +#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h" + +FontAccessPermissionContext::FontAccessPermissionContext( + content::BrowserContext* browser_context) + : PermissionContextBase(browser_context, + ContentSettingsType::FONT_ACCESS, + blink::mojom::FeaturePolicyFeature::kNotFound) {} + +FontAccessPermissionContext::~FontAccessPermissionContext() = default; + +bool FontAccessPermissionContext::IsRestrictedToSecureOrigins() const { + return true; +}
diff --git a/components/permissions/contexts/font_access_permission_context.h b/components/permissions/contexts/font_access_permission_context.h new file mode 100644 index 0000000..00ac3033 --- /dev/null +++ b/components/permissions/contexts/font_access_permission_context.h
@@ -0,0 +1,24 @@ +// Copyright 2020 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 COMPONENTS_PERMISSIONS_CONTEXTS_FONT_ACCESS_PERMISSION_CONTEXT_H_ +#define COMPONENTS_PERMISSIONS_CONTEXTS_FONT_ACCESS_PERMISSION_CONTEXT_H_ + +#include "components/permissions/permission_context_base.h" + +class FontAccessPermissionContext : public permissions::PermissionContextBase { + public: + explicit FontAccessPermissionContext( + content::BrowserContext* browser_context); + ~FontAccessPermissionContext() override; + + FontAccessPermissionContext(const FontAccessPermissionContext&) = delete; + FontAccessPermissionContext& operator=(const FontAccessPermissionContext&) = + delete; + + protected: + bool IsRestrictedToSecureOrigins() const override; +}; + +#endif // COMPONENTS_PERMISSIONS_CONTEXTS_FONT_ACCESS_PERMISSION_CONTEXT_H_
diff --git a/components/permissions/permission_manager.cc b/components/permissions/permission_manager.cc index a956644..0ca29923 100644 --- a/components/permissions/permission_manager.cc +++ b/components/permissions/permission_manager.cc
@@ -128,6 +128,8 @@ return ContentSettingsType::CAMERA_PAN_TILT_ZOOM; case PermissionType::WINDOW_PLACEMENT: return ContentSettingsType::WINDOW_PLACEMENT; + case PermissionType::FONT_ACCESS: + return ContentSettingsType::FONT_ACCESS; case PermissionType::NUM: break; }
diff --git a/components/permissions/permission_request.h b/components/permissions/permission_request.h index f05dc7c..9a7ae7d 100644 --- a/components/permissions/permission_request.h +++ b/components/permissions/permission_request.h
@@ -56,6 +56,7 @@ PERMISSION_STORAGE_ACCESS = 23, PERMISSION_CAMERA_PAN_TILT_ZOOM = 24, PERMISSION_WINDOW_PLACEMENT = 25, + PERMISSION_FONT_ACCESS = 26, // NUM must be the last value in the enum. NUM };
diff --git a/components/permissions/permission_request_impl.cc b/components/permissions/permission_request_impl.cc index e354561..e795646 100644 --- a/components/permissions/permission_request_impl.cc +++ b/components/permissions/permission_request_impl.cc
@@ -102,6 +102,8 @@ return vector_icons::kCookieIcon; case ContentSettingsType::WINDOW_PLACEMENT: return vector_icons::kWindowPlacementIcon; + case ContentSettingsType::FONT_ACCESS: + return vector_icons::kFontDownloadIcon; default: NOTREACHED(); return vector_icons::kExtensionIcon; @@ -245,6 +247,9 @@ case ContentSettingsType::WINDOW_PLACEMENT: message_id = IDS_WINDOW_PLACEMENT_PERMISSION_FRAGMENT; break; + case ContentSettingsType::FONT_ACCESS: + message_id = IDS_FONT_ACCESS_PERMISSION_FRAGMENT; + break; default: NOTREACHED(); return base::string16();
diff --git a/components/permissions/permission_uma_util.cc b/components/permissions/permission_uma_util.cc index 039722c..a5475f3 100644 --- a/components/permissions/permission_uma_util.cc +++ b/components/permissions/permission_uma_util.cc
@@ -92,6 +92,8 @@ return "CameraPanTiltZoom"; case PermissionRequestType::PERMISSION_WINDOW_PLACEMENT: return "WindowPlacement"; + case PermissionRequestType::PERMISSION_FONT_ACCESS: + return "FontAccess"; default: NOTREACHED(); return ""; @@ -559,6 +561,10 @@ base::UmaHistogramEnumeration("Permissions.Action.WindowPlacement", action, PermissionAction::NUM); break; + case ContentSettingsType::FONT_ACCESS: + base::UmaHistogramEnumeration("Permissions.Action.FontAccess", action, + PermissionAction::NUM); + break; // The user is not prompted for these permissions, thus there is no // permission action recorded for them. default:
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc index 0cd41b8..0ee9060 100644 --- a/components/permissions/permission_util.cc +++ b/components/permissions/permission_util.cc
@@ -69,6 +69,8 @@ return "CameraPanTiltZoom"; case ContentSettingsType::WINDOW_PLACEMENT: return "WindowPlacement"; + case ContentSettingsType::FONT_ACCESS: + return "FontAccess"; default: break; } @@ -110,6 +112,8 @@ return PermissionRequestType::PERMISSION_CAMERA_PAN_TILT_ZOOM; case ContentSettingsType::WINDOW_PLACEMENT: return PermissionRequestType::PERMISSION_WINDOW_PLACEMENT; + case ContentSettingsType::FONT_ACCESS: + return PermissionRequestType::PERMISSION_FONT_ACCESS; default: NOTREACHED(); return PermissionRequestType::UNKNOWN; @@ -173,6 +177,8 @@ *out = PermissionType::CAMERA_PAN_TILT_ZOOM; } else if (type == ContentSettingsType::WINDOW_PLACEMENT) { *out = PermissionType::WINDOW_PLACEMENT; + } else if (type == ContentSettingsType::FONT_ACCESS) { + *out = PermissionType::FONT_ACCESS; } else { return false; } @@ -206,6 +212,7 @@ case ContentSettingsType::STORAGE_ACCESS: case ContentSettingsType::CAMERA_PAN_TILT_ZOOM: case ContentSettingsType::WINDOW_PLACEMENT: + case ContentSettingsType::FONT_ACCESS: return true; default: return false;
diff --git a/components/permissions_strings.grdp b/components/permissions_strings.grdp index a692bc87..54c98b6a 100644 --- a/components/permissions_strings.grdp +++ b/components/permissions_strings.grdp
@@ -118,6 +118,9 @@ <message name="IDS_WINDOW_PLACEMENT_PERMISSION_FRAGMENT" desc="Permission request shown if the user is visiting a site that wants to place windows. Follows a prompt: 'This site would like to:'"> Open and place windows on your screens </message> + <message name="IDS_FONT_ACCESS_PERMISSION_FRAGMENT" desc="Permission request shown if the user is visiting a site that wants to access locally installed font data. Follows a prompt: 'This site would like to:'"> + Use the fonts installed on your computer so you can create advanced typography + </message> <message name="IDS_PERMISSION_ALLOW" desc="Label on button to allow a permissions request."> Allow </message>
diff --git a/components/permissions_strings_grdp/IDS_FONT_ACCESS_PERMISSION_FRAGMENT.png.sha1 b/components/permissions_strings_grdp/IDS_FONT_ACCESS_PERMISSION_FRAGMENT.png.sha1 new file mode 100644 index 0000000..b8432b9 --- /dev/null +++ b/components/permissions_strings_grdp/IDS_FONT_ACCESS_PERMISSION_FRAGMENT.png.sha1
@@ -0,0 +1 @@ +1acf180e72599e85eaf3dfd47606fc3509bb226e \ No newline at end of file
diff --git a/components/policy/proto/record_constants.proto b/components/policy/proto/record_constants.proto index b082002c..6972ac4 100644 --- a/components/policy/proto/record_constants.proto +++ b/components/policy/proto/record_constants.proto
@@ -14,6 +14,10 @@ // |UPLOAD_EVENTS| handler sends records to the Eventing pipeline. UPLOAD_EVENTS = 1; + + // |APP_INSTALL_EVENT| for sending events to the DmServer for the + // APP_INSTALL_EVENT pipeline. + APP_INSTALL_EVENT = 2; } // |Priority| is used to determine when items from the queue should be rate
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index f76df7b2..ae6ff46 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1358,18 +1358,18 @@ metafile.FinishFrameContent(); - // Send the printed result back. + // Send the printed result back, if possible. Do not return early here on + // failure, as DispatchAfterPrintEvent() still need to be called. mojom::DidPrintContentParamsPtr printed_frame_params = mojom::DidPrintContentParams::New(); - if (!CopyMetafileDataToReadOnlySharedMem(metafile, - printed_frame_params.get())) { + if (CopyMetafileDataToReadOnlySharedMem(metafile, + printed_frame_params.get())) { + std::move(callback).Run(params->document_cookie, + std::move(printed_frame_params)); + } else { DLOG(ERROR) << "CopyMetafileDataToSharedMem failed"; - return; } - std::move(callback).Run(params->document_cookie, - std::move(printed_frame_params)); - if (!render_frame_gone_) frame->DispatchAfterPrintEvent(); }
diff --git a/components/search_engines/BUILD.gn b/components/search_engines/BUILD.gn index 84ebf46..aa65c00 100644 --- a/components/search_engines/BUILD.gn +++ b/components/search_engines/BUILD.gn
@@ -19,6 +19,7 @@ "keyword_table.h", "keyword_web_data_service.cc", "keyword_web_data_service.h", + "omnibox_focus_type.h", "search_engines_pref_names.cc", "search_engines_pref_names.h", "search_engines_switches.cc",
diff --git a/components/search_engines/omnibox_focus_type.h b/components/search_engines/omnibox_focus_type.h new file mode 100644 index 0000000..fc3bf21 --- /dev/null +++ b/components/search_engines/omnibox_focus_type.h
@@ -0,0 +1,34 @@ +// Copyright 2020 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 COMPONENTS_SEARCH_ENGINES_OMNIBOX_FOCUS_TYPE_H_ +#define COMPONENTS_SEARCH_ENGINES_OMNIBOX_FOCUS_TYPE_H_ + +// For search requests, this enum specifies how the user last interacted with +// the UI control. This is used for both the omnibox and NTP realbox. +// It's called OmniboxFocusType so this enum matches the "oft" GET param. +// +// These values are used as HTTP GET parameter values. Entries should not be +// renumbered and numeric values should never be reused. +enum class OmniboxFocusType { + // The default value. This is used for any search requests without any + // special interaction annotation, including: normal omnibox searches, + // as-you-type omnibox suggestions, as well as non-omnibox searches. + DEFAULT = 0, + + // This search request is triggered by the user focusing the omnibox. + ON_FOCUS = 1, + + // This search request is triggered by the user deleting all of the + // omnibox permanent text at once, i.e. user is on "https://example.com", + // does Ctrl+L which selects the whole URL, then presses Backspace. + // + // This value does not apply in these circumstances: + // - User deletes their own typed text. + // - User deletes the permanent text one character at a time. + // - User uses Cut (Ctrl+X) to delete the permanent text. + DELETED_PERMANENT_TEXT = 2, +}; + +#endif // COMPONENTS_SEARCH_ENGINES_OMNIBOX_FOCUS_TYPE_H_
diff --git a/components/search_engines/template_url.cc b/components/search_engines/template_url.cc index 02f5f64a..52f0de37 100644 --- a/components/search_engines/template_url.cc +++ b/components/search_engines/template_url.cc
@@ -1073,11 +1073,10 @@ case GOOGLE_OMNIBOX_FOCUS_TYPE: DCHECK(!i->is_post_param); - if (search_terms_args.omnibox_focus_type != - SearchTermsArgs::OmniboxFocusType::DEFAULT) { + if (search_terms_args.focus_type != OmniboxFocusType::DEFAULT) { HandleReplacement("oft", - base::NumberToString(static_cast<int>( - search_terms_args.omnibox_focus_type)), + base::NumberToString( + static_cast<int>(search_terms_args.focus_type)), *i, &url); } break;
diff --git a/components/search_engines/template_url.h b/components/search_engines/template_url.h index 79800834..4a656ef 100644 --- a/components/search_engines/template_url.h +++ b/components/search_engines/template_url.h
@@ -14,6 +14,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/time/time.h" +#include "components/search_engines/omnibox_focus_type.h" #include "components/search_engines/search_engine_type.h" #include "components/search_engines/template_url_data.h" #include "components/search_engines/template_url_id.h" @@ -76,21 +77,6 @@ SearchTermsArgs(const SearchTermsArgs& other); ~SearchTermsArgs(); - // If the search request is from the omnibox, this enum may specify details - // about how the user last interacted with the omnibox. - // - // These values are used as HTTP GET parameter values. Entries should not be - // renumbered and numeric values should never be reused. - enum class OmniboxFocusType { - // The default value. This is used for any search requests without any - // special interaction annotation, including: normal omnibox searches, - // as-you-type omnibox suggestions, as well as non-omnibox searches. - DEFAULT = 0, - - // This search request is triggered by the user focusing the omnibox. - ON_FOCUS = 1, - }; - struct ContextualSearchParams { ContextualSearchParams(); // Modern constructor, used when the content is sent in the HTTP header @@ -186,9 +172,8 @@ // The type the original input query was identified as. metrics::OmniboxInputType input_type = metrics::OmniboxInputType::EMPTY; - // If the search request is from the omnibox, this may specify how the user - // last interacted with the omnibox. - OmniboxFocusType omnibox_focus_type = OmniboxFocusType::DEFAULT; + // Specifies how the user last interacted with the searchbox UI element. + OmniboxFocusType focus_type = OmniboxFocusType::DEFAULT; // The optional assisted query stats, aka AQS, used for logging purposes. // This string contains impressions of all autocomplete matches shown
diff --git a/components/search_engines/template_url_unittest.cc b/components/search_engines/template_url_unittest.cc index e04b704..78962a03b 100644 --- a/components/search_engines/template_url_unittest.cc +++ b/components/search_engines/template_url_unittest.cc
@@ -736,18 +736,19 @@ TEST_F(TemplateURLTest, ReplaceOmniboxFocusType) { struct TestData { const base::string16 search_term; - TemplateURLRef::SearchTermsArgs::OmniboxFocusType omnibox_focus_type; + OmniboxFocusType focus_type; const std::string url; const std::string expected_result; } test_data[] = { - {ASCIIToUTF16("foo"), - TemplateURLRef::SearchTermsArgs::OmniboxFocusType::DEFAULT, + {ASCIIToUTF16("foo"), OmniboxFocusType::DEFAULT, "{google:baseURL}?{searchTerms}&{google:omniboxFocusType}", "http://www.google.com/?foo&"}, - {ASCIIToUTF16("foo"), - TemplateURLRef::SearchTermsArgs::OmniboxFocusType::ON_FOCUS, + {ASCIIToUTF16("foo"), OmniboxFocusType::ON_FOCUS, "{google:baseURL}?{searchTerms}&{google:omniboxFocusType}", "http://www.google.com/?foo&oft=1&"}, + {ASCIIToUTF16("foo"), OmniboxFocusType::DELETED_PERMANENT_TEXT, + "{google:baseURL}?{searchTerms}&{google:omniboxFocusType}", + "http://www.google.com/?foo&oft=2&"}, }; TemplateURLData data; data.input_encodings.push_back("UTF-8"); @@ -757,7 +758,7 @@ EXPECT_TRUE(url.url_ref().IsValid(search_terms_data_)); ASSERT_TRUE(url.url_ref().SupportsReplacement(search_terms_data_)); TemplateURLRef::SearchTermsArgs search_terms_args(test_data[i].search_term); - search_terms_args.omnibox_focus_type = test_data[i].omnibox_focus_type; + search_terms_args.focus_type = test_data[i].focus_type; GURL result(url.url_ref().ReplaceSearchTerms(search_terms_args, search_terms_data_)); ASSERT_TRUE(result.is_valid());
diff --git a/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java b/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java index c9b5490..ab862cab 100644 --- a/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java +++ b/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java
@@ -14,7 +14,6 @@ import android.content.Intent; import android.os.Bundle; import android.os.UserManager; -import android.support.test.rule.UiThreadTestRule; import androidx.test.filters.SmallTest; @@ -22,7 +21,6 @@ import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; @@ -51,9 +49,6 @@ @Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class, CustomShadowUserManager.class}) public class AccountManagerFacadeRobolectricTest { - @Rule - public final UiThreadTestRule mRule = new UiThreadTestRule(); - private CustomShadowUserManager mShadowUserManager; private FakeAccountManagerDelegate mDelegate; private AccountManagerFacade mFacade;
diff --git a/components/translate/content/renderer/translate_agent.cc b/components/translate/content/renderer/translate_agent.cc index 162c7c67..c17ac71 100644 --- a/components/translate/content/renderer/translate_agent.cc +++ b/components/translate/content/renderer/translate_agent.cc
@@ -4,6 +4,7 @@ #include "components/translate/content/renderer/translate_agent.h" +#include <stddef.h> #include <utility> #include "base/bind.h" @@ -230,10 +231,13 @@ } v8::Local<v8::String> v8_str = result.As<v8::String>(); - int length = v8_str->Utf8Length(isolate) + 1; - std::unique_ptr<char[]> str(new char[length]); - v8_str->WriteUtf8(isolate, str.get(), length); - return std::string(str.get()); + int length = v8_str->Utf8Length(isolate); + if (length <= 0) + return std::string(); + + std::string str(static_cast<size_t>(length), '\0'); + v8_str->WriteUtf8(isolate, &str[0], length); + return str; } double TranslateAgent::ExecuteScriptAndGetDoubleResult(
diff --git a/components/translate/core/browser/language_state_unittest.cc b/components/translate/core/browser/language_state_unittest.cc index bf08eaf..7bc54d07 100644 --- a/components/translate/core/browser/language_state_unittest.cc +++ b/components/translate/core/browser/language_state_unittest.cc
@@ -4,8 +4,6 @@ #include "components/translate/core/browser/language_state.h" -#include <memory> - #include "base/macros.h" #include "components/translate/core/browser/language_state.h" #include "components/translate/core/browser/mock_translate_driver.h" @@ -17,8 +15,8 @@ namespace translate { TEST(LanguageStateTest, IsPageTranslated) { - std::unique_ptr<MockTranslateDriver> driver(new MockTranslateDriver); - LanguageState language_state(driver.get()); + MockTranslateDriver driver; + LanguageState language_state(&driver); EXPECT_FALSE(language_state.IsPageTranslated()); // Navigate to a French page. @@ -41,36 +39,36 @@ } TEST(LanguageStateTest, Driver) { - std::unique_ptr<MockTranslateDriver> driver(new MockTranslateDriver); - LanguageState language_state(driver.get()); + MockTranslateDriver driver; + LanguageState language_state(&driver); // Enable/Disable translate. EXPECT_FALSE(language_state.translate_enabled()); - EXPECT_FALSE(driver->on_translate_enabled_changed_called()); + EXPECT_FALSE(driver.on_translate_enabled_changed_called()); language_state.SetTranslateEnabled(true); EXPECT_TRUE(language_state.translate_enabled()); - EXPECT_TRUE(driver->on_translate_enabled_changed_called()); + EXPECT_TRUE(driver.on_translate_enabled_changed_called()); - driver->Reset(); + driver.Reset(); language_state.SetTranslateEnabled(false); EXPECT_FALSE(language_state.translate_enabled()); - EXPECT_TRUE(driver->on_translate_enabled_changed_called()); + EXPECT_TRUE(driver.on_translate_enabled_changed_called()); // Navigate to a French page. - driver->Reset(); + driver.Reset(); language_state.LanguageDetermined("fr", true); EXPECT_FALSE(language_state.translate_enabled()); - EXPECT_FALSE(driver->on_is_page_translated_changed_called()); - EXPECT_FALSE(driver->on_translate_enabled_changed_called()); + EXPECT_FALSE(driver.on_is_page_translated_changed_called()); + EXPECT_FALSE(driver.on_translate_enabled_changed_called()); // Translate. language_state.SetCurrentLanguage("en"); EXPECT_TRUE(language_state.IsPageTranslated()); - EXPECT_TRUE(driver->on_is_page_translated_changed_called()); + EXPECT_TRUE(driver.on_is_page_translated_changed_called()); // Translate feature must be enabled after an actual translation. EXPECT_TRUE(language_state.translate_enabled()); - EXPECT_TRUE(driver->on_translate_enabled_changed_called()); + EXPECT_TRUE(driver.on_translate_enabled_changed_called()); } } // namespace translate
diff --git a/components/translate/core/browser/translate_download_manager.cc b/components/translate/core/browser/translate_download_manager.cc index 4f7a3a2..3c2d39b 100644 --- a/components/translate/core/browser/translate_download_manager.cc +++ b/components/translate/core/browser/translate_download_manager.cc
@@ -17,8 +17,8 @@ } TranslateDownloadManager::TranslateDownloadManager() - : language_list_(new TranslateLanguageList), - script_(new TranslateScript) {} + : language_list_(std::make_unique<TranslateLanguageList>()), + script_(std::make_unique<TranslateScript>()) {} TranslateDownloadManager::~TranslateDownloadManager() {} @@ -71,8 +71,8 @@ void TranslateDownloadManager::ResetForTesting() { DCHECK(sequence_checker_.CalledOnValidSequence()); - language_list_.reset(new TranslateLanguageList); - script_.reset(new TranslateScript); + language_list_ = std::make_unique<TranslateLanguageList>(); + script_ = std::make_unique<TranslateScript>(); url_loader_factory_ = nullptr; }
diff --git a/components/translate/core/browser/translate_prefs_unittest.cc b/components/translate/core/browser/translate_prefs_unittest.cc index 676b09b..d7866d1 100644 --- a/components/translate/core/browser/translate_prefs_unittest.cc +++ b/components/translate/core/browser/translate_prefs_unittest.cc
@@ -66,33 +66,32 @@ class TranslatePrefsTest : public testing::Test { protected: - TranslatePrefsTest() - : prefs_(new sync_preferences::TestingPrefServiceSyncable()) { - language::LanguagePrefs::RegisterProfilePrefs(prefs_->registry()); - TranslatePrefs::RegisterProfilePrefs(prefs_->registry()); + TranslatePrefsTest() { + language::LanguagePrefs::RegisterProfilePrefs(prefs_.registry()); + TranslatePrefs::RegisterProfilePrefs(prefs_.registry()); translate_prefs_ = std::make_unique<translate::TranslatePrefs>( - prefs_.get(), kAcceptLanguagesPref, kPreferredLanguagesPref); + &prefs_, kAcceptLanguagesPref, kPreferredLanguagesPref); now_ = base::Time::Now(); two_days_ago_ = now_ - base::TimeDelta::FromDays(2); } void SetUp() override { - prefs_->SetString(kAcceptLanguagesPref, std::string()); + prefs_.SetString(kAcceptLanguagesPref, std::string()); #if defined(OS_CHROMEOS) - prefs_->SetString(kPreferredLanguagesPref, std::string()); + prefs_.SetString(kPreferredLanguagesPref, std::string()); #endif - prefs_->registry()->RegisterBooleanPref( + prefs_.registry()->RegisterBooleanPref( prefs::kOfferTranslateEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); } void SetLastDeniedTime(const std::string& language, base::Time time) { - DenialTimeUpdate update(prefs_.get(), language, 2); + DenialTimeUpdate update(&prefs_, language, 2); update.AddDenialTime(time); } base::Time GetLastDeniedTime(const std::string& language) { - DenialTimeUpdate update(prefs_.get(), language, 2); + DenialTimeUpdate update(&prefs_, language, 2); return update.GetOldestDenialTime(); } @@ -101,15 +100,15 @@ void ExpectLanguagePrefs(const std::string& expected, const std::string& expected_chromeos) const { if (expected.empty()) { - EXPECT_TRUE(prefs_->GetString(kAcceptLanguagesPref).empty()); + EXPECT_TRUE(prefs_.GetString(kAcceptLanguagesPref).empty()); } else { - EXPECT_EQ(expected, prefs_->GetString(kAcceptLanguagesPref)); + EXPECT_EQ(expected, prefs_.GetString(kAcceptLanguagesPref)); } #if defined(OS_CHROMEOS) if (expected_chromeos.empty()) { - EXPECT_TRUE(prefs_->GetString(kPreferredLanguagesPref).empty()); + EXPECT_TRUE(prefs_.GetString(kPreferredLanguagesPref).empty()); } else { - EXPECT_EQ(expected_chromeos, prefs_->GetString(kPreferredLanguagesPref)); + EXPECT_EQ(expected_chromeos, prefs_.GetString(kPreferredLanguagesPref)); } #endif } @@ -123,7 +122,7 @@ void ExpectBlockedLanguageListContent( const std::vector<std::string>& list) const { const base::ListValue* const blacklist = - prefs_->GetList(kTranslateBlockedLanguagesPref); + prefs_.GetList(kTranslateBlockedLanguagesPref); ExpectEqualLanguageLists(*blacklist, list); } @@ -164,7 +163,7 @@ return result; } - std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs_; + sync_preferences::TestingPrefServiceSyncable prefs_; std::unique_ptr<translate::TranslatePrefs> translate_prefs_; // Shared time constants. @@ -216,14 +215,14 @@ // Test that the default value for non-existing entries is base::Time::Null(). TEST_F(TranslatePrefsTest, DenialTimeUpdate_DefaultTimeIsNull) { - DenialTimeUpdate update(prefs_.get(), kTestLanguage, 2); + DenialTimeUpdate update(&prefs_, kTestLanguage, 2); EXPECT_TRUE(update.GetOldestDenialTime().is_null()); } // Test that non-existing entries automatically create a ListValue. TEST_F(TranslatePrefsTest, DenialTimeUpdate_ForceListExistence) { DictionaryPrefUpdate dict_update( - prefs_.get(), TranslatePrefs::kPrefTranslateLastDeniedTimeForLanguage); + &prefs_, TranslatePrefs::kPrefTranslateLastDeniedTimeForLanguage); base::DictionaryValue* denial_dict = dict_update.Get(); EXPECT_TRUE(denial_dict); @@ -232,7 +231,7 @@ EXPECT_FALSE(has_list); // Calling GetDenialTimes will force creation of a properly populated list. - DenialTimeUpdate update(prefs_.get(), kTestLanguage, 2); + DenialTimeUpdate update(&prefs_, kTestLanguage, 2); base::ListValue* time_list = update.GetDenialTimes(); EXPECT_TRUE(time_list); EXPECT_EQ(0U, time_list->GetSize()); @@ -243,7 +242,7 @@ TEST_F(TranslatePrefsTest, DenialTimeUpdate_Migrate) { translate_prefs_->ResetDenialState(); DictionaryPrefUpdate dict_update( - prefs_.get(), TranslatePrefs::kPrefTranslateLastDeniedTimeForLanguage); + &prefs_, TranslatePrefs::kPrefTranslateLastDeniedTimeForLanguage); base::DictionaryValue* denial_dict = dict_update.Get(); EXPECT_TRUE(denial_dict); denial_dict->SetDouble(kTestLanguage, two_days_ago_.ToJsTime()); @@ -253,7 +252,7 @@ EXPECT_FALSE(has_list); // Calling GetDenialTimes will force creation of a properly populated list. - DenialTimeUpdate update(prefs_.get(), kTestLanguage, 2); + DenialTimeUpdate update(&prefs_, kTestLanguage, 2); base::ListValue* time_list = update.GetDenialTimes(); EXPECT_TRUE(time_list); @@ -265,7 +264,7 @@ } TEST_F(TranslatePrefsTest, DenialTimeUpdate_SlidingWindow) { - DenialTimeUpdate update(prefs_.get(), kTestLanguage, 4); + DenialTimeUpdate update(&prefs_, kTestLanguage, 4); update.AddDenialTime(now_ - base::TimeDelta::FromMinutes(5)); EXPECT_EQ(update.GetOldestDenialTime(), @@ -958,12 +957,12 @@ } TEST_F(TranslatePrefsTest, CanTranslateLanguage) { - prefs_->SetString(kAcceptLanguagesPref, "en"); + prefs_.SetString(kAcceptLanguagesPref, "en"); TranslateDownloadManager::GetInstance()->set_application_locale("en"); translate_prefs_->ResetToDefaults(); - TranslateAcceptLanguages translate_accept_languages(prefs_.get(), + TranslateAcceptLanguages translate_accept_languages(&prefs_, kAcceptLanguagesPref); // Unblocked language. @@ -991,8 +990,8 @@ } TEST_F(TranslatePrefsTest, ForceTriggerOnEnglishPagesCount) { - prefs_->SetInteger(kForceTriggerTranslateCountPref, - std::numeric_limits<int>::max() - 1); + prefs_.SetInteger(kForceTriggerTranslateCountPref, + std::numeric_limits<int>::max() - 1); EXPECT_EQ(std::numeric_limits<int>::max() - 1, translate_prefs_->GetForceTriggerOnEnglishPagesCount());
diff --git a/components/translate/core/browser/translate_script.cc b/components/translate/core/browser/translate_script.cc index dbd721cd..bc59e97 100644 --- a/components/translate/core/browser/translate_script.cc +++ b/components/translate/core/browser/translate_script.cc
@@ -120,7 +120,7 @@ void TranslateScript::OnScriptFetchComplete(bool success, const std::string& data) { - std::unique_ptr<const TranslateURLFetcher> delete_ptr(fetcher_.release()); + std::unique_ptr<const TranslateURLFetcher> delete_ptr(std::move(fetcher_)); if (success) { DCHECK(data_.empty());
diff --git a/components/translate/ios/browser/translate_controller_unittest.mm b/components/translate/ios/browser/translate_controller_unittest.mm index 14245ef4..b3ec2bfa 100644 --- a/components/translate/ios/browser/translate_controller_unittest.mm +++ b/components/translate/ios/browser/translate_controller_unittest.mm
@@ -26,8 +26,8 @@ public TranslateController::Observer { protected: TranslateControllerTest() - : test_web_state_(new web::TestWebState), - test_browser_state_(new web::TestBrowserState), + : test_web_state_(std::make_unique<web::TestWebState>()), + test_browser_state_(std::make_unique<web::TestBrowserState>()), fake_main_frame_(/*frame_id=*/"", /*is_main_frame=*/true, GURL()), fake_iframe_(/*frame_id=*/"", /*is_main_frame=*/false, GURL()), error_type_(TranslateErrors::Type::NONE),
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 5320902c..ff5d902 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -889,6 +889,8 @@ "find_in_page_client.h", "find_request_manager.cc", "find_request_manager.h", + "font_access/font_access_manager_impl.cc", + "font_access/font_access_manager_impl.h", "font_list_async.cc", "frame_host/ancestor_throttle.cc", "frame_host/ancestor_throttle.h",
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 2e17479..c138880 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1725,7 +1725,14 @@ RunHtmlTest(FILE_PATH_LITERAL("input-email.html")); } -IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputFile) { +// http://crbug.com/1114193 +#if defined(OS_ANDROID) +#define MAYBE_AccessibilityInputFile DISABLED_AccessibilityInputFile +#else +#define MAYBE_AccessibilityInputFile AccessibilityInputFile +#endif +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + MAYBE_AccessibilityInputFile) { RunHtmlTest(FILE_PATH_LITERAL("input-file.html")); }
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 98e1c9d..04594ff 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -519,6 +519,11 @@ map->Add<blink::mojom::FeatureObserver>(base::BindRepeating( &RenderFrameHostImpl::GetFeatureObserver, base::Unretained(host))); + if (base::FeatureList::IsEnabled(blink::features::kFontAccess)) { + map->Add<blink::mojom::FontAccessManager>(base::BindRepeating( + &RenderFrameHostImpl::GetFontAccessManager, base::Unretained(host))); + } + map->Add<blink::mojom::FileSystemManager>(base::BindRepeating( &RenderFrameHostImpl::GetFileSystemManager, base::Unretained(host)));
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage.cc b/content/browser/cache_storage/legacy/legacy_cache_storage.cc index 004dcefd..ce232613 100644 --- a/content/browser/cache_storage/legacy/legacy_cache_storage.cc +++ b/content/browser/cache_storage/legacy/legacy_cache_storage.cc
@@ -86,8 +86,9 @@ // Handles the loading and clean up of CacheStorageCache objects. class LegacyCacheStorage::CacheLoader { public: - using CacheCallback = - base::OnceCallback<void(std::unique_ptr<LegacyCacheStorageCache>)>; + using CacheAndErrorCallback = + base::OnceCallback<void(std::unique_ptr<LegacyCacheStorageCache>, + CacheStorageError status)>; using BoolCallback = base::OnceCallback<void(bool)>; using CacheStorageIndexLoadCallback = base::OnceCallback<void(std::unique_ptr<CacheStorageIndex>)>; @@ -121,7 +122,7 @@ // Deletes any pre-existing cache of the same name and then loads it. virtual void PrepareNewCacheDestination(const std::string& cache_name, - CacheCallback callback) = 0; + CacheAndErrorCallback callback) = 0; // After the backend has been deleted, do any extra house keeping such as // removing the cache's directory. @@ -194,11 +195,11 @@ } void PrepareNewCacheDestination(const std::string& cache_name, - CacheCallback callback) override { + CacheAndErrorCallback callback) override { std::unique_ptr<LegacyCacheStorageCache> cache = CreateCache(cache_name, 0 /*cache_size*/, 0 /* cache_padding */, storage::CopyDefaultPaddingKey()); - std::move(callback).Run(std::move(cache)); + std::move(callback).Run(std::move(cache), CacheStorageError::kSuccess); } void CleanUpDeletedCache(CacheStorageCache* cache) override {} @@ -272,7 +273,7 @@ } void PrepareNewCacheDestination(const std::string& cache_name, - CacheCallback callback) override { + CacheAndErrorCallback callback) override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); PostTaskAndReplyWithResult( @@ -285,8 +286,8 @@ } // Runs on the cache_task_runner_. - static std::string PrepareNewCacheDirectoryInPool( - const base::FilePath& origin_path) { + static std::tuple<CacheStorageError, std::string> + PrepareNewCacheDirectoryInPool(const base::FilePath& origin_path) { std::string cache_dir; base::FilePath cache_path; do { @@ -294,21 +295,38 @@ cache_path = origin_path.AppendASCII(cache_dir); } while (base::PathExists(cache_path)); - return base::CreateDirectory(cache_path) ? cache_dir : ""; + base::File::Error error = base::File::FILE_OK; + if (base::CreateDirectoryAndGetError(cache_path, &error)) { + return std::make_tuple(CacheStorageError::kSuccess, cache_dir); + } else { + CacheStorageError status = + error == base::File::FILE_ERROR_NO_SPACE + ? CacheStorageError::kErrorQuotaExceeded + : MakeErrorStorage(ErrorStorageType::kDidCreateNullCache); + return std::make_tuple(status, cache_dir); + } } - void PrepareNewCacheCreateCache(const std::string& cache_name, - CacheCallback callback, - const std::string& cache_dir) { - if (cache_dir.empty()) { - std::move(callback).Run(nullptr); + void PrepareNewCacheCreateCache( + const std::string& cache_name, + CacheAndErrorCallback callback, + const std::tuple<CacheStorageError, std::string>& result) { + CacheStorageError status; + std::string cache_dir; + std::tie(status, cache_dir) = result; + + if (status != CacheStorageError::kSuccess) { + std::move(callback).Run(nullptr, status); return; } + DCHECK(!cache_dir.empty()); cache_name_to_cache_dir_[cache_name] = cache_dir; - std::move(callback).Run(CreateCache( - cache_name, LegacyCacheStorage::kSizeUnknown, - LegacyCacheStorage::kSizeUnknown, storage::CopyDefaultPaddingKey())); + std::move(callback).Run( + CreateCache(cache_name, LegacyCacheStorage::kSizeUnknown, + LegacyCacheStorage::kSizeUnknown, + storage::CopyDefaultPaddingKey()), + CacheStorageError::kSuccess); } void CleanUpDeletedCache(CacheStorageCache* cache) override { @@ -1019,7 +1037,8 @@ const std::string& cache_name, int64_t trace_id, CacheAndErrorCallback callback, - std::unique_ptr<LegacyCacheStorageCache> cache) { + std::unique_ptr<LegacyCacheStorageCache> cache, + CacheStorageError status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); TRACE_EVENT_WITH_FLOW0("CacheStorage", @@ -1030,10 +1049,8 @@ UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult", static_cast<bool>(cache)); - if (!cache) { - std::move(callback).Run( - CacheStorageCacheHandle(), - MakeErrorStorage(ErrorStorageType::kDidCreateNullCache)); + if (status != CacheStorageError::kSuccess) { + std::move(callback).Run(CacheStorageCacheHandle(), status); return; }
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage.h b/content/browser/cache_storage/legacy/legacy_cache_storage.h index abcf8382..145f49d 100644 --- a/content/browser/cache_storage/legacy/legacy_cache_storage.h +++ b/content/browser/cache_storage/legacy/legacy_cache_storage.h
@@ -187,11 +187,11 @@ void OpenCacheImpl(const std::string& cache_name, int64_t trace_id, CacheAndErrorCallback callback); - void CreateCacheDidCreateCache( - const std::string& cache_name, - int64_t trace_id, - CacheAndErrorCallback callback, - std::unique_ptr<LegacyCacheStorageCache> cache); + void CreateCacheDidCreateCache(const std::string& cache_name, + int64_t trace_id, + CacheAndErrorCallback callback, + std::unique_ptr<LegacyCacheStorageCache> cache, + blink::mojom::CacheStorageError status); void CreateCacheDidWriteIndex(CacheAndErrorCallback callback, CacheStorageCacheHandle cache_handle, int64_t trace_id,
diff --git a/content/browser/devtools/protocol/browser_handler.cc b/content/browser/devtools/protocol/browser_handler.cc index d446d4f..e5c9aaa 100644 --- a/content/browser/devtools/protocol/browser_handler.cc +++ b/content/browser/devtools/protocol/browser_handler.cc
@@ -203,6 +203,8 @@ *permission_type = PermissionType::NFC; } else if (name == "window-placement") { *permission_type = PermissionType::WINDOW_PLACEMENT; + } else if (name == "font-access") { + *permission_type = PermissionType::FONT_ACCESS; } else { return Response::InvalidParams("Invalid PermissionDescriptor name: " + name);
diff --git a/content/browser/font_access/OWNERS b/content/browser/font_access/OWNERS new file mode 100644 index 0000000..99465b1 --- /dev/null +++ b/content/browser/font_access/OWNERS
@@ -0,0 +1,5 @@ +jsbell@chromium.org +oyiptong@chromium.org + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage>FontAccess \ No newline at end of file
diff --git a/content/browser/font_access/font_access_manager_impl.cc b/content/browser/font_access/font_access_manager_impl.cc new file mode 100644 index 0000000..f4919f2 --- /dev/null +++ b/content/browser/font_access/font_access_manager_impl.cc
@@ -0,0 +1,48 @@ +// Copyright 2020 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 "content/browser/font_access/font_access_manager_impl.h" + +#include "base/bind.h" +#include "content/browser/permissions/permission_controller_impl.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" + +namespace content { + +FontAccessManagerImpl::FontAccessManagerImpl() = default; + +FontAccessManagerImpl::~FontAccessManagerImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void FontAccessManagerImpl::BindReceiver( + const BindingContext& context, + mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + receivers_.Add(this, std::move(receiver), context); +} + +void FontAccessManagerImpl::RequestPermission( + RequestPermissionCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + const BindingContext& context = receivers_.current_context(); + RenderFrameHost* rfh = RenderFrameHost::FromID(context.frame_id); + + auto* permission_controller = PermissionControllerImpl::FromBrowserContext( + rfh->GetProcess()->GetBrowserContext()); + permission_controller->RequestPermission( + PermissionType::FONT_ACCESS, rfh, context.origin.GetURL(), + /*user_gesture=*/false, + base::BindOnce( + [](RequestPermissionCallback callback, + blink::mojom::PermissionStatus status) { + std::move(callback).Run(status); + }, + std::move(callback))); +} + +} // namespace content
diff --git a/content/browser/font_access/font_access_manager_impl.h b/content/browser/font_access/font_access_manager_impl.h new file mode 100644 index 0000000..bc11daa1 --- /dev/null +++ b/content/browser/font_access/font_access_manager_impl.h
@@ -0,0 +1,49 @@ +// Copyright 2020 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 CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_IMPL_H_ +#define CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_IMPL_H_ + +#include "base/macros.h" +#include "base/sequence_checker.h" +#include "content/common/content_export.h" +#include "content/public/browser/global_routing_id.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "third_party/blink/public/mojom/font_access/font_access.mojom.h" +#include "url/origin.h" + +namespace content { + +class CONTENT_EXPORT FontAccessManagerImpl + : public blink::mojom::FontAccessManager { + public: + FontAccessManagerImpl(); + ~FontAccessManagerImpl() override; + + struct BindingContext { + BindingContext(const url::Origin& origin, GlobalFrameRoutingId frame_id) + : origin(origin), frame_id(frame_id) {} + + url::Origin origin; + GlobalFrameRoutingId frame_id; + }; + + void BindReceiver( + const BindingContext& context, + mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver); + + // blink.mojom.FontAccessManager: + void RequestPermission(RequestPermissionCallback callback) override; + + private: + // Registered clients. + mojo::ReceiverSet<blink::mojom::FontAccessManager, BindingContext> receivers_; + + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(FontAccessManagerImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_FONT_ACCESS_FONT_ACCESS_MANAGER_IMPL_H_
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index ce4e7bf..075c3baa 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -7552,6 +7552,15 @@ geolocation_service_->Bind(std::move(receiver)); } +void RenderFrameHostImpl::GetFontAccessManager( + mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver) { + static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition()) + ->GetFontAccessManager() + ->BindReceiver(FontAccessManagerImpl::BindingContext( + GetLastCommittedOrigin(), GetGlobalFrameRoutingId()), + std::move(receiver)); +} + void RenderFrameHostImpl::GetNativeFileSystemManager( mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 7437341..df5f8945 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -99,6 +99,7 @@ #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" +#include "third_party/blink/public/mojom/font_access/font_access.mojom.h" #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" #include "third_party/blink/public/mojom/frame/frame.mojom-forward.h" @@ -1287,6 +1288,9 @@ void GetGeolocationService( mojo::PendingReceiver<blink::mojom::GeolocationService> receiver); + void GetFontAccessManager( + mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver); + void GetNativeFileSystemManager( mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver);
diff --git a/content/browser/permissions/permission_controller_impl.cc b/content/browser/permissions/permission_controller_impl.cc index c6edd2e..2591866 100644 --- a/content/browser/permissions/permission_controller_impl.cc +++ b/content/browser/permissions/permission_controller_impl.cc
@@ -66,6 +66,7 @@ case PermissionType::VR: case PermissionType::CAMERA_PAN_TILT_ZOOM: case PermissionType::WINDOW_PLACEMENT: + case PermissionType::FONT_ACCESS: return base::nullopt; } }
diff --git a/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc b/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc index c5a70090..e4ed928e 100644 --- a/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc +++ b/content/browser/renderer_host/input/compositor_event_ack_browsertest.cc
@@ -260,7 +260,6 @@ touch_event.SetTimeStamp(ui::EventTimeForNow()); input_event_router->RouteTouchEvent(root_view, &touch_event, ui::LatencyInfo()); - GetWidgetHost()->input_router()->OnSetTouchAction(cc::TouchAction::kAuto); // Send GSB to start scrolling sequence. blink::WebGestureEvent gesture_scroll_begin(
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h index ee162263..7279bd2 100644 --- a/content/browser/renderer_host/input/input_router.h +++ b/content/browser/renderer_host/input/input_router.h
@@ -92,10 +92,6 @@ // Used to stop an active fling if such exists. virtual void StopFling() = 0; - // Called when a set-touch-action message is received from the renderer - // for a touch start event that is currently in flight. - virtual void OnSetTouchAction(cc::TouchAction touch_action) = 0; - // In the case when a gesture event is bubbled from a child frame to the main // frame, we set the touch action in the main frame Auto even if there is no // pending touch start.
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index fffec86..af95eb2 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -639,12 +639,9 @@ // send it in the input event ack to ensure it is available at the // time the ACK is handled. if (touch_action) { + // For main thread ACKs, Blink will directly call SetTouchActionFromMain. if (source == blink::mojom::InputEventResultSource::kCompositorThread) OnSetCompositorAllowedTouchAction(touch_action->touch_action); - else if (source == blink::mojom::InputEventResultSource::kMainThread) - OnSetTouchAction(touch_action->touch_action); - else - NOTREACHED(); } // TODO(crbug.com/953547): find a proper way to stop the timeout monitor. @@ -736,25 +733,6 @@ return gesture_event_queue_.IsFlingActiveForTest(); } -void InputRouterImpl::OnSetTouchAction(cc::TouchAction touch_action) { - TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction", "action", - cc::TouchActionToString(touch_action)); - - // It is possible we get a touch action for a touch start that is no longer - // in the queue. eg. Events that have fired the Touch ACK timeout. - if (!touch_event_queue_.IsPendingAckTouchStart()) - return; - - touch_action_filter_.AppendToGestureSequenceForDebugging("S"); - touch_action_filter_.AppendToGestureSequenceForDebugging( - base::NumberToString(static_cast<int>(touch_action)).c_str()); - touch_action_filter_.OnSetTouchAction(touch_action); - touch_event_queue_.StopTimeoutMonitor(); - - // TouchAction::kNone should disable the touch ack timeout. - UpdateTouchAckTimeoutEnabled(); -} - void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { // TouchAction::kNone will prevent scrolling, in which case the timeout serves // little purpose. It's also a strong signal that touch handling is critical
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h index bb3186b..3b2124b9 100644 --- a/content/browser/renderer_host/input/input_router_impl.h +++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -85,7 +85,6 @@ mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewHost() override; void StopFling() override; - void OnSetTouchAction(cc::TouchAction touch_action) override; void ForceSetTouchActionAuto() override; // InputHandlerHost impl
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index 9461366..666f2c73 100644 --- a/content/browser/renderer_host/input/input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -438,11 +438,25 @@ void PressAndSetTouchActionAuto() { PressTouchPoint(1, 1); SendTouchEvent(); - input_router_->OnSetTouchAction(cc::TouchAction::kAuto); + input_router_->SetTouchActionFromMain(cc::TouchAction::kAuto); GetAndResetDispatchedMessages(); disposition_handler_->GetAndResetAckCount(); } + void TouchActionSetFromMainNotOverridden() { + input_router_->SetTouchActionFromMain(cc::TouchAction::kAuto); + ASSERT_TRUE(input_router_->AllowedTouchAction().has_value()); + EXPECT_EQ(input_router_->AllowedTouchAction().value(), + cc::TouchAction::kAuto); + input_router_->TouchEventHandled( + TouchEventWithLatencyInfo(touch_event_), + blink::mojom::InputEventResultSource::kMainThread, ui::LatencyInfo(), + blink::mojom::InputEventResultState::kNoConsumerExists, nullptr, + blink::mojom::TouchActionOptional::New(cc::TouchAction::kPanY)); + EXPECT_EQ(input_router_->AllowedTouchAction().value(), + cc::TouchAction::kAuto); + } + void ActiveTouchSequenceCountTest( blink::mojom::TouchActionOptionalPtr touch_action, blink::mojom::InputEventResultState state) { @@ -702,6 +716,12 @@ blink::mojom::InputEventResultState::kNoConsumerExists); } +// Test that after touch action is set from the main thread, the touch action +// won't be overridden by the call to TouchEventHandled. +TEST_F(InputRouterImplTest, TouchActionSetFromMainNotOverridden) { + TouchActionSetFromMainNotOverridden(); +} + TEST_F(InputRouterImplTest, TouchActionAutoWithAckStateConsumed) { base::Optional<cc::TouchAction> expected_touch_action; OnTouchEventAckWithAckState( @@ -764,7 +784,7 @@ PressTouchPoint(1, 1); SendTouchEvent(); - input_router_->OnSetTouchAction(cc::TouchAction::kAuto); + input_router_->SetTouchActionFromMain(cc::TouchAction::kAuto); EXPECT_TRUE(client_->GetAndResetFilterEventCalled()); DispatchedMessages touch_start_event = GetAndResetDispatchedMessages(); ASSERT_EQ(1U, touch_start_event.size()); @@ -908,7 +928,7 @@ // Precede the TouchCancel with an appropriate TouchStart; PressTouchPoint(1, 1); SendTouchEvent(); - input_router_->OnSetTouchAction(cc::TouchAction::kAuto); + input_router_->SetTouchActionFromMain(cc::TouchAction::kAuto); DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages(); ASSERT_EQ(1U, dispatched_messages.size()); ASSERT_TRUE(dispatched_messages[0]->ToEvent()); @@ -1302,7 +1322,7 @@ PressTouchPoint(1, 1); SendTouchEvent(); - input_router_->OnSetTouchAction(cc::TouchAction::kNone); + input_router_->SetTouchActionFromMain(cc::TouchAction::kNone); DispatchedMessages touch_press_event3 = GetAndResetDispatchedMessages(); ASSERT_EQ(1u, touch_press_event3.size()); ASSERT_TRUE(touch_press_event3[0]->ToEvent()); @@ -1323,7 +1343,7 @@ PressTouchPoint(1, 1); SendTouchEvent(); ResetTouchAction(); - input_router_->OnSetTouchAction(cc::TouchAction::kAuto); + input_router_->SetTouchActionFromMain(cc::TouchAction::kAuto); EXPECT_TRUE(TouchEventTimeoutEnabled()); } @@ -1616,7 +1636,7 @@ PressTouchPoint(1, 1); SendTouchEvent(); - input_router_->OnSetTouchAction(cc::TouchAction::kAuto); + input_router_->SetTouchActionFromMain(cc::TouchAction::kAuto); EXPECT_TRUE(client_->GetAndResetFilterEventCalled()); DispatchedMessages dispatched_messages = GetAndResetDispatchedMessages(); ASSERT_EQ(1U, dispatched_messages.size());
diff --git a/content/browser/renderer_host/input/mock_input_router.h b/content/browser/renderer_host/input/mock_input_router.h index de9cd99..c8e716d 100644 --- a/content/browser/renderer_host/input/mock_input_router.h +++ b/content/browser/renderer_host/input/mock_input_router.h
@@ -47,7 +47,6 @@ mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewHost() override; void StopFling() override {} - void OnSetTouchAction(cc::TouchAction touch_action) override {} void ForceSetTouchActionAuto() override {} void OnHasTouchEventHandlers(bool has_handlers) override; void WaitForInputProcessed(base::OnceClosure callback) override {}
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index be9220a..fa8228d 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -1786,7 +1786,7 @@ // Tests RWHI::ForwardGestureEvent(). PressTouchPoint(0, 1); SendTouchEvent(); - host_->input_router()->OnSetTouchAction(cc::TouchAction::kAuto); + widget_.SetTouchActionFromMain(cc::TouchAction::kAuto); dispatched_events = host_->mock_widget_input_handler_.GetAndResetDispatchedMessages(); CheckLatencyInfoComponentInMessage(dispatched_events,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 1e01f307..653245a7 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -410,6 +410,10 @@ return new_content_rendering_timeout_fired_; } + void SetTouchActionFromMain(cc::TouchAction touch_action) { + widget_.SetTouchActionFromMain(touch_action); + } + private: MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate, RenderProcessHost* process, @@ -919,7 +923,7 @@ void PressAndSetTouchActionAuto() { PressTouchPoint(0, 1); SendTouchEvent(); - widget_host_->input_router()->OnSetTouchAction(cc::TouchAction::kAuto); + widget_host_->SetTouchActionFromMain(cc::TouchAction::kAuto); MockWidgetInputHandler::MessageVector events = GetAndResetDispatchedMessages(); EXPECT_EQ("TouchStart", GetMessageNames(events)); @@ -1458,7 +1462,7 @@ EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(ui::MotionEvent::Action::DOWN, pointer_state().GetAction()); EXPECT_EQ(1U, pointer_state().GetPointerCount()); - widget_host_->input_router()->OnSetTouchAction(cc::TouchAction::kAuto); + widget_host_->SetTouchActionFromMain(cc::TouchAction::kAuto); view_->OnTouchEvent(&move); base::RunLoop().RunUntilIdle(); @@ -2395,8 +2399,8 @@ ui::PointerDetails(ui::EventPointerType::kTouch, 0)); view_->OnTouchEvent(&press0); - view_->GetFocusedWidget()->input_router()->OnSetTouchAction( - cc::TouchAction::kAuto); + static_cast<InputRouterImpl*>(view_->GetFocusedWidget()->input_router()) + ->SetTouchActionFromMain(cc::TouchAction::kAuto); base::RunLoop().RunUntilIdle(); MockWidgetInputHandler::MessageVector events = @@ -4235,7 +4239,7 @@ // The test sends an intermingled sequence of touch and gesture events. PressTouchPoint(0, 1); SendTouchEvent(); - widget_host_->input_router()->OnSetTouchAction(cc::TouchAction::kAuto); + widget_host_->SetTouchActionFromMain(cc::TouchAction::kAuto); MockWidgetInputHandler::MessageVector events = GetAndResetDispatchedMessages(); EXPECT_EQ("TouchStart", GetMessageNames(events)); @@ -5397,7 +5401,7 @@ // Simulate touch press and release to generate a GestureTap. generator.EnterPenPointerMode(); generator.PressTouch(); - widget_host_->input_router()->OnSetTouchAction(cc::TouchAction::kAuto); + widget_host_->SetTouchActionFromMain(cc::TouchAction::kAuto); generator.ReleaseTouch(); base::RunLoop().RunUntilIdle(); MockWidgetInputHandler::MessageVector events =
diff --git a/content/browser/sandbox_mac_unittest.mm b/content/browser/sandbox_mac_unittest.mm index 1ba270d..04963fa 100644 --- a/content/browser/sandbox_mac_unittest.mm +++ b/content/browser/sandbox_mac_unittest.mm
@@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" +#include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/memory/ref_counted.h" #include "base/posix/eintr_wrapper.h" @@ -256,4 +257,28 @@ ASSERT_TRUE(base::DeleteFile(temp_file_path)); } +MULTIPROCESS_TEST_MAIN(BuiltinAvailable) { + CheckCreateSeatbeltServer(); + + if (__builtin_available(macOS 10.10, *)) { + // Can't negate a __builtin_available condition. But success! + } else { + return 10; + } + + if (base::mac::IsAtLeastOS10_13()) { + if (__builtin_available(macOS 10.13, *)) { + // Can't negate a __builtin_available condition. But success! + } else { + return 13; + } + } + + return 0; +} + +TEST_F(SandboxMacTest, BuiltinAvailable) { + ExecuteInAllSandboxTypes("BuiltinAvailable", {}); +} + } // namespace content
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 7bcc883..cc7630ec 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -13395,8 +13395,16 @@ EXPECT_EQ(expected_touch_action, allowed_touch_action.value()); } +// Failes on Win. https://crbug.com/1097060 +#if defined(OS_WIN) +#define MAYBE_ChildFrameCrashMetrics_KilledWhileVisible \ + DISABLED_ChildFrameCrashMetrics_KilledWhileVisible +#else +#define MAYBE_ChildFrameCrashMetrics_KilledWhileVisible \ + ChildFrameCrashMetrics_KilledWhileVisible +#endif IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest, - ChildFrameCrashMetrics_KilledWhileVisible) { + MAYBE_ChildFrameCrashMetrics_KilledWhileVisible) { // Set-up a frame tree that helps verify what the metrics tracks: // 1) frames (12 frames are affected if B process gets killed) or // 2) crashes (simply 1 crash if B process gets killed)?
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 2fed7da..44bef94 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -1374,6 +1374,8 @@ GetGeneratedCodeCacheContext()->Initialize(code_cache_path, settings.size_in_bytes()); } + + font_access_manager_ = std::make_unique<FontAccessManagerImpl>(); } void StoragePartitionImpl::OnStorageServiceDisconnected() { @@ -1628,6 +1630,11 @@ return conversion_manager_.get(); } +FontAccessManagerImpl* StoragePartitionImpl::GetFontAccessManager() { + DCHECK(initialized_); + return font_access_manager_.get(); +} + ContentIndexContextImpl* StoragePartitionImpl::GetContentIndexContext() { DCHECK(initialized_); return content_index_context_.get();
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 5da8609f..7f352f5 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -32,6 +32,7 @@ #include "content/browser/content_index/content_index_context_impl.h" #include "content/browser/devtools/devtools_background_services_context_impl.h" #include "content/browser/dom_storage/dom_storage_context_wrapper.h" +#include "content/browser/font_access/font_access_manager_impl.h" #include "content/browser/indexed_db/indexed_db_control_wrapper.h" #include "content/browser/locks/lock_manager.h" #include "content/browser/notifications/platform_notification_context_impl.h" @@ -196,6 +197,7 @@ QuotaContext* GetQuotaContext(); NativeIOContext* GetNativeIOContext(); ConversionManagerImpl* GetConversionManager(); + FontAccessManagerImpl* GetFontAccessManager(); std::string GetPartitionDomain(); // blink::mojom::DomStorage interface. @@ -506,6 +508,7 @@ scoped_refptr<ContentIndexContextImpl> content_index_context_; std::unique_ptr<NativeIOContext> native_io_context_; std::unique_ptr<ConversionManagerImpl> conversion_manager_; + std::unique_ptr<FontAccessManagerImpl> font_access_manager_; // ReceiverSet for DomStorage, using the // ChildProcessSecurityPolicyImpl::Handle as the binding context type. The
diff --git a/content/common/navigation_params.mojom b/content/common/navigation_params.mojom index 9a0f1f2..e610aad 100644 --- a/content/common/navigation_params.mojom +++ b/content/common/navigation_params.mojom
@@ -97,33 +97,38 @@ // Routing id of the initiator of the navigation. This routing id may no // longer be valid by the time the navigation is seen by the browser process, // if the initiator frame is deleted before the navigation IPC arrives. A - // value of MSG_ROUTING_NONE indicates this navigation is not associated - // with a frame. - int32 initiator_routing_id; + // default value of MSG_ROUTING_NONE indicates this navigation is not + // associated with a frame. + int32 initiator_routing_id = -2; // -2 == MSG_ROUTING_NONE // Additional HTTP request headers. string headers; // net::URLRequest load flags (net::LOAD_NORMAL) by default). - int32 load_flags; + int32 load_flags = 0; // 0 == net::LOAD_NORMAL // True if the ServiceWorker should be skipped. - bool skip_service_worker; + bool skip_service_worker = false; // Indicates the request context type. - blink.mojom.RequestContextType request_context_type; + blink.mojom.RequestContextType request_context_type = + blink.mojom.RequestContextType.UNSPECIFIED; // Indicates the request destination. - network.mojom.RequestDestination request_destination; + network.mojom.RequestDestination request_destination = + network.mojom.RequestDestination.kEmpty; // The mixed content context type for potential mixed content checks. + // + // [Native] enums are by default initialized to 0 + // (i.e. blink::WebMixedContentContextType::kNotMixedContent below). MixedContentContextType mixed_content_context_type; // Whether or not the navigation has been initiated by a form submission. - bool is_form_submission; + bool is_form_submission = false; // Whether or not the navigation has been initiated by a link click. - bool was_initiated_by_link_click; + bool was_initiated_by_link_click = false; // See WebSearchableFormData for a description of these. url.mojom.Url searchable_form_url; @@ -181,6 +186,8 @@ blink.mojom.Referrer referrer; // The type of transition. + // + // [Native] enums are by default initialized to 0 (i.e. PAGE_TRANSITION_LINK). PageTransition transition; // Type of navigation. @@ -206,7 +213,7 @@ // Bitmask that has whether or not to request a Preview version of the // document for various preview types or let the browser decide. // Defined in third_party/blink/public/common/loader/previews_state.h. - int32 previews_state; + int32 previews_state = 0; // 0 == PREVIEWS_UNSPECIFIED // The navigationStart time exposed through the Navigation Timing API to JS. mojo_base.mojom.TimeTicks navigation_start;
diff --git a/content/public/browser/permission_type.cc b/content/public/browser/permission_type.cc index 8bb88e8..f39b27b7 100644 --- a/content/public/browser/permission_type.cc +++ b/content/public/browser/permission_type.cc
@@ -97,6 +97,8 @@ return PermissionType::STORAGE_ACCESS_GRANT; case PermissionName::WINDOW_PLACEMENT: return PermissionType::WINDOW_PLACEMENT; + case PermissionName::FONT_ACCESS: + return PermissionType::FONT_ACCESS; } NOTREACHED();
diff --git a/content/public/browser/permission_type.h b/content/public/browser/permission_type.h index 764190e..f0d17e4 100644 --- a/content/public/browser/permission_type.h +++ b/content/public/browser/permission_type.h
@@ -49,6 +49,7 @@ STORAGE_ACCESS_GRANT = 27, CAMERA_PAN_TILT_ZOOM = 28, WINDOW_PLACEMENT = 29, + FONT_ACCESS = 30, // Always keep this at the end. NUM,
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc index d0396ea3..570dc6fa 100644 --- a/content/shell/browser/shell_permission_manager.cc +++ b/content/shell/browser/shell_permission_manager.cc
@@ -55,6 +55,7 @@ case PermissionType::VR: case PermissionType::AR: case PermissionType::CAMERA_PAN_TILT_ZOOM: + case PermissionType::FONT_ACCESS: return false; }
diff --git a/content/test/data/accessibility/html/input-file-expected-android.txt b/content/test/data/accessibility/html/input-file-expected-android.txt index 2e514e1..4d53f70 100644 --- a/content/test/data/accessibility/html/input-file-expected-android.txt +++ b/content/test/data/accessibility/html/input-file-expected-android.txt
@@ -1,3 +1,3 @@ android.webkit.WebView focusable focused scrollable ++android.view.View -++++android.widget.Button role_description='button' clickable focusable name='Choose File' \ No newline at end of file +++++android.widget.Button role_description='button' clickable focusable name='No file chosen, Choose File'
diff --git a/content/test/data/accessibility/html/input-file-expected-auralinux.txt b/content/test/data/accessibility/html/input-file-expected-auralinux.txt index 0c1b255..c765e17 100644 --- a/content/test/data/accessibility/html/input-file-expected-auralinux.txt +++ b/content/test/data/accessibility/html/input-file-expected-auralinux.txt
@@ -1,4 +1,4 @@ [document web] ++[section] -++++[push button] name='Choose File' -++++++[push button] name='Choose File' +++++[push button] name='No file chosen, Choose File' +++++++[push button] name='Choose File' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-file-expected-blink.txt b/content/test/data/accessibility/html/input-file-expected-blink.txt index 26a674cf..565453a 100644 --- a/content/test/data/accessibility/html/input-file-expected-blink.txt +++ b/content/test/data/accessibility/html/input-file-expected-blink.txt
@@ -1,7 +1,7 @@ rootWebArea ++genericContainer ignored ++++genericContainer -++++++button inputType='file' name='Choose File' value='No file chosen' +++++++button inputType='file' name='No file chosen, Choose File' value='No file chosen' ++++++++button inputType='button' name='Choose File' ++++++++++staticText name='Choose File' -++++++++++++inlineTextBox name='Choose File' +++++++++++++inlineTextBox name='Choose File' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-file-expected-mac.txt b/content/test/data/accessibility/html/input-file-expected-mac.txt index 8ce79f7..90591b4 100644 --- a/content/test/data/accessibility/html/input-file-expected-mac.txt +++ b/content/test/data/accessibility/html/input-file-expected-mac.txt
@@ -1,4 +1,4 @@ AXWebArea ++AXGroup -++++AXButton AXTitle='Choose File' -++++++AXButton AXTitle='Choose File' +++++AXButton AXTitle='No file chosen, Choose File' +++++++AXButton AXTitle='Choose File' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-file-expected-uia-win.txt b/content/test/data/accessibility/html/input-file-expected-uia-win.txt index 4791dbd1..864eb85c 100644 --- a/content/test/data/accessibility/html/input-file-expected-uia-win.txt +++ b/content/test/data/accessibility/html/input-file-expected-uia-win.txt
@@ -1,4 +1,4 @@ Document ++Group IsControlElement=false -++++Button Name='Choose File' -++++++Button Name='Choose File' +++++Button Name='No file chosen, Choose File' +++++++Button Name='Choose File' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-file-expected-win.txt b/content/test/data/accessibility/html/input-file-expected-win.txt index 3f98ef0..32305241 100644 --- a/content/test/data/accessibility/html/input-file-expected-win.txt +++ b/content/test/data/accessibility/html/input-file-expected-win.txt
@@ -1,4 +1,4 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>' ++IA2_ROLE_SECTION ia2_hypertext='<obj0>' -++++ROLE_SYSTEM_PUSHBUTTON name='Choose File' value='No file chosen' FOCUSABLE ia2_hypertext='<obj0>' -++++++ROLE_SYSTEM_PUSHBUTTON name='Choose File' FOCUSABLE ia2_hypertext='Choose File' +++++ROLE_SYSTEM_PUSHBUTTON name='No file chosen, Choose File' value='No file chosen' FOCUSABLE ia2_hypertext='<obj0>' +++++++ROLE_SYSTEM_PUSHBUTTON name='Choose File' FOCUSABLE ia2_hypertext='Choose File' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/legend-expected-blink.txt b/content/test/data/accessibility/html/legend-expected-blink.txt index 1dec39a..cf24c2c7b 100644 --- a/content/test/data/accessibility/html/legend-expected-blink.txt +++ b/content/test/data/accessibility/html/legend-expected-blink.txt
@@ -11,7 +11,6 @@ ++++++++++textField ++++++++++++genericContainer ++++++++++staticText name=' Rendering Engine: ' -++++++++++++inlineTextBox name=' ' -++++++++++++inlineTextBox name='Rendering Engine: ' +++++++++++++inlineTextBox name=' Rendering Engine: ' ++++++++++textField ++++++++++++genericContainer
diff --git a/content/test/data/accessibility/html/modal-dialog-opened-expected-blink.txt b/content/test/data/accessibility/html/modal-dialog-opened-expected-blink.txt index 1976aea..7aa8061 100644 --- a/content/test/data/accessibility/html/modal-dialog-opened-expected-blink.txt +++ b/content/test/data/accessibility/html/modal-dialog-opened-expected-blink.txt
@@ -11,5 +11,5 @@ ++++++++popUpButton collapsed ignored invisible value='This should be pruned out of the tree.' ++++++++++menuListPopup invisible ++++++++++++menuListOption ignored name='This should be pruned out of the tree.' selected=true -++++++button ignored invisible name='Choose File' value='No file chosen' -++++++dialog ignored invisible +++++++button ignored invisible name='No file chosen, Choose File' value='No file chosen' +++++++dialog ignored invisible \ No newline at end of file
diff --git a/content/test/mock_widget.cc b/content/test/mock_widget.cc index 646222b..418be6b 100644 --- a/content/test/mock_widget.cc +++ b/content/test/mock_widget.cc
@@ -41,7 +41,17 @@ void MockWidget::GetWidgetInputHandler( mojo::PendingReceiver<blink::mojom::WidgetInputHandler> request, - mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) {} + mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) { + // Some tests try to reinitialize a host against same MockWidget multiple + // times. We assume this happens against the same host and avoid changing the + // binding. + if (!input_handler_host_.is_bound()) + input_handler_host_.Bind(std::move(host)); +} + +void MockWidget::SetTouchActionFromMain(cc::TouchAction touch_action) { + input_handler_host_->SetTouchActionFromMain(touch_action); +} void MockWidget::UpdateVisualProperties( const blink::VisualProperties& visual_properties) {
diff --git a/content/test/mock_widget.h b/content/test/mock_widget.h index e9546c4..88ce3e2 100644 --- a/content/test/mock_widget.h +++ b/content/test/mock_widget.h
@@ -11,6 +11,7 @@ #include <utility> #include "mojo/public/cpp/bindings/associated_receiver.h" +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/common/widget/visual_properties.h" #include "third_party/blink/public/mojom/page/widget.mojom.h" @@ -28,6 +29,7 @@ const std::vector<std::pair<gfx::Rect, gfx::Rect>>& ReceivedScreenRects(); void ClearScreenRects(); + void SetTouchActionFromMain(cc::TouchAction touch_action); // blink::mojom::Widget overrides. void ForceRedraw(ForceRedrawCallback callback) override; @@ -47,6 +49,7 @@ std::vector<blink::VisualProperties> visual_properties_; std::vector<std::pair<gfx::Rect, gfx::Rect>> screen_rects_; std::vector<UpdateScreenRectsCallback> screen_rects_callbacks_; + mojo::Remote<blink::mojom::WidgetInputHandlerHost> input_handler_host_; mojo::AssociatedReceiver<blink::mojom::Widget> blink_widget_{this}; };
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h index 3a8b351..b79fcb186 100644 --- a/fuchsia/engine/browser/frame_impl.h +++ b/fuchsia/engine/browser/frame_impl.h
@@ -268,7 +268,7 @@ std::unique_ptr<MediaPlayerImpl> media_player_; std::unique_ptr<CastStreamingSessionClient> cast_streaming_session_client_; - on_load_script_injector::OnLoadScriptInjectorHost script_injector_; + on_load_script_injector::OnLoadScriptInjectorHost<uint64_t> script_injector_; fidl::Binding<fuchsia::web::Frame> binding_; media_control::MediaBlocker media_blocker_;
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index 35ae864..1263185 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -10226,7 +10226,7 @@ cipd_version: "refs/heads/master" cmd: "recipes" } - properties: "{\"$build/archive\":{\"archive_datas\":[{\"archive_type\":\"ARCHIVE_TYPE_ZIP\",\"dirs\":[\"locales\",\"swiftshader\"],\"files\":[\"chrome\",\"chrome_100_percent.pak\",\"chrome_200_percent.pak\",\"crashpad_handler\",\"headless_lib.pak\",\"icudtl.dat\",\"libminigbm.so\",\"nacl_helper\",\"nacl_irt_x86_64.nexe\",\"resources.pak\",\"snapshot_blob.bin\"],\"gcs_bucket\":\"ash-chromium-on-linux-prebuilts\",\"gcs_path\":\"x86_64/{%position%}/ash-chromium.zip\"}]},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.fyi\",\"recipe\":\"chromium\"}" + properties: "{\"$build/archive\":{\"archive_datas\":[{\"archive_type\":\"ARCHIVE_TYPE_ZIP\",\"dirs\":[\"locales\",\"swiftshader\"],\"files\":[\"chrome\",\"chrome_100_percent.pak\",\"chrome_200_percent.pak\",\"crashpad_handler\",\"headless_lib.pak\",\"icudtl.dat\",\"libminigbm.so\",\"nacl_helper\",\"nacl_irt_x86_64.nexe\",\"resources.pak\",\"snapshot_blob.bin\"],\"gcs_bucket\":\"ash-chromium-on-linux-prebuilts\",\"gcs_path\":\"x86_64/{%position%}/ash-chromium.zip\",\"latest_upload\":{\"gcs_file_content\":\"{%position%}\",\"gcs_path\":\"x86_64/latest/ash-chromium.txt\"}}]},\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.fyi\",\"recipe\":\"chromium\"}" execution_timeout_secs: 36000 build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/subprojects/chromium/master-only/ci.star b/infra/config/subprojects/chromium/master-only/ci.star index 48f5dce..abf057f 100644 --- a/infra/config/subprojects/chromium/master-only/ci.star +++ b/infra/config/subprojects/chromium/master-only/ci.star
@@ -1516,6 +1516,10 @@ "gcs_bucket": "ash-chromium-on-linux-prebuilts", "gcs_path": "x86_64/{%position%}/ash-chromium.zip", "archive_type": "ARCHIVE_TYPE_ZIP", + "latest_upload": { + "gcs_path": "x86_64/latest/ash-chromium.txt", + "gcs_file_content": "{%position%}", + }, }, ], },
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm index 901efa3..b378631e 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -208,7 +208,12 @@ [[AppStartupParameters alloc] initWithURLs:URLs]; startupParams.launchInIncognito = YES; [connectionInformation setStartupParameters:startupParams]; - return YES; + return [self continueUserActivityURLs:URLs + applicationIsActive:applicationIsActive + tabOpener:tabOpener + connectionInformation:connectionInformation + startupInformation:startupInformation + Incognito:YES]; } else { // Do nothing for unknown activity type. @@ -267,6 +272,65 @@ return YES; } ++ (void)openMultipleTabsWithConnectionInformation: + (id<ConnectionInformation>)connectionInformation + tabOpener:(id<TabOpening>)tabOpener { + ApplicationModeForTabOpening mode = + connectionInformation.startupParameters.launchInIncognito + ? ApplicationModeForTabOpening::INCOGNITO + : ApplicationModeForTabOpening::NORMAL; + + BOOL dismissOmnibox = [[connectionInformation startupParameters] + postOpeningAction] != FOCUS_OMNIBOX; + + // Using a weak reference to |connectionInformation| to solve a memory leak + // issue. |tabOpener| and |connectionInformation| are the same object in + // some cases (SceneController). This retains the object while the block + // exists. Then this block is passed around and in some cases it ends up + // stored in BrowserViewController. This results in a memory leak that looks + // like this: SceneController -> BrowserViewWrangler -> BrowserCoordinator + // -> BrowserViewController -> SceneController + __weak id<ConnectionInformation> weakConnectionInfo = connectionInformation; + + [tabOpener + dismissModalsAndOpenMultipleTabsInMode:mode + URLs:weakConnectionInfo + .startupParameters.URLs + dismissOmnibox:dismissOmnibox + completion:^{ + weakConnectionInfo.startupParameters = nil; + }]; +} + ++ (BOOL)continueUserActivityURLs:(const std::vector<GURL>&)webpageURLs + applicationIsActive:(BOOL)applicationIsActive + tabOpener:(id<TabOpening>)tabOpener + connectionInformation: + (id<ConnectionInformation>)connectionInformation + startupInformation:(id<StartupInformation>)startupInformation + Incognito:(BOOL)Incognito { + if (applicationIsActive && ![startupInformation isPresentingFirstRunUI]) { + // The app is already active so the applicationDidBecomeActive: method will + // never be called. Open the requested URLs immediately. + [self openMultipleTabsWithConnectionInformation:connectionInformation + tabOpener:tabOpener]; + return YES; + } + + // Don't record the first action as a user action, since it will not be + // initiated by the user. + [startupInformation resetFirstUserActionRecorder]; + + if (![connectionInformation startupParameters]) { + AppStartupParameters* startupParams = + [[AppStartupParameters alloc] initWithURLs:webpageURLs]; + + startupParams.launchInIncognito = Incognito; + [connectionInformation setStartupParameters:startupParams]; + } + return YES; +} + + (void)performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler tabOpener:(id<TabOpening>)tabOpener @@ -315,32 +379,8 @@ } if (!connectionInformation.startupParameters.URLs.empty()) { - ApplicationModeForTabOpening mode = - connectionInformation.startupParameters.launchInIncognito - ? ApplicationModeForTabOpening::INCOGNITO - : ApplicationModeForTabOpening::NORMAL; - - BOOL dismissOmnibox = [[connectionInformation startupParameters] - postOpeningAction] != FOCUS_OMNIBOX; - - // Using a weak reference to |connectionInformation| to solve a memory leak - // issue. |tabOpener| and |connectionInformation| are the same object in - // some cases (SceneController). This retains the object while the block - // exists. Then this block is passed around and in some cases it ends up - // stored in BrowserViewController. This results in a memory leak that looks - // like this: SceneController -> BrowserViewWrangler -> BrowserCoordinator - // -> BrowserViewController -> SceneController - __weak id<ConnectionInformation> weakConnectionInfo = connectionInformation; - - [tabOpener - dismissModalsAndOpenMultipleTabsInMode:mode - URLs:weakConnectionInfo - .startupParameters.URLs - dismissOmnibox:dismissOmnibox - completion:^{ - weakConnectionInfo.startupParameters = - nil; - }]; + [self openMultipleTabsWithConnectionInformation:connectionInformation + tabOpener:tabOpener]; return; }
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm index ae811ad..9b3ab7a 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -594,6 +594,16 @@ [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI]; + std::vector<GURL> URLs; + for (NSURL* URL in urls) { + URLs.push_back(net::GURLWithNSURL(URL)); + } + + AppStartupParameters* startupParams = + [[AppStartupParameters alloc] initWithURLs:URLs]; + [[[connectionInformationMock stub] andReturn:startupParams] + startupParameters]; + MockTabOpener* tabOpener = [[MockTabOpener alloc] init]; // Action.
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index c3d8ad9..751773d 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -719,6 +719,9 @@ <message name="IDS_IOS_DISCOVER_FEED_MENU_LEARN_MORE_ITEM" desc="The 'Learn More' action for the Discover feed header menu."> Learn More </message> + <message name="IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ACTIVITY_ITEM" desc="The 'Manage Activity' action for the Discover feed header menu."> + Manage Activity + </message> <message name="IDS_IOS_DISCOVER_FEED_MENU_MANAGE_INTERESTS_ITEM" desc="The 'Manage Interests' action for the Discover feed header menu."> Manage Interests </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ACTIVITY_ITEM.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ACTIVITY_ITEM.png.sha1 new file mode 100644 index 0000000..4a507f7 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ACTIVITY_ITEM.png.sha1
@@ -0,0 +1 @@ +f2e5ed92fe61e6273b00ede67dee92c411afd017 \ No newline at end of file
diff --git a/ios/chrome/browser/browsing_data/BUILD.gn b/ios/chrome/browser/browsing_data/BUILD.gn index adac5f5..cb074006 100644 --- a/ios/chrome/browser/browsing_data/BUILD.gn +++ b/ios/chrome/browser/browsing_data/BUILD.gn
@@ -45,6 +45,7 @@ "//components/open_from_clipboard", "//components/password_manager/core/browser", "//components/prefs", + "//components/safe_browsing/core:features", "//components/sessions", "//components/signin/ios/browser", "//components/translate/core/browser:browser", @@ -57,6 +58,7 @@ "//ios/chrome/browser/language", "//ios/chrome/browser/passwords", "//ios/chrome/browser/reading_list:reading_list_remover", + "//ios/chrome/browser/safe_browsing", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/sessions", "//ios/chrome/browser/sessions:serialisation",
diff --git a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm index 2123ad2..1f6ad4b1 100644 --- a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm +++ b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm
@@ -33,6 +33,7 @@ #include "components/open_from_clipboard/clipboard_recent_content.h" #include "components/password_manager/core/browser/password_store.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/core/features.h" #include "components/search_engines/template_url_service.h" #include "components/sessions/core/tab_restore_service.h" #include "components/signin/ios/browser/account_consistency_service.h" @@ -52,6 +53,7 @@ #include "ios/chrome/browser/language/url_language_histogram_factory.h" #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" #include "ios/chrome/browser/reading_list/reading_list_remover_helper.h" +#import "ios/chrome/browser/safe_browsing/safe_browsing_service.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #import "ios/chrome/browser/sessions/session_service_ios.h" @@ -294,14 +296,24 @@ if (IsRemoveDataMaskSet(mask, BrowsingDataRemoveMask::REMOVE_COOKIES)) { base::RecordAction(base::UserMetricsAction("ClearBrowsingData_Cookies")); + net::CookieDeletionInfo::TimeRange deletion_time_range = + net::CookieDeletionInfo::TimeRange(delete_begin, delete_end); base::PostTask( FROM_HERE, task_traits, base::BindOnce( - &ClearCookies, context_getter_, - net::CookieDeletionInfo::TimeRange(delete_begin, delete_end), + &ClearCookies, context_getter_, deletion_time_range, base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask), current_task_runner, FROM_HERE, CreatePendingTaskCompletionClosure()))); + if (base::FeatureList::IsEnabled( + safe_browsing::kSafeBrowsingAvailableOnIOS) && + !browser_state_->IsOffTheRecord()) { + GetApplicationContext()->GetSafeBrowsingService()->ClearCookies( + deletion_time_range, + base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask), + current_task_runner, FROM_HERE, + CreatePendingTaskCompletionClosure())); + } } // There is no need to clean the remaining types of data for off-the-record
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h index a896e061..30f6d9e 100644 --- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h
@@ -46,6 +46,11 @@ // InfobarBannerUserInitiatedDismissalResponse. void BannerDismissedByUser(OverlayRequest* request, OverlayResponse* response); + // Used as a callback for OverlayResponses dispatched through |request|'s + // callback manager. The OverlayDispatchCallback is created with an + // OverlayResponseSupport that guarantees that |response| is created with an + // InfobarBannerRemoveInfobarResponse. + void RemoveInfobar(OverlayRequest* request, OverlayResponse* response); // OverlayRequestCallbackInstaller: const OverlayRequestSupport* GetRequestSupport() const override;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm index 8f79e7b1..28b1ff7 100644 --- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm
@@ -7,6 +7,8 @@ #include "base/bind.h" #include "base/callback.h" #include "base/check.h" +#include "ios/chrome/browser/infobars/infobar_ios.h" +#include "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h" #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h" #include "ios/chrome/browser/infobars/overlays/infobar_overlay_util.h" @@ -62,6 +64,16 @@ interaction_handler_->BannerDismissedByUser(infobar); } +void InfobarBannerOverlayRequestCallbackInstaller::RemoveInfobar( + OverlayRequest* request, + OverlayResponse* response) { + InfoBarIOS* infobar = GetOverlayRequestInfobar(request); + if (!infobar) + return; + InfoBarManagerImpl::FromWebState(request->GetQueueWebState()) + ->RemoveInfoBar(infobar); +} + #pragma mark - OverlayRequestCallbackInstaller const OverlayRequestSupport* @@ -87,4 +99,9 @@ &InfobarBannerOverlayRequestCallbackInstaller::BannerDismissedByUser, weak_factory_.GetWeakPtr(), request), InfobarBannerUserInitiatedDismissalResponse::ResponseSupport())); + manager->AddDispatchCallback(OverlayDispatchCallback( + base::BindRepeating( + &InfobarBannerOverlayRequestCallbackInstaller::RemoveInfobar, + weak_factory_.GetWeakPtr(), request), + InfobarBannerRemoveInfobarResponse::ResponseSupport())); }
diff --git a/ios/chrome/browser/ios_chrome_main_parts.mm b/ios/chrome/browser/ios_chrome_main_parts.mm index 6fbcd03..d8b4536 100644 --- a/ios/chrome/browser/ios_chrome_main_parts.mm +++ b/ios/chrome/browser/ios_chrome_main_parts.mm
@@ -77,6 +77,8 @@ #endif namespace { + +#if BUILDFLAG(USE_ALLOCATOR_SHIM) // Do not install allocator shim on iOS 13.4 due to high crash volume on this // particular version of OS. TODO(crbug.com/1108219): Remove this workaround // when/if the bug gets fixed. @@ -84,6 +86,8 @@ return !base::ios::IsRunningOnOrLater(13, 4, 0) || base::ios::IsRunningOnOrLater(13, 5, 0); } +#endif + } // namespace IOSChromeMainParts::IOSChromeMainParts(
diff --git a/ios/chrome/browser/net/BUILD.gn b/ios/chrome/browser/net/BUILD.gn index 3d1cb2b..4ed5f6f 100644 --- a/ios/chrome/browser/net/BUILD.gn +++ b/ios/chrome/browser/net/BUILD.gn
@@ -32,7 +32,6 @@ "//components/update_client", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/browsing_data", "//ios/net", "//ios/web/common", "//net",
diff --git a/ios/chrome/browser/omaha/omaha_service.h b/ios/chrome/browser/omaha/omaha_service.h index 1385429..96c7c27 100644 --- a/ios/chrome/browser/omaha/omaha_service.h +++ b/ios/chrome/browser/omaha/omaha_service.h
@@ -172,6 +172,9 @@ pending_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + // Whether the service has been started. + bool started_; + // The timer that call this object back when needed. base::OneShotTimer timer_;
diff --git a/ios/chrome/browser/omaha/omaha_service.mm b/ios/chrome/browser/omaha/omaha_service.mm index 6657e612..6775b2e 100644 --- a/ios/chrome/browser/omaha/omaha_service.mm +++ b/ios/chrome/browser/omaha/omaha_service.mm
@@ -332,6 +332,8 @@ } OmahaService* service = GetInstance(); + service->StartInternal(); + service->set_upgrade_recommended_callback(callback); // This should only be called once. DCHECK(!service->pending_url_loader_factory_ || @@ -353,23 +355,22 @@ service->StopInternal(); } -OmahaService::OmahaService() - : schedule_(true), - application_install_date_(0), - sending_install_event_(false) { - StartInternal(); -} +OmahaService::OmahaService() : OmahaService(/*schedule=*/true) {} OmahaService::OmahaService(bool schedule) - : schedule_(schedule), + : started_(false), + schedule_(schedule), application_install_date_(0), - sending_install_event_(false) { - StartInternal(); -} + sending_install_event_(false) {} OmahaService::~OmahaService() {} void OmahaService::StartInternal() { + if (started_) { + return; + } + started_ = true; + // Start the provider at the same time as the rest of the service. ios::GetChromeBrowserProvider()->GetOmahaServiceProvider()->Start(); @@ -432,6 +433,10 @@ } void OmahaService::StopInternal() { + if (!started_) { + return; + } + ios::GetChromeBrowserProvider()->GetOmahaServiceProvider()->Stop(); }
diff --git a/ios/chrome/browser/omaha/omaha_service_unittest.mm b/ios/chrome/browser/omaha/omaha_service_unittest.mm index 0e59b0c3..19c5616 100644 --- a/ios/chrome/browser/omaha/omaha_service_unittest.mm +++ b/ios/chrome/browser/omaha/omaha_service_unittest.mm
@@ -115,6 +115,8 @@ "<ping active=\"1\" ad=\"-2\" rd=\"-2\"/></app></request>"; OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); std::string content = service.GetPingContent( @@ -141,6 +143,8 @@ "<ping active=\"1\" ad=\"-2\" rd=\"-2\"/></app></request>"; OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); std::string content = service.GetPingContent( @@ -171,6 +175,8 @@ // First install. OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); CleanService(&service, ""); @@ -207,6 +213,8 @@ TEST_F(OmahaServiceTest, SendPingSuccess) { base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -241,6 +249,8 @@ TEST_F(OmahaServiceTest, ParseAndEchoLastServerDate) { OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -288,6 +298,8 @@ TEST_F(OmahaServiceTest, SendInstallEventSuccess) { base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -320,6 +332,8 @@ TEST_F(OmahaServiceTest, SendPingReceiveUpdate) { base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -365,6 +379,8 @@ TEST_F(OmahaServiceTest, SendPingFailure) { base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -416,6 +432,8 @@ std::string version_string = version_info::GetVersionNumber(); base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.number_of_tries_ = 5; @@ -426,6 +444,8 @@ service.PersistStates(); OmahaService service2(false); + service2.StartInternal(); + EXPECT_EQ(service.number_of_tries_, 5); EXPECT_EQ(service2.last_sent_time_, now - base::TimeDelta::FromSeconds(1)); EXPECT_EQ(service2.next_tries_time_, now + base::TimeDelta::FromSeconds(2)); @@ -449,6 +469,8 @@ TEST_F(OmahaServiceTest, ActivePingAfterInstallEventTest) { base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -483,6 +505,8 @@ TEST_F(OmahaServiceTest, NonSpammingTest) { base::Time now = base::Time::Now(); OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_); @@ -516,6 +540,8 @@ TEST_F(OmahaServiceTest, InstallRetryTest) { OmahaService service(false); + service.StartInternal(); + service.set_upgrade_recommended_callback( base::Bind(&OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); service.InitializeURLLoaderFactory(test_shared_url_loader_factory_);
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc index 2afb58be..d8a977a 100644 --- a/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc +++ b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.cc
@@ -9,3 +9,5 @@ OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerShowModalResponse); OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerUserInitiatedDismissalResponse); + +OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerRemoveInfobarResponse);
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h index 6f8e30b..6fb81887 100644 --- a/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h +++ b/ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h
@@ -21,4 +21,8 @@ DEFINE_STATELESS_OVERLAY_RESPONSE_INFO( InfobarBannerUserInitiatedDismissalResponse); +// Response info used to create dispatched OverlayResponses that notify the +// model layer that the request's Infobar should be removed. +DEFINE_STATELESS_OVERLAY_RESPONSE_INFO(InfobarBannerRemoveInfobarResponse); + #endif // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_RESPONSES_H_
diff --git a/ios/chrome/browser/safe_browsing/BUILD.gn b/ios/chrome/browser/safe_browsing/BUILD.gn index bf8b57b..45452191 100644 --- a/ios/chrome/browser/safe_browsing/BUILD.gn +++ b/ios/chrome/browser/safe_browsing/BUILD.gn
@@ -52,6 +52,7 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/content_settings", "//ios/chrome/browser/history", + "//ios/chrome/browser/net", "//ios/chrome/browser/prerender", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", @@ -176,6 +177,8 @@ "//ios/chrome/test:test_support", "//ios/web/public", "//ios/web/public/test", + "//net:test_support", + "//net/traffic_annotation:test_support", "//services/network/public/cpp", "//testing/gmock", "//testing/gtest",
diff --git a/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.h b/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.h index c2eb65d..a3d5c7b 100644 --- a/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.h +++ b/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.h
@@ -32,6 +32,8 @@ web::WebState* web_state) override; bool CanCheckUrl(const GURL& url) const override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; + void ClearCookies(const net::CookieDeletionInfo::TimeRange& creation_range, + base::OnceClosure callback) override; protected: ~FakeSafeBrowsingService() override;
diff --git a/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.mm b/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.mm index ff4f963..e6f462f 100644 --- a/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.mm +++ b/ios/chrome/browser/safe_browsing/fake_safe_browsing_service.mm
@@ -85,3 +85,9 @@ return base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &url_loader_factory_); } + +void FakeSafeBrowsingService::ClearCookies( + const net::CookieDeletionInfo::TimeRange& creation_range, + base::OnceClosure callback) { + DCHECK_CURRENTLY_ON(web::WebThread::UI); +}
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_service.h b/ios/chrome/browser/safe_browsing/safe_browsing_service.h index a764b521..fcd2bedb 100644 --- a/ios/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/ios/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -5,7 +5,9 @@ #ifndef IOS_CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ #define IOS_CHROME_BROWSER_SAFE_BROWSING_SAFE_BROWSING_SERVICE_H_ +#include "base/callback.h" #include "base/memory/ref_counted.h" +#include "net/cookies/cookie_deletion_info.h" #include "url/gurl.h" class PrefService; @@ -58,6 +60,12 @@ virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() = 0; + // Clears cookies if the given deletion time range is for "all time". Calls + // the given |callback| once deletion is complete. + virtual void ClearCookies( + const net::CookieDeletionInfo::TimeRange& creation_range, + base::OnceClosure callback) = 0; + protected: SafeBrowsingService() = default; virtual ~SafeBrowsingService() = default;
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.h b/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.h index a9b5ff3b..ff90b00 100644 --- a/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.h +++ b/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.h
@@ -44,6 +44,8 @@ web::WebState* web_state) override; bool CanCheckUrl(const GURL& url) const override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; + void ClearCookies(const net::CookieDeletionInfo::TimeRange& creation_range, + base::OnceClosure callback) override; private: // A helper class for enabling/disabling Safe Browsing and maintaining state @@ -63,7 +65,8 @@ void Initialize( scoped_refptr<SafeBrowsingServiceImpl> safe_browsing_service, mojo::PendingReceiver<network::mojom::NetworkContext> - network_context_receiver); + network_context_receiver, + const base::FilePath& safe_browsing_data_path); // Disables Safe Browsing, and destroys the network context and URL loader // factory used by the SafeBrowsingDatabaseManager. @@ -72,6 +75,9 @@ // Enables or disables Safe Browsing database updates and lookups. void SetSafeBrowsingEnabled(bool enabled); + // Clears all cookies. Calls the given |callback| when deletion is complete. + void ClearAllCookies(base::OnceClosure callback); + private: friend base::RefCountedThreadSafe<IOThreadEnabler>; ~IOThreadEnabler(); @@ -80,8 +86,9 @@ // queries. void StartSafeBrowsingDBManager(); - // Constructs a URLRequestContext. - void SetUpURLRequestContext(); + // Constructs a URLRequestContext, using the given path as the location for + // the cookie store. + void SetUpURLRequestContext(const base::FilePath& safe_browsing_data_path); // Constructs a SharedURLLoaderFactory. void SetUpURLLoaderFactory(
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.mm b/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.mm index dbe7243..7d9017b 100644 --- a/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.mm +++ b/ios/chrome/browser/safe_browsing/safe_browsing_service_impl.mm
@@ -18,11 +18,14 @@ #include "components/safe_browsing/core/features.h" #include "components/safe_browsing/core/realtime/url_lookup_service.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/net/cookie_util.h" #import "ios/chrome/browser/safe_browsing/real_time_url_lookup_service_factory.h" #import "ios/chrome/browser/safe_browsing/url_checker_delegate_impl.h" +#import "ios/net/cookies/system_cookie_store.h" #include "ios/web/public/thread/web_task_traits.h" #include "ios/web/public/thread/web_thread.h" #import "ios/web/public/web_state.h" +#include "net/cookies/cookie_store.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -61,7 +64,8 @@ FROM_HERE, {web::WebThread::IO}, base::BindOnce(&IOThreadEnabler::Initialize, io_thread_enabler_, base::WrapRefCounted(this), - network_context_client_.BindNewPipeAndPassReceiver())); + network_context_client_.BindNewPipeAndPassReceiver(), + safe_browsing_data_path)); // Watch for changes to the Safe Browsing opt-out preference. pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); @@ -111,6 +115,21 @@ return shared_url_loader_factory_; } +void SafeBrowsingServiceImpl::ClearCookies( + const net::CookieDeletionInfo::TimeRange& creation_range, + base::OnceClosure callback) { + if (creation_range.start() == base::Time() && + creation_range.end() == base::Time::Max()) { + base::PostTask( + FROM_HERE, + {web::WebThread::IO, base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, + base::BindOnce(&IOThreadEnabler::ClearAllCookies, io_thread_enabler_, + std::move(callback))); + } else { + base::PostTask(FROM_HERE, {web::WebThread::IO}, std::move(callback)); + } +} + void SafeBrowsingServiceImpl::SetUpURLLoaderFactory( mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) { DCHECK_CURRENTLY_ON(web::WebThread::UI); @@ -146,8 +165,9 @@ void SafeBrowsingServiceImpl::IOThreadEnabler::Initialize( scoped_refptr<SafeBrowsingServiceImpl> safe_browsing_service, mojo::PendingReceiver<network::mojom::NetworkContext> - network_context_receiver) { - SetUpURLRequestContext(); + network_context_receiver, + const base::FilePath& safe_browsing_data_path) { + SetUpURLRequestContext(safe_browsing_data_path); std::vector<std::string> cors_exempt_header_list; network_context_ = std::make_unique<network::NetworkContext>( /*network_service=*/nullptr, std::move(network_context_receiver), @@ -178,6 +198,15 @@ safe_browsing_db_manager_->StopOnIOThread(shutting_down_); } +void SafeBrowsingServiceImpl::IOThreadEnabler::ClearAllCookies( + base::OnceClosure callback) { + DCHECK_CURRENTLY_ON(web::WebThread::IO); + net::CookieStore* cookie_store = url_request_context_->cookie_store(); + cookie_store->DeleteAllAsync(base::BindOnce( + [](base::OnceClosure callback, uint32_t) { std::move(callback).Run(); }, + std::move(callback))); +} + void SafeBrowsingServiceImpl::IOThreadEnabler::StartSafeBrowsingDBManager() { DCHECK_CURRENTLY_ON(web::WebThread::IO); @@ -195,12 +224,23 @@ config); } -void SafeBrowsingServiceImpl::IOThreadEnabler::SetUpURLRequestContext() { +void SafeBrowsingServiceImpl::IOThreadEnabler::SetUpURLRequestContext( + const base::FilePath& safe_browsing_data_path) { DCHECK_CURRENTLY_ON(web::WebThread::IO); - // This uses an in-memory non-persistent cookie store. The Safe Browsing V4 - // Update API does not depend on cookies. net::URLRequestContextBuilder builder; + base::FilePath cookie_file_path(safe_browsing_data_path.value() + + safe_browsing::kCookiesFile); + std::unique_ptr<net::CookieStore> cookie_store = + cookie_util::CreateCookieStore( + cookie_util::CookieStoreConfig( + cookie_file_path, + cookie_util::CookieStoreConfig::RESTORED_SESSION_COOKIES, + cookie_util::CookieStoreConfig::COOKIE_MONSTER, + /*crypto_delegate=*/nullptr), + /*system_cookie_store=*/nullptr, net::NetLog::Get()); + + builder.SetCookieStore(std::move(cookie_store)); url_request_context_ = builder.Build(); }
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_service_unittest.mm b/ios/chrome/browser/safe_browsing/safe_browsing_service_unittest.mm index dec0044..598bb0a 100644 --- a/ios/chrome/browser/safe_browsing/safe_browsing_service_unittest.mm +++ b/ios/chrome/browser/safe_browsing/safe_browsing_service_unittest.mm
@@ -8,6 +8,7 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/task/post_task.h" +#include "base/test/bind_test_util.h" #include "base/test/scoped_feature_list.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h" @@ -37,6 +38,11 @@ #include "ios/web/public/test/web_task_environment.h" #include "ios/web/public/thread/web_task_traits.h" #include "ios/web/public/thread/web_thread.h" +#include "net/test/embedded_test_server/default_handlers.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" #include "testing/platform_test.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -195,6 +201,7 @@ web::WebTaskEnvironment task_environment_; scoped_refptr<SafeBrowsingService> safe_browsing_service_; std::unique_ptr<TestChromeBrowserState> browser_state_; + base::ScopedTempDir temp_dir_; private: void MarkUrlAsMalwareOnIOThread(const GURL& bad_url) { @@ -218,8 +225,6 @@ v4_get_hash_factory_->AddToFullHashCache(full_hash_info); } - base::ScopedTempDir temp_dir_; - // Owned by V4Database. safe_browsing::TestV4DatabaseFactory* v4_db_factory_; // Owned by V4GetHashProtocolManager. @@ -301,3 +306,119 @@ EXPECT_FALSE(client.result_pending()); EXPECT_FALSE(client.url_is_unsafe()); } + +// Verifies that cookies are persisted across instantiations of +// SafeBrowsingServiceImpl. +TEST_F(SafeBrowsingServiceTest, PersistentCookies) { + net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS); + net::test_server::RegisterDefaultHandlers(&server); + ASSERT_TRUE(server.Start()); + std::string cookie = "test=123"; + std::unique_ptr<network::ResourceRequest> resource_request = + std::make_unique<network::ResourceRequest>(); + + // Set a cookie that expires in an hour. + resource_request->url = server.GetURL("/set-cookie?" + cookie + + ";max-age=3600;SameSite=None;Secure"); + std::unique_ptr<network::SimpleURLLoader> url_loader = + network::SimpleURLLoader::Create(std::move(resource_request), + TRAFFIC_ANNOTATION_FOR_TESTS); + base::RunLoop run_loop1; + url_loader->DownloadHeadersOnly( + safe_browsing_service_->GetURLLoaderFactory().get(), + base::BindLambdaForTesting( + [&](scoped_refptr<net::HttpResponseHeaders> headers) { + run_loop1.Quit(); + })); + run_loop1.Run(); + + // Destroy and re-create safe_browsing_service_, and verify that the cookie + // is still set. + safe_browsing_service_->ShutDown(); + base::RunLoop().RunUntilIdle(); + safe_browsing_service_ = base::MakeRefCounted<SafeBrowsingServiceImpl>(); + safe_browsing_service_->Initialize(browser_state_->GetPrefs(), + temp_dir_.GetPath()); + base::RunLoop().RunUntilIdle(); + + resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = server.GetURL("/echoheader?Cookie"); + url_loader = network::SimpleURLLoader::Create(std::move(resource_request), + TRAFFIC_ANNOTATION_FOR_TESTS); + base::RunLoop run_loop2; + url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + safe_browsing_service_->GetURLLoaderFactory().get(), + base::BindLambdaForTesting([&](std::unique_ptr<std::string> body) { + EXPECT_NE(std::string::npos, body->find(cookie)); + run_loop2.Quit(); + })); + run_loop2.Run(); +} + +// Verifies that cookies are cleared when ClearCookies() is called with a +// time range of all-time, but not otherwise. +TEST_F(SafeBrowsingServiceTest, ClearCookies) { + net::EmbeddedTestServer server(net::EmbeddedTestServer::TYPE_HTTPS); + net::test_server::RegisterDefaultHandlers(&server); + ASSERT_TRUE(server.Start()); + std::string cookie = "test=123"; + std::unique_ptr<network::ResourceRequest> resource_request = + std::make_unique<network::ResourceRequest>(); + + // Set a cookie that expires in an hour. + resource_request->url = server.GetURL("/set-cookie?" + cookie + + ";max-age=3600;SameSite=None;Secure"); + std::unique_ptr<network::SimpleURLLoader> url_loader = + network::SimpleURLLoader::Create(std::move(resource_request), + TRAFFIC_ANNOTATION_FOR_TESTS); + base::RunLoop run_loop1; + url_loader->DownloadHeadersOnly( + safe_browsing_service_->GetURLLoaderFactory().get(), + base::BindLambdaForTesting( + [&](scoped_refptr<net::HttpResponseHeaders> headers) { + run_loop1.Quit(); + })); + run_loop1.Run(); + + // Call ClearCookies() with a non-all-time time range, and verify that the + // cookie is still set. + base::RunLoop run_loop2; + safe_browsing_service_->ClearCookies( + net::CookieDeletionInfo::TimeRange(base::Time(), base::Time::Now()), + base::BindLambdaForTesting([&]() { run_loop2.Quit(); })); + run_loop2.Run(); + + resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = server.GetURL("/echoheader?Cookie"); + url_loader = network::SimpleURLLoader::Create(std::move(resource_request), + TRAFFIC_ANNOTATION_FOR_TESTS); + base::RunLoop run_loop3; + url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + safe_browsing_service_->GetURLLoaderFactory().get(), + base::BindLambdaForTesting([&](std::unique_ptr<std::string> body) { + EXPECT_NE(std::string::npos, body->find(cookie)); + run_loop3.Quit(); + })); + run_loop3.Run(); + + // Call ClearCookies() with a time range of all-time, and verify that the + // cookie is no longer set. + base::RunLoop run_loop4; + safe_browsing_service_->ClearCookies( + net::CookieDeletionInfo::TimeRange(base::Time(), base::Time::Max()), + base::BindLambdaForTesting([&]() { run_loop4.Quit(); })); + run_loop4.Run(); + + resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = server.GetURL("/echoheader?Cookie"); + url_loader = network::SimpleURLLoader::Create(std::move(resource_request), + TRAFFIC_ANNOTATION_FOR_TESTS); + base::RunLoop run_loop5; + url_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + safe_browsing_service_->GetURLLoaderFactory().get(), + base::BindLambdaForTesting([&](std::unique_ptr<std::string> body) { + EXPECT_EQ(std::string::npos, body->find(cookie)); + run_loop5.Quit(); + })); + run_loop5.Run(); +}
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h index 66e2c05..6f77404c 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h
@@ -35,6 +35,8 @@ - (void)handlePromoTapped; // Handles the actions following a tap on the "Learn more" item. - (void)handleLearnMoreTapped; +// Handles the actions following a tap on the "Manage Activity" item. +- (void)handleManageActivityTapped; // Handles the actions following a tap on the "Manage Interests" item. - (void)handleManageInterestsTapped;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index dd1182a..09ebfd4c 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -26,6 +26,7 @@ #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" +#import "ios/chrome/browser/signin/authentication_service.h" #import "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" @@ -103,6 +104,8 @@ @property(nonatomic, weak) id<DiscoverFeedHeaderChanging> discoverFeedHeaderDelegate; @property(nonatomic) CGFloat discoverFeedHeight; +// Authentication Service for the user's signed-in state. +@property(nonatomic, assign) AuthenticationService* authService; @end @@ -144,14 +147,16 @@ ntp_home::RecordNTPImpression(ntp_home::LOCAL_SUGGESTIONS); } + self.authService = AuthenticationServiceFactory::GetForBrowserState( + self.browser->GetBrowserState()); + self.NTPMediator = [[NTPHomeMediator alloc] initWithWebState:self.webState templateURLService:ios::TemplateURLServiceFactory:: GetForBrowserState( self.browser->GetBrowserState()) URLLoader:UrlLoadingBrowserAgent::FromBrowser(self.browser) - authService:AuthenticationServiceFactory::GetForBrowserState( - self.browser->GetBrowserState()) + authService:self.authService identityManager:IdentityManagerFactory::GetForBrowserState( self.browser->GetBrowserState()) logoVendor:ios::GetChromeBrowserProvider()->CreateLogoVendor( @@ -410,13 +415,23 @@ style:UIAlertActionStyleDefault]; } - [self.alertCoordinator - addItemWithTitle:l10n_util::GetNSString( - IDS_IOS_DISCOVER_FEED_MENU_MANAGE_INTERESTS_ITEM) - action:^{ - [weakSelf.NTPMediator handleManageInterestsTapped]; - } - style:UIAlertActionStyleDefault]; + if (self.authService->IsAuthenticated()) { + [self.alertCoordinator + addItemWithTitle:l10n_util::GetNSString( + IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ACTIVITY_ITEM) + action:^{ + [weakSelf.NTPMediator handleManageActivityTapped]; + } + style:UIAlertActionStyleDefault]; + + [self.alertCoordinator + addItemWithTitle:l10n_util::GetNSString( + IDS_IOS_DISCOVER_FEED_MENU_MANAGE_INTERESTS_ITEM) + action:^{ + [weakSelf.NTPMediator handleManageInterestsTapped]; + } + style:UIAlertActionStyleDefault]; + } [self.alertCoordinator addItemWithTitle:l10n_util::GetNSString( @@ -437,6 +452,7 @@ self.discoverFeedViewController = [self discoverFeed]; self.contentSuggestionsMediator.discoverFeed = self.discoverFeedViewController; + [self.alertCoordinator stop]; } #pragma mark - ContentSuggestionsActionHandler
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm index 266e667..5f1f707b 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm
@@ -65,6 +65,9 @@ #endif namespace { +// URL for 'Manage Activity' item in the Discover feed menu. +const char kFeedManageActivityURL[] = + "https://myactivity.google.com/myactivity?product=50"; // URL for 'Manage Interests' item in the Discover feed menu. const char kFeedManageInterestsURL[] = "https://google.com/preferences/interests"; @@ -390,22 +393,26 @@ NOTREACHED() << "Promo type is neither URL or command."; } -- (void)handleManageInterestsTapped { +// Opens web page for a menu item in the NTP. +- (void)openMenuItemWebPage:(GURL)URL { NewTabPageTabHelper* NTPHelper = NewTabPageTabHelper::FromWebState(self.webState); if (NTPHelper && NTPHelper->IgnoreLoadRequests()) return; - _URLLoader->Load(UrlLoadParams::InCurrentTab(GURL(kFeedManageInterestsURL))); + _URLLoader->Load(UrlLoadParams::InCurrentTab(URL)); // TODO(crbug.com/1085419): Add metrics. } +- (void)handleManageActivityTapped { + [self openMenuItemWebPage:GURL(kFeedManageActivityURL)]; +} + +- (void)handleManageInterestsTapped { + [self openMenuItemWebPage:GURL(kFeedManageInterestsURL)]; +} + - (void)handleLearnMoreTapped { - NewTabPageTabHelper* NTPHelper = - NewTabPageTabHelper::FromWebState(self.webState); - if (NTPHelper && NTPHelper->IgnoreLoadRequests()) - return; - _URLLoader->Load(UrlLoadParams::InCurrentTab(GURL(kNTPHelpURL))); - [self.NTPMetrics recordAction:new_tab_page_uma::ACTION_OPENED_LEARN_MORE]; + [self openMenuItemWebPage:GURL(kNTPHelpURL)]; } #pragma mark - ContentSuggestionsGestureCommands
diff --git a/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm b/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm index 598c2e2..4db8bc4 100644 --- a/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm +++ b/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
@@ -84,6 +84,19 @@ @implementation ARQuickLookEGTest +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 +// TODO(crbug.com/1114202): The XCUIElement queries in this test are broken on +// Xcode 12 beta 4 when running on the iOS 12 simulator. Disable until Xcode +// is fixed. ++ (NSArray*)testInvocations { + if (@available(iOS 13, *)) { + return [super testInvocations]; + } else { + return @[]; + } +} +#endif + - (void)setUp { [super setUp];
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/confirm/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_banner/confirm/BUILD.gn index df22790..688e4a0 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/confirm/BUILD.gn +++ b/ios/chrome/browser/ui/overlays/infobar_banner/confirm/BUILD.gn
@@ -16,6 +16,7 @@ "//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays/public/infobar_banner", "//ios/chrome/browser/ui/infobars/banners", + "//ios/chrome/browser/ui/overlays:coordinators", "//ios/chrome/browser/ui/overlays/infobar_banner:mediators", "//ui/base", ]
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm index 231cbd6..2bd473e 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm
@@ -6,8 +6,11 @@ #include "base/strings/sys_string_conversions.h" #import "ios/chrome/browser/overlays/public/infobar_banner/confirm_infobar_banner_overlay_request_config.h" +#include "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h" +#include "ios/chrome/browser/overlays/public/overlay_response.h" #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h" #import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h" +#import "ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h" #include "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -36,6 +39,11 @@ return ConfirmBannerRequestConfig::RequestSupport(); } +- (void)finishDismissal { + [self dispatchResponse:OverlayResponse::CreateWithInfo< + InfobarBannerRemoveInfobarResponse>()]; +} + @end @implementation ConfirmInfobarBannerOverlayMediator (ConsumerSupport)
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm index eef9ba3..4ac22f7 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_coordinator.mm
@@ -146,6 +146,9 @@ // Called when the dismissal of the banner UI is finished. - (void)finishDismissal { + InfobarBannerOverlayMediator* mediator = + base::mac::ObjCCast<InfobarBannerOverlayMediator>(self.mediator); + [mediator finishDismissal]; self.bannerViewController = nil; self.mediator = nil; // Notify the presentation context that the dismissal has finished. This
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h index db2d895..e1aaac0 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h +++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.h
@@ -18,6 +18,10 @@ // the new consumer. @property(nonatomic, weak) id<InfobarBannerConsumer> consumer; +// Indicates to the mediator to do any cleanup work in response to a banner +// dismissal. +- (void)finishDismissal; + @end #endif // IOS_CHROME_BROWSER_UI_OVERLAYS_INFOBAR_BANNER_INFOBAR_BANNER_OVERLAY_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm index 4473d32..7218053d 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm
@@ -31,6 +31,10 @@ return self; } +- (void)finishDismissal { + // No-op as default. +} + #pragma mark - Accessors - (void)setConsumer:(id<InfobarBannerConsumer>)consumer {
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index 6117582..d2d41e2 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -840,6 +840,8 @@ TableViewDetailTextCell* textCell = base::mac::ObjCCastStrict<TableViewDetailTextCell>(cell); textCell.detailTextLabel.numberOfLines = 0; + textCell.detailTextLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; textCell.selectionStyle = UITableViewCellSelectionStyleNone; textCell.separatorInset = UIEdgeInsetsMake(0, tableView.bounds.size.width, 0, 0);
diff --git a/net/BUILD.gn b/net/BUILD.gn index 3331c59c..6b23faea 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -928,6 +928,8 @@ "quic/quic_crypto_client_config_handle.h", "quic/quic_crypto_client_stream_factory.cc", "quic/quic_crypto_client_stream_factory.h", + "quic/quic_event_logger.cc", + "quic/quic_event_logger.h", "quic/quic_flags_list.h", "quic/quic_http3_logger.cc", "quic/quic_http3_logger.h",
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java index e020566c..a922d54b7 100644 --- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java +++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
@@ -26,15 +26,12 @@ import android.os.Looper; import android.os.StrictMode; import android.support.test.InstrumentationRegistry; -import android.support.test.annotation.UiThreadTest; -import android.support.test.rule.UiThreadTestRule; import android.telephony.TelephonyManager; import androidx.test.filters.MediumTest; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,6 +43,7 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.net.NetworkChangeNotifierAutoDetect.ConnectivityManagerDelegate; @@ -65,9 +63,6 @@ @RunWith(BaseJUnit4ClassRunner.class) @SuppressLint("NewApi") public class NetworkChangeNotifierTest { - @Rule - public UiThreadTestRule mUiThreadRule = new UiThreadTestRule(); - /** * Listens for alerts fired by the NetworkChangeNotifier when network status changes. */ @@ -495,19 +490,16 @@ LibraryLoader.getInstance().setLibraryProcessType(LibraryProcessType.PROCESS_BROWSER); LibraryLoader.getInstance().ensureInitialized(); - mUiThreadRule.runOnUiThread(new Runnable() { - @Override - public void run() { - if (sActivity == null) { - sActivity = new Activity(); - if (!ApplicationStatus.isInitialized()) { - ApplicationStatus.initialize(BaseJUnit4ClassRunner.getApplication()); - } - ApplicationStatus.onStateChangeForTesting(sActivity, ActivityState.CREATED); + ThreadUtils.runOnUiThreadBlocking(() -> { + if (sActivity == null) { + sActivity = new Activity(); + if (!ApplicationStatus.isInitialized()) { + ApplicationStatus.initialize(BaseJUnit4ClassRunner.getApplication()); } - setApplicationHasVisibleActivities(false); - createTestNotifier(WatchForChanges.ONLY_WHEN_APP_IN_FOREGROUND); + ApplicationStatus.onStateChangeForTesting(sActivity, ActivityState.CREATED); } + setApplicationHasVisibleActivities(false); + createTestNotifier(WatchForChanges.ONLY_WHEN_APP_IN_FOREGROUND); }); }
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index 06225c6..d9fd805 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc
@@ -16,9 +16,6 @@ #include "base/values.h" #include "net/base/ip_address.h" #include "net/cert/x509_certificate.h" -#include "net/log/net_log_capture_mode.h" -#include "net/log/net_log_event_type.h" -#include "net/log/net_log_values.h" #include "net/quic/address_utils.h" #include "net/quic/quic_address_mismatch.h" #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" @@ -37,336 +34,6 @@ namespace { -base::Value NetLogQuicPacketParams(const quic::QuicSocketAddress& self_address, - const quic::QuicSocketAddress& peer_address, - size_t packet_size) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("self_address", self_address.ToString()); - dict.SetStringKey("peer_address", peer_address.ToString()); - dict.SetIntKey("size", packet_size); - return dict; -} - -base::Value NetLogQuicPacketSentParams( - const quic::SerializedPacket& serialized_packet, - quic::TransmissionType transmission_type, - quic::QuicTime sent_time) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("transmission_type", - quic::TransmissionTypeToString(transmission_type)); - dict.SetKey("packet_number", - NetLogNumberValue(serialized_packet.packet_number.ToUint64())); - dict.SetIntKey("size", serialized_packet.encrypted_length); - dict.SetKey("sent_time_us", NetLogNumberValue(sent_time.ToDebuggingValue())); - dict.SetStringKey( - "encryption_level", - quic::EncryptionLevelToString(serialized_packet.encryption_level)); - return dict; -} - -base::Value NetLogQuicPacketLostParams(quic::QuicPacketNumber packet_number, - quic::TransmissionType transmission_type, - quic::QuicTime detection_time) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("transmission_type", - quic::TransmissionTypeToString(transmission_type)); - dict.SetKey("packet_number", NetLogNumberValue(packet_number.ToUint64())); - dict.SetKey("detection_time_us", - NetLogNumberValue(detection_time.ToDebuggingValue())); - return dict; -} - -base::Value NetLogQuicDuplicatePacketParams( - quic::QuicPacketNumber packet_number) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("packet_number", NetLogNumberValue(packet_number.ToUint64())); - return dict; -} - -base::Value NetLogReceivedQuicPacketHeaderParams( - const quic::QuicPacketHeader& header, - const quic::ParsedQuicVersion& session_version, - const quic::QuicConnectionId& connection_id, - const quic::QuicConnectionId& client_connection_id) { - base::Value dict(base::Value::Type::DICTIONARY); - quic::ParsedQuicVersion version = session_version; - if (header.version_flag && - header.version != quic::ParsedQuicVersion::Unsupported()) { - version = header.version; - if (version != session_version) { - dict.SetStringKey("version", quic::ParsedQuicVersionToString(version)); - } - } - dict.SetStringKey("connection_id", connection_id.ToString()); - if (!client_connection_id.IsEmpty()) { - dict.SetStringKey("client_connection_id", client_connection_id.ToString()); - } - if (version.HasIetfInvariantHeader()) { - if (header.destination_connection_id_included == - quic::CONNECTION_ID_PRESENT && - header.destination_connection_id != client_connection_id && - !header.destination_connection_id.IsEmpty()) { - dict.SetStringKey("destination_connection_id", - header.destination_connection_id.ToString()); - } - if (header.source_connection_id_included == quic::CONNECTION_ID_PRESENT && - header.source_connection_id != connection_id && - !header.source_connection_id.IsEmpty()) { - dict.SetStringKey("source_connection_id", - header.source_connection_id.ToString()); - } - } else { - if (header.destination_connection_id_included == - quic::CONNECTION_ID_PRESENT && - header.destination_connection_id != connection_id && - !header.destination_connection_id.IsEmpty()) { - dict.SetStringKey("destination_connection_id", - header.destination_connection_id.ToString()); - } - dict.SetIntKey("reset_flag", header.reset_flag); - dict.SetIntKey("version_flag", header.version_flag); - } - dict.SetKey("packet_number", - NetLogNumberValue(header.packet_number.ToUint64())); - dict.SetStringKey("header_format", - quic::PacketHeaderFormatToString(header.form)); - if (header.form == quic::IETF_QUIC_LONG_HEADER_PACKET) { - dict.SetStringKey("long_header_type", quic::QuicLongHeaderTypeToString( - header.long_packet_type)); - } - return dict; -} - -base::Value NetLogQuicStreamFrameParams(const quic::QuicStreamFrame& frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_id", frame.stream_id); - dict.SetBoolKey("fin", frame.fin); - dict.SetKey("offset", NetLogNumberValue(frame.offset)); - dict.SetIntKey("length", frame.data_length); - return dict; -} - -base::Value NetLogQuicAckFrameParams(const quic::QuicAckFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("largest_observed", - NetLogNumberValue(frame->largest_acked.ToUint64())); - dict.SetKey("delta_time_largest_observed_us", - NetLogNumberValue(frame->ack_delay_time.ToMicroseconds())); - - base::Value missing(base::Value::Type::LIST); - quic::QuicPacketNumber smallest_observed; - if (!frame->packets.Empty()) { - // V34 and above express acked packets, but only print - // missing packets, because it's typically a shorter list. - smallest_observed = frame->packets.Min(); - for (quic::QuicPacketNumber packet = smallest_observed; - packet < frame->largest_acked; ++packet) { - if (!frame->packets.Contains(packet)) { - missing.Append(NetLogNumberValue(packet.ToUint64())); - } - } - } else { - smallest_observed = frame->largest_acked; - } - dict.SetKey("smallest_observed", - NetLogNumberValue(smallest_observed.ToUint64())); - dict.SetKey("missing_packets", std::move(missing)); - - base::Value received(base::Value::Type::LIST); - const quic::PacketTimeVector& received_times = frame->received_packet_times; - for (auto it = received_times.begin(); it != received_times.end(); ++it) { - base::Value info(base::Value::Type::DICTIONARY); - info.SetKey("packet_number", NetLogNumberValue(it->first.ToUint64())); - info.SetKey("received", NetLogNumberValue(it->second.ToDebuggingValue())); - received.Append(std::move(info)); - } - dict.SetKey("received_packet_times", std::move(received)); - - return dict; -} - -base::Value NetLogQuicRstStreamFrameParams( - const quic::QuicRstStreamFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_id", frame->stream_id); - dict.SetIntKey("quic_rst_stream_error", frame->error_code); - dict.SetKey("offset", NetLogNumberValue(frame->byte_offset)); - return dict; -} - -base::Value NetLogQuicConnectionCloseFrameParams( - const quic::QuicConnectionCloseFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("quic_error", frame->quic_error_code); - dict.SetStringKey("details", frame->error_details); - return dict; -} - -base::Value NetLogQuicWindowUpdateFrameParams( - const quic::QuicWindowUpdateFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_id", frame->stream_id); - dict.SetKey("byte_offset", NetLogNumberValue(frame->max_data)); - return dict; -} - -base::Value NetLogQuicBlockedFrameParams(const quic::QuicBlockedFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_id", frame->stream_id); - return dict; -} - -base::Value NetLogQuicGoAwayFrameParams(const quic::QuicGoAwayFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("quic_error", frame->error_code); - dict.SetIntKey("last_good_stream_id", frame->last_good_stream_id); - dict.SetStringKey("reason_phrase", frame->reason_phrase); - return dict; -} - -base::Value NetLogQuicStopWaitingFrameParams( - const quic::QuicStopWaitingFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("least_unacked", - NetLogNumberValue(frame->least_unacked.ToUint64())); - return dict; -} - -base::Value NetLogQuicVersionNegotiationPacketParams( - const quic::QuicVersionNegotiationPacket* packet) { - base::Value dict(base::Value::Type::DICTIONARY); - base::Value versions(base::Value::Type::LIST); - for (auto it = packet->versions.begin(); it != packet->versions.end(); ++it) { - versions.Append(ParsedQuicVersionToString(*it)); - } - dict.SetKey("versions", std::move(versions)); - return dict; -} - -base::Value NetLogQuicPublicResetPacketParams( - const IPEndPoint& server_hello_address, - const quic::QuicSocketAddress& public_reset_address) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("server_hello_address", server_hello_address.ToString()); - dict.SetStringKey("public_reset_address", public_reset_address.ToString()); - return dict; -} - -base::Value NetLogQuicPathData(const quic::QuicPathFrameBuffer& buffer) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("data", - NetLogBinaryValue(reinterpret_cast<const char*>(buffer.data()), - buffer.size())); - return dict; -} - -base::Value NetLogQuicCryptoHandshakeMessageParams( - const quic::CryptoHandshakeMessage* message) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("quic_crypto_handshake_message", message->DebugString()); - return dict; -} - -base::Value NetLogQuicTransportParametersParams( - const quic::TransportParameters& transport_parameters) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("quic_transport_parameters", - transport_parameters.ToString()); - return dict; -} - -base::Value NetLogQuicOnConnectionClosedParams( - quic::QuicErrorCode error, - string error_details, - quic::ConnectionCloseSource source) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("quic_error", error); - dict.SetStringKey("details", error_details); - dict.SetBoolKey("from_peer", source == quic::ConnectionCloseSource::FROM_PEER - ? true - : false); - return dict; -} - -base::Value NetLogQuicCertificateVerifiedParams( - scoped_refptr<X509Certificate> cert) { - // Only the subjects are logged so that we can investigate connection pooling. - // More fields could be logged in the future. - std::vector<std::string> dns_names; - cert->GetSubjectAltName(&dns_names, nullptr); - base::Value dict(base::Value::Type::DICTIONARY); - base::Value subjects(base::Value::Type::LIST); - for (auto& dns_name : dns_names) { - subjects.Append(std::move(dns_name)); - } - dict.SetKey("subjects", std::move(subjects)); - return dict; -} - -base::Value NetLogQuicCryptoFrameParams(const quic::QuicCryptoFrame* frame, - bool has_buffer) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("encryption_level", - quic::EncryptionLevelToString(frame->level)); - dict.SetIntKey("data_length", frame->data_length); - dict.SetKey("offset", NetLogNumberValue(frame->offset)); - if (has_buffer) { - dict.SetKey("bytes", NetLogBinaryValue( - reinterpret_cast<const void*>(frame->data_buffer), - frame->data_length)); - } - return dict; -} - -base::Value NetLogQuicStopSendingFrameParams( - const quic::QuicStopSendingFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_id", frame->stream_id); - dict.SetIntKey("application_error_code", frame->application_error_code); - return dict; -} - -base::Value NetLogQuicStreamsBlockedFrameParams( - const quic::QuicStreamsBlockedFrame& frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_count", frame.stream_count); - dict.SetBoolKey("is_unidirectional", frame.unidirectional); - return dict; -} - -base::Value NetLogQuicMaxStreamsFrameParams( - const quic::QuicMaxStreamsFrame& frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("stream_count", frame.stream_count); - dict.SetBoolKey("is_unidirectional", frame.unidirectional); - return dict; -} - -base::Value NetLogQuicNewConnectionIdFrameParams( - const quic::QuicNewConnectionIdFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("connection_id", frame->connection_id.ToString()); - dict.SetKey("sequence_number", NetLogNumberValue(frame->sequence_number)); - dict.SetKey("retire_prior_to", NetLogNumberValue(frame->retire_prior_to)); - return dict; -} - -base::Value NetLogQuicRetireConnectionIdFrameParams( - const quic::QuicRetireConnectionIdFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("sequence_number", NetLogNumberValue(frame->sequence_number)); - return dict; -} - -base::Value NetLogQuicNewTokenFrameParams( - const quic::QuicNewTokenFrame* frame) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("token", NetLogBinaryValue( - reinterpret_cast<const void*>(frame->token.data()), - frame->token.length())); - return dict; -} - void UpdatePublicResetAddressMismatchHistogram( const IPEndPoint& server_hello_address, const IPEndPoint& public_reset_address) { @@ -391,12 +58,11 @@ } // namespace QuicConnectionLogger::QuicConnectionLogger( - quic::QuicSpdySession* session, + quic::QuicSession* session, const char* const connection_description, std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, const NetLogWithSource& net_log) - : net_log_(net_log), - session_(session), + : session_(session), last_received_packet_size_(0), no_packet_received_after_ping_(false), previous_received_packet_size_(0), @@ -411,7 +77,8 @@ num_blocked_frames_received_(0), num_blocked_frames_sent_(0), connection_description_(connection_description), - socket_performance_watcher_(std::move(socket_performance_watcher)) {} + socket_performance_watcher_(std::move(socket_performance_watcher)), + event_logger_(session, net_log) {} QuicConnectionLogger::~QuicConnectionLogger() { UMA_HISTOGRAM_COUNTS_1M("Net.QuicSession.OutOfOrderPacketsReceived", @@ -507,146 +174,12 @@ default: DCHECK(false) << "Illegal frame type: " << frame.type; } - if (!net_log_.IsCapturing()) - return; - switch (frame.type) { - case quic::PADDING_FRAME: - net_log_.AddEventWithIntParams( - NetLogEventType::QUIC_SESSION_PADDING_FRAME_SENT, "num_padding_bytes", - frame.padding_frame.num_padding_bytes); - break; - case quic::STREAM_FRAME: - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STREAM_FRAME_SENT, [&] { - return NetLogQuicStreamFrameParams(frame.stream_frame); - }); - break; - case quic::ACK_FRAME: { - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_ACK_FRAME_SENT, [&] { - return NetLogQuicAckFrameParams(frame.ack_frame); - }); - break; - } - case quic::RST_STREAM_FRAME: - base::UmaHistogramSparse("Net.QuicSession.RstStreamErrorCodeClient", - frame.rst_stream_frame->error_code); - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_RST_STREAM_FRAME_SENT, [&] { - return NetLogQuicRstStreamFrameParams(frame.rst_stream_frame); - }); - break; - case quic::CONNECTION_CLOSE_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_CONNECTION_CLOSE_FRAME_SENT, [&] { - return NetLogQuicConnectionCloseFrameParams( - frame.connection_close_frame); - }); - break; - case quic::GOAWAY_FRAME: - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_GOAWAY_FRAME_SENT, [&] { - return NetLogQuicGoAwayFrameParams(frame.goaway_frame); - }); - break; - case quic::WINDOW_UPDATE_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_WINDOW_UPDATE_FRAME_SENT, [&] { - return NetLogQuicWindowUpdateFrameParams(frame.window_update_frame); - }); - break; - case quic::BLOCKED_FRAME: - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_BLOCKED_FRAME_SENT, [&] { - return NetLogQuicBlockedFrameParams(frame.blocked_frame); - }); - break; - case quic::STOP_WAITING_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_STOP_WAITING_FRAME_SENT, [&] { - return NetLogQuicStopWaitingFrameParams(&frame.stop_waiting_frame); - }); - break; - case quic::PING_FRAME: - UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionFlowControlBlocked", - session_->IsConnectionFlowControlBlocked()); - UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StreamFlowControlBlocked", - session_->IsStreamFlowControlBlocked()); - // PingFrame has no contents to log, so just record that it was sent. - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PING_FRAME_SENT); - break; - case quic::MTU_DISCOVERY_FRAME: - // MtuDiscoveryFrame is PingFrame on wire, it does not have any payload. - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_MTU_DISCOVERY_FRAME_SENT); - break; - case quic::NEW_CONNECTION_ID_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_NEW_CONNECTION_ID_FRAME_SENT, [&] { - return NetLogQuicNewConnectionIdFrameParams( - frame.new_connection_id_frame); - }); - break; - case quic::MAX_STREAMS_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_MAX_STREAMS_FRAME_SENT, [&] { - return NetLogQuicMaxStreamsFrameParams(frame.max_streams_frame); - }); - break; - case quic::STREAMS_BLOCKED_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_STREAMS_BLOCKED_FRAME_SENT, [&] { - return NetLogQuicStreamsBlockedFrameParams( - frame.streams_blocked_frame); - }); - break; - case quic::PATH_RESPONSE_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_PATH_RESPONSE_FRAME_SENT, [&] { - return NetLogQuicPathData(frame.path_response_frame->data_buffer); - }); - break; - case quic::PATH_CHALLENGE_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_PATH_CHALLENGE_FRAME_SENT, [&] { - return NetLogQuicPathData(frame.path_challenge_frame->data_buffer); - }); - break; - case quic::STOP_SENDING_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_STOP_SENDING_FRAME_SENT, [&] { - return NetLogQuicStopSendingFrameParams(frame.stop_sending_frame); - }); - break; - case quic::MESSAGE_FRAME: - net_log_.AddEventWithIntParams( - NetLogEventType::QUIC_SESSION_MESSAGE_FRAME_SENT, "message_length", - frame.message_frame->message_length); - break; - case quic::CRYPTO_FRAME: - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CRYPTO_FRAME_SENT, [&] { - return NetLogQuicCryptoFrameParams(frame.crypto_frame, - /*has_buffer = */ false); - }); - break; - case quic::NEW_TOKEN_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_NEW_TOKEN_FRAME_SENT, - [&] { return NetLogQuicNewTokenFrameParams(frame.new_token_frame); }); - break; - case quic::RETIRE_CONNECTION_ID_FRAME: - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_RETIRE_CONNECTION_ID_FRAME_SENT, [&] { - return NetLogQuicRetireConnectionIdFrameParams( - frame.retire_connection_id_frame); - }); - break; - default: - DCHECK(false) << "Illegal frame type: " << frame.type; - } + event_logger_.OnFrameAddedToPacket(frame); } void QuicConnectionLogger::OnStreamFrameCoalesced( const quic::QuicStreamFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STREAM_FRAME_COALESCED, - [&] { return NetLogQuicStreamFrameParams(frame); }); + event_logger_.OnStreamFrameCoalesced(frame); } void QuicConnectionLogger::OnPacketSent( @@ -691,25 +224,16 @@ break; } - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_SENT, [&] { - return NetLogQuicPacketSentParams(serialized_packet, transmission_type, - sent_time); - }); + event_logger_.OnPacketSent(serialized_packet, transmission_type, sent_time); } void QuicConnectionLogger::OnPacketLoss( quic::QuicPacketNumber lost_packet_number, - quic::EncryptionLevel /*encryption_level*/, + quic::EncryptionLevel encryption_level, quic::TransmissionType transmission_type, quic::QuicTime detection_time) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_LOST, [&] { - return NetLogQuicPacketLostParams(lost_packet_number, transmission_type, - detection_time); - }); + event_logger_.OnPacketLoss(lost_packet_number, encryption_level, + transmission_type, detection_time); } void QuicConnectionLogger::OnPingSent() { @@ -730,25 +254,12 @@ previous_received_packet_size_ = last_received_packet_size_; last_received_packet_size_ = packet.length(); - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_RECEIVED, [&] { - return NetLogQuicPacketParams(self_address, peer_address, packet.length()); - }); + event_logger_.OnPacketReceived(self_address, peer_address, packet); } void QuicConnectionLogger::OnUnauthenticatedHeader( const quic::QuicPacketHeader& header) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_UNAUTHENTICATED_PACKET_HEADER_RECEIVED, - [&] { - return NetLogReceivedQuicPacketHeaderParams( - header, session_->version(), - session_->connection()->connection_id(), - session_->connection()->client_connection_id()); - }); + event_logger_.OnUnauthenticatedHeader(header); } void QuicConnectionLogger::OnIncorrectConnectionId( @@ -760,36 +271,18 @@ quic::EncryptionLevel decryption_level, bool dropped) { ++num_undecryptable_packets_; - if (!net_log_.IsCapturing()) - return; - if (dropped) { - net_log_.AddEventWithStringParams( - NetLogEventType::QUIC_SESSION_DROPPED_UNDECRYPTABLE_PACKET, - "encryption_level", quic::EncryptionLevelToString(decryption_level)); - return; - } - net_log_.AddEventWithStringParams( - NetLogEventType::QUIC_SESSION_BUFFERED_UNDECRYPTABLE_PACKET, - "encryption_level", quic::EncryptionLevelToString(decryption_level)); + event_logger_.OnUndecryptablePacket(decryption_level, dropped); } void QuicConnectionLogger::OnAttemptingToProcessUndecryptablePacket( quic::EncryptionLevel decryption_level) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEventWithStringParams( - NetLogEventType::QUIC_SESSION_ATTEMPTING_TO_PROCESS_UNDECRYPTABLE_PACKET, - "encryption_level", quic::EncryptionLevelToString(decryption_level)); + event_logger_.OnAttemptingToProcessUndecryptablePacket(decryption_level); } void QuicConnectionLogger::OnDuplicatePacket( quic::QuicPacketNumber packet_number) { ++num_duplicate_packets_; - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_DUPLICATE_PACKET_RECEIVED, - [&] { return NetLogQuicDuplicatePacketParams(packet_number); }); + event_logger_.OnDuplicatePacket(packet_number); } void QuicConnectionLogger::OnProtocolVersionMismatch( @@ -845,70 +338,45 @@ no_packet_received_after_ping_ = false; } last_received_packet_number_ = header.packet_number; - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_AUTHENTICATED); + event_logger_.OnPacketHeader(header); } void QuicConnectionLogger::OnStreamFrame(const quic::QuicStreamFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STREAM_FRAME_RECEIVED, - [&] { return NetLogQuicStreamFrameParams(frame); }); + event_logger_.OnStreamFrame(frame); } void QuicConnectionLogger::OnPathChallengeFrame( const quic::QuicPathChallengeFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PATH_CHALLENGE_FRAME_RECEIVED, - [&] { return NetLogQuicPathData(frame.data_buffer); }); + event_logger_.OnPathChallengeFrame(frame); } void QuicConnectionLogger::OnPathResponseFrame( const quic::QuicPathResponseFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PATH_RESPONSE_FRAME_RECEIVED, - [&] { return NetLogQuicPathData(frame.data_buffer); }); + event_logger_.OnPathResponseFrame(frame); } void QuicConnectionLogger::OnCryptoFrame(const quic::QuicCryptoFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CRYPTO_FRAME_RECEIVED, [&] { - return NetLogQuicCryptoFrameParams(&frame, /*has_buffer = */ true); - }); + event_logger_.OnCryptoFrame(frame); } void QuicConnectionLogger::OnStopSendingFrame( const quic::QuicStopSendingFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STOP_SENDING_FRAME_RECEIVED, - [&] { return NetLogQuicStopSendingFrameParams(&frame); }); + event_logger_.OnStopSendingFrame(frame); } void QuicConnectionLogger::OnStreamsBlockedFrame( const quic::QuicStreamsBlockedFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_STREAMS_BLOCKED_FRAME_RECEIVED, - [&] { return NetLogQuicStreamsBlockedFrameParams(frame); }); + event_logger_.OnStreamsBlockedFrame(frame); } void QuicConnectionLogger::OnMaxStreamsFrame( const quic::QuicMaxStreamsFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_MAX_STREAMS_FRAME_RECEIVED, - [&] { return NetLogQuicMaxStreamsFrameParams(frame); }); + event_logger_.OnMaxStreamsFrame(frame); } void QuicConnectionLogger::OnIncomingAck( quic::QuicPacketNumber ack_packet_number, - quic::EncryptionLevel /*ack_decrypted_level*/, + quic::EncryptionLevel ack_decrypted_level, const quic::QuicAckFrame& frame, quic::QuicTime ack_receive_time, quic::QuicPacketNumber largest_observed, @@ -922,153 +390,94 @@ first_received_packet_number_] = true; } - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_ACK_FRAME_RECEIVED, - [&] { return NetLogQuicAckFrameParams(&frame); }); + event_logger_.OnIncomingAck(ack_packet_number, ack_decrypted_level, frame, + ack_receive_time, largest_observed, rtt_updated, + least_unacked_sent_packet); } void QuicConnectionLogger::OnStopWaitingFrame( const quic::QuicStopWaitingFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STOP_WAITING_FRAME_RECEIVED, - [&] { return NetLogQuicStopWaitingFrameParams(&frame); }); + event_logger_.OnStopWaitingFrame(frame); } void QuicConnectionLogger::OnRstStreamFrame( const quic::QuicRstStreamFrame& frame) { base::UmaHistogramSparse("Net.QuicSession.RstStreamErrorCodeServer", frame.error_code); - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_RST_STREAM_FRAME_RECEIVED, - [&] { return NetLogQuicRstStreamFrameParams(&frame); }); + event_logger_.OnRstStreamFrame(frame); } void QuicConnectionLogger::OnConnectionCloseFrame( const quic::QuicConnectionCloseFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_CONNECTION_CLOSE_FRAME_RECEIVED, - [&] { return NetLogQuicConnectionCloseFrameParams(&frame); }); + event_logger_.OnConnectionCloseFrame(frame); } void QuicConnectionLogger::OnWindowUpdateFrame( const quic::QuicWindowUpdateFrame& frame, const quic::QuicTime& receive_time) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_WINDOW_UPDATE_FRAME_RECEIVED, - [&] { return NetLogQuicWindowUpdateFrameParams(&frame); }); + event_logger_.OnWindowUpdateFrame(frame, receive_time); } void QuicConnectionLogger::OnBlockedFrame(const quic::QuicBlockedFrame& frame) { ++num_blocked_frames_received_; - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_BLOCKED_FRAME_RECEIVED, - [&] { return NetLogQuicBlockedFrameParams(&frame); }); + event_logger_.OnBlockedFrame(frame); } void QuicConnectionLogger::OnGoAwayFrame(const quic::QuicGoAwayFrame& frame) { UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.GoAwayReceivedForConnectionMigration", frame.error_code == quic::QUIC_ERROR_MIGRATING_PORT); - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_GOAWAY_FRAME_RECEIVED, - [&] { return NetLogQuicGoAwayFrameParams(&frame); }); + event_logger_.OnGoAwayFrame(frame); } void QuicConnectionLogger::OnPingFrame(const quic::QuicPingFrame& frame) { - // PingFrame has no contents to log, so just record that it was received. - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PING_FRAME_RECEIVED); + event_logger_.OnPingFrame(frame); } void QuicConnectionLogger::OnPaddingFrame(const quic::QuicPaddingFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEventWithIntParams( - NetLogEventType::QUIC_SESSION_PADDING_FRAME_RECEIVED, "num_padding_bytes", - frame.num_padding_bytes); + event_logger_.OnPaddingFrame(frame); } void QuicConnectionLogger::OnNewConnectionIdFrame( const quic::QuicNewConnectionIdFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_NEW_CONNECTION_ID_FRAME_RECEIVED, - [&] { return NetLogQuicNewConnectionIdFrameParams(&frame); }); + event_logger_.OnNewConnectionIdFrame(frame); } void QuicConnectionLogger::OnNewTokenFrame( const quic::QuicNewTokenFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_NEW_TOKEN_FRAME_RECEIVED, - [&] { return NetLogQuicNewTokenFrameParams(&frame); }); + event_logger_.OnNewTokenFrame(frame); } void QuicConnectionLogger::OnRetireConnectionIdFrame( const quic::QuicRetireConnectionIdFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_RETIRE_CONNECTION_ID_FRAME_RECEIVED, - [&] { return NetLogQuicRetireConnectionIdFrameParams(&frame); }); + event_logger_.OnRetireConnectionIdFrame(frame); } void QuicConnectionLogger::OnMessageFrame(const quic::QuicMessageFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEventWithIntParams( - NetLogEventType::QUIC_SESSION_MESSAGE_FRAME_RECEIVED, "message_length", - frame.message_length); + event_logger_.OnMessageFrame(frame); } void QuicConnectionLogger::OnHandshakeDoneFrame( const quic::QuicHandshakeDoneFrame& frame) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_HANDSHAKE_DONE_FRAME_RECEIVED); + event_logger_.OnHandshakeDoneFrame(frame); } void QuicConnectionLogger::OnCoalescedPacketSent( const quic::QuicCoalescedPacket& coalesced_packet, size_t length) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEventWithStringParams( - NetLogEventType::QUIC_SESSION_COALESCED_PACKET_SENT, "info", - coalesced_packet.ToString(length)); + event_logger_.OnCoalescedPacketSent(coalesced_packet, length); } void QuicConnectionLogger::OnPublicResetPacket( const quic::QuicPublicResetPacket& packet) { UpdatePublicResetAddressMismatchHistogram( local_address_from_shlo_, ToIPEndPoint(packet.client_address)); - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED, - [&] { - return NetLogQuicPublicResetPacketParams( - local_address_from_shlo_, packet.client_address); - }); + event_logger_.OnPublicResetPacket(packet); } void QuicConnectionLogger::OnVersionNegotiationPacket( const quic::QuicVersionNegotiationPacket& packet) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_VERSION_NEGOTIATION_PACKET_RECEIVED, - [&] { return NetLogQuicVersionNegotiationPacketParams(&packet); }); + event_logger_.OnVersionNegotiationPacket(packet); } void QuicConnectionLogger::OnCryptoHandshakeMessageReceived( @@ -1096,41 +505,23 @@ } } } - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_RECEIVED, - [&] { return NetLogQuicCryptoHandshakeMessageParams(&message); }); + event_logger_.OnCryptoHandshakeMessageReceived(message); } void QuicConnectionLogger::OnCryptoHandshakeMessageSent( const quic::CryptoHandshakeMessage& message) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_SENT, - [&] { return NetLogQuicCryptoHandshakeMessageParams(&message); }); + event_logger_.OnCryptoHandshakeMessageSent(message); } void QuicConnectionLogger::OnConnectionClosed( const quic::QuicConnectionCloseFrame& frame, quic::ConnectionCloseSource source) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CLOSED, [&] { - return NetLogQuicOnConnectionClosedParams(frame.quic_error_code, - frame.error_details, source); - }); + event_logger_.OnConnectionClosed(frame, source); } void QuicConnectionLogger::OnSuccessfulVersionNegotiation( const quic::ParsedQuicVersion& version) { - if (!net_log_.IsCapturing()) - return; - string quic_version = quic::ParsedQuicVersionToString(version); - net_log_.AddEventWithStringParams( - NetLogEventType::QUIC_SESSION_VERSION_NEGOTIATED, "version", - quic_version); + event_logger_.OnSuccessfulVersionNegotiation(version); } void QuicConnectionLogger::UpdateReceivedFrameCounts( @@ -1146,15 +537,7 @@ void QuicConnectionLogger::OnCertificateVerified( const CertVerifyResult& result) { - if (!net_log_.IsCapturing()) - return; - if (result.cert_status == CERT_STATUS_INVALID) { - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CERTIFICATE_VERIFY_FAILED); - return; - } - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CERTIFICATE_VERIFIED, [&] { - return NetLogQuicCertificateVerifiedParams(result.verified_cert); - }); + event_logger_.OnCertificateVerified(result); } base::HistogramBase* QuicConnectionLogger::Get6PacketHistogram( @@ -1191,22 +574,12 @@ void QuicConnectionLogger::OnTransportParametersSent( const quic::TransportParameters& transport_parameters) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_TRANSPORT_PARAMETERS_SENT, [&] { - return NetLogQuicTransportParametersParams(transport_parameters); - }); + event_logger_.OnTransportParametersSent(transport_parameters); } void QuicConnectionLogger::OnTransportParametersReceived( const quic::TransportParameters& transport_parameters) { - if (!net_log_.IsCapturing()) - return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_TRANSPORT_PARAMETERS_RECEIVED, [&] { - return NetLogQuicTransportParametersParams(transport_parameters); - }); + event_logger_.OnTransportParametersReceived(transport_parameters); } void QuicConnectionLogger::RecordAggregatePacketLossRate() const {
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h index 879ebf1c..232cc9f2 100644 --- a/net/quic/quic_connection_logger.h +++ b/net/quic/quic_connection_logger.h
@@ -16,6 +16,7 @@ #include "net/base/network_change_notifier.h" #include "net/cert/cert_verify_result.h" #include "net/log/net_log_with_source.h" +#include "net/quic/quic_event_logger.h" #include "net/socket/socket_performance_watcher.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h" #include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h" @@ -28,14 +29,13 @@ namespace net { -// This class is a debug visitor of a quic::QuicConnection which logs -// events to |net_log|. +// Handles both NetLog support and UMA histograms for QUIC. class NET_EXPORT_PRIVATE QuicConnectionLogger : public quic::QuicConnectionDebugVisitor, public quic::QuicPacketCreator::DebugDelegate { public: QuicConnectionLogger( - quic::QuicSpdySession* session, + quic::QuicSession* session, const char* const connection_description, std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher, const NetLogWithSource& net_log); @@ -136,8 +136,7 @@ // the overall packet loss rate, and record it into a histogram. void RecordAggregatePacketLossRate() const; - NetLogWithSource net_log_; - quic::QuicSpdySession* session_; // Unowned. + quic::QuicSession* session_; // Unowned. // The last packet number received. quic::QuicPacketNumber last_received_packet_number_; // The size of the most recently received packet. @@ -199,6 +198,8 @@ // for the QUIC connection. May be null. const std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher_; + QuicEventLogger event_logger_; + DISALLOW_COPY_AND_ASSIGN(QuicConnectionLogger); };
diff --git a/net/quic/quic_event_logger.cc b/net/quic/quic_event_logger.cc new file mode 100644 index 0000000..cf9e13cb --- /dev/null +++ b/net/quic/quic_event_logger.cc
@@ -0,0 +1,861 @@ +// Copyright 2020 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 "net/quic/quic_event_logger.h" + +#include "net/cert/x509_certificate.h" +#include "net/log/net_log_values.h" +#include "net/quic/address_utils.h" +#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h" + +namespace net { + +namespace { + +base::Value NetLogQuicPacketParams(const quic::QuicSocketAddress& self_address, + const quic::QuicSocketAddress& peer_address, + size_t packet_size) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("self_address", self_address.ToString()); + dict.SetStringKey("peer_address", peer_address.ToString()); + dict.SetIntKey("size", packet_size); + return dict; +} + +base::Value NetLogQuicPacketSentParams( + const quic::SerializedPacket& serialized_packet, + quic::TransmissionType transmission_type, + quic::QuicTime sent_time) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("transmission_type", + quic::TransmissionTypeToString(transmission_type)); + dict.SetKey("packet_number", + NetLogNumberValue(serialized_packet.packet_number.ToUint64())); + dict.SetIntKey("size", serialized_packet.encrypted_length); + dict.SetKey("sent_time_us", NetLogNumberValue(sent_time.ToDebuggingValue())); + dict.SetStringKey( + "encryption_level", + quic::EncryptionLevelToString(serialized_packet.encryption_level)); + return dict; +} + +base::Value NetLogQuicPacketLostParams(quic::QuicPacketNumber packet_number, + quic::TransmissionType transmission_type, + quic::QuicTime detection_time) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("transmission_type", + quic::TransmissionTypeToString(transmission_type)); + dict.SetKey("packet_number", NetLogNumberValue(packet_number.ToUint64())); + dict.SetKey("detection_time_us", + NetLogNumberValue(detection_time.ToDebuggingValue())); + return dict; +} + +base::Value NetLogQuicDuplicatePacketParams( + quic::QuicPacketNumber packet_number) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("packet_number", NetLogNumberValue(packet_number.ToUint64())); + return dict; +} + +base::Value NetLogReceivedQuicPacketHeaderParams( + const quic::QuicPacketHeader& header, + const quic::ParsedQuicVersion& session_version, + const quic::QuicConnectionId& connection_id, + const quic::QuicConnectionId& client_connection_id) { + base::Value dict(base::Value::Type::DICTIONARY); + quic::ParsedQuicVersion version = session_version; + if (header.version_flag && + header.version != quic::ParsedQuicVersion::Unsupported()) { + version = header.version; + if (version != session_version) { + dict.SetStringKey("version", quic::ParsedQuicVersionToString(version)); + } + } + dict.SetStringKey("connection_id", connection_id.ToString()); + if (!client_connection_id.IsEmpty()) { + dict.SetStringKey("client_connection_id", client_connection_id.ToString()); + } + if (version.HasIetfInvariantHeader()) { + if (header.destination_connection_id_included == + quic::CONNECTION_ID_PRESENT && + header.destination_connection_id != client_connection_id && + !header.destination_connection_id.IsEmpty()) { + dict.SetStringKey("destination_connection_id", + header.destination_connection_id.ToString()); + } + if (header.source_connection_id_included == quic::CONNECTION_ID_PRESENT && + header.source_connection_id != connection_id && + !header.source_connection_id.IsEmpty()) { + dict.SetStringKey("source_connection_id", + header.source_connection_id.ToString()); + } + } else { + if (header.destination_connection_id_included == + quic::CONNECTION_ID_PRESENT && + header.destination_connection_id != connection_id && + !header.destination_connection_id.IsEmpty()) { + dict.SetStringKey("destination_connection_id", + header.destination_connection_id.ToString()); + } + dict.SetIntKey("reset_flag", header.reset_flag); + dict.SetIntKey("version_flag", header.version_flag); + } + dict.SetKey("packet_number", + NetLogNumberValue(header.packet_number.ToUint64())); + dict.SetStringKey("header_format", + quic::PacketHeaderFormatToString(header.form)); + if (header.form == quic::IETF_QUIC_LONG_HEADER_PACKET) { + dict.SetStringKey("long_header_type", quic::QuicLongHeaderTypeToString( + header.long_packet_type)); + } + return dict; +} + +base::Value NetLogQuicStreamFrameParams(const quic::QuicStreamFrame& frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_id", frame.stream_id); + dict.SetBoolKey("fin", frame.fin); + dict.SetKey("offset", NetLogNumberValue(frame.offset)); + dict.SetIntKey("length", frame.data_length); + return dict; +} + +base::Value NetLogQuicAckFrameParams(const quic::QuicAckFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("largest_observed", + NetLogNumberValue(frame->largest_acked.ToUint64())); + dict.SetKey("delta_time_largest_observed_us", + NetLogNumberValue(frame->ack_delay_time.ToMicroseconds())); + + base::Value missing(base::Value::Type::LIST); + quic::QuicPacketNumber smallest_observed; + if (!frame->packets.Empty()) { + // V34 and above express acked packets, but only print + // missing packets, because it's typically a shorter list. + smallest_observed = frame->packets.Min(); + for (quic::QuicPacketNumber packet = smallest_observed; + packet < frame->largest_acked; ++packet) { + if (!frame->packets.Contains(packet)) { + missing.Append(NetLogNumberValue(packet.ToUint64())); + } + } + } else { + smallest_observed = frame->largest_acked; + } + dict.SetKey("smallest_observed", + NetLogNumberValue(smallest_observed.ToUint64())); + dict.SetKey("missing_packets", std::move(missing)); + + base::Value received(base::Value::Type::LIST); + const quic::PacketTimeVector& received_times = frame->received_packet_times; + for (auto it = received_times.begin(); it != received_times.end(); ++it) { + base::Value info(base::Value::Type::DICTIONARY); + info.SetKey("packet_number", NetLogNumberValue(it->first.ToUint64())); + info.SetKey("received", NetLogNumberValue(it->second.ToDebuggingValue())); + received.Append(std::move(info)); + } + dict.SetKey("received_packet_times", std::move(received)); + + return dict; +} + +base::Value NetLogQuicRstStreamFrameParams( + const quic::QuicRstStreamFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_id", frame->stream_id); + dict.SetIntKey("quic_rst_stream_error", frame->error_code); + dict.SetKey("offset", NetLogNumberValue(frame->byte_offset)); + return dict; +} + +base::Value NetLogQuicConnectionCloseFrameParams( + const quic::QuicConnectionCloseFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("quic_error", frame->quic_error_code); + dict.SetStringKey("details", frame->error_details); + return dict; +} + +base::Value NetLogQuicWindowUpdateFrameParams( + const quic::QuicWindowUpdateFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_id", frame->stream_id); + dict.SetKey("byte_offset", NetLogNumberValue(frame->max_data)); + return dict; +} + +base::Value NetLogQuicBlockedFrameParams(const quic::QuicBlockedFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_id", frame->stream_id); + return dict; +} + +base::Value NetLogQuicGoAwayFrameParams(const quic::QuicGoAwayFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("quic_error", frame->error_code); + dict.SetIntKey("last_good_stream_id", frame->last_good_stream_id); + dict.SetStringKey("reason_phrase", frame->reason_phrase); + return dict; +} + +base::Value NetLogQuicStopWaitingFrameParams( + const quic::QuicStopWaitingFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("least_unacked", + NetLogNumberValue(frame->least_unacked.ToUint64())); + return dict; +} + +base::Value NetLogQuicVersionNegotiationPacketParams( + const quic::QuicVersionNegotiationPacket* packet) { + base::Value dict(base::Value::Type::DICTIONARY); + base::Value versions(base::Value::Type::LIST); + for (auto it = packet->versions.begin(); it != packet->versions.end(); ++it) { + versions.Append(ParsedQuicVersionToString(*it)); + } + dict.SetKey("versions", std::move(versions)); + return dict; +} + +base::Value NetLogQuicPublicResetPacketParams( + const IPEndPoint& server_hello_address, + const quic::QuicSocketAddress& public_reset_address) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("server_hello_address", server_hello_address.ToString()); + dict.SetStringKey("public_reset_address", public_reset_address.ToString()); + return dict; +} + +base::Value NetLogQuicPathData(const quic::QuicPathFrameBuffer& buffer) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("data", + NetLogBinaryValue(reinterpret_cast<const char*>(buffer.data()), + buffer.size())); + return dict; +} + +base::Value NetLogQuicCryptoHandshakeMessageParams( + const quic::CryptoHandshakeMessage* message) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("quic_crypto_handshake_message", message->DebugString()); + return dict; +} + +base::Value NetLogQuicTransportParametersParams( + const quic::TransportParameters& transport_parameters) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("quic_transport_parameters", + transport_parameters.ToString()); + return dict; +} + +base::Value NetLogQuicOnConnectionClosedParams( + quic::QuicErrorCode error, + std::string error_details, + quic::ConnectionCloseSource source) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("quic_error", error); + dict.SetStringKey("details", error_details); + dict.SetBoolKey("from_peer", source == quic::ConnectionCloseSource::FROM_PEER + ? true + : false); + return dict; +} + +base::Value NetLogQuicCertificateVerifiedParams( + scoped_refptr<X509Certificate> cert) { + // Only the subjects are logged so that we can investigate connection pooling. + // More fields could be logged in the future. + std::vector<std::string> dns_names; + cert->GetSubjectAltName(&dns_names, nullptr); + base::Value dict(base::Value::Type::DICTIONARY); + base::Value subjects(base::Value::Type::LIST); + for (auto& dns_name : dns_names) { + subjects.Append(std::move(dns_name)); + } + dict.SetKey("subjects", std::move(subjects)); + return dict; +} + +base::Value NetLogQuicCryptoFrameParams(const quic::QuicCryptoFrame* frame, + bool has_buffer) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("encryption_level", + quic::EncryptionLevelToString(frame->level)); + dict.SetIntKey("data_length", frame->data_length); + dict.SetKey("offset", NetLogNumberValue(frame->offset)); + if (has_buffer) { + dict.SetKey("bytes", NetLogBinaryValue( + reinterpret_cast<const void*>(frame->data_buffer), + frame->data_length)); + } + return dict; +} + +base::Value NetLogQuicStopSendingFrameParams( + const quic::QuicStopSendingFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_id", frame->stream_id); + dict.SetIntKey("application_error_code", frame->application_error_code); + return dict; +} + +base::Value NetLogQuicStreamsBlockedFrameParams( + const quic::QuicStreamsBlockedFrame& frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_count", frame.stream_count); + dict.SetBoolKey("is_unidirectional", frame.unidirectional); + return dict; +} + +base::Value NetLogQuicMaxStreamsFrameParams( + const quic::QuicMaxStreamsFrame& frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetIntKey("stream_count", frame.stream_count); + dict.SetBoolKey("is_unidirectional", frame.unidirectional); + return dict; +} + +base::Value NetLogQuicNewConnectionIdFrameParams( + const quic::QuicNewConnectionIdFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("connection_id", frame->connection_id.ToString()); + dict.SetKey("sequence_number", NetLogNumberValue(frame->sequence_number)); + dict.SetKey("retire_prior_to", NetLogNumberValue(frame->retire_prior_to)); + return dict; +} + +base::Value NetLogQuicRetireConnectionIdFrameParams( + const quic::QuicRetireConnectionIdFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("sequence_number", NetLogNumberValue(frame->sequence_number)); + return dict; +} + +base::Value NetLogQuicNewTokenFrameParams( + const quic::QuicNewTokenFrame* frame) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetKey("token", NetLogBinaryValue( + reinterpret_cast<const void*>(frame->token.data()), + frame->token.length())); + return dict; +} + +} // namespace + +QuicEventLogger::QuicEventLogger(quic::QuicSession* session, + const NetLogWithSource& net_log) + : session_(session), net_log_(net_log) {} + +void QuicEventLogger::OnFrameAddedToPacket(const quic::QuicFrame& frame) { + if (!net_log_.IsCapturing()) + return; + switch (frame.type) { + case quic::PADDING_FRAME: + net_log_.AddEventWithIntParams( + NetLogEventType::QUIC_SESSION_PADDING_FRAME_SENT, "num_padding_bytes", + frame.padding_frame.num_padding_bytes); + break; + case quic::STREAM_FRAME: + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STREAM_FRAME_SENT, [&] { + return NetLogQuicStreamFrameParams(frame.stream_frame); + }); + break; + case quic::ACK_FRAME: { + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_ACK_FRAME_SENT, [&] { + return NetLogQuicAckFrameParams(frame.ack_frame); + }); + break; + } + case quic::RST_STREAM_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_RST_STREAM_FRAME_SENT, [&] { + return NetLogQuicRstStreamFrameParams(frame.rst_stream_frame); + }); + break; + case quic::CONNECTION_CLOSE_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_CONNECTION_CLOSE_FRAME_SENT, [&] { + return NetLogQuicConnectionCloseFrameParams( + frame.connection_close_frame); + }); + break; + case quic::GOAWAY_FRAME: + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_GOAWAY_FRAME_SENT, [&] { + return NetLogQuicGoAwayFrameParams(frame.goaway_frame); + }); + break; + case quic::WINDOW_UPDATE_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_WINDOW_UPDATE_FRAME_SENT, [&] { + return NetLogQuicWindowUpdateFrameParams(frame.window_update_frame); + }); + break; + case quic::BLOCKED_FRAME: + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_BLOCKED_FRAME_SENT, [&] { + return NetLogQuicBlockedFrameParams(frame.blocked_frame); + }); + break; + case quic::STOP_WAITING_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_STOP_WAITING_FRAME_SENT, [&] { + return NetLogQuicStopWaitingFrameParams(&frame.stop_waiting_frame); + }); + break; + case quic::PING_FRAME: + // PingFrame has no contents to log, so just record that it was sent. + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PING_FRAME_SENT); + break; + case quic::MTU_DISCOVERY_FRAME: + // MtuDiscoveryFrame is PingFrame on wire, it does not have any payload. + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_MTU_DISCOVERY_FRAME_SENT); + break; + case quic::NEW_CONNECTION_ID_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_NEW_CONNECTION_ID_FRAME_SENT, [&] { + return NetLogQuicNewConnectionIdFrameParams( + frame.new_connection_id_frame); + }); + break; + case quic::MAX_STREAMS_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_MAX_STREAMS_FRAME_SENT, [&] { + return NetLogQuicMaxStreamsFrameParams(frame.max_streams_frame); + }); + break; + case quic::STREAMS_BLOCKED_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_STREAMS_BLOCKED_FRAME_SENT, [&] { + return NetLogQuicStreamsBlockedFrameParams( + frame.streams_blocked_frame); + }); + break; + case quic::PATH_RESPONSE_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_PATH_RESPONSE_FRAME_SENT, [&] { + return NetLogQuicPathData(frame.path_response_frame->data_buffer); + }); + break; + case quic::PATH_CHALLENGE_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_PATH_CHALLENGE_FRAME_SENT, [&] { + return NetLogQuicPathData(frame.path_challenge_frame->data_buffer); + }); + break; + case quic::STOP_SENDING_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_STOP_SENDING_FRAME_SENT, [&] { + return NetLogQuicStopSendingFrameParams(frame.stop_sending_frame); + }); + break; + case quic::MESSAGE_FRAME: + net_log_.AddEventWithIntParams( + NetLogEventType::QUIC_SESSION_MESSAGE_FRAME_SENT, "message_length", + frame.message_frame->message_length); + break; + case quic::CRYPTO_FRAME: + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CRYPTO_FRAME_SENT, [&] { + return NetLogQuicCryptoFrameParams(frame.crypto_frame, + /*has_buffer = */ false); + }); + break; + case quic::NEW_TOKEN_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_NEW_TOKEN_FRAME_SENT, + [&] { return NetLogQuicNewTokenFrameParams(frame.new_token_frame); }); + break; + case quic::RETIRE_CONNECTION_ID_FRAME: + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_RETIRE_CONNECTION_ID_FRAME_SENT, [&] { + return NetLogQuicRetireConnectionIdFrameParams( + frame.retire_connection_id_frame); + }); + break; + default: + DCHECK(false) << "Illegal frame type: " << frame.type; + } +} + +void QuicEventLogger::OnStreamFrameCoalesced( + const quic::QuicStreamFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STREAM_FRAME_COALESCED, + [&] { return NetLogQuicStreamFrameParams(frame); }); +} + +void QuicEventLogger::OnPacketSent( + const quic::SerializedPacket& serialized_packet, + quic::TransmissionType transmission_type, + quic::QuicTime sent_time) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_SENT, [&] { + return NetLogQuicPacketSentParams(serialized_packet, transmission_type, + sent_time); + }); +} + +void QuicEventLogger::OnIncomingAck( + quic::QuicPacketNumber ack_packet_number, + quic::EncryptionLevel /*ack_decrypted_level*/, + const quic::QuicAckFrame& frame, + quic::QuicTime ack_receive_time, + quic::QuicPacketNumber largest_observed, + bool rtt_updated, + quic::QuicPacketNumber least_unacked_sent_packet) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_ACK_FRAME_RECEIVED, + [&] { return NetLogQuicAckFrameParams(&frame); }); +} + +void QuicEventLogger::OnPacketLoss(quic::QuicPacketNumber lost_packet_number, + quic::EncryptionLevel /*encryption_level*/, + quic::TransmissionType transmission_type, + quic::QuicTime detection_time) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_LOST, [&] { + return NetLogQuicPacketLostParams(lost_packet_number, transmission_type, + detection_time); + }); +} + +void QuicEventLogger::OnPacketReceived( + const quic::QuicSocketAddress& self_address, + const quic::QuicSocketAddress& peer_address, + const quic::QuicEncryptedPacket& packet) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_RECEIVED, [&] { + return NetLogQuicPacketParams(self_address, peer_address, packet.length()); + }); +} + +void QuicEventLogger::OnUnauthenticatedHeader( + const quic::QuicPacketHeader& header) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_UNAUTHENTICATED_PACKET_HEADER_RECEIVED, + [&] { + return NetLogReceivedQuicPacketHeaderParams( + header, session_->version(), + session_->connection()->connection_id(), + session_->connection()->client_connection_id()); + }); +} + +void QuicEventLogger::OnUndecryptablePacket( + quic::EncryptionLevel decryption_level, + bool dropped) { + if (!net_log_.IsCapturing()) + return; + if (dropped) { + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_DROPPED_UNDECRYPTABLE_PACKET, + "encryption_level", quic::EncryptionLevelToString(decryption_level)); + return; + } + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_BUFFERED_UNDECRYPTABLE_PACKET, + "encryption_level", quic::EncryptionLevelToString(decryption_level)); +} + +void QuicEventLogger::OnAttemptingToProcessUndecryptablePacket( + quic::EncryptionLevel decryption_level) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_ATTEMPTING_TO_PROCESS_UNDECRYPTABLE_PACKET, + "encryption_level", quic::EncryptionLevelToString(decryption_level)); +} + +void QuicEventLogger::OnDuplicatePacket(quic::QuicPacketNumber packet_number) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_DUPLICATE_PACKET_RECEIVED, + [&] { return NetLogQuicDuplicatePacketParams(packet_number); }); +} + +void QuicEventLogger::OnPacketHeader(const quic::QuicPacketHeader& header) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_AUTHENTICATED); +} + +void QuicEventLogger::OnStreamFrame(const quic::QuicStreamFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STREAM_FRAME_RECEIVED, + [&] { return NetLogQuicStreamFrameParams(frame); }); +} + +void QuicEventLogger::OnPathChallengeFrame( + const quic::QuicPathChallengeFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PATH_CHALLENGE_FRAME_RECEIVED, + [&] { return NetLogQuicPathData(frame.data_buffer); }); +} + +void QuicEventLogger::OnPathResponseFrame( + const quic::QuicPathResponseFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PATH_RESPONSE_FRAME_RECEIVED, + [&] { return NetLogQuicPathData(frame.data_buffer); }); +} + +void QuicEventLogger::OnCryptoFrame(const quic::QuicCryptoFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CRYPTO_FRAME_RECEIVED, [&] { + return NetLogQuicCryptoFrameParams(&frame, /*has_buffer = */ true); + }); +} + +void QuicEventLogger::OnStopSendingFrame( + const quic::QuicStopSendingFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STOP_SENDING_FRAME_RECEIVED, + [&] { return NetLogQuicStopSendingFrameParams(&frame); }); +} + +void QuicEventLogger::OnStreamsBlockedFrame( + const quic::QuicStreamsBlockedFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_STREAMS_BLOCKED_FRAME_RECEIVED, + [&] { return NetLogQuicStreamsBlockedFrameParams(frame); }); +} + +void QuicEventLogger::OnMaxStreamsFrame( + const quic::QuicMaxStreamsFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_MAX_STREAMS_FRAME_RECEIVED, + [&] { return NetLogQuicMaxStreamsFrameParams(frame); }); +} + +void QuicEventLogger::OnStopWaitingFrame( + const quic::QuicStopWaitingFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_STOP_WAITING_FRAME_RECEIVED, + [&] { return NetLogQuicStopWaitingFrameParams(&frame); }); +} + +void QuicEventLogger::OnRstStreamFrame(const quic::QuicRstStreamFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_RST_STREAM_FRAME_RECEIVED, + [&] { return NetLogQuicRstStreamFrameParams(&frame); }); +} + +void QuicEventLogger::OnConnectionCloseFrame( + const quic::QuicConnectionCloseFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_CONNECTION_CLOSE_FRAME_RECEIVED, + [&] { return NetLogQuicConnectionCloseFrameParams(&frame); }); +} + +void QuicEventLogger::OnWindowUpdateFrame( + const quic::QuicWindowUpdateFrame& frame, + const quic::QuicTime& receive_time) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_WINDOW_UPDATE_FRAME_RECEIVED, + [&] { return NetLogQuicWindowUpdateFrameParams(&frame); }); +} + +void QuicEventLogger::OnBlockedFrame(const quic::QuicBlockedFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_BLOCKED_FRAME_RECEIVED, + [&] { return NetLogQuicBlockedFrameParams(&frame); }); +} + +void QuicEventLogger::OnGoAwayFrame(const quic::QuicGoAwayFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_GOAWAY_FRAME_RECEIVED, + [&] { return NetLogQuicGoAwayFrameParams(&frame); }); +} + +void QuicEventLogger::OnPingFrame(const quic::QuicPingFrame& frame) { + // PingFrame has no contents to log, so just record that it was received. + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PING_FRAME_RECEIVED); +} + +void QuicEventLogger::OnPaddingFrame(const quic::QuicPaddingFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEventWithIntParams( + NetLogEventType::QUIC_SESSION_PADDING_FRAME_RECEIVED, "num_padding_bytes", + frame.num_padding_bytes); +} + +void QuicEventLogger::OnNewConnectionIdFrame( + const quic::QuicNewConnectionIdFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_NEW_CONNECTION_ID_FRAME_RECEIVED, + [&] { return NetLogQuicNewConnectionIdFrameParams(&frame); }); +} + +void QuicEventLogger::OnNewTokenFrame(const quic::QuicNewTokenFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_NEW_TOKEN_FRAME_RECEIVED, + [&] { return NetLogQuicNewTokenFrameParams(&frame); }); +} + +void QuicEventLogger::OnRetireConnectionIdFrame( + const quic::QuicRetireConnectionIdFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_RETIRE_CONNECTION_ID_FRAME_RECEIVED, + [&] { return NetLogQuicRetireConnectionIdFrameParams(&frame); }); +} + +void QuicEventLogger::OnMessageFrame(const quic::QuicMessageFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEventWithIntParams( + NetLogEventType::QUIC_SESSION_MESSAGE_FRAME_RECEIVED, "message_length", + frame.message_length); +} + +void QuicEventLogger::OnHandshakeDoneFrame( + const quic::QuicHandshakeDoneFrame& frame) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_HANDSHAKE_DONE_FRAME_RECEIVED); +} + +void QuicEventLogger::OnCoalescedPacketSent( + const quic::QuicCoalescedPacket& coalesced_packet, + size_t length) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_COALESCED_PACKET_SENT, "info", + coalesced_packet.ToString(length)); +} + +void QuicEventLogger::OnPublicResetPacket( + const quic::QuicPublicResetPacket& packet) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED, + [&] { + return NetLogQuicPublicResetPacketParams( + local_address_from_shlo_, packet.client_address); + }); +} + +void QuicEventLogger::OnVersionNegotiationPacket( + const quic::QuicVersionNegotiationPacket& packet) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_VERSION_NEGOTIATION_PACKET_RECEIVED, + [&] { return NetLogQuicVersionNegotiationPacketParams(&packet); }); +} + +void QuicEventLogger::OnCryptoHandshakeMessageReceived( + const quic::CryptoHandshakeMessage& message) { + if (message.tag() == quic::kSHLO) { + quiche::QuicheStringPiece address; + quic::QuicSocketAddressCoder decoder; + if (message.GetStringPiece(quic::kCADR, &address) && + decoder.Decode(address.data(), address.size())) { + local_address_from_shlo_ = + IPEndPoint(ToIPAddress(decoder.ip()), decoder.port()); + } + } + + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_RECEIVED, + [&] { return NetLogQuicCryptoHandshakeMessageParams(&message); }); +} + +void QuicEventLogger::OnCryptoHandshakeMessageSent( + const quic::CryptoHandshakeMessage& message) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_CRYPTO_HANDSHAKE_MESSAGE_SENT, + [&] { return NetLogQuicCryptoHandshakeMessageParams(&message); }); +} + +void QuicEventLogger::OnConnectionClosed( + const quic::QuicConnectionCloseFrame& frame, + quic::ConnectionCloseSource source) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CLOSED, [&] { + return NetLogQuicOnConnectionClosedParams(frame.quic_error_code, + frame.error_details, source); + }); +} + +void QuicEventLogger::OnSuccessfulVersionNegotiation( + const quic::ParsedQuicVersion& version) { + if (!net_log_.IsCapturing()) + return; + std::string quic_version = quic::ParsedQuicVersionToString(version); + net_log_.AddEventWithStringParams( + NetLogEventType::QUIC_SESSION_VERSION_NEGOTIATED, "version", + quic_version); +} + +void QuicEventLogger::OnCertificateVerified(const CertVerifyResult& result) { + if (!net_log_.IsCapturing()) + return; + if (result.cert_status == CERT_STATUS_INVALID) { + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CERTIFICATE_VERIFY_FAILED); + return; + } + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CERTIFICATE_VERIFIED, [&] { + return NetLogQuicCertificateVerifiedParams(result.verified_cert); + }); +} + +void QuicEventLogger::OnTransportParametersSent( + const quic::TransportParameters& transport_parameters) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_TRANSPORT_PARAMETERS_SENT, [&] { + return NetLogQuicTransportParametersParams(transport_parameters); + }); +} + +void QuicEventLogger::OnTransportParametersReceived( + const quic::TransportParameters& transport_parameters) { + if (!net_log_.IsCapturing()) + return; + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_TRANSPORT_PARAMETERS_RECEIVED, [&] { + return NetLogQuicTransportParametersParams(transport_parameters); + }); +} + +} // namespace net
diff --git a/net/quic/quic_event_logger.h b/net/quic/quic_event_logger.h new file mode 100644 index 0000000..c2f84e9 --- /dev/null +++ b/net/quic/quic_event_logger.h
@@ -0,0 +1,113 @@ +// Copyright 2020 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 NET_QUIC_QUIC_EVENT_LOGGER_H_ +#define NET_QUIC_QUIC_EVENT_LOGGER_H_ + +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" +#include "net/cert/cert_verify_result.h" +#include "net/log/net_log_with_source.h" +#include "net/third_party/quiche/src/quic/core/quic_connection.h" +#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h" +#include "net/third_party/quiche/src/quic/core/quic_session.h" + +namespace net { + +// Logs QUIC-related events into the supplied NetLog. Note that while most of +// the logging is done by registering this object as a debug delegate, some of +// the methods have to be called manually. +class NET_EXPORT_PRIVATE QuicEventLogger + : public quic::QuicConnectionDebugVisitor, + public quic::QuicPacketCreator::DebugDelegate { + public: + QuicEventLogger(quic::QuicSession* session, const NetLogWithSource& net_log); + + // quic::QuicPacketCreator::DebugDelegateInterface + void OnFrameAddedToPacket(const quic::QuicFrame& frame) override; + void OnStreamFrameCoalesced(const quic::QuicStreamFrame& frame) override; + + // QuicConnectionDebugVisitor Interface + void OnPacketSent(const quic::SerializedPacket& serialized_packet, + quic::TransmissionType transmission_type, + quic::QuicTime sent_time) override; + void OnIncomingAck(quic::QuicPacketNumber ack_packet_number, + quic::EncryptionLevel ack_decrypted_level, + const quic::QuicAckFrame& frame, + quic::QuicTime ack_receive_time, + quic::QuicPacketNumber largest_observed, + bool rtt_updated, + quic::QuicPacketNumber least_unacked_sent_packet) override; + void OnPacketLoss(quic::QuicPacketNumber lost_packet_number, + quic::EncryptionLevel encryption_level, + quic::TransmissionType transmission_type, + quic::QuicTime detection_time) override; + void OnPacketReceived(const quic::QuicSocketAddress& self_address, + const quic::QuicSocketAddress& peer_address, + const quic::QuicEncryptedPacket& packet) override; + void OnUnauthenticatedHeader(const quic::QuicPacketHeader& header) override; + void OnUndecryptablePacket(quic::EncryptionLevel decryption_level, + bool dropped) override; + void OnAttemptingToProcessUndecryptablePacket( + quic::EncryptionLevel decryption_level) override; + void OnDuplicatePacket(quic::QuicPacketNumber packet_number) override; + void OnPacketHeader(const quic::QuicPacketHeader& header) override; + void OnPathChallengeFrame(const quic::QuicPathChallengeFrame& frame) override; + void OnPathResponseFrame(const quic::QuicPathResponseFrame& frame) override; + void OnCryptoFrame(const quic::QuicCryptoFrame& frame) override; + void OnStopSendingFrame(const quic::QuicStopSendingFrame& frame) override; + void OnStreamsBlockedFrame( + const quic::QuicStreamsBlockedFrame& frame) override; + void OnMaxStreamsFrame(const quic::QuicMaxStreamsFrame& frame) override; + void OnStreamFrame(const quic::QuicStreamFrame& frame) override; + void OnStopWaitingFrame(const quic::QuicStopWaitingFrame& frame) override; + void OnRstStreamFrame(const quic::QuicRstStreamFrame& frame) override; + void OnConnectionCloseFrame( + const quic::QuicConnectionCloseFrame& frame) override; + void OnWindowUpdateFrame(const quic::QuicWindowUpdateFrame& frame, + const quic::QuicTime& receive_time) override; + void OnBlockedFrame(const quic::QuicBlockedFrame& frame) override; + void OnGoAwayFrame(const quic::QuicGoAwayFrame& frame) override; + void OnPingFrame(const quic::QuicPingFrame& frame) override; + void OnPaddingFrame(const quic::QuicPaddingFrame& frame) override; + void OnNewConnectionIdFrame( + const quic::QuicNewConnectionIdFrame& frame) override; + void OnNewTokenFrame(const quic::QuicNewTokenFrame& frame) override; + void OnRetireConnectionIdFrame( + const quic::QuicRetireConnectionIdFrame& frame) override; + void OnMessageFrame(const quic::QuicMessageFrame& frame) override; + void OnHandshakeDoneFrame(const quic::QuicHandshakeDoneFrame& frame) override; + void OnCoalescedPacketSent(const quic::QuicCoalescedPacket& coalesced_packet, + size_t length) override; + void OnPublicResetPacket(const quic::QuicPublicResetPacket& packet) override; + void OnVersionNegotiationPacket( + const quic::QuicVersionNegotiationPacket& packet) override; + void OnConnectionClosed(const quic::QuicConnectionCloseFrame& frame, + quic::ConnectionCloseSource source) override; + void OnSuccessfulVersionNegotiation( + const quic::ParsedQuicVersion& version) override; + void OnTransportParametersSent( + const quic::TransportParameters& transport_parameters) override; + void OnTransportParametersReceived( + const quic::TransportParameters& transport_parameters) override; + + // Events that are not received via the visitor and have to be called manually + // from the session. + void OnCryptoHandshakeMessageReceived( + const quic::CryptoHandshakeMessage& message); + void OnCryptoHandshakeMessageSent( + const quic::CryptoHandshakeMessage& message); + void OnCertificateVerified(const CertVerifyResult& result); + + private: + quic::QuicSession* session_; // Unowned. + NetLogWithSource net_log_; + + // The quic::kCADR value provided by the server in ServerHello. + IPEndPoint local_address_from_shlo_; +}; + +} // namespace net + +#endif /* NET_QUIC_QUIC_EVENT_LOGGER_H_ */
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 4cd88fe1..374b6f2 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -1386,7 +1386,11 @@ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - session->OnGoAway(quic::QuicGoAwayFrame()); + if (version_.UsesHttp3()) { + session->OnHttp3GoAway(0); + } else { + session->OnGoAway(quic::QuicGoAwayFrame()); + } EXPECT_FALSE(HasActiveSession(host_port_pair_)); @@ -1396,6 +1400,11 @@ TEST_P(QuicStreamFactoryTest, GoAwayForConnectionMigrationWithPortOnly) { Initialize(); + // GoAway in HTTP/3 doesn't contain error code. Thus the session can't do + // error code specific handling. + if (version_.UsesHttp3()) { + return; + } ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -1501,7 +1510,11 @@ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_, kNetworkIsolationKeys[i]); - session->OnGoAway(quic::QuicGoAwayFrame()); + if (version_.UsesHttp3()) { + session->OnHttp3GoAway(0); + } else { + session->OnGoAway(quic::QuicGoAwayFrame()); + } EXPECT_FALSE(HasActiveSession(host_port_pair_, kNetworkIsolationKeys[i]));
diff --git a/remoting/codec/webrtc_video_encoder_vpx.cc b/remoting/codec/webrtc_video_encoder_vpx.cc index 52285e6..efe6af7 100644 --- a/remoting/codec/webrtc_video_encoder_vpx.cc +++ b/remoting/codec/webrtc_video_encoder_vpx.cc
@@ -416,6 +416,13 @@ DCHECK(use_vp9_ || !lossless_color_); DCHECK(use_vp9_ || !lossless_encode_); + if (use_vp9_) { + VLOG(0) << "Configuring VP9 encoder with lossless-color=" + << (lossless_color_ ? "true" : "false") + << ", lossless-encode=" << (lossless_encode_ ? "true" : "false") + << "."; + } + // Tear down |image_| if it no longer matches the size and color settings. // PrepareImage() will then create a new buffer of the required dimensions if // |image_| is not allocated.
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc index fe03fda..a05b067 100644 --- a/remoting/protocol/webrtc_video_stream.cc +++ b/remoting/protocol/webrtc_video_stream.cc
@@ -190,10 +190,8 @@ } void WebrtcVideoStream::SetLosslessColor(bool want_lossless) { - lossless_color_ = want_lossless; - if (encoder_) { - encoder_->SetLosslessColor(want_lossless); - } + NOTIMPLEMENTED() << "Changing lossless-color for VP9 requires SDP " + "offer/answer exchange."; } void WebrtcVideoStream::SetObserver(Observer* observer) { @@ -233,7 +231,6 @@ encoder_selector_.SetDesktopFrame(*frame); encoder_ = encoder_selector_.CreateEncoder(); encoder_->SetLosslessEncode(lossless_encode_); - encoder_->SetLosslessColor(lossless_color_); // TODO(zijiehe): Permanently stop the video stream if we cannot create an // encoder for the |frame|.
diff --git a/remoting/protocol/webrtc_video_stream.h b/remoting/protocol/webrtc_video_stream.h index 2784244..42e927b9 100644 --- a/remoting/protocol/webrtc_video_stream.h +++ b/remoting/protocol/webrtc_video_stream.h
@@ -113,8 +113,11 @@ // Settings that are received from video-control messages. These are stored // here in case a message is received before the encoder is created. + // Lossless-color is not stored here because, for VP9 encoder, WebRTC handles + // it via an SDP codec parameter, "profile-id=1". Changing it requires a + // new SDP offer/answer exchange, and therefore it cannot be changed directly + // via video-control message. bool lossless_encode_ = false; - bool lossless_color_ = false; base::WeakPtrFactory<WebrtcVideoStream> weak_factory_{this};
diff --git a/sandbox/policy/mac/common.sb b/sandbox/policy/mac/common.sb index e15e9d9..27b5a183 100644 --- a/sandbox/policy/mac/common.sb +++ b/sandbox/policy/mac/common.sb
@@ -158,6 +158,7 @@ ; Reads from /System. (allow file-read-data (path "/System/Library/CoreServices/SystemVersion.plist") + (path "/System/Library/CoreServices/SystemVersionCompat.plist") ; https://crbug.com/1108832 (path "/System/Library/CoreServices/checkfixlist") )
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json index a230e83a..27d71e9f 100644 --- a/testing/buildbot/chromium.ci.json +++ b/testing/buildbot/chromium.ci.json
@@ -69682,32 +69682,6 @@ }, { "args": [ - "--num-retries=3" - ], - "isolate_name": "blink_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "none", - "os": "Mac-10.10.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ "--test-type=integration" ], "isolate_name": "chromedriver_py_tests", @@ -71350,32 +71324,6 @@ }, { "args": [ - "--num-retries=3" - ], - "isolate_name": "blink_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "none", - "os": "Mac-10.11.6" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ "--test-type=integration" ], "isolate_name": "chromedriver_py_tests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 83ee81e..e2b6d5f 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -1428,32 +1428,6 @@ }, { "args": [ - "--num-retries=3" - ], - "isolate_name": "blink_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "none", - "os": "Mac-10.10.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ "--test-type=integration" ], "isolate_name": "chromedriver_py_tests", @@ -3096,32 +3070,6 @@ }, { "args": [ - "--num-retries=3" - ], - "isolate_name": "blink_web_tests", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "blink_web_tests", - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "none", - "os": "Mac-10.11.6" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test_id_prefix": "ninja://:blink_web_tests/" - }, - { - "args": [ "--test-type=integration" ], "isolate_name": "chromedriver_py_tests",
diff --git a/testing/buildbot/filters/lacros.browser_tests.filter b/testing/buildbot/filters/lacros.browser_tests.filter index 9bcbabbc..3f0c48a 100644 --- a/testing/buildbot/filters/lacros.browser_tests.filter +++ b/testing/buildbot/filters/lacros.browser_tests.filter
@@ -9,6 +9,8 @@ -All/HostedOrWebAppTest.CtrlClickLink/HostedApp -All/HostedOrWebAppTest.CtrlClickLink/WebApp -All/HostedOrWebAppTest.OpenLinkInNewTab/HostedApp +-All/IntentPickerBubbleViewBrowserTest.NavigationInAppWindowToInScopeLinkDoesNotShowIntentPicker* +-All/WebAppFileHandlingOriginTrialBrowserTest.ExpiredTrialHandlersAreCleanedUpAtLaunch/BookmarkApps -AudioFocusWebContentsObserverBrowserTest.PlatformAppHasDifferentAudioFocus -BluetoothApiTest.DeviceEvents -BluetoothApiTest.DeviceInfo @@ -64,11 +66,15 @@ -BrowserViewTest.GetAccessibleTabModalDialogTitle -BrowserViewTest.GetAccessibleTabModalDialogTree -BrowsingDataRemoverBrowserTest.StorageRemovedFromDisk +-CaptivePortalBrowserTest.SlowLoadSecureDnsErrorWithCaptivePortal -ClientHintsBrowserTest.ClientHintsClearSession -ClipboardApiTest.Extension +-ContentSettingsTest.AllowCookiesForASessionUsingExceptions -ContextMenuBrowserTest.GifImageDownscaleToJpeg +-ContextMenuBrowserTest.JpgImageDownscaleToJpg -ContextMenuBrowserTest.OpenLinkInProfile -ContextMenuBrowserTest.OpenLinkInProfileEntryPresent +-ContextMenuBrowserTest.OpenLinkInWebApp -ContextMenuBrowserTest.PngImageDownscaleToPng -CrComponentsCertificateManagerV3Test.All -CrComponentsManagedFootnoteV3Test.All @@ -91,17 +97,22 @@ -DownloadTest.DownloadTest_History -ExtensionPreferenceApiTest.Standard -ExtensionsMenuViewBrowserTest.ClickingContextMenuButton +-ExtensionWebRequestApiTest.WebSocketRequest +-ExtensionWebRequestApiTest.WebSocketRequestAuthRequired -ExternalProtocolDialogBrowserTest.TestFocus -FeedbackTest.AnonymousUser -FeedbackTest.ExtraDiagnostics +-FeedbackTest.ShowFeedback -FeedbackTest.ShowFeedbackFromAssistant -FeedbackTest.ShowLoginFeedback -FeedbackTest.SubmissionTest -FindInPageControllerTest.FindMovesOnTabClose_Issue1343052 +-FindInPageControllerTest.FindMovesWhenObscuring -FolderUploadConfirmationViewTest.InitiallyFocusesCancel -GlobalErrorBubbleTest.InvokeUi_ExternalInstallBubbleAlert -IconLoaderBrowserTest.LoadGroup -KeepAliveDevToolsTest.KeepsAliveUntilBrowserClose +-LoadImageBrowserTest.LoadImageWithMap -MediaRouterUIBrowserTest.OpenDialogFromAppMenu -OmniboxPopupContentsViewTest.ClickOmnibox -OmniboxPopupContentsViewTest.PopupMatchesLocationBarBackground @@ -124,6 +135,7 @@ -ProfileManagerBrowserTest.SwitchToProfile -RunInBackgroundTest.RunInBackgroundBasicTest -SearchByImageBrowserTest.ImageSearchWithCorruptImage +-SearchByImageBrowserTest.ImageSearchWithValidImage -SessionRestoreTest.RestoredTabsHaveCorrectInitialSize -SettingsA11yAccessibilityV3.Accessibility_accesskeys -SettingsA11yAccessibilityV3.Accessibility_area_alt @@ -395,6 +407,7 @@ -SettingsA11ySignoutV3.Signout_valid_lang -SettingsA11ySignoutV3.Signout_video_caption -SettingsA11ySignoutV3.Signout_video_description +-SSLUITest.DisplayedContentWithCertErrorsClearedOnNavigation -StartupBrowserCreatorExtensionsCheckupExperimentTest.ExtensionsCheckup -StartupBrowserCreatorTest.RestoreWithNoStartupWindow -TabActivityWatcherTest.AllWindowMetricsArePopulated @@ -403,6 +416,7 @@ -TabHoverCardBubbleViewBrowserTest.WidgetVisibleOnKeyPressAfterTabFocus -TabRestoreTest.RestoreWindowBounds -TabStripDragManagerTest.All +-WebAppLinkCapturingBrowserTest.AboutBlankNavigationReparented -WebRtcDesktopCaptureBrowserTest.RunsScreenshareFromOneTabToAnother -WebRtcGetDisplayMediaBrowserTestWithPicker.GetDisplayMediaVideo -WebRtcGetDisplayMediaBrowserTestWithPicker.GetDisplayMediaVideoAndAudio
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 74590f5..147e14c 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -126,6 +126,8 @@ }, 'blink_web_tests': { 'remove_from': [ + 'Mac10.10 Tests', + 'Mac10.11 Tests', 'Win 7 Tests x64 (1)', # 64-bit win is unsupported by the layout tests. 'Win10 Tests x64 (dbg)', ],
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 6f8c1ad..363291c 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -7904,6 +7904,24 @@ ] } ], + "WebProtectConnectors": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "EnterpriseConnectorsEnabled" + ] + } + ] + } + ], "WebRTC-Audio-NetEqDecisionLogicSettings": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 2d2aecb7..11fdd68 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -57,6 +57,7 @@ "fetch/fetch_api_response.mojom", "file/file_utilities.mojom", "filesystem/file_system.mojom", + "font_access/font_access.mojom", "geolocation/geolocation_service.mojom", "hid/hid.mojom", "hyphenation/hyphenation.mojom",
diff --git a/third_party/blink/public/mojom/font_access/OWNERS b/third_party/blink/public/mojom/font_access/OWNERS new file mode 100644 index 0000000..0467eaf --- /dev/null +++ b/third_party/blink/public/mojom/font_access/OWNERS
@@ -0,0 +1,7 @@ +file://content/browser/font_access/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage>FontAccess \ No newline at end of file
diff --git a/third_party/blink/public/mojom/font_access/font_access.mojom b/third_party/blink/public/mojom/font_access/font_access.mojom new file mode 100644 index 0000000..243c76a --- /dev/null +++ b/third_party/blink/public/mojom/font_access/font_access.mojom
@@ -0,0 +1,17 @@ +// Copyright 2020 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. + +module blink.mojom; + +import "third_party/blink/public/mojom/permissions/permission_status.mojom"; + +// Implemented in the browser process to pass font data to windows +// and workers in renderer processes. +// Provides methods related to enumerating locally installed fonts. +interface FontAccessManager { + // Provides a permission request response. Used on Mac because fonts are + // enumerated in-renderer on that platform. + // TODO(crbug.com/1113876): [EnableIf=is_mac] since this only applies to Mac. + RequestPermission() => (PermissionStatus status); +};
diff --git a/third_party/blink/public/mojom/permissions/permission.mojom b/third_party/blink/public/mojom/permissions/permission.mojom index 372df35d..7c47d2b 100644 --- a/third_party/blink/public/mojom/permissions/permission.mojom +++ b/third_party/blink/public/mojom/permissions/permission.mojom
@@ -28,6 +28,7 @@ NFC, STORAGE_ACCESS, WINDOW_PLACEMENT, + FONT_ACCESS, }; struct MidiPermissionDescriptor {
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 96def447..2bd980b 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -225,7 +225,6 @@ "//third_party/blink/renderer/modules/font_access/font_metadata.idl", "//third_party/blink/renderer/modules/font_access/font_table_map.idl", "//third_party/blink/renderer/modules/font_access/navigator_fonts.idl", - "//third_party/blink/renderer/modules/font_access/worker_navigator_fonts.idl", "//third_party/blink/renderer/modules/gamepad/gamepad.idl", "//third_party/blink/renderer/modules/gamepad/gamepad_axis_event.idl", "//third_party/blink/renderer/modules/gamepad/gamepad_axis_event_init.idl",
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index 2e00b61..b849df6 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -540,7 +540,7 @@ void LocalFrameClientImpl::DispatchDidCommitLoad( HistoryItem* item, WebHistoryCommitType commit_type, - GlobalObjectReusePolicy global_object_reuse_policy) { + bool should_reset_browser_interface_broker) { if (!web_frame_->Parent()) { web_frame_->ViewImpl()->DidCommitLoad(commit_type == kWebStandardCommit, false); @@ -549,7 +549,7 @@ if (web_frame_->Client()) { web_frame_->Client()->DidCommitNavigation( WebHistoryItem(item), commit_type, - global_object_reuse_policy == GlobalObjectReusePolicy::kCreateNew); + should_reset_browser_interface_broker); if (web_frame_->GetFrame()->IsLocalRoot()) { // This update should be sent as soon as loading the new document begins // so that the browser and compositor could reset their states. However,
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h index 2d6e5d798..dd60568 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -52,7 +52,6 @@ class WebDevToolsAgentImpl; class WebLocalFrameImpl; class WebSpellCheckPanelHostClient; -enum class GlobalObjectReusePolicy; class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient { public: @@ -101,9 +100,10 @@ WebHistoryCommitType, bool content_initiated) override; void DispatchDidReceiveTitle(const String&) override; - void DispatchDidCommitLoad(HistoryItem*, - WebHistoryCommitType, - GlobalObjectReusePolicy) override; + void DispatchDidCommitLoad( + HistoryItem*, + WebHistoryCommitType, + bool should_reset_browser_interface_broker) override; void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) override; void DispatchDidFinishDocumentLoad() override; void DispatchDidFinishLoad() override;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 96bf50bf..0360e07b 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -131,9 +131,10 @@ WebHistoryCommitType, bool content_initiated) {} virtual void DispatchDidReceiveTitle(const String&) = 0; - virtual void DispatchDidCommitLoad(HistoryItem*, - WebHistoryCommitType, - GlobalObjectReusePolicy) = 0; + virtual void DispatchDidCommitLoad( + HistoryItem*, + WebHistoryCommitType, + bool should_reset_browser_interface_broker) = 0; virtual void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) = 0; virtual void DispatchDidFinishDocumentLoad() = 0;
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 21cb4245..bf4be9e 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1602,15 +1602,12 @@ return origin; } -GlobalObjectReusePolicy DocumentLoader::CalculateGlobalObjectReusePolicy( - SecurityOrigin* security_origin) { +bool ShouldReuseDOMWindow(LocalFrame* frame, SecurityOrigin* security_origin) { // Secure transitions can only happen when navigating from the initial empty // document. - if (!GetFrameLoader().StateMachine()->IsDisplayingInitialEmptyDocument()) - return GlobalObjectReusePolicy::kCreateNew; - if (!frame_->DomWindow()->GetSecurityOrigin()->CanAccess(security_origin)) - return GlobalObjectReusePolicy::kCreateNew; - return GlobalObjectReusePolicy::kUseExisting; + if (!frame->Loader().StateMachine()->IsDisplayingInitialEmptyDocument()) + return false; + return frame->DomWindow()->GetSecurityOrigin()->CanAccess(security_origin); } WindowAgent* GetWindowAgentForOrigin(LocalFrame* frame, @@ -1625,53 +1622,10 @@ V8PerIsolateData::MainThreadIsolate(), origin); } -void DocumentLoader::CommitNavigation() { - CHECK_GE(state_, kCommitted); - DCHECK(frame_->GetPage()); - DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->IsActive()); - DCHECK_EQ(frame_->Tree().ChildCount(), 0u); - - // Prepare a DocumentInit before clearing the frame, because it may need to - // inherit an aliased security context. - Document* owner_document = nullptr; - - // TODO(dcheng): This differs from the behavior of both IE and Firefox: the - // origin is inherited from the document that loaded the URL. - if (Document::ShouldInheritSecurityOriginFromOwner(Url())) { - Frame* owner_frame = frame_->Tree().Parent(); - if (!owner_frame) - owner_frame = frame_->Loader().Opener(); - if (auto* owner_local_frame = DynamicTo<LocalFrame>(owner_frame)) - owner_document = owner_local_frame->GetDocument(); - } - - // Re-validate Document Policy feature before installing the new document. - if (!RuntimeEnabledFeatures::DocumentPolicyEnabled( - owner_document ? owner_document->GetExecutionContext() : nullptr)) { - document_policy_ = DocumentPolicy::ParsedDocumentPolicy{}; - } - - if (document_policy_.feature_state.contains( - mojom::blink::DocumentPolicyFeature::kForceLoadAtTop)) { - navigation_scroll_allowed_ = !( - document_policy_ - .feature_state[mojom::blink::DocumentPolicyFeature::kForceLoadAtTop] - .BoolValue()); - } - +void DocumentLoader::InitializeWindow(Document* owner_document) { auto sandbox_flags = CalculateSandboxFlags(); auto security_origin = CalculateOrigin(owner_document, sandbox_flags); - GlobalObjectReusePolicy global_object_reuse_policy = - CalculateGlobalObjectReusePolicy(security_origin.get()); - - if (GetFrameLoader().StateMachine()->IsDisplayingInitialEmptyDocument()) { - GetFrameLoader().StateMachine()->AdvanceTo( - FrameLoaderStateMachine::kCommittedFirstRealLoad); - } - - LocalDOMWindow* previous_window = frame_->DomWindow(); - // In some rare cases, we'll re-use a LocalDOMWindow for a new Document. For // example, when a script calls window.open("..."), the browser gives // JavaScript a window synchronously but kicks off the load in the window @@ -1680,7 +1634,7 @@ // commits. To make that happen, we "securely transition" the existing // LocalDOMWindow to the Document that results from the network load. See also // Document::IsSecureTransitionTo. - if (global_object_reuse_policy != GlobalObjectReusePolicy::kUseExisting) { + if (!ShouldReuseDOMWindow(frame_.Get(), security_origin.get())) { auto* agent = GetWindowAgentForOrigin(frame_.Get(), security_origin.get()); frame_->SetDOMWindow(MakeGarbageCollected<LocalDOMWindow>(*frame_, agent)); @@ -1723,18 +1677,69 @@ security_origin = security_origin->GetOriginForAgentCluster( frame_->DomWindow()->GetAgent()->cluster_id()); - frame_->DomWindow()->GetSecurityContext().SetContentSecurityPolicy( - content_security_policy_.Get()); - frame_->DomWindow()->GetSecurityContext().ApplySandboxFlags(sandbox_flags); + SecurityContext& security_context = frame_->DomWindow()->GetSecurityContext(); + security_context.SetContentSecurityPolicy(content_security_policy_.Get()); + security_context.ApplySandboxFlags(sandbox_flags); // Conceptually, SecurityOrigin doesn't have to be initialized after sandbox // flags are applied, but there's a UseCounter in SetSecurityOrigin() that // wants to inspect sandbox flags. - frame_->DomWindow()->GetSecurityContext().SetSecurityOrigin( - std::move(security_origin)); + security_context.SetSecurityOrigin(std::move(security_origin)); // Requires SecurityOrigin to be initialized. OriginTrialContext::AddTokensFromHeader( frame_->DomWindow(), response_.HttpHeaderField(http_names::kOriginTrial)); + if (auto* parent = frame_->Tree().Parent()) { + const SecurityContext* parent_context = parent->GetSecurityContext(); + security_context.SetInsecureRequestPolicy( + parent_context->GetInsecureRequestPolicy()); + for (auto to_upgrade : parent_context->InsecureNavigationsToUpgrade()) + security_context.AddInsecureNavigationUpgrade(to_upgrade); + } + frame_->DomWindow()->SetAddressSpace(ip_address_space_); +} + +void DocumentLoader::CommitNavigation() { + CHECK_GE(state_, kCommitted); + DCHECK(frame_->GetPage()); + DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->IsActive()); + DCHECK_EQ(frame_->Tree().ChildCount(), 0u); + + // Prepare a DocumentInit before clearing the frame, because it may need to + // inherit an aliased security context. + Document* owner_document = nullptr; + + // TODO(dcheng): This differs from the behavior of both IE and Firefox: the + // origin is inherited from the document that loaded the URL. + if (Document::ShouldInheritSecurityOriginFromOwner(Url())) { + Frame* owner_frame = frame_->Tree().Parent(); + if (!owner_frame) + owner_frame = frame_->Loader().Opener(); + if (auto* owner_local_frame = DynamicTo<LocalFrame>(owner_frame)) + owner_document = owner_local_frame->GetDocument(); + } + + // Re-validate Document Policy feature before installing the new document. + if (!RuntimeEnabledFeatures::DocumentPolicyEnabled( + owner_document ? owner_document->GetExecutionContext() : nullptr)) { + document_policy_ = DocumentPolicy::ParsedDocumentPolicy{}; + } + + if (document_policy_.feature_state.contains( + mojom::blink::DocumentPolicyFeature::kForceLoadAtTop)) { + navigation_scroll_allowed_ = !( + document_policy_ + .feature_state[mojom::blink::DocumentPolicyFeature::kForceLoadAtTop] + .BoolValue()); + } + + LocalDOMWindow* previous_window = frame_->DomWindow(); + InitializeWindow(owner_document); + + if (GetFrameLoader().StateMachine()->IsDisplayingInitialEmptyDocument()) { + GetFrameLoader().StateMachine()->AdvanceTo( + FrameLoaderStateMachine::kCommittedFirstRealLoad); + } + SecurityContextInit security_init(frame_->DomWindow()); // FeaturePolicy and DocumentPolicy require SecurityOrigin and origin trials // to be initialized. @@ -1752,26 +1757,16 @@ document_policy_, response_.HttpHeaderField(http_names::kDocumentPolicyReportOnly)); - if (auto* parent = frame_->Tree().Parent()) { - SecurityContext& this_context = frame_->DomWindow()->GetSecurityContext(); - const SecurityContext* parent_context = parent->GetSecurityContext(); - this_context.SetInsecureRequestPolicy( - parent_context->GetInsecureRequestPolicy()); - for (auto to_upgrade : parent_context->InsecureNavigationsToUpgrade()) - this_context.AddInsecureNavigationUpgrade(to_upgrade); - } - frame_->DomWindow()->SetAddressSpace(ip_address_space_); - WillCommitNavigation(); - DocumentInit init = DocumentInit::Create() - .WithWindow(frame_->DomWindow(), owner_document) - .WithURL(Url()) - .WithTypeFrom(MimeType()) - .WithSrcdocDocument(loading_srcdoc_) - .WithNewRegistrationContext() - .WithWebBundleClaimedUrl(web_bundle_claimed_url_); - Document* document = frame_->DomWindow()->InstallNewDocument(init); + Document* document = frame_->DomWindow()->InstallNewDocument( + DocumentInit::Create() + .WithWindow(frame_->DomWindow(), owner_document) + .WithURL(Url()) + .WithTypeFrom(MimeType()) + .WithSrcdocDocument(loading_srcdoc_) + .WithNewRegistrationContext() + .WithWebBundleClaimedUrl(web_bundle_claimed_url_)); // Clear the user activation state. // TODO(crbug.com/736415): Clear this bit unconditionally for all frames. @@ -1898,7 +1893,7 @@ } else { GetLocalFrameClient().DispatchDidCommitLoad( history_item_.Get(), LoadTypeToCommitType(load_type_), - global_object_reuse_policy); + previous_window != frame_->DomWindow()); } // TODO(dgozman): make DidCreateScriptContext notification call currently // triggered by installing new document happen here, after commit.
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 5ba686a..3a83e9a 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -99,12 +99,6 @@ enum class CommitResult : int32_t; } -// Indicates whether the global object (i.e. Window instance) associated with -// the previous document in a browsing context was replaced or reused for the -// new Document corresponding to the just-committed navigation; effective in the -// main world and all isolated worlds. WindowProxies are not affected. -enum class GlobalObjectReusePolicy { kCreateNew, kUseExisting }; - // The DocumentLoader fetches a main resource and handles the result. // TODO(https://crbug.com/855189). This was originally structured to have a // provisional load, then commit but that is no longer necessary and this class @@ -343,7 +337,7 @@ scoped_refptr<SecurityOrigin> CalculateOrigin( Document* owner_document, network::mojom::blink::WebSandboxFlags); - GlobalObjectReusePolicy CalculateGlobalObjectReusePolicy(SecurityOrigin*); + void InitializeWindow(Document* owner_document); void DidInstallNewDocument(Document*); void WillCommitNavigation(); void DidCommitNavigation();
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 8c0451bf..c233b9b 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -83,8 +83,6 @@ namespace blink { -enum class GlobalObjectReusePolicy; - class CORE_EXPORT EmptyChromeClient : public ChromeClient { public: ~EmptyChromeClient() override = default; @@ -248,7 +246,7 @@ void DispatchDidReceiveTitle(const String&) override {} void DispatchDidCommitLoad(HistoryItem*, WebHistoryCommitType, - GlobalObjectReusePolicy) override {} + bool) override {} void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) override {} void DispatchDidFinishDocumentLoad() override {}
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index b15e4092..4a7a526 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -3949,8 +3949,6 @@ String text_alternative; AXRelatedObjectVector local_related_objects; - const auto* input_element = DynamicTo<HTMLInputElement>(GetNode()); - // 5.1/5.5 Text inputs, Other labelable Elements // If you change this logic, update AXNodeObject::nameFromLabelElement, too. auto* html_element = DynamicTo<HTMLElement>(GetNode()); @@ -4001,6 +3999,7 @@ } // 5.2 input type="button", input type="submit" and input type="reset" + const auto* input_element = DynamicTo<HTMLInputElement>(GetNode()); if (input_element && input_element->IsTextButton()) { // value attribute. name_from = ax::mojom::blink::NameFrom::kValue; @@ -4146,6 +4145,31 @@ } } + // Input type=file. Not part of the spec, but Blink implements it + // as a single control that has both a button ("Choose file...") and + // some text showing the filename, and we need to concatenate both into + // the name of the button. + if (input_element && input_element->type() == input_type_names::kFile) { + name_from = ax::mojom::blink::NameFrom::kValue; + + String displayed_file_path = StringValue(); + String upload_button_text = input_element->UploadButton()->value(); + if (!displayed_file_path.IsEmpty()) { + text_alternative = displayed_file_path + ", " + upload_button_text; + } else { + text_alternative = upload_button_text; + } + *found_text_alternative = true; + + if (name_sources) { + name_sources->push_back(NameSource(true, kValueAttr)); + name_sources->back().type = name_from; + name_sources->back().text = text_alternative; + } else { + return text_alternative; + } + } + // Also check for aria-placeholder. if (IsTextControl()) { name_from = ax::mojom::blink::NameFrom::kPlaceholder;
diff --git a/third_party/blink/renderer/modules/font_access/OWNERS b/third_party/blink/renderer/modules/font_access/OWNERS index e19788b..7f72f63 100644 --- a/third_party/blink/renderer/modules/font_access/OWNERS +++ b/third_party/blink/renderer/modules/font_access/OWNERS
@@ -3,4 +3,4 @@ oyiptong@chromium.org # TEAM: storage-dev@chromium.org -# COMPONENT: Blink>Storage +# COMPONENT: Blink>Storage>FontAccess
diff --git a/third_party/blink/renderer/modules/font_access/font_iterator.cc b/third_party/blink/renderer/modules/font_access/font_iterator.cc index 7aeaa07..d64dd30 100644 --- a/third_party/blink/renderer/modules/font_access/font_iterator.cc +++ b/third_party/blink/renderer/modules/font_access/font_iterator.cc
@@ -4,10 +4,12 @@ #include "third_party/blink/renderer/modules/font_access/font_iterator.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer_or_array_buffer_view.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_font_iterator_entry.h" +#include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/modules/font_access/font_metadata.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" @@ -15,28 +17,81 @@ namespace blink { -FontIterator::FontIterator(const std::vector<FontEnumerationEntry>& entries) { - for (auto entry : entries) { - entries_.push_back(FontMetadata::Create(entry)); - } +FontIterator::FontIterator(ExecutionContext* context) + : ExecutionContextLifecycleObserver(context) { + context->GetBrowserInterfaceBroker().GetInterface( + remote_manager_.BindNewPipeAndPassReceiver()); + remote_manager_.set_disconnect_handler( + WTF::Bind(&FontIterator::OnDisconnect, WrapWeakPersistent(this))); } ScriptPromise FontIterator::next(ScriptState* script_state) { - if (!entries_.IsEmpty()) { - FontMetadata* entry = entries_.TakeFirst(); - auto* result = FontIteratorEntry::Create(); - result->setValue(entry); - return ScriptPromise::Cast(script_state, ToV8(result, script_state)); + if (permission_status_ == PermissionStatus::ASK) { + if (!pending_resolver_) { + remote_manager_->RequestPermission(WTF::Bind( + &FontIterator::DidGetPermissionResponse, WrapWeakPersistent(this))); + pending_resolver_ = + MakeGarbageCollected<ScriptPromiseResolver>(script_state); + } + return pending_resolver_->Promise(); } - auto* result = FontIteratorEntry::Create(); - result->setDone(true); - return ScriptPromise::Cast(script_state, ToV8(result, script_state)); + if (permission_status_ == PermissionStatus::DENIED) { + return ScriptPromise::RejectWithDOMException( + script_state, + MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotAllowedError, + "Permission Error")); + } + + return ScriptPromise::Cast(script_state, ToV8(GetNextEntry(), script_state)); } void FontIterator::Trace(Visitor* visitor) const { ScriptWrappable::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); visitor->Trace(entries_); + visitor->Trace(pending_resolver_); +} + +FontIteratorEntry* FontIterator::GetNextEntry() { + auto* result = FontIteratorEntry::Create(); + if (entries_.IsEmpty()) { + result->setDone(true); + return result; + } + + FontMetadata* entry = entries_.TakeFirst(); + result->setValue(entry); + + return result; +} + +void FontIterator::DidGetPermissionResponse(PermissionStatus status) { + permission_status_ = status; + + if (permission_status_ != PermissionStatus::GRANTED) { + pending_resolver_->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNotAllowedError, "Permission Error")); + pending_resolver_.Clear(); + return; + } + + FontCache* font_cache = FontCache::GetFontCache(); + auto metadata = font_cache->EnumerateAvailableFonts(); + for (const auto& entry : metadata) { + entries_.push_back(FontMetadata::Create(entry)); + } + + pending_resolver_->Resolve(GetNextEntry()); + pending_resolver_.Clear(); +} + +void FontIterator::ContextDestroyed() { + remote_manager_.reset(); +} + +void FontIterator::OnDisconnect() { + remote_manager_.reset(); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/font_access/font_iterator.h b/third_party/blink/renderer/modules/font_access/font_iterator.h index 3e2c1fff9..ebc6074a 100644 --- a/third_party/blink/renderer/modules/font_access/font_iterator.h +++ b/third_party/blink/renderer/modules/font_access/font_iterator.h
@@ -5,29 +5,45 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FONT_ACCESS_FONT_ITERATOR_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FONT_ACCESS_FONT_ITERATOR_H_ +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/font_access/font_access.mojom-blink.h" +#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" namespace blink { class ScriptPromise; +class ScriptPromiseResolver; class ScriptState; class FontMetadata; -struct FontEnumerationEntry; +class FontIteratorEntry; -class FontIterator final : public ScriptWrappable { +class FontIterator final : public ScriptWrappable, + public ExecutionContextLifecycleObserver { DEFINE_WRAPPERTYPEINFO(); public: - // Using std::vector, because at the boundary with platform code. - explicit FontIterator(const std::vector<FontEnumerationEntry>& entries); + using PermissionStatus = mojom::blink::PermissionStatus; + explicit FontIterator(ExecutionContext* context); ScriptPromise next(ScriptState*); void Trace(Visitor*) const override; private: + FontIteratorEntry* GetNextEntry(); + void DidGetPermissionResponse(PermissionStatus); + void ContextDestroyed() override; + void OnDisconnect(); + HeapDeque<Member<FontMetadata>> entries_; + Member<ScriptPromiseResolver> pending_resolver_; + mojo::Remote<mojom::blink::FontAccessManager> remote_manager_; + + PermissionStatus permission_status_ = PermissionStatus::ASK; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/font_access/font_manager.cc b/third_party/blink/renderer/modules/font_access/font_manager.cc index 34783d3c..e119ad6 100644 --- a/third_party/blink/renderer/modules/font_access/font_manager.cc +++ b/third_party/blink/renderer/modules/font_access/font_manager.cc
@@ -11,7 +11,6 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/modules/font_access/font_iterator.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" -#include "third_party/blink/renderer/platform/fonts/font_cache.h" namespace blink { @@ -24,10 +23,8 @@ } // namespace ScriptValue FontManager::query(ScriptState* script_state) { - FontCache* font_cache = FontCache::GetFontCache(); - auto* iterator = - MakeGarbageCollected<FontIterator>(font_cache->EnumerateAvailableFonts()); + MakeGarbageCollected<FontIterator>(ExecutionContext::From(script_state)); auto* isolate = script_state->GetIsolate(); auto context = script_state->GetContext();
diff --git a/third_party/blink/renderer/modules/font_access/idls.gni b/third_party/blink/renderer/modules/font_access/idls.gni index 6b1465c6..ab6264c6f 100644 --- a/third_party/blink/renderer/modules/font_access/idls.gni +++ b/third_party/blink/renderer/modules/font_access/idls.gni
@@ -11,7 +11,4 @@ modules_dictionary_idl_files = [ "font_iterator_entry.idl" ] -modules_dependency_idl_files = [ - "navigator_fonts.idl", - "worker_navigator_fonts.idl", -] +modules_dependency_idl_files = [ "navigator_fonts.idl" ]
diff --git a/third_party/blink/renderer/modules/font_access/navigator_fonts.cc b/third_party/blink/renderer/modules/font_access/navigator_fonts.cc index 2177bde8..777410f7 100644 --- a/third_party/blink/renderer/modules/font_access/navigator_fonts.cc +++ b/third_party/blink/renderer/modules/font_access/navigator_fonts.cc
@@ -69,13 +69,4 @@ return NavigatorFontsImpl<Navigator>::From(navigator).GetFontManager(); } -FontManager* NavigatorFonts::fonts(ScriptState* script_state, - WorkerNavigator& navigator, - ExceptionState& exception_state) { - DCHECK(ExecutionContext::From(script_state)->IsContextThread()); - // TODO(https://crbug.com/1043348): Support FeaturePolicy when it's ready for - // workers. - return NavigatorFontsImpl<WorkerNavigator>::From(navigator).GetFontManager(); -} - } // namespace blink
diff --git a/third_party/blink/renderer/modules/font_access/navigator_fonts.h b/third_party/blink/renderer/modules/font_access/navigator_fonts.h index dc44c0c6..9450024 100644 --- a/third_party/blink/renderer/modules/font_access/navigator_fonts.h +++ b/third_party/blink/renderer/modules/font_access/navigator_fonts.h
@@ -12,7 +12,6 @@ class ExceptionState; class FontManager; class Navigator; -class WorkerNavigator; class ScriptState; class NavigatorFonts final { @@ -20,7 +19,6 @@ public: static FontManager* fonts(ScriptState*, Navigator&, ExceptionState&); - static FontManager* fonts(ScriptState*, WorkerNavigator&, ExceptionState&); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/font_access/worker_navigator_fonts.idl b/third_party/blink/renderer/modules/font_access/worker_navigator_fonts.idl deleted file mode 100644 index bf8cd276..0000000 --- a/third_party/blink/renderer/modules/font_access/worker_navigator_fonts.idl +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2020 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. - -// Entrypoint to the font enumeration API for workers. -// https://wicg.github.io/local-font-access/ -[ - Exposed=Worker, - SecureContext, - ImplementedAs=NavigatorFonts -] partial interface WorkerNavigator { - [CallWith=ScriptState, RaisesException, RuntimeEnabled=FontAccess] readonly attribute FontManager fonts; -};
diff --git a/third_party/blink/renderer/modules/permissions/permission_descriptor.idl b/third_party/blink/renderer/modules/permissions/permission_descriptor.idl index 747cfe1..ee54fab2 100644 --- a/third_party/blink/renderer/modules/permissions/permission_descriptor.idl +++ b/third_party/blink/renderer/modules/permissions/permission_descriptor.idl
@@ -34,6 +34,7 @@ "system-wake-lock", "storage-access", "window-placement", + "font-access", }; // The PermissionDescriptor dictionary is a base to describe permissions. Some
diff --git a/third_party/blink/renderer/modules/permissions/permission_utils.cc b/third_party/blink/renderer/modules/permissions/permission_utils.cc index b0bf8e6..03c232b 100644 --- a/third_party/blink/renderer/modules/permissions/permission_utils.cc +++ b/third_party/blink/renderer/modules/permissions/permission_utils.cc
@@ -235,6 +235,13 @@ } return CreatePermissionDescriptor(PermissionName::WINDOW_PLACEMENT); } + if (name == "font-access") { + if (!RuntimeEnabledFeatures::FontAccessEnabled()) { + exception_state.ThrowTypeError("Font Access is not enabled."); + return nullptr; + } + return CreatePermissionDescriptor(PermissionName::FONT_ACCESS); + } return nullptr; }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 061359e..7eed2de2 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -358,6 +358,7 @@ { name: "ConversionMeasurement", origin_trial_feature_name: "ConversionMeasurement", + origin_trial_allows_third_party: true, status: "experimental", }, { @@ -953,7 +954,7 @@ // provides a convenient way for testing legacy layout code path in blink // unit tests. name: "LayoutNG", - implied_by: ["LayoutNGFieldset", "LayoutNGGrid", "BidiCaretAffinity", "LayoutNGTable"], + implied_by: ["LayoutNGGrid", "BidiCaretAffinity", "LayoutNGTable"], status: "stable", }, { @@ -961,6 +962,8 @@ }, { name: "LayoutNGFieldset", + depends_on: ["LayoutNG"], + status: "experimental", }, { name: "LayoutNGFlexBox",
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/driver.py b/third_party/blink/tools/blinkpy/web_tests/port/driver.py index e8bb4f4..0d59012 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/driver.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/driver.py
@@ -451,7 +451,7 @@ deadline = time.time() + DRIVER_START_TIMEOUT_SECS if not self._wait_for_server_process_output( self._server_process, deadline, '#READY'): - _log.error('content_shell took too long to startup.') + _log.error('%s took too long to startup.' % server_name) def _wait_for_server_process_output(self, server_process, deadline, text): output = ''
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint index 2210584..28e0d6d 100644 --- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint +++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -10,7 +10,6 @@ virtual/composite-after-paint/* [ Skip ] virtual/layout_ng_block_frag/* [ Skip ] -virtual/layout_ng_fieldset/* [ Skip ] virtual/layout_ng_fragment_traversal/* [ Skip ] virtual/prefer_compositing_to_lcd_text/compositing/overflow/* [ Skip ] virtual/stable/* [ Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index 272b392..f42f17f 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -410,6 +410,7 @@ crbug.com/591099 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Failure ] ### external/wpt/html/rendering +crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Failure ] crbug.com/875235 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-painting-order.html [ Failure ] ### virtual/text-antialias/ @@ -439,9 +440,6 @@ ### virtual/layout_ng_block_frag/ virtual/layout_ng_block_frag/* [ Skip ] -### virtual/layout_ng_fieldset/ -virtual/layout_ng_fieldset/* [ Skip ] - ### virtual/layout_ng_fragment_traversal/ virtual/layout_ng_fragment_traversal/* [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 5e98459e..e03bf88 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -914,7 +914,6 @@ # LayoutNG failures that needs to be triaged crbug.com/591099 virtual/text-antialias/selection/selection-rect-line-height-too-small.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/hyphens/hyphens-out-of-flow-002.html [ Failure ] -crbug.com/591099 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Failure ] crbug.com/591099 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ] crbug.com/591099 fast/selectors/shadow-host-div-with-span.html [ Failure ] crbug.com/591099 fast/selectors/shadow-host-div-with-text.html [ Failure ] @@ -1296,9 +1295,13 @@ # Fieldset in NG # -## Fieldseet in NG - Passing reference tests -crbug.com/875235 virtual/layout_ng_block_frag/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Pass ] -crbug.com/875235 virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Pass ] +# A simpified Layout issue +crbug.com/875235 external/wpt/inert/inert-retargeting-iframe.tentative.html [ Crash Pass ] +crbug.com/875235 external/wpt/inert/inert-retargeting.tentative.html [ Crash Pass ] +# Size containment +crbug.com/875235 external/wpt/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-014.html [ Failure ] +# Mask paiting area +crbug.com/875235 paint/masks/fieldset-mask.html [ Failure ] # ====== LayoutNG-only failures until here ====== @@ -1403,9 +1406,6 @@ crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-getTables.html [ Skip ] crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html [ Skip ] crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-blob.html [ Skip ] -crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-workers-enumeration.html [ Skip ] -crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-workers-getTables.html [ Skip ] -crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-workers-blob.html [ Skip ] crbug.com/1087671 [ Mac ] virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html [ Skip ] # ====== Style team owned tests from here ======
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 4aac2f2..4290a944 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -254,14 +254,6 @@ "args": ["--enable-blink-features=LayoutNGFragmentTraversal"] }, { - "prefix": "layout_ng_fieldset", - "bases": ["external/wpt/css/css-contain", - "external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain", - "external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements", - "fast/forms/fieldset"], - "args": ["--enable-blink-features=LayoutNGFieldset"] - }, - { "prefix": "layout-ng-grid", "bases": ["fast/css-grid-layout", "external/wpt/css/css-grid"],
diff --git a/third_party/blink/web_tests/accessibility/file-upload-button-name.html b/third_party/blink/web_tests/accessibility/file-upload-button-name.html new file mode 100644 index 0000000..5dfe34a --- /dev/null +++ b/third_party/blink/web_tests/accessibility/file-upload-button-name.html
@@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/third_party/blink/public/mojom/choosers/file_chooser.mojom.js"></script> +<script src="../fast/forms/resources/mock-file-chooser.js"></script> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +</head> +<body> + +<input id="filetype" type="file"> + +<script> +async_test((t) => { + testRunner.waitUntilDone(); + + // Initially the name is just the button title. + var fileChooser = document.getElementById("filetype"); + let axFileChooser = accessibilityController.accessibleElementById("filetype"); + assert_equals(axFileChooser.name, "No file chosen, Choose File"); + assert_equals(axFileChooser.stringValue, "AXValue: No file chosen"); + + // After a file is selected, the value should be the file chosen, + // and the name should concatenate both - because ATs think of this as a single + // control and they're only going to read the name. + axFileChooser.addNotificationListener((e) => { + assert_equals(axFileChooser.name, "cake.png, Choose File"); + assert_equals(axFileChooser.stringValue, "AXValue: cake.png"); + t.done(); + }); + + // Simulate dragging a file to the file control. + eventSender.beginDragWithFiles(['resources/cake.png']); + var centerX = fileChooser.offsetLeft + fileChooser.offsetWidth / 2; + var centerY = fileChooser.offsetTop + fileChooser.offsetHeight / 2; + eventSender.mouseMoveTo(centerX, centerY); + eventSender.mouseUp(); + +}, "Test that the accessible name of a file control changes when you choose a file."); + +</script> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-001.html index 4647c2c9..7d18ef9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-001.html
@@ -3,6 +3,7 @@ <title>transform interpolation</title> <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-property"> <meta name="assert" content="transform supports animation as a transform list"> +<meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-005.html index 451850f2..879ff3f4 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-005.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/transform-interpolation-005.html
@@ -3,7 +3,7 @@ <title>transform interpolation</title> <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-property"> <meta name="assert" content="transform supports animation as a transform list"> - +<meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/translate-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/translate-interpolation.html index 67d9b136..24368f01 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/translate-interpolation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/animation/translate-interpolation.html
@@ -5,6 +5,7 @@ <title>translate interpolation</title> <link rel="help" href="https://drafts.csswg.org/css-transforms-2/#propdef-translate"> <meta name="assert" content="translate supports <length> and <percentage> animation."> + <meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/fast/borders/fieldsetBorderRadius-expected.png b/third_party/blink/web_tests/fast/borders/fieldsetBorderRadius-expected.png index e65a841..2c002a8 100644 --- a/third_party/blink/web_tests/fast/borders/fieldsetBorderRadius-expected.png +++ b/third_party/blink/web_tests/fast/borders/fieldsetBorderRadius-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/linux/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt similarity index 100% rename from third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt similarity index 75% rename from third_party/blink/web_tests/platform/linux/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt index 2c1519b..780bc66 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS div[align=left] legend -PASS div[align=center] legend -PASS div[align=right] legend +FAIL div[align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394 +FAIL div[align=right] legend assert_equals: expected legend[align=left] expected 24 but got 764 PASS div[align=justify] legend FAIL div[style="text-align: center"] legend assert_equals: expected legend[align=left] expected 24 but got 394 FAIL div[style="text-align: center"][align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/fieldsetBorderRadius-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/fieldsetBorderRadius-expected.png new file mode 100644 index 0000000..e65a841 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/borders/fieldsetBorderRadius-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/006-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/006-expected.png new file mode 100644 index 0000000..87cec572 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/006-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/fieldset-crash-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/fieldset/fieldset-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/fieldset-crash-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/fieldset/fieldset-crash-expected.txt
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/focus-in-fieldset-disabled-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/fieldset/focus-in-fieldset-disabled-expected.txt similarity index 100% rename from third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/focus-in-fieldset-disabled-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/fieldset/focus-in-fieldset-disabled-expected.txt
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/validation-in-fieldset-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/fieldset/validation-in-fieldset-expected.txt similarity index 100% rename from third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/validation-in-fieldset-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/fieldset/validation-in-fieldset-expected.txt
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/custom/inline-svg-in-xhtml-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/custom/inline-svg-in-xhtml-expected.png new file mode 100644 index 0000000..7df6b47 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/custom/inline-svg-in-xhtml-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt index 780bc66..2c1519b 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS div[align=left] legend -FAIL div[align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394 -FAIL div[align=right] legend assert_equals: expected legend[align=left] expected 24 but got 764 +PASS div[align=center] legend +PASS div[align=right] legend PASS div[align=justify] legend FAIL div[style="text-align: center"] legend assert_equals: expected legend[align=left] expected 24 but got 394 FAIL div[style="text-align: center"][align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/006-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/006-expected.png index 87cec572..fd38b88 100644 --- a/third_party/blink/web_tests/platform/linux/fast/forms/006-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/forms/006-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/writing-mode/fieldsets-expected.png b/third_party/blink/web_tests/platform/linux/fast/writing-mode/fieldsets-expected.png index d187fd97..27f91a7 100644 --- a/third_party/blink/web_tests/platform/linux/fast/writing-mode/fieldsets-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/writing-mode/fieldsets-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/custom/inline-svg-in-xhtml-expected.png b/third_party/blink/web_tests/platform/linux/svg/custom/inline-svg-in-xhtml-expected.png index 7df6b47..8128bb3 100644 --- a/third_party/blink/web_tests/platform/linux/svg/custom/inline-svg-in-xhtml-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/custom/inline-svg-in-xhtml-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_fieldset/fast/forms/fieldset/fieldset-with-float-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_fieldset/fast/forms/fieldset/fieldset-with-float-expected.png deleted file mode 100644 index 7009730..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_fieldset/fast/forms/fieldset/fieldset-with-float-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png index 44afc1c..b819bfaa 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png index e278570..cec8dd7 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png index a4f7e4d..c84d82f 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png deleted file mode 100644 index bedc555..0000000 --- a/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-skip-ink-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png deleted file mode 100644 index 42e2f2b..0000000 --- a/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png deleted file mode 100644 index d5f253f..0000000 --- a/third_party/blink/web_tests/platform/mac-retina/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/paint/markers/composition-marker-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/paint/markers/composition-marker-basic-expected.png deleted file mode 100644 index 7df2b5f0..0000000 --- a/third_party/blink/web_tests/platform/mac-retina/paint/markers/composition-marker-basic-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/dark-color-scheme/composition_marker/composition-marker-basic-dark-mode-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/dark-color-scheme/composition_marker/composition-marker-basic-dark-mode-expected.png deleted file mode 100644 index f0616d8..0000000 --- a/third_party/blink/web_tests/platform/mac-retina/virtual/dark-color-scheme/composition_marker/composition-marker-basic-dark-mode-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt deleted file mode 100644 index 17ebed60..0000000 --- a/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL Flex assert_equals: height expected "18px" but got "162px" -FAIL Inline flex assert_equals: height expected "18px" but got "162px" -FAIL Dynamic change of flex-direction assert_equals: expected 44 but got 26 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt deleted file mode 100644 index 05ad38a..0000000 --- a/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -FAIL Grid assert_equals: height expected "86px" but got "162px" -FAIL Inline grid assert_equals: height expected "86px" but got "162px" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt index 780bc66..2c1519b 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS div[align=left] legend -FAIL div[align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394 -FAIL div[align=right] legend assert_equals: expected legend[align=left] expected 24 but got 764 +PASS div[align=center] legend +PASS div[align=right] legend PASS div[align=justify] legend FAIL div[style="text-align: center"] legend assert_equals: expected legend[align=left] expected 24 but got 394 FAIL div[style="text-align: center"][align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/006-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/006-expected.png index c9fb87ed..444491f 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/006-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/006-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/007-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/007-expected.png index 2b2c1c2..52359f8 100644 --- a/third_party/blink/web_tests/platform/mac/fast/forms/007-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/forms/007-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/writing-mode/fieldsets-expected.png b/third_party/blink/web_tests/platform/mac/fast/writing-mode/fieldsets-expected.png index 1639348..c131903f 100644 --- a/third_party/blink/web_tests/platform/mac/fast/writing-mode/fieldsets-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/writing-mode/fieldsets-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/inline-svg-in-xhtml-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/inline-svg-in-xhtml-expected.png index 9f76010..5320ef4 100644 --- a/third_party/blink/web_tests/platform/mac/svg/custom/inline-svg-in-xhtml-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/custom/inline-svg-in-xhtml-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt deleted file mode 100644 index 2c1519b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -PASS div[align=left] legend -PASS div[align=center] legend -PASS div[align=right] legend -PASS div[align=justify] legend -FAIL div[style="text-align: center"] legend assert_equals: expected legend[align=left] expected 24 but got 394 -FAIL div[style="text-align: center"][align=center] legend assert_equals: expected legend[align=left] expected 24 but got 394 -PASS legend[style="margin: 0 auto"] -PASS legend[style="margin: 0 0 0 auto"] -PASS fieldset[dir=rtl] legend -FAIL fieldset[dir=rtl] legend[style="text-align: left"] assert_equals: expected legend[align=right] expected 764 but got 24 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png index f23ecbb..1509538 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png +++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt deleted file mode 100644 index 5978c26..0000000 --- a/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL Flex assert_equals: height expected "20px" but got "180px" -FAIL Inline flex assert_equals: height expected "20px" but got "180px" -FAIL Dynamic change of flex-direction assert_equals: expected 48 but got 28 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt index 1f2cd7fa..7493d20 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS div[align=left] legend -FAIL div[align=center] legend assert_equals: expected legend[align=left] expected 24 but got 395 -FAIL div[align=right] legend assert_equals: expected legend[align=left] expected 24 but got 765 +PASS div[align=center] legend +PASS div[align=right] legend PASS div[align=justify] legend FAIL div[style="text-align: center"] legend assert_equals: expected legend[align=left] expected 24 but got 395 FAIL div[style="text-align: center"][align=center] legend assert_equals: expected legend[align=left] expected 24 but got 395
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/006-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/006-expected.png index 9ab1952..73ffb87b 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/006-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/006-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/fieldsets-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/fieldsets-expected.png index 73f2de8..81d1da4a 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/fieldsets-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/fieldsets-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/custom/inline-svg-in-xhtml-expected.png b/third_party/blink/web_tests/platform/win/svg/custom/inline-svg-in-xhtml-expected.png index 6d2f874..5a021b9 100644 --- a/third_party/blink/web_tests/platform/win/svg/custom/inline-svg-in-xhtml-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/custom/inline-svg-in-xhtml-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt b/third_party/blink/web_tests/platform/win/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt deleted file mode 100644 index 7493d20..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-align-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -PASS div[align=left] legend -PASS div[align=center] legend -PASS div[align=right] legend -PASS div[align=justify] legend -FAIL div[style="text-align: center"] legend assert_equals: expected legend[align=left] expected 24 but got 395 -FAIL div[style="text-align: center"][align=center] legend assert_equals: expected legend[align=left] expected 24 but got 395 -PASS legend[style="margin: 0 auto"] -PASS legend[style="margin: 0 0 0 auto"] -PASS fieldset[dir=rtl] legend -FAIL fieldset[dir=rtl] legend[style="text-align: left"] assert_equals: expected legend[align=right] expected 765 but got 24 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png index f6de4f4d..a5309107 100644 --- a/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png index a3d8c91..13c5811 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png +++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/whitespace/normal-after-nowrap-breaking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-blob.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-blob.html index 5c792ca0..8694207 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-blob.html +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-blob.html
@@ -1,5 +1,7 @@ <!DOCTYPE html> <script src="../../../../../resources/testharness.js"></script> <script src="../../../../../resources/testharnessreport.js"></script> +<script src="../../../../../resources/testdriver.js"></script> +<script src="../../../../../resources/testdriver-vendor.js"></script> <script src="resources/test-expectations.js"></script> <script src="resources/window-tests-blob.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-enumeration.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-enumeration.html index 52a4317..caa3ce2 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-enumeration.html +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-enumeration.html
@@ -1,5 +1,7 @@ <!DOCTYPE html> <script src="../../../../../resources/testharness.js"></script> <script src="../../../../../resources/testharnessreport.js"></script> +<script src="../../../../../resources/testdriver.js"></script> +<script src="../../../../../resources/testdriver-vendor.js"></script> <script src="resources/test-expectations.js"></script> <script src="resources/window-tests-enumeration.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html index 2e9b1ad..76adbec3 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html
@@ -1,5 +1,7 @@ <!DOCTYPE html> <script src="../../../../../resources/testharness.js"></script> <script src="../../../../../resources/testharnessreport.js"></script> +<script src="../../../../../resources/testdriver.js"></script> +<script src="../../../../../resources/testdriver-vendor.js"></script> <script src="resources/test-expectations.js"></script> <script src="resources/window-tests-getTables-large-fonts.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html index b937adcf..edeb9aa 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html
@@ -1,5 +1,7 @@ <!DOCTYPE html> <script src="../../../../../resources/testharness.js"></script> <script src="../../../../../resources/testharnessreport.js"></script> +<script src="../../../../../resources/testdriver.js"></script> +<script src="../../../../../resources/testdriver-vendor.js"></script> <script src="resources/test-expectations.js"></script> <script src="resources/window-tests-getTables.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-blob.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-blob.html deleted file mode 100644 index f8aa4d0..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-blob.html +++ /dev/null
@@ -1,6 +0,0 @@ -<!DOCTYPE html> -<script src="../../../../../resources/testharness.js"></script> -<script src="../../../../../resources/testharnessreport.js"></script> -<script src="resources/test-expectations.js"></script> -<script src="resources/worker-utils.js"></script> -<script src="resources/worker-tests-blob.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-enumeration.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-enumeration.html deleted file mode 100644 index ec4ce74..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-enumeration.html +++ /dev/null
@@ -1,6 +0,0 @@ -<!DOCTYPE html> -<script src="../../../../../resources/testharness.js"></script> -<script src="../../../../../resources/testharnessreport.js"></script> -<script src="resources/test-expectations.js"></script> -<script src="resources/worker-utils.js"></script> -<script src="resources/worker-tests-enumeration.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-getTables.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-getTables.html deleted file mode 100644 index 2ffa4f9..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-workers-getTables.html +++ /dev/null
@@ -1,6 +0,0 @@ -<!DOCTYPE html> -<script src="../../../../../resources/testharness.js"></script> -<script src="../../../../../resources/testharnessreport.js"></script> -<script src="resources/test-expectations.js"></script> -<script src="resources/worker-utils.js"></script> -<script src="resources/worker-tests-getTables.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-blob.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-blob.js index 0183232f..6733a1d 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-blob.js +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-blob.js
@@ -1,6 +1,7 @@ 'use strict'; promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectedFonts = await filterEnumeration(iterator, getEnumerationTestSet({
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-enumeration.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-enumeration.js index 7365430..75599dfe7 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-enumeration.js +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-enumeration.js
@@ -1,7 +1,8 @@ 'use strict'; promise_test(async t => { - const iterator = navigator.fonts.query(); + await test_driver.set_permission({name: 'font-access'}, 'granted'); + const iterator = navigator.fonts.query(); assert_equals(typeof iterator, 'object', 'query() should return an Object'); assert_true(!!iterator[Symbol.asyncIterator], 'query() has an asyncIterator method');
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js index a4c11df..97d957f8 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js
@@ -1,6 +1,7 @@ 'use strict'; promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectations = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.large]});
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js index 88026a01..ed08979e3 100644 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js +++ b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js
@@ -1,6 +1,7 @@ 'use strict'; promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectations = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); @@ -18,6 +19,7 @@ }, 'getTables(): small sized fonts have expected non-empty tables'); promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectations = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.medium]}); @@ -35,6 +37,7 @@ }, 'getTables(): medium sized fonts have expected non-empty tables'); promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectedFonts = await filterEnumeration(iterator, @@ -58,6 +61,7 @@ }, 'getTables([...]) returns tables'); promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectedFonts = await filterEnumeration(iterator, @@ -80,6 +84,7 @@ }, 'getTables([tableName,...]) returns if a table name does not exist'); promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectedFonts = await filterEnumeration(iterator, @@ -119,6 +124,7 @@ }, 'getTables([tableName,...]) rejects for invalid input'); promise_test(async t => { + await test_driver.set_permission({name: 'font-access'}, 'granted'); const iterator = navigator.fonts.query(); const expectedFonts = await filterEnumeration(iterator,
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-font-access.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-font-access.js deleted file mode 100644 index f0e3e7a7..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-font-access.js +++ /dev/null
@@ -1,111 +0,0 @@ -'use strict'; - -if (self.postMessage) { - self.onmessage = handleMessage; -} else { - // Makes Shared workers behave more like Dedicated workers. - self.onconnect = (event) => { - self.postMessage = (msg) => { - event.ports[0].postMessage(msg); - }; - event.ports[0].onmessage = handleMessage; - }; -} - -async function enumerate() { - const output = []; - for await (const f of navigator.fonts.query()) { - output.push({ - postscriptName: f.postscriptName, - fullName: f.fullName, - family: f.family, - }); - } - return output; -} - -async function getTables(options) { - options = Object.assign({ - postscriptNameFilter: [], - tables: [], - }, options); - - const nameFilterSet = new Set(options.postscriptNameFilter); - const iterator = navigator.fonts.query(); - const localFonts = []; - for await (const f of navigator.fonts.query()) { - if (nameFilterSet.size > 0) { - if (!nameFilterSet.has(f.postscriptName)) { - continue; - } - } - localFonts.push(f); - } - - let output = []; - for (const f of localFonts) { - const fontTableMap = await f.getTables(options.tables); - output.push({ - postscriptName: f.postscriptName, - fullName: f.fullName, - family: f.family, - tables: new Map(fontTableMap), // fontTableMap is not cloneable. - }); - } - - return output; -} - -async function blob(options) { - options = Object.assign({ - postscriptNameFilter: [], - }, options); - - const nameFilterSet = new Set(options.postscriptNameFilter); - const iterator = navigator.fonts.query(); - const localFonts = []; - for await (const f of navigator.fonts.query()) { - if (nameFilterSet.size > 0) { - if (!nameFilterSet.has(f.postscriptName)) { - continue; - } - } - localFonts.push(f); - } - - let output = []; - for (const f of localFonts) { - const tableBlob = await f.blob(); - output.push({ - postscriptName: f.postscriptName, - fullName: f.fullName, - family: f.family, - blob: tableBlob, - }); - } - - return output; -} - -async function handleMessage(event) { - try { - switch(event.data.action) { - case "ping": - postMessage({type: "ready"}); - break; - case "query": - postMessage({type: "query", data: await enumerate()}); - break; - case "getTables": - postMessage({type: "getTables", data: await getTables(event.data.options)}); - break; - case "blob": - postMessage({type: "blob", data: await blob(event.data.options)}); - break; - default: - postMessage({type: "error", data: "FAILURE: Received unknown message: " + event.data}); - } - } catch(e) { - postMessage({type: "error", data: `Error: ${e}`}); - } -}
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-blob.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-blob.js deleted file mode 100644 index 901c05f..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-blob.js +++ /dev/null
@@ -1,49 +0,0 @@ -'use strict'; - -promise_test(async t => { - const worker = new Worker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - const expectedFonts = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); - - const promise = promiseHandleMessage(t, worker); - worker.postMessage({ - action: 'blob', - options: { - postscriptNameFilter: expectedFonts.map(f => f.postscriptName), - } - }); - const event = await promise; - - assert_equals(event.data.type, 'blob', 'Response is of type blob.'); - - const localFonts = event.data.data; - assert_fonts_exist(localFonts, expectedFonts); - for (const f of localFonts) { - const parsedData = await parseFontData(f.blob); - assert_font_has_tables(f.postscriptName, parsedData.tables, BASE_TABLES); - } -}, 'DedicatedWorker, blob(): all fonts have base tables that are not empty'); - -promise_test(async t => { - const worker = new SharedWorker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - const expectedFonts = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); - - const promise = promiseHandleMessage(t, worker); - worker.port.postMessage({ - action: 'blob', - options: { - postscriptNameFilter: expectedFonts.map(f => f.postscriptName), - } - }); - const event = await promise; - - assert_equals(event.data.type, 'blob', 'Response is of type blob.'); - - const localFonts = event.data.data; - assert_fonts_exist(localFonts, expectedFonts); - for (const f of localFonts) { - const parsedData = await parseFontData(f.blob); - assert_font_has_tables(f.postscriptName, parsedData.tables, BASE_TABLES); - } -}, 'SharedWorker, blob(): all fonts have base tables that are not empty');
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-enumeration.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-enumeration.js deleted file mode 100644 index af11e09..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-enumeration.js +++ /dev/null
@@ -1,33 +0,0 @@ -'use strict'; - -promise_test(async t => { - const worker = new Worker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - - const promise = promiseHandleMessage(t, worker); - worker.postMessage({action: 'query'}); - const event = await promise; - - assert_equals(event.data.type, 'query', "Response is of type query."); - - const localFonts = event.data.data; - assert_true(Array.isArray(localFonts), - `Response is of type Array. Instead got: ${localFonts}.`); - assert_fonts_exist(localFonts, getEnumerationTestSet()); -}, 'DedicatedWorker, query(): returns fonts'); - -promise_test(async t => { - const worker = new SharedWorker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - - const promise = promiseHandleMessage(t, worker); - worker.port.postMessage({action: 'query'}); - const event = await promise; - - assert_equals(event.data.type, 'query', 'Response is of type query.'); - - const localFonts = event.data.data; - assert_true(Array.isArray(localFonts), - `Response is of type Array. Instead got: ${localFonts}.`); - assert_fonts_exist(localFonts, getEnumerationTestSet()); -}, 'SharedWorker, query(): returns fonts');
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-getTables.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-getTables.js deleted file mode 100644 index 39af27a..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-tests-getTables.js +++ /dev/null
@@ -1,103 +0,0 @@ -'use strict'; - -promise_test(async t => { - const worker = new Worker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - const expectedFonts = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); - - const promise = promiseHandleMessage(t, worker); - worker.postMessage({ - action: 'getTables', - options: { - postscriptNameFilter: expectedFonts.map(f => f.postscriptName), - } - }); - const event = await promise; - - assert_equals(event.data.type, 'getTables', 'Response is of type getTables.'); - - const localFonts = event.data.data; - assert_fonts_exist(localFonts, expectedFonts); - for (const f of localFonts) { - assert_font_has_tables(f.postscriptName, f.tables, BASE_TABLES); - } -}, 'DedicatedWorker, getTables(): all fonts have base tables that are not empty'); - -promise_test(async t => { - const worker = new Worker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - const expectedFonts = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); - - const promise = promiseHandleMessage(t, worker); - - const tableQuery = ["cmap", "head"]; - worker.postMessage({ - action: 'getTables', - options: { - postscriptNameFilter: expectedFonts.map(f => f.postscriptName), - tables: tableQuery, - } - }); - - const event = await promise; - - assert_equals(event.data.type, 'getTables', 'Response is of type getTables.'); - - const localFonts = event.data.data; - assert_fonts_exist(localFonts, expectedFonts); - for (const f of localFonts) { - assert_font_has_tables(f.postscriptName, f.tables, tableQuery); - } -}, 'DedicatedWorker, getTables([tableName,...]): returns tables'); - -promise_test(async t => { - const worker = new SharedWorker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - const expectedFonts = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); - - const promise = promiseHandleMessage(t, worker); - - worker.port.postMessage({ - action: 'getTables', - options: { - postscriptNameFilter: expectedFonts.map(f => f.postscriptName), - } - }); - - const event = await promise; - - assert_equals(event.data.type, 'getTables', 'Response is of type getTables.'); - - const localFonts = event.data.data; - assert_fonts_exist(localFonts, expectedFonts); - for (const f of localFonts) { - assert_font_has_tables(f.postscriptName, f.tables, BASE_TABLES); - } -}, 'SharedWorker, getTables(): all fonts have base tables that are not empty'); - -promise_test(async t => { - const worker = new SharedWorker('resources/worker-font-access.js'); - await promiseWorkerReady(t, worker); - const expectedFonts = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]}); - - const promise = promiseHandleMessage(t, worker); - - const tableQuery = ["cmap", "head"]; - worker.port.postMessage({ - action: 'getTables', - options: { - postscriptNameFilter: expectedFonts.map(f => f.postscriptName), - tables: tableQuery, - } - }); - - const event = await promise; - - assert_equals(event.data.type, 'getTables', 'Response is of type getTables.'); - - const localFonts = event.data.data; - assert_fonts_exist(localFonts, expectedFonts); - for (const f of localFonts) { - assert_font_has_tables(f.postscriptName, f.tables, tableQuery); - } -}, 'SharedWorker, getTables([tableName,...]): returns tables that are not empty');
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-utils.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-utils.js deleted file mode 100644 index 712d07305e2..0000000 --- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/worker-utils.js +++ /dev/null
@@ -1,54 +0,0 @@ -'use strict'; - -function promiseWorkerReady(t, worker) { - return new Promise((resolve, reject) => { - let timeout; - - const readyFunc = t.step_func(event => { - if (event.data.type != 'ready') { - reject(event); - } - window.clearTimeout(timeout); - resolve(); - }); - - // Setting a timeout because the the worker - // may not be ready to listen to the postMessage. - timeout = t.step_timeout(() => { - if ('port' in worker) { - if (!worker.port.onmessage) { - worker.port.onmessage = readyFunc; - } - worker.port.postMessage({action: 'ping'}); - } else { - if (!worker.onmessage) { - worker.onmessage = readyFunc; - } - worker.postMessage({action: 'ping'}); - } - }, 10); - }); -} - -function promiseHandleMessage(t, worker) { - return new Promise((resolve, reject) => { - const handler = t.step_func(event => { - if (event.data.type === 'ready') { - // Ignore: may received duplicate readiness messages. - return; - } - - if (event.data.type === 'error') { - reject(event); - } - - resolve(event); - }); - - if ('port' in worker) { - worker.port.onmessage = handler; - } else { - worker.onmessage = handler; - } - }); -}
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/css/css-contain/README.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/css/css-contain/README.txt deleted file mode 100644 index 18ec75c..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/css/css-contain/README.txt +++ /dev/null
@@ -1 +0,0 @@ -LayoutNG experimental css-contain tests.
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/README.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/README.txt deleted file mode 100644 index 4d933be..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -LayoutNG experimental css-contain tests. -
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/README.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/README.txt deleted file mode 100644 index a06310f..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -These tests are run with --enable-blink-features=LayoutNGFieldset -The LayoutNG project is described here: http://goo.gl/1hwhfX
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt deleted file mode 100644 index c151c1e..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-flexbox-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS Flex -PASS Inline flex -PASS Dynamic change of flex-direction -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt deleted file mode 100644 index d18e0b2..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-grid-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS Grid -PASS Inline grid -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt deleted file mode 100644 index 6105087f..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-percentage-block-size-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -This is a testharness.js-based test. -PASS rendered legend (writing-mode: horizontal-tb) -PASS second legend (writing-mode: horizontal-tb) -PASS div (writing-mode: horizontal-tb) -PASS rendered legend (writing-mode: vertical-lr) -PASS second legend (writing-mode: vertical-lr) -PASS div (writing-mode: vertical-lr) -PASS rendered legend (writing-mode: vertical-rl) -PASS second legend (writing-mode: vertical-rl) -PASS div (writing-mode: vertical-rl) -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/README.txt b/third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/README.txt deleted file mode 100644 index a06310f..0000000 --- a/third_party/blink/web_tests/virtual/layout_ng_fieldset/fast/forms/fieldset/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -These tests are run with --enable-blink-features=LayoutNGFieldset -The LayoutNG project is described here: http://goo.gl/1hwhfX
diff --git a/third_party/subresource-filter-ruleset/README.chromium b/third_party/subresource-filter-ruleset/README.chromium index 8290eb4e..866c86b 100644 --- a/third_party/subresource-filter-ruleset/README.chromium +++ b/third_party/subresource-filter-ruleset/README.chromium
@@ -1,6 +1,6 @@ Name: EasyList URL: https://easylist.to/easylist/easylist.txt -Version: 202006221619 +Version: 202007281111 License: Creative Commons Attribution-ShareAlike 3.0 Unported License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1 b/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1 index 8b18c33..0cfcc5e 100644 --- a/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1 +++ b/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1
@@ -1 +1 @@ -9e1d963efc9c074940dbcf6199617c84df223dbb \ No newline at end of file +502aa54e29d82495a76757c45531d5ff6c63e6f2 \ No newline at end of file
diff --git a/tools/android/dependency_analysis/js/src/display_settings_data.js b/tools/android/dependency_analysis/js/src/display_settings_data.js index b3604de..4cfadaeb 100644 --- a/tools/android/dependency_analysis/js/src/display_settings_data.js +++ b/tools/android/dependency_analysis/js/src/display_settings_data.js
@@ -16,6 +16,32 @@ }; /** + * Various different display setting presets. + * @enum {string} + */ +const DisplaySettingsPreset = { + CUSTOM: 'Custom', + COLOR_ON_HOVER: 'Red-blue on hover', + GREY_VIEW: 'Constant grey gradient', +}; + +// A map from DisplaySettingsPreset to display setting objects. The keys in each +// object should correspond to properties of NodeFilterData. +const PRESET_SETTINGS = { + [DisplaySettingsPreset.CUSTOM]: {}, // Applying the custom preset is a no-op. + [DisplaySettingsPreset.COLOR_ON_HOVER]: { + 'curveEdges': true, + 'colorOnlyOnHover': true, + 'graphEdgeColor': GraphEdgeColor.BLUE_TO_RED, + }, + [DisplaySettingsPreset.GREY_VIEW]: { + 'curveEdges': false, + 'colorOnlyOnHover': false, + 'graphEdgeColor': GraphEdgeColor.GREY_GRADIENT, + }, +}; + +/** * Underlying data for node filtering. The UI shows a "filter list" that * displays nodes of interest, and each can be toggled on/off using a checkbox. * Each node is classified as: @@ -104,6 +130,8 @@ class DisplaySettingsData { /** Sets up default values for display settings. */ constructor() { + /** @public {!DisplaySettingsPreset} */ + this.displaySettingsPreset = DisplaySettingsPreset.CUSTOM; /** @public {!NodeFilterData} */ this.nodeFilterData = new NodeFilterData(); /** @public {number} */ @@ -119,10 +147,21 @@ } /** + * Applies a preset by copying all its properties to the current display + * settings, overwriting existing values. + * @param {string} presetName The key of the preset to apply. + */ + applyPreset(presetName) { + Object.assign(this, PRESET_SETTINGS[presetName]); + } + + /** * Updates a UrlProcessor with all contained data. * @param {!UrlProcessor} urlProcessor The UrlProcessor to update. */ updateUrlProcessor(urlProcessor) { + urlProcessor.append(URL_PARAM_KEYS.DISPLAY_SETTINGS_PRESET, + this.displaySettingsPreset); urlProcessor.append(URL_PARAM_KEYS.INBOUND_DEPTH, this.inboundDepth); urlProcessor.append(URL_PARAM_KEYS.OUTBOUND_DEPTH, this.outboundDepth); urlProcessor.append(URL_PARAM_KEYS.CURVE_EDGES, this.curveEdges); @@ -143,6 +182,8 @@ * @param {!UrlProcessor} urlProcessor The UrlProcessor to read from. */ readUrlProcessor(urlProcessor) { + this.displaySettingsPreset = urlProcessor.getString( + URL_PARAM_KEYS.DISPLAY_SETTINGS_PRESET, this.displaySettingsPreset); this.inboundDepth = urlProcessor.getInt( URL_PARAM_KEYS.INBOUND_DEPTH, this.inboundDepth); this.outboundDepth = urlProcessor.getInt( @@ -204,7 +245,8 @@ class PackageDisplaySettingsData extends DisplaySettingsData {} export { - GraphEdgeColor, ClassDisplaySettingsData, + DisplaySettingsPreset, + GraphEdgeColor, PackageDisplaySettingsData, };
diff --git a/tools/android/dependency_analysis/js/src/url_processor.js b/tools/android/dependency_analysis/js/src/url_processor.js index 23d6c28..a0c6877 100644 --- a/tools/android/dependency_analysis/js/src/url_processor.js +++ b/tools/android/dependency_analysis/js/src/url_processor.js
@@ -14,6 +14,7 @@ // Keys for identifying URL params. const URL_PARAM_KEYS = { // Common keys: + DISPLAY_SETTINGS_PRESET: 'dsp', FILTER_NAMES: 'fn', FILTER_CHECKED: 'fc', INBOUND_DEPTH: 'ibd',
diff --git a/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue b/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue index 3478df5..02d15b9 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue
@@ -7,7 +7,8 @@ <label>Convex hull display:</label> <div v-for="hullDisplay in HullDisplay" - :key="hullDisplay"> + :key="hullDisplay" + @change="displayOptionChanged"> <input :id="hullDisplay" v-model="internalSelectedHullDisplay" @@ -22,6 +23,7 @@ </template> <script> +import {CUSTOM_EVENTS} from '../vue_custom_events.js'; import {HullDisplay} from '../class_view_consts.js'; // @vue/component @@ -40,6 +42,11 @@ }, }, }, + methods: { + displayOptionChanged: function() { + this.$emit(CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED); + }, + }, }; export default ClassGraphHullSettings;
diff --git a/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue b/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue index 4ee5608..42023e5 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue
@@ -40,10 +40,17 @@ @[CUSTOM_EVENTS.NODE_CLICKED]="graphNodeClicked" @[CUSTOM_EVENTS.NODE_DOUBLE_CLICKED]="graphNodeDoubleClicked"/> <div id="node-details-container"> - <GraphDisplaySettings - :display-settings-data="displaySettingsData"/> - <ClassGraphHullSettings - :selected-hull-display.sync="displaySettingsData.hullDisplay"/> + <GraphDisplayPanel + :display-settings-data="displaySettingsData" + :display-settings-preset.sync=" + displaySettingsData.displaySettingsPreset"> + <GraphDisplaySettings + :display-settings-data="displaySettingsData" + @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> + <ClassGraphHullSettings + :selected-hull-display.sync="displaySettingsData.hullDisplay" + @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> + </GraphDisplayPanel> <GraphSelectedNodeDetails :selected-node-details-data="pageModel.selectedNodeDetailsData" @[CUSTOM_EVENTS.DETAILS_CHECK_NODE]="filterAddOrCheckNode" @@ -62,12 +69,16 @@ import {ClassNode, GraphNode} from '../graph_model.js'; import {PageModel} from '../page_model.js'; -import {ClassDisplaySettingsData} from '../display_settings_data.js'; +import { + ClassDisplaySettingsData, + DisplaySettingsPreset, +} from '../display_settings_data.js'; import {parseClassGraphModelFromJson} from '../process_graph_json.js'; import {shortenClassNameWithPackage} from '../chrome_hooks.js'; import ClassDetailsPanel from './class_details_panel.vue'; import ClassGraphHullSettings from './class_graph_hull_settings.vue'; +import GraphDisplayPanel from './graph_display_panel.vue'; import GraphDisplaySettings from './graph_display_settings.vue'; import GraphFilterInput from './graph_filter_input.vue'; import GraphFilterItems from './graph_filter_items.vue'; @@ -92,6 +103,7 @@ components: { ClassDetailsPanel, ClassGraphHullSettings, + GraphDisplayPanel, GraphDisplaySettings, GraphFilterInput, GraphFilterItems, @@ -163,6 +175,10 @@ } }, methods: { + displayOptionChanged: function() { + this.displaySettingsData.displaySettingsPreset = + DisplaySettingsPreset.CUSTOM; + }, updateDocumentUrl() { const urlProcessor = UrlProcessor.createForOutput(); this.displaySettingsData.updateUrlProcessor(urlProcessor);
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue new file mode 100644 index 0000000..3a0e9b1 --- /dev/null +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue
@@ -0,0 +1,75 @@ +<!-- Copyright 2020 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. --> + +<template> + <div id="display-panel"> + <div id="preset-container"> + <select + v-model="internalDisplaySettingsPreset" + @change="applySelectedPreset"> + <option + v-for="presetName in DisplaySettingsPreset" + :key="presetName" + :value="presetName"> + {{ presetName }} + </option> + </select> + <button @click="settingsExpanded = !settingsExpanded"> + {{ settingsExpanded ? 'Collapse' : 'Expand' }} Advanced Settings + </button> + </div> + <slot v-if="settingsExpanded"/> + </div> +</template> + +<script> +import {DisplaySettingsPreset} from '../display_settings_data.js'; + +// @vue/component +const GraphDisplaySettings = { + props: { + displaySettingsData: Object, + displaySettingsPreset: String, + }, + data: function() { + return { + settingsExpanded: false, + }; + }, + computed: { + DisplaySettingsPreset: () => DisplaySettingsPreset, + internalDisplaySettingsPreset: { + get: function() { + return this.displaySettingsPreset; + }, + set: function(newValue) { + this.$emit('update:displaySettingsPreset', newValue); + }, + }, + }, + methods: { + applySelectedPreset() { + // nextTick is needed here since we need to wait for the parent/child data + // sync on `displaySettingsPreset` to finish. + this.$nextTick(() => this.displaySettingsData.applyPreset( + this.internalDisplaySettingsPreset)); + }, + }, +}; + +export default GraphDisplaySettings; +</script> + +<style scoped> +#preset-container { + display: flex; + flex-direction: row; +} + +#display-panel { + display: flex; + flex-direction: column; + margin-bottom: 10px; +} +</style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue index 3ca94aa..4be37dba 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue
@@ -8,20 +8,23 @@ <input id="curve-edges" v-model="displaySettingsData.curveEdges" - type="checkbox"> + type="checkbox" + @change="displayOptionChanged"> <label for="curve-edges">Curve graph edges</label> </div> <div> <input id="color-on-hover" v-model="displaySettingsData.colorOnlyOnHover" - type="checkbox"> + type="checkbox" + @change="displayOptionChanged"> <label for="color-on-hover">Color graph edges only on node hover</label> </div> <label for="graph-edge-color">Graph edge color scheme:</label> <select id="graph-edge-color" - v-model="displaySettingsData.graphEdgeColor"> + v-model="displaySettingsData.graphEdgeColor" + @change="displayOptionChanged"> <option v-for="edgeColor in GraphEdgeColor" :key="edgeColor" @@ -33,6 +36,7 @@ </template> <script> +import {CUSTOM_EVENTS} from '../vue_custom_events.js'; import {GraphEdgeColor} from '../display_settings_data.js'; // @vue/component @@ -43,6 +47,11 @@ computed: { GraphEdgeColor: () => GraphEdgeColor, }, + methods: { + displayOptionChanged: function() { + this.$emit(CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED); + }, + }, }; export default GraphDisplaySettings;
diff --git a/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue b/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue index 17e1dea..020904abc 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue
@@ -38,8 +38,14 @@ @[CUSTOM_EVENTS.NODE_CLICKED]="graphNodeClicked" @[CUSTOM_EVENTS.NODE_DOUBLE_CLICKED]="graphNodeDoubleClicked"/> <div id="node-details-container"> - <GraphDisplaySettings - :display-settings-data="displaySettingsData"/> + <GraphDisplayPanel + :display-settings-data="displaySettingsData" + :display-settings-preset.sync=" + displaySettingsData.displaySettingsPreset"> + <GraphDisplaySettings + :display-settings-data="displaySettingsData" + @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> + </GraphDisplayPanel> <GraphSelectedNodeDetails :selected-node-details-data="pageModel.selectedNodeDetailsData" @[CUSTOM_EVENTS.DETAILS_CHECK_NODE]="filterAddOrCheckNode" @@ -57,10 +63,14 @@ import {GraphNode} from '../graph_model.js'; import {PageModel} from '../page_model.js'; -import {PackageDisplaySettingsData} from '../display_settings_data.js'; +import { + PackageDisplaySettingsData, + DisplaySettingsPreset, +} from '../display_settings_data.js'; import {parsePackageGraphModelFromJson} from '../process_graph_json.js'; import {shortenPackageName} from '../chrome_hooks.js'; +import GraphDisplayPanel from './graph_display_panel.vue'; import GraphDisplaySettings from './graph_display_settings.vue'; import GraphFilterInput from './graph_filter_input.vue'; import GraphFilterItems from './graph_filter_items.vue'; @@ -72,6 +82,7 @@ // @vue/component const PackageGraphPage = { components: { + GraphDisplayPanel, GraphDisplaySettings, GraphFilterInput, GraphFilterItems, @@ -138,6 +149,10 @@ } }, methods: { + displayOptionChanged: function() { + this.displaySettingsData.displaySettingsPreset = + DisplaySettingsPreset.CUSTOM; + }, updateDocumentUrl() { const urlProcessor = UrlProcessor.createForOutput(); this.displaySettingsData.updateUrlProcessor(urlProcessor);
diff --git a/tools/android/dependency_analysis/js/src/vue_custom_events.js b/tools/android/dependency_analysis/js/src/vue_custom_events.js index 05fe9de0..1a426b5 100644 --- a/tools/android/dependency_analysis/js/src/vue_custom_events.js +++ b/tools/android/dependency_analysis/js/src/vue_custom_events.js
@@ -7,6 +7,8 @@ const CUSTOM_EVENTS = { DETAILS_CHECK_NODE: 'details-check-node', DETAILS_UNCHECK_NODE: 'details-uncheck-node', + DISPLAY_OPTION_CHANGED: 'display-option-changed', + DISPLAY_PRESET_SELECTED: 'display-preset-selected', FILTER_REMOVE: 'filter-remove', FILTER_CHECK_ALL: 'filter-check-all', FILTER_UNCHECK_ALL: 'filter-uncheck-all',
diff --git a/tools/binary_size/README.md b/tools/binary_size/README.md index 1866ed1..0f7b8c9 100644 --- a/tools/binary_size/README.md +++ b/tools/binary_size/README.md
@@ -18,6 +18,10 @@ * https://chrome-supersize.firebaseapp.com/chrome-supersize/index.html +Guide to dealing with chrome-perf size alerts: + + * [//docs/speed/apk_size_regressions.md](/docs/speed/apk_size_regressions.md) + [TOC] ## Binary Size Trybot (android-binary-size) @@ -38,7 +42,7 @@ [chromeperf](https://chromeperf.appspot.com/report) under `Test suite="resource_sizes ($APK)"`. * Metrics reported by this tool are described in - [//docs/speed/binary_size/metrics.md](//docs/speed/binary_size/metrics.md). + [//docs/speed/binary_size/metrics.md](/docs/speed/binary_size/metrics.md). ## SuperSize
diff --git a/tools/binary_size/libsupersize/path_util.py b/tools/binary_size/libsupersize/path_util.py index bf123b4e..7712d54 100644 --- a/tools/binary_size/libsupersize/path_util.py +++ b/tools/binary_size/libsupersize/path_util.py
@@ -6,6 +6,7 @@ import abc import distutils.spawn +import json import logging import os @@ -134,11 +135,11 @@ def _LoadBuildVars(output_directory): - build_vars_path = os.path.join(output_directory, 'build_vars.txt') + build_vars_path = os.path.join(output_directory, 'build_vars.json') if os.path.exists(build_vars_path): with open(build_vars_path) as f: - return dict(l.rstrip().split('=', 1) for l in f if '=' in l) - return dict() + return json.load(f) + return {} def GetSrcRootFromOutputDirectory(output_directory):
diff --git a/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.json b/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.json new file mode 100644 index 0000000..53e11e8e4 --- /dev/null +++ b/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.json
@@ -0,0 +1,4 @@ +{ + "android_sdk_root": "../../../mock_sdk", + "android_tool_prefix": "../../../mock_toolchain/" +}
diff --git a/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.txt b/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.txt deleted file mode 100644 index ab47517..0000000 --- a/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.txt +++ /dev/null
@@ -1,2 +0,0 @@ -android_sdk_root=../../../mock_sdk -android_tool_prefix=../../../mock_toolchain/
diff --git a/tools/clang/scripts/upload_revision.py b/tools/clang/scripts/upload_revision.py index a979629..3d2e5382 100755 --- a/tools/clang/scripts/upload_revision.py +++ b/tools/clang/scripts/upload_revision.py
@@ -53,12 +53,12 @@ def PatchRevision(clang_git_revision, clang_sub_revision): with open(UPDATE_PY_PATH, 'rb') as f: content = f.read() - m = re.search("CLANG_REVISION = '([0-9a-f-]+)'", content) + m = re.search("CLANG_REVISION = '([0-9a-z-]+)'", content) clang_old_git_revision = m.group(1) m = re.search("CLANG_SUB_REVISION = ([0-9]+)", content) clang_old_sub_revision = m.group(1) - content = re.sub("CLANG_REVISION = '[0-9a-f-]+'", + content = re.sub("CLANG_REVISION = '[0-9a-z-]+'", "CLANG_REVISION = '{}'".format(clang_git_revision), content, count=1) @@ -67,7 +67,7 @@ content, count=1) with open(UPDATE_PY_PATH, 'wb') as f: f.write(content) - return "{}-{}" % (clang_old_git_revision, clang_old_sub_revision) + return "{}-{}".format(clang_old_git_revision, clang_old_sub_revision) def Git(args):
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 8efdfca..4df66a3 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -11650,6 +11650,7 @@ <int value="68" label="Camera pan tilt zoom"/> <int value="69" label="Window placement"/> <int value="70" label="Insecure private network requests"/> + <int value="71" label="Font Access"/> </enum> <enum name="ContentTypeParseableResult"> @@ -40241,6 +40242,7 @@ <int value="-1740519217" label="disable-software-rasterizer"/> <int value="-1740093155" label="UnifiedMediaView:disabled"/> <int value="-1738416948" label="OptimizationHints:enabled"/> + <int value="-1737769448" label="WebUITabStripTabDragIntegration:disabled"/> <int value="-1736075054" label="EnableFullscreenAppList:enabled"/> <int value="-1735643253" label="enable-display-list-2d-canvas"/> <int value="-1734885284" label="enable-navigation-predictor"/> @@ -40482,6 +40484,7 @@ <int value="-1480926949" label="MaterialDesignBookmarks:enabled"/> <int value="-1480866718" label="ash-disable-login-dim-and-blur"/> <int value="-1478876902" label="disable-permission-action-reporting"/> + <int value="-1478137998" label="lite-video-default-downlink-bandwidth-kbps"/> <int value="-1477686864" label="OmniboxRichAutocompletion:enabled"/> <int value="-1477560322" label="kiosk"/> <int value="-1476930281" label="Windows10CustomTitlebar:enabled"/> @@ -42691,6 +42694,7 @@ <int value="871713352" label="ImprovedLanguageSettings:enabled"/> <int value="876879670" label="OfflinePagesInDownloadHomeOpenInCct:enabled"/> <int value="877059804" label="AutofillPreventMixedFormsFilling:disabled"/> + <int value="877238334" label="WebUITabStripTabDragIntegration:enabled"/> <int value="878773995" label="ChromeHomeBottomNavLabels:disabled"/> <int value="879699575" label="disable-gesture-tap-highlight"/> <int value="879992337" label="disable-pull-to-refresh-effect"/> @@ -68800,6 +68804,17 @@ </int> </enum> +<enum name="TabSearchCloseActions"> + <int value="0" label="User did not close via Tab Search UI"> + The UI was dismissed via interactions outside what is offered by the Tab + Search UI. + </int> + <int value="1" label="User switched to an open tab"> + The Tab Search UI was dismissed as a result of the user opting to switch to + a currently open tab. + </int> +</enum> + <enum name="TabStatus"> <int value="0" label="Memory resident"/> <int value="1" label="Evicted and reloaded"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3ba740b8..8ae20a780 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -27736,7 +27736,19 @@ </summary> </histogram> -<histogram name="Clipboard.Format.Read" enum="ClipboardFormatRead" +<histogram name="Clipboard.IncognitoUseCase" enum="ClipboardAction" + expires_after="2013-04-08"> + <obsolete> + Removed as of 4/2013, experiment confirmed correctness of our patch. + </obsolete> + <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <summary> + Counts how often the user writes or reads from the clipboard and whether the + write was from an incognito window or not. + </summary> +</histogram> + +<histogram name="Clipboard.Read" enum="ClipboardFormatRead" expires_after="2021-01-01"> <owner>huangdarwin@chromium.org</owner> <owner>src/ui/base/clipboard/OWNERS</owner> @@ -27750,29 +27762,6 @@ </summary> </histogram> -<histogram name="Clipboard.Format.Write" enum="ClipboardFormatWrite" - expires_after="2021-01-01"> - <owner>huangdarwin@chromium.org</owner> - <owner>src/ui/base/clipboard/OWNERS</owner> - <summary> - Counts how often each Clipboard format is written by the platform clipboard. - These writes all imply that an application had this format available, and - therefore wrote this format. - </summary> -</histogram> - -<histogram name="Clipboard.IncognitoUseCase" enum="ClipboardAction" - expires_after="2013-04-08"> - <obsolete> - Removed as of 4/2013, experiment confirmed correctness of our patch. - </obsolete> - <owner>Please list the metric's owners. Add more owner tags as needed.</owner> - <summary> - Counts how often the user writes or reads from the clipboard and whether the - write was from an incognito window or not. - </summary> -</histogram> - <histogram name="Clipboard.RegisterClipboardFormatFailure" units="count" expires_after="2021-01-01"> <owner>huangdarwin@chromium.org</owner> @@ -27784,6 +27773,17 @@ </summary> </histogram> +<histogram name="Clipboard.Write" enum="ClipboardFormatWrite" + expires_after="2021-01-01"> + <owner>huangdarwin@chromium.org</owner> + <owner>src/ui/base/clipboard/OWNERS</owner> + <summary> + Counts how often each Clipboard format is written by the platform clipboard. + These writes all imply that an application had this format available, and + therefore wrote this format. + </summary> +</histogram> + <histogram name="Clipboard.X11StoreCopyPasteDuration" units="ms" expires_after="M90"> <owner>dcheng@chromium.org</owner> @@ -31518,6 +31518,23 @@ </summary> </histogram> +<histogram name="ContentSuggestions.Feed.VisitDuration" units="ms" + expires_after="2021-07-01"> + <owner>harringtond@chromium.org</owner> + <owner>freedjm@chromium.org</owner> + <owner>feed@chromium.org</owner> + <summary> + Android: Time spent reading the page linked by an opened suggestion card. + This is a lower-bound time. Does not include time after Chrome is closed and + re-opened. Does not include time after the visited tab no longer has focus, + or after the tab is navigated. For the 'open in new tab' action, time starts + when the user switches to the new tab. If the user returns by tapping the + suggestion again, it will be recorded as another entry in this histogram. + + Feed v2 only. + </summary> +</histogram> + <histogram name="ContentSuggestions.Feed.VisualElement.Clicked" units="index" expires_after="2020-10-01"> <owner>carlosk@chromium.org</owner> @@ -153827,6 +153844,10 @@ <histogram name="Scheduling.Browser.ReadyToActivateToActivationDuration2.Main" units="microseconds" expires_after="M85"> + <obsolete> + Replaced by EndCommitToActivation of CompositorLatency metrics as of + 08/2020. + </obsolete> <owner>vmiura@chromium.org</owner> <owner>sadrul@chromium.org</owner> <summary> @@ -154291,6 +154312,10 @@ <histogram name="Scheduling.Renderer.ReadyToActivateToActivationDuration2" units="microseconds" expires_after="M81"> + <obsolete> + Replaced by EndCommitToActivation of CompositorLatency metrics as of + 08/2020. + </obsolete> <owner>vmiura@chromium.org</owner> <owner>sadrul@chromium.org</owner> <summary> @@ -170171,8 +170196,8 @@ </summary> </histogram> -<histogram name="Startup.Android.FeedContentFirstLoadedTime" units="ms" - expires_after="2021-06-10"> +<histogram base="true" name="Startup.Android.FeedContentFirstLoadedTime" + units="ms" expires_after="2021-06-10"> <!-- Name completed by histogram_suffixes name="JavaStartMode" --> <owner>hanxi@chromium.org</owner> @@ -170199,6 +170224,20 @@ </summary> </histogram> +<histogram base="true" name="Startup.Android.FeedStreamCreatedTime" units="ms" + expires_after="2021-06-10"> +<!-- Name completed by histogram_suffixes name="JavaStartMode" --> + + <owner>hanxi@chromium.org</owner> + <owner>spdonghao@chromium.org</owner> + <owner>wychen@chromium.org</owner> + <summary> + Records the time duration from a cold start till the Feeds stream is created + on the StartSurface. This histogram is only recorded when StartSurface is + shown at launch due to "return to tab switcher" feature. + </summary> +</histogram> + <histogram name="Startup.Android.GURLEnsureMainDexInitialized" units="ms" expires_after="2021-01-31"> <owner>mthiesse@chromium.org</owner> @@ -170209,8 +170248,8 @@ </summary> </histogram> -<histogram name="Startup.Android.SingleTabTitleAvailableTime" units="ms" - expires_after="2021-06-10"> +<histogram base="true" name="Startup.Android.SingleTabTitleAvailableTime" + units="ms" expires_after="2021-06-10"> <!-- Name completed by histogram_suffixes name="JavaStartMode" --> <owner>hanxi@chromium.org</owner> @@ -179907,6 +179946,57 @@ </details> </histogram> +<histogram name="Tabs.TabSearch.CloseAction" enum="TabSearchCloseActions" + expires_after="M90"> + <owner>tluk@chromium.org</owner> + <owner>robliao@chromium.org</owner> + <summary> + Tab Search is a feature that allows users to better search for and switch to + their desired tabs. The Tab Search UI is shown in a bubble anchored to an + element of the UI in the browser window. + + The bubble is dismissed when it loses focus or the escape key is pressed. + This metric tracks if the UI bubble was dismissed as a result of an action + taken from within the UI (such as switching to an open tab) or dismissed + without direct interaction with the Tab Search UI. + </summary> +</histogram> + +<histogram name="Tabs.TabSearch.NumTabsClosedPerInstance" units="tabs" + expires_after="M90"> + <owner>tluk@chromium.org</owner> + <owner>robliao@chromium.org</owner> + <summary> + Tab Search is a feature that allows users to better search their browsers + for their desired tabs and close any currently open tabs. This records the + number of tabs closed from a single instance of the UI (the number of tabs + closed from within Tab Search in the time between when the UI is open and + when it is closed). + </summary> +</histogram> + +<histogram name="Tabs.TabSearch.NumTabsOnOpen" units="tabs" expires_after="M90"> + <owner>tluk@chromium.org</owner> + <owner>robliao@chromium.org</owner> + <summary> + Tab Search is a feature that allows users to better search their browsers + for their desired tabs. It can be opened and closed. This records the number + of tabs there are in the payload Tab Search is sent when it is first opened. + </summary> +</histogram> + +<histogram name="Tabs.TabSearch.NumWindowsOnOpen" units="windows" + expires_after="M90"> + <owner>tluk@chromium.org</owner> + <owner>robliao@chromium.org</owner> + <summary> + Tab Search is a feature that allows users to better search their browsers + for their desired tabs. It can be opened and closed. This records the number + of windows there are in the payload Tab Search is sent when it is first + opened. + </summary> +</histogram> + <histogram name="Tabs.TabSearch.WebUI.InitialTabsRenderTime" units="ms" expires_after="M90"> <owner>tluk@chromium.org</owner> @@ -206213,6 +206303,7 @@ <suffix name="Instant" label=""/> <suffix name="NoInstant" label=""/> <affected-histogram name="Startup.Android.FeedContentFirstLoadedTime"/> + <affected-histogram name="Startup.Android.FeedStreamCreatedTime"/> <affected-histogram name="Startup.Android.SingleTabTitleAvailableTime"/> </histogram_suffixes>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index e6931c25..e024057 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -2,15 +2,15 @@ "trace_processor_shell": { "win": { "hash": "4d8a03fb547a349f28ff875a5511d6425fda5420", - "remote_path": "perfetto_binaries/trace_processor_shell/win/e69d5b2de9433980adaa09301bae62b8d467b390/trace_processor_shell.exe" + "remote_path": "perfetto_binaries/trace_processor_shell/win/56f14dabfe991afdf09f35a56418657dbcb81791/trace_processor_shell.exe" }, "mac": { "hash": "2d61c350c440b9c0183368092b5a20e3b1d1dd9d", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/e69d5b2de9433980adaa09301bae62b8d467b390/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/mac/56f14dabfe991afdf09f35a56418657dbcb81791/trace_processor_shell" }, "linux": { "hash": "e6355871974e3232db70f33ff3ae6c8d6ee4dfa7", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/56f14dabfe991afdf09f35a56418657dbcb81791/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/linux/0c0349252934019978f01fe83ec8a2b83567fe63/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 7ad126c..01c847b 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -182,6 +182,7 @@ "java/res/values/attrs.xml", "java/res/values/color_palette.xml", "java/res/values/dimens.xml", + "java/res/values/font_certs.xml", "java/res/values/ids.xml", "java/res/values/one_off_colors.xml", "java/res/values/semantic_colors_adaptive.xml",
diff --git a/ui/android/java/res/values/font_certs.xml b/ui/android/java/res/values/font_certs.xml new file mode 100644 index 0000000..2c3a45a --- /dev/null +++ b/ui/android/java/res/values/font_certs.xml
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. --> + +<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources"> + <array name="com_google_android_gms_fonts_certs"> + <item>@array/com_google_android_gms_fonts_certs_dev</item> + <item>@array/com_google_android_gms_fonts_certs_prod</item> + </array> + <string-array name="com_google_android_gms_fonts_certs_dev" translatable="false"> + <item> + MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs= + </item> + </string-array> + <string-array name="com_google_android_gms_fonts_certs_prod" translatable="false"> + <item> + MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK + </item> + </string-array> +</resources>
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java b/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java index fd2dd78..a7d5bac 100644 --- a/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/RenderTestRule.java
@@ -206,6 +206,42 @@ Assert.fail("Failed to create Skia Gold JSON keys: " + e.toString()); } saveString(goldKeys.toString(), createOutputPath(SKIA_GOLD_FOLDER_RELATIVE, jsonName)); + + // TODO(crbug.com/1077274): Make this the default behavior instead of calling in addition to + // the above once we're ready to switch. + compareForResultNoDeviceInfo(testBitmap, id); + } + + /** + * A temporary version of compareForResult that does not include OS/device model information in + * the test name. This is in preparation for the switch to doing this be default. In the + * interim period, results both with and without the extra information will be uploaded, but the + * latter will be ignored on Gold's end for a period of time. + */ + private void compareForResultNoDeviceInfo(Bitmap testBitmap, String id) throws IOException { + Assert.assertTrue("Render Tests must have the RenderTest feature.", mHasRenderTestFeature); + + // Save the image and its metadata to a location where it can be pulled by the test runner + // for comparison after the test finishes. + String imageName = getImageNameNoDeviceInfo(mTestClassName, mVariantPrefix, id); + String jsonName = getJsonNameNoDeviceInfo(mTestClassName, mVariantPrefix, id); + + saveBitmap(testBitmap, createOutputPath(SKIA_GOLD_FOLDER_RELATIVE, imageName)); + JSONObject goldKeys = new JSONObject(); + try { + goldKeys.put("source_type", mSkiaGoldCorpus); + goldKeys.put("model", Build.MODEL); + goldKeys.put("sdk_version", String.valueOf(Build.VERSION.SDK_INT)); + if (!TextUtils.isEmpty(mSkiaGoldRevisionDescription)) { + goldKeys.put("revision_description", mSkiaGoldRevisionDescription); + } + goldKeys.put("fail_on_unsupported_configs", String.valueOf(mFailOnUnsupportedConfigs)); + // TODO(crbug.com/1077274): Remove this ignore key once this is the default behavior. + goldKeys.put("ignore", "1"); + } catch (JSONException e) { + Assert.fail("Failed to create Skia Gold JSON keys: " + e.toString()); + } + saveString(goldKeys.toString(), createOutputPath(SKIA_GOLD_FOLDER_RELATIVE, jsonName)); } /** @@ -254,6 +290,13 @@ } /** + * Version of getImageName that does not include OS/device model in the name. + */ + private String getImageNameNoDeviceInfo(String testClass, String variantPrefix, String desc) { + return String.format("%s.png", getFileNameNoDeviceInfo(testClass, variantPrefix, desc)); + } + + /** * Creates a JSON name combining the description with details about the device (e.g. model, * current orientation). */ @@ -262,6 +305,13 @@ } /** + * Version of getJsonName that does not include OS/device model in the name. + */ + private String getJsonNameNoDeviceInfo(String testClass, String variantPrefix, String desc) { + return String.format("%s.json", getFileNameNoDeviceInfo(testClass, variantPrefix, desc)); + } + + /** * Creates a generic filename (without a file extension) combining the description with details * about the device (e.g. model, current orientation). * @@ -282,6 +332,21 @@ } /** + * Version of getFileName that does not include OS/device model in the name. + */ + private String getFileNameNoDeviceInfo(String testClass, String variantPrefix, String desc) { + if (!TextUtils.isEmpty(mNightModePrefix)) { + desc = mNightModePrefix + "-" + desc; + } + + if (!TextUtils.isEmpty(variantPrefix)) { + desc = variantPrefix + "-" + desc; + } + + return String.format("%s.%s.rev_%s", testClass, desc, mSkiaGoldRevision); + } + + /** * Returns a string encoding the device model and sdk. It is used to identify device goldens. */ private static String modelSdkIdentifier() {
diff --git a/ui/gfx/platform_font_mac.h b/ui/gfx/platform_font_mac.h index 1854a95..667b8dba 100644 --- a/ui/gfx/platform_font_mac.h +++ b/ui/gfx/platform_font_mac.h
@@ -8,18 +8,39 @@ #include "base/compiler_specific.h" #include "base/mac/scoped_nsobject.h" #include "base/macros.h" +#include "base/optional.h" #include "ui/gfx/font_render_params.h" #include "ui/gfx/platform_font.h" namespace gfx { -class PlatformFontMac : public PlatformFont { +class GFX_EXPORT PlatformFontMac : public PlatformFont { public: - PlatformFontMac(); + // An enum indicating a type of system-specified font. + // - kGeneral: +[NSFont systemFontOfSize:(weight:)] + // - kMenu: +[NSFont menuFontOfSize:] + // - kToolTip: +[NSFont toolTipsFontOfSize:] + enum class SystemFontType { kGeneral, kMenu, kToolTip }; + + // Constructs a PlatformFontMac for a system-specified font of + // |system_font_type| type. For a non-system-specified font, use any other + // constructor. + explicit PlatformFontMac(SystemFontType system_font_type); + + // Constructs a PlatformFontMac for containing the NSFont* |native_font|. Do + // not call this for a system-specified font; use the |SystemFontType| + // constructor for that. |native_font| must not be null. explicit PlatformFontMac(NativeFont native_font); + + // Constructs a PlatformFontMac representing the font with name |font_name| + // and the size |font_size|. Do not call this for a system-specified font; use + // the |SystemFontType| constructor for that. PlatformFontMac(const std::string& font_name, int font_size); + // Constructs a PlatformFontMac representing the font specified by |typeface| + // and the size |font_size_pixels|. Do not call this for a system-specified + // font; use the |SystemFontType| constructor for that. PlatformFontMac(sk_sp<SkTypeface> typeface, int font_size_pixels, const base::Optional<FontRenderParams>& params); @@ -41,35 +62,44 @@ NativeFont GetNativeFont() const override; sk_sp<SkTypeface> GetNativeSkTypeface() const override; + // A utility function to get the weight of an NSFont. Used by the unit test. + static Font::Weight GetFontWeightFromNSFontForTesting(NSFont* font); + private: - PlatformFontMac(const std::string& font_name, - int font_size, - int font_style, - Font::Weight font_weight); + struct FontSpec { + std::string name; // Corresponds to -[NSFont fontFamily]. + int size; + int style; + Font::Weight weight; + }; PlatformFontMac(NativeFont font, - const std::string& font_name, - int font_size, - int font_style, - Font::Weight font_weight); + base::Optional<SystemFontType> system_font_type); + + PlatformFontMac(NativeFont font, + base::Optional<SystemFontType> system_font_type, + FontSpec spec); ~PlatformFontMac() override; - // Calculates and caches the font metrics and inits |render_params_|. + // Calculates and caches the font metrics and initializes |render_params_|. void CalculateMetricsAndInitRenderParams(); + // Returns an autoreleased NSFont created with the passed-in specifications. + NSFont* NSFontWithSpec(FontSpec font_spec) const; + // The NSFont instance for this object. If this object was constructed from an // NSFont instance, this holds that NSFont instance. Otherwise this NSFont // instance is constructed from the name, size, and style. If there is no // active font that matched those criteria a default font is used. base::scoped_nsobject<NSFont> native_font_; - // The name/size/style trio that specify the font. Initialized in the - // constructors. - const std::string font_name_; // Corresponds to -[NSFont fontFamily]. - const int font_size_; - const int font_style_; - const Font::Weight font_weight_; + // If the font is a system font, and if so, what kind. + const base::Optional<SystemFontType> system_font_type_; + + // The name/size/style/weight quartet that specify the font. Initialized in + // the constructors. + const FontSpec font_spec_; // Cached metrics, generated in CalculateMetrics(). int height_;
diff --git a/ui/gfx/platform_font_mac.mm b/ui/gfx/platform_font_mac.mm index 6061fb57..9c79b98 100644 --- a/ui/gfx/platform_font_mac.mm +++ b/ui/gfx/platform_font_mac.mm
@@ -5,12 +5,15 @@ #include "ui/gfx/platform_font_mac.h" #include <cmath> +#include <set> #include <Cocoa/Cocoa.h> +#include "base/bit_cast.h" #import "base/mac/foundation_util.h" #include "base/mac/scoped_cftyperef.h" #import "base/mac/scoped_nsobject.h" +#include "base/no_destructor.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/ports/SkTypeface_mac.h" @@ -20,62 +23,14 @@ namespace gfx { -namespace { +using Weight = Font::Weight; -// How to get from NORMAL weight to a fine-grained font weight using calls to -// -[NSFontManager convertWeight:(BOOL)upFlag ofFont:(NSFont)]. -struct WeightSolver { - int steps_up; // Times to call with upFlag:YES. - int steps_down; // Times to call with upFlag:NO. - // Either NORMAL or BOLD: whether to set the NSBoldFontMask symbolic trait. - Font::Weight nearest; -}; - -// Solve changes to the font weight according to the following table, from -// https://developer.apple.com/reference/appkit/nsfontmanager/1462321-convertweight -// 1. ultralight | none -// 2. thin | W1. ultralight -// 3. light, extralight | W2. extralight -// 4. book | W3. light -// 5. regular, plain, display, roman | W4. semilight -// 6. medium | W5. medium -// 7. demi, demibold | none -// 8. semi, semibold | W6. semibold -// 9. bold | W7. bold -// 10. extra, extrabold | W8. extrabold -// 11. heavy, heavyface | none -// 12. black, super | W9. ultrabold -// 13. ultra, ultrablack, fat | none -// 14. extrablack, obese, nord | none -WeightSolver WeightChangeFromNormal(Font::Weight desired) { - using Weight = Font::Weight; - switch (desired) { - case Weight::THIN: - // It's weird, but to get LIGHT and THIN fonts, first go up a step. - // Without this, the font stays stuck at NORMAL. See - // PlatformFontMacTest, FontWeightAPIConsistency. - return {1, 3, Weight::NORMAL}; - case Weight::EXTRA_LIGHT: - return {1, 2, Weight::NORMAL}; - case Weight::LIGHT: - return {1, 1, Weight::NORMAL}; - case Weight::NORMAL: - return {0, 0, Weight::NORMAL}; - case Weight::MEDIUM: - return {1, 0, Weight::NORMAL}; - case Weight::SEMIBOLD: - return {0, 1, Weight::BOLD}; - case Weight::BOLD: - return {0, 0, Weight::BOLD}; - case Weight::EXTRA_BOLD: - return {1, 0, Weight::BOLD}; - case Weight::BLACK: - return {3, 0, Weight::BOLD}; // Skip row 12. - case Weight::INVALID: - return {0, 0, Weight::NORMAL}; - } +extern "C" { +bool CTFontDescriptorIsSystemUIFont(CTFontDescriptorRef); } +namespace { + // Returns the font style for |font|. Disregards Font::UNDERLINE, since NSFont // does not support it as a trait. int GetFontStyleFromNSFont(NSFont* font) { @@ -86,21 +41,21 @@ return font_style; } -// Returns the Font weight for |font|. -Font::Weight GetFontWeightFromNSFont(NSFont* font) { +// Returns the Font::Weight for |font|. +Weight GetFontWeightFromNSFont(NSFont* font) { DCHECK(font); // Map CoreText weights in a manner similar to ct_weight_to_fontstyle() from // SkFontHost_mac.cpp, but adjusted for the weights actually used by the // system fonts. See PlatformFontMacTest.FontWeightAPIConsistency for details. - // The Mac uses specific float values, but to avoid float comparison - // inaccuracies as well as for paranoia in case float values other than these - // appear, use ranges. + // macOS uses specific float values in its constants, but individual fonts can + // and do specify arbitrary values in the -1.0 to 1.0 range. Therefore, to + // accomodate that, and to avoid float comparison issues, use ranges. constexpr struct { // A range of CoreText weights. CGFloat weight_lower; CGFloat weight_upper; - Font::Weight gfx_weight; + Weight gfx_weight; } weight_map[] = { // NSFontWeight constants introduced in 10.11: // NSFontWeightUltraLight: -0.80 @@ -115,29 +70,35 @@ // // Actual system font weights: // 10.10: + // .HelveticaNeueDeskInterface-UltraLightP2: -0.80 + // .HelveticaNeueDeskInterface-Thin: -0.50 + // .HelveticaNeueDeskInterface-Light: -0.425 // .HelveticaNeueDeskInterface-Regular: 0.0 // .HelveticaNeueDeskInterface-MediumP4: 0.23 - // .HelveticaNeueDeskInterface-Bold: 0.4 - // .HelveticaNeueDeskInterface-Heavy: 0.62 + // .HelveticaNeueDeskInterface-Bold (if requested as semibold): 0.24 + // .HelveticaNeueDeskInterface-Bold (if requested as bold): 0.4 + // .HelveticaNeueDeskInterface-Heavy (if requested as heavy): 0.576 + // .HelveticaNeueDeskInterface-Heavy (if requested as black): 0.662 // 10.11-: - // .AppleSystemUIFontUltraLight: -0.80 (10.12-) - // .AppleSystemUIFontLight: -0.40 (10.12-) - // .AppleSystemUIFont: 0 (10.11-) - // .AppleSystemUIFontMedium: 0.23 (10.12-) - // .AppleSystemUIFontDemi: 0.30 (10.12-) - // .AppleSystemUIFontBold: 0.40 (10.11) - // .AppleSystemUIFontEmphasized: 0.40 (10.12-) - // .AppleSystemUIFontHeavy: 0.56 (10.11-) - // .AppleSystemUIFontBlack: 0.62 (10.11-) - {-1.0, -0.70, Font::Weight::THIN}, // NSFontWeightUltraLight - {-0.70, -0.45, Font::Weight::EXTRA_LIGHT}, // NSFontWeightThin - {-0.45, -0.10, Font::Weight::LIGHT}, // NSFontWeightLight - {-0.10, 0.10, Font::Weight::NORMAL}, // NSFontWeightRegular - {0.10, 0.27, Font::Weight::MEDIUM}, // NSFontWeightMedium - {0.27, 0.35, Font::Weight::SEMIBOLD}, // NSFontWeightSemibold - {0.35, 0.50, Font::Weight::BOLD}, // NSFontWeightBold - {0.50, 0.60, Font::Weight::EXTRA_BOLD}, // NSFontWeightHeavy - {0.60, 1.0, Font::Weight::BLACK}, // NSFontWeightBlack + // .AppleSystemUIFontUltraLight: -0.80 + // .AppleSystemUIFontThin: -0.60 + // .AppleSystemUIFontLight: -0.40 + // .AppleSystemUIFont: 0.0 + // .AppleSystemUIFontMedium: 0.23 + // .AppleSystemUIFontDemi: 0.30 + // .AppleSystemUIFontBold (10.11): 0.40 + // .AppleSystemUIFontEmphasized (10.12-): 0.40 + // .AppleSystemUIFontHeavy: 0.56 + // .AppleSystemUIFontBlack: 0.62 + {-1.0, -0.70, Weight::THIN}, // NSFontWeightUltraLight + {-0.70, -0.45, Weight::EXTRA_LIGHT}, // NSFontWeightThin + {-0.45, -0.10, Weight::LIGHT}, // NSFontWeightLight + {-0.10, 0.10, Weight::NORMAL}, // NSFontWeightRegular + {0.10, 0.27, Weight::MEDIUM}, // NSFontWeightMedium + {0.27, 0.35, Weight::SEMIBOLD}, // NSFontWeightSemibold + {0.35, 0.50, Weight::BOLD}, // NSFontWeightBold + {0.50, 0.60, Weight::EXTRA_BOLD}, // NSFontWeightHeavy + {0.60, 1.0, Weight::BLACK}, // NSFontWeightBlack }; base::ScopedCFTypeRef<CFDictionaryRef> traits( @@ -147,7 +108,7 @@ traits, kCTFontWeightTrait); // A missing weight attribute just means 0 -> NORMAL. if (!cf_weight) - return Font::Weight::NORMAL; + return Weight::NORMAL; // The value of kCTFontWeightTrait empirically is a kCFNumberFloat64Type // (double) on all tested versions of macOS. However, that doesn't really @@ -160,47 +121,116 @@ if (item.weight_lower <= weight && weight <= item.weight_upper) return item.gfx_weight; } - return Font::Weight::INVALID; + return Weight::INVALID; } -// Returns an autoreleased NSFont created with the passed-in specifications. -NSFont* NSFontWithSpec(const std::string& font_name, - int font_size, - int font_style, - Font::Weight font_weight) { - NSFontSymbolicTraits trait_bits = 0; - // TODO(mboc): Add support for other weights as well. - if (font_weight >= Font::Weight::BOLD) - trait_bits |= NSFontBoldTrait; - if (font_style & Font::ITALIC) - trait_bits |= NSFontItalicTrait; - // The Mac doesn't support underline as a font trait, so just drop it. - // (Underlines must be added as an attribute on an NSAttributedString.) - NSDictionary* traits = @{ NSFontSymbolicTrait : @(trait_bits) }; +// Converts a Font::Weight value to the corresponding NSFontWeight value. +NSFontWeight ToNSFontWeight(Weight weight) { + if (@available(macOS 10.11, *)) { + switch (weight) { + case Weight::THIN: + return NSFontWeightUltraLight; + case Weight::EXTRA_LIGHT: + return NSFontWeightThin; + case Weight::LIGHT: + return NSFontWeightLight; + case Weight::INVALID: + case Weight::NORMAL: + return NSFontWeightRegular; + case Weight::MEDIUM: + return NSFontWeightMedium; + case Weight::SEMIBOLD: + return NSFontWeightSemibold; + case Weight::BOLD: + return NSFontWeightBold; + case Weight::EXTRA_BOLD: + return NSFontWeightHeavy; + case Weight::BLACK: + return NSFontWeightBlack; + } + } else { + // See third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm. + uint64_t int_value = 0; + switch (weight) { + case Weight::THIN: + int_value = 0xbfe99999a0000000; // NSFontWeightUltraLight; + break; + case Weight::EXTRA_LIGHT: + int_value = 0xbfe3333340000000; // NSFontWeightThin; + break; + case Weight::LIGHT: + int_value = 0xbfd99999a0000000; // NSFontWeightLight; + break; + case Weight::INVALID: + case Weight::NORMAL: + int_value = 0x0000000000000000; // NSFontWeightRegular; + break; + case Weight::MEDIUM: + int_value = 0x3fcd70a3e0000000; // NSFontWeightMedium; + break; + case Weight::SEMIBOLD: + int_value = 0x3fd3333340000000; // NSFontWeightSemibold; + break; + case Weight::BOLD: + int_value = 0x3fd99999a0000000; // NSFontWeightBold; + break; + case Weight::EXTRA_BOLD: + int_value = 0x3fe1eb8520000000; // NSFontWeightHeavy; + break; + case Weight::BLACK: + int_value = 0x3fe3d70a40000000; // NSFontWeightBlack; + break; + } - NSDictionary* attrs = @{ - NSFontFamilyAttribute : base::SysUTF8ToNSString(font_name), - NSFontTraitsAttribute : traits - }; - NSFontDescriptor* descriptor = - [NSFontDescriptor fontDescriptorWithFontAttributes:attrs]; - NSFont* font = [NSFont fontWithDescriptor:descriptor size:font_size]; - if (font) - return font; - - // Make one fallback attempt by looking up via font name rather than font - // family name. - attrs = @{ - NSFontNameAttribute : base::SysUTF8ToNSString(font_name), - NSFontTraitsAttribute : traits - }; - descriptor = [NSFontDescriptor fontDescriptorWithFontAttributes:attrs]; - return [NSFont fontWithDescriptor:descriptor size:font_size]; + return bit_cast<CGFloat>(int_value); + } } -// Returns |font| or a default font if |font| is nil. -NSFont* ValidateFont(NSFont* font) { - return font ? font : [NSFont systemFontOfSize:[NSFont systemFontSize]]; +// Chromium uses the ISO-style, 9-value ladder of font weights (THIN-BLACK). The +// new font API in macOS also uses these weights, though they are constants +// defined in terms of CGFloat with values from -1.0 to 1.0. +// +// However, the old API used by the NSFontManager uses integer values on a +// "scale of 0 to 15". These values are used in: +// +// -[NSFontManager availableMembersOfFontFamily:] +// -[NSFontManager convertWeight:ofFont:] +// -[NSFontManager fontWithFamily:traits:weight:size:] +// -[NSFontManager weightOfFont:] +// +// Apple provides a chart of how the ISO values correspond: +// https://developer.apple.com/reference/appkit/nsfontmanager/1462321-convertweight +// However, it's more complicated than that. A survey of fonts yields the +// correspondence in this function, but the outliers imply that the ISO-style +// weight is more along the lines of "weight role within the font family" vs +// this number which is more like "how weighty is this font compared to all +// other fonts". +// +// These numbers can't really be forced to line up; different fonts disagree on +// how to map them. This function mostly follows the documented chart as +// inspired by actual fonts, and should be good enough. +NSInteger ToNSFontManagerWeight(Weight weight) { + switch (weight) { + case Weight::THIN: + return 2; + case Weight::EXTRA_LIGHT: + return 3; + case Weight::LIGHT: + return 4; + case Weight::INVALID: + case Weight::NORMAL: + return 5; + case Weight::MEDIUM: + return 6; + case Weight::SEMIBOLD: + return 8; + case Weight::BOLD: + return 9; + case Weight::EXTRA_BOLD: + return 10; + case Weight::BLACK: + return 11; + } } std::string GetFamilyNameFromTypeface(sk_sp<SkTypeface> typeface) { @@ -209,88 +239,155 @@ return family.c_str(); } +NSFont* SystemFontForConstructorOfType(PlatformFontMac::SystemFontType type) { + switch (type) { + case PlatformFontMac::SystemFontType::kGeneral: + return [NSFont systemFontOfSize:[NSFont systemFontSize]]; + case PlatformFontMac::SystemFontType::kMenu: + return [NSFont menuFontOfSize:0]; + case PlatformFontMac::SystemFontType::kToolTip: + return [NSFont toolTipsFontOfSize:0]; + } +} + +base::Optional<PlatformFontMac::SystemFontType> +SystemFontTypeFromUndocumentedCTFontRefInternals(CTFontRef font) { + // The macOS APIs can't reliably derive one font from another. That's why for + // non-system fonts PlatformFontMac::DeriveFont() uses the family name of the + // font to find look up new fonts from scratch, and why, for system fonts, it + // uses the system font APIs to generate new system fonts. + // + // Skia's font handling assumes that given a font object, new fonts can be + // derived from it. That's absolutely not true on the Mac. However, this needs + // to be fixed, and a rewrite of how Skia handles fonts is not on the table. + // + // Therefore this sad hack. If Skia provides an SkTypeface, dig into the + // undocumented bowels of CoreText and magically determine if the font is a + // system font. This allows PlatformFontMac to correctly derive variants of + // the provided font. + // + // TODO(avi, etienneb): Figure out this font stuff. + base::ScopedCFTypeRef<CTFontDescriptorRef> descriptor( + CTFontCopyFontDescriptor(font)); + if (CTFontDescriptorIsSystemUIFont(descriptor.get())) { + // Assume it's the standard system font. The fact that this much is known is + // enough. + return PlatformFontMac::SystemFontType::kGeneral; + } else { + return base::nullopt; + } +} + +#if DCHECK_IS_ON() + +const std::set<std::string>& SystemFontNames() { + static const base::NoDestructor<std::set<std::string>> names([] { + std::set<std::string> names; + names.insert(base::SysNSStringToUTF8( + [NSFont systemFontOfSize:[NSFont systemFontSize]].familyName)); + names.insert(base::SysNSStringToUTF8([NSFont menuFontOfSize:0].familyName)); + names.insert( + base::SysNSStringToUTF8([NSFont toolTipsFontOfSize:0].familyName)); + return names; + }()); + + return *names; +} + +#endif + } // namespace //////////////////////////////////////////////////////////////////////////////// // PlatformFontMac, public: -PlatformFontMac::PlatformFontMac() - : PlatformFontMac([NSFont systemFontOfSize:[NSFont systemFontSize]]) { -} +PlatformFontMac::PlatformFontMac(SystemFontType system_font_type) + : PlatformFontMac(SystemFontForConstructorOfType(system_font_type), + system_font_type) {} PlatformFontMac::PlatformFontMac(NativeFont native_font) - : PlatformFontMac(native_font, - base::SysNSStringToUTF8([native_font familyName]), - [native_font pointSize], - GetFontStyleFromNSFont(native_font), - GetFontWeightFromNSFont(native_font)) { - DCHECK(native_font); // Null should not be passed to this constructor. + : PlatformFontMac(native_font, base::nullopt) { + DCHECK(native_font); // nil should not be passed to this constructor. } PlatformFontMac::PlatformFontMac(const std::string& font_name, int font_size) - : PlatformFontMac(font_name, - font_size, - Font::NORMAL, - Font::Weight::NORMAL) {} + : PlatformFontMac( + NSFontWithSpec({font_name, font_size, Font::NORMAL, Weight::NORMAL}), + base::nullopt, + {font_name, font_size, Font::NORMAL, Weight::NORMAL}) {} PlatformFontMac::PlatformFontMac(sk_sp<SkTypeface> typeface, int font_size_pixels, const base::Optional<FontRenderParams>& params) : PlatformFontMac( base::mac::CFToNSCast(SkTypeface_GetCTFontRef(typeface.get())), - GetFamilyNameFromTypeface(typeface), - font_size_pixels, - (typeface->isItalic() ? Font::ITALIC : Font::NORMAL), - FontWeightFromInt(typeface->fontStyle().weight())) {} + SystemFontTypeFromUndocumentedCTFontRefInternals( + SkTypeface_GetCTFontRef(typeface.get())), + {GetFamilyNameFromTypeface(typeface), font_size_pixels, + (typeface->isItalic() ? Font::ITALIC : Font::NORMAL), + FontWeightFromInt(typeface->fontStyle().weight())}) {} //////////////////////////////////////////////////////////////////////////////// // PlatformFontMac, PlatformFont implementation: Font PlatformFontMac::DeriveFont(int size_delta, int style, - Font::Weight weight) const { - // For some reason, creating fonts using the NSFontDescriptor API's seem to be - // unreliable. Hence use the NSFontManager. - NSFont* derived = native_font_; - NSFontManager* font_manager = [NSFontManager sharedFontManager]; + Weight weight) const { + // What doesn't work? + // + // For all fonts, -[NSFontManager convertWeight:ofFont:] will reliably + // misbehave, skipping over particular weights of fonts, refusing to go + // lighter than regular unless you go heavier first, and in earlier versions + // of the system would accidentally introduce italic fonts when changing + // weights from a non-italic instance. + // + // For system fonts, -[NSFontManager convertFont:to(Not)HaveTrait:], if used + // to change weight, will sometimes switch to a compatibility system font that + // does not have all the weights available. + // + // For system fonts, the most reliable call to use is +[NSFont + // systemFontOfSize:weight:]. This uses the new-style NSFontWeight which maps + // perfectly to the ISO weights that Chromium uses. For non-system fonts, + // -[NSFontManager fontWithFamily:traits:weight:size:] is the only reasonable + // way to query fonts with more granularity than bold/non-bold short of + // walking the font family and querying their kCTFontWeightTrait values. Font + // descriptors hold promise but querying using them often fails to find fonts + // that match; hopefully their matching abilities will improve in future + // versions of the macOS. - if (weight != font_weight_) { - // Find a font without any bold traits. Ideally, all bold traits are - // removed here, but non-symbolic traits are read-only properties of a - // particular set of glyphs. And attempting to "reset" the attribute with a - // new font descriptor will lose internal properties that Mac decorates its - // UI fonts with. E.g., solving the plans below from NORMAL result in a - // CTFontDescriptor attribute entry of NSCTFontUIUsageAttribute in - // CTFont{Regular,Medium,Demi,Emphasized,Heavy,Black}Usage. Attempting to - // "solve" weights starting at other than NORMAL has unpredictable results. - if (font_weight_ != Font::Weight::NORMAL) - derived = [font_manager convertFont:derived toHaveTrait:NSUnboldFontMask]; - DLOG_IF(WARNING, GetFontWeightFromNSFont(derived) != Font::Weight::NORMAL) - << "Deriving from a font with an internal unmodifiable weight."; - - WeightSolver plan = WeightChangeFromNormal(weight); - if (plan.nearest == Font::Weight::BOLD) - derived = [font_manager convertFont:derived toHaveTrait:NSBoldFontMask]; - for (int i = 0; i < plan.steps_up; ++i) - derived = [font_manager convertWeight:YES ofFont:derived]; - for (int i = 0; i < plan.steps_down; ++i) - derived = [font_manager convertWeight:NO ofFont:derived]; - } - - // Always apply the italic trait, even if the italic trait is not changing. - // it's possible for a change in the weight to trigger the font to go italic. - // This is due to an AppKit bug. See http://crbug.com/742261. - if (style != font_style_ || weight != font_weight_) { + if (system_font_type_ == SystemFontType::kGeneral) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + // +[NSFont systemFontOfSize:weight:] is declared as available on 10.11+, + // but actually it is there and works on 10.10. + NSFont* derived = [NSFont systemFontOfSize:font_spec_.size + size_delta + weight:ToNSFontWeight(weight)]; +#pragma clang diagnostic pop NSFontTraitMask italic_trait_mask = (style & Font::ITALIC) ? NSItalicFontMask : NSUnitalicFontMask; - derived = [font_manager convertFont:derived toHaveTrait:italic_trait_mask]; + derived = [[NSFontManager sharedFontManager] convertFont:derived + toHaveTrait:italic_trait_mask]; + + return Font(new PlatformFontMac( + derived, SystemFontType::kGeneral, + {font_spec_.name, font_spec_.size + size_delta, style, weight})); + } else if (system_font_type_ == SystemFontType::kMenu) { + NSFont* derived = [NSFont menuFontOfSize:font_spec_.size + size_delta]; + return Font(new PlatformFontMac( + derived, SystemFontType::kMenu, + {font_spec_.name, font_spec_.size + size_delta, style, weight})); + } else if (system_font_type_ == SystemFontType::kToolTip) { + NSFont* derived = [NSFont toolTipsFontOfSize:font_spec_.size + size_delta]; + return Font(new PlatformFontMac( + derived, SystemFontType::kToolTip, + {font_spec_.name, font_spec_.size + size_delta, style, weight})); + } else { + NSFont* derived = NSFontWithSpec( + {font_spec_.name, font_spec_.size + size_delta, style, weight}); + return Font(new PlatformFontMac( + derived, base::nullopt, + {font_spec_.name, font_spec_.size + size_delta, style, weight})); } - - if (size_delta != 0) - derived = [font_manager convertFont:derived toSize:font_size_ + size_delta]; - - return Font(new PlatformFontMac(derived, font_name_, font_size_ + size_delta, - style, weight)); } int PlatformFontMac::GetHeight() { @@ -323,15 +420,15 @@ } int PlatformFontMac::GetStyle() const { - return font_style_; + return font_spec_.style; } -Font::Weight PlatformFontMac::GetWeight() const { - return font_weight_; +Weight PlatformFontMac::GetWeight() const { + return font_spec_.weight; } const std::string& PlatformFontMac::GetFontName() const { - return font_name_; + return font_spec_.name; } std::string PlatformFontMac::GetActualFontName() const { @@ -339,7 +436,7 @@ } int PlatformFontMac::GetFontSize() const { - return font_size_; + return font_spec_.size; } const FontRenderParams& PlatformFontMac::GetFontRenderParams() { @@ -354,30 +451,35 @@ return SkMakeTypefaceFromCTFont(base::mac::NSToCFCast(GetNativeFont())); } +// static +Weight PlatformFontMac::GetFontWeightFromNSFontForTesting(NSFont* font) { + return GetFontWeightFromNSFont(font); +} + //////////////////////////////////////////////////////////////////////////////// // PlatformFontMac, private: -PlatformFontMac::PlatformFontMac(const std::string& font_name, - int font_size, - int font_style, - Font::Weight font_weight) +PlatformFontMac::PlatformFontMac( + NativeFont font, + base::Optional<SystemFontType> system_font_type) : PlatformFontMac( - NSFontWithSpec(font_name, font_size, font_style, font_weight), - font_name, - font_size, - font_style, - font_weight) {} + font, + system_font_type, + {base::SysNSStringToUTF8([font familyName]), [font pointSize], + GetFontStyleFromNSFont(font), GetFontWeightFromNSFont(font)}) {} -PlatformFontMac::PlatformFontMac(NativeFont font, - const std::string& font_name, - int font_size, - int font_style, - Font::Weight font_weight) - : native_font_([ValidateFont(font) retain]), - font_name_(font_name), - font_size_(font_size), - font_style_(font_style), - font_weight_(font_weight) { +PlatformFontMac::PlatformFontMac( + NativeFont font, + base::Optional<SystemFontType> system_font_type, + FontSpec spec) + : native_font_([font retain]), + system_font_type_(system_font_type), + font_spec_(spec) { + DCHECK(system_font_type.has_value() || + SystemFontNames().count(spec.name) == 0) + << "Do not pass a system font (" << spec.name << ") to PlatformFontMac; " + << "use the SystemFontType constructor. Extend the SystemFontType enum " + << "if necessary."; CalculateMetricsAndInitRenderParams(); } @@ -400,11 +502,71 @@ height_ = ceil(ascent_ + std::abs([font descender]) + [font leading]); FontRenderParamsQuery query; - query.families.push_back(font_name_); - query.pixel_size = font_size_; - query.style = font_style_; - query.weight = font_weight_; - render_params_ = gfx::GetFontRenderParams(query, NULL); + query.families.push_back(font_spec_.name); + query.pixel_size = font_spec_.size; + query.style = font_spec_.style; + query.weight = font_spec_.weight; + render_params_ = gfx::GetFontRenderParams(query, nullptr); +} + +NSFont* PlatformFontMac::NSFontWithSpec(FontSpec font_spec) const { + // One might think that a font descriptor with the NSFontWeightTrait/ + // kCTFontWeightTrait trait could be used to look up a font with a specific + // weight. That doesn't work, though. You can ask a font for its weight, but + // you can't use weight to query for the font. + // + // The way that does work is to use the old-style integer weight API. + + NSFontManager* font_manager = [NSFontManager sharedFontManager]; + + NSFontTraitMask traits = 0; + if (font_spec.style & Font::ITALIC) + traits |= NSItalicFontMask; + // The Mac doesn't support underline as a font trait, so just drop it. + // (Underlines must be added as an attribute on an NSAttributedString.) Do not + // add NSBoldFontMask here; if it is added then the weight parameter below + // will be ignored. + + NSFont* font = + [font_manager fontWithFamily:base::SysUTF8ToNSString(font_spec.name) + traits:traits + weight:ToNSFontManagerWeight(font_spec.weight) + size:font_spec.size]; + if (font) + return font; + + // Make one fallback attempt by looking up via font name rather than font + // family name. With this API, the available granularity of font weight is + // bold/not-bold, but that's what's available. + NSFontSymbolicTraits trait_bits = 0; + if (font_spec.weight >= Weight::BOLD) + trait_bits |= NSFontBoldTrait; + if (font_spec.style & Font::ITALIC) + trait_bits |= NSFontItalicTrait; + + NSDictionary* attrs = @{ + NSFontNameAttribute : base::SysUTF8ToNSString(font_spec.name), + NSFontTraitsAttribute : @{NSFontSymbolicTrait : @(trait_bits)}, + }; + NSFontDescriptor* descriptor = + [NSFontDescriptor fontDescriptorWithFontAttributes:attrs]; + + font = [NSFont fontWithDescriptor:descriptor size:font_spec.size]; + if (font) + return font; + + // If that doesn't find a font, whip up a system font to stand in for the + // specified font. + if (@available(macOS 10.11, *)) { + font = [NSFont systemFontOfSize:font_spec.size + weight:ToNSFontWeight(font_spec.weight)]; + return [font_manager convertFont:font toHaveTrait:traits]; + } else { + font = [NSFont systemFontOfSize:font_spec.size]; + if (font_spec.weight >= Weight::BOLD) + traits |= NSBoldFontMask; + return [font_manager convertFont:font toHaveTrait:traits]; + } } //////////////////////////////////////////////////////////////////////////////// @@ -412,12 +574,12 @@ // static PlatformFont* PlatformFont::CreateDefault() { - return new PlatformFontMac; + return new PlatformFontMac(PlatformFontMac::SystemFontType::kGeneral); } // static PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) { - return new PlatformFontMac(ValidateFont(native_font)); + return new PlatformFontMac(native_font); } // static
diff --git a/ui/gfx/platform_font_mac_unittest.mm b/ui/gfx/platform_font_mac_unittest.mm index f955a6b..0f812e9 100644 --- a/ui/gfx/platform_font_mac_unittest.mm +++ b/ui/gfx/platform_font_mac_unittest.mm
@@ -7,292 +7,187 @@ #include <Cocoa/Cocoa.h> #include <stddef.h> +#import "base/mac/foundation_util.h" #include "base/mac/mac_util.h" +#include "base/mac/scoped_cftyperef.h" #include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/font.h" -// TODO(tapted): Remove gfx:: prefixes. namespace gfx { -TEST(PlatformFontMacTest, DeriveFont) { - // Use a base font that support all traits. - gfx::Font base_font("Helvetica", 13); +using Weight = Font::Weight; - // Bold - gfx::Font bold_font( - base_font.Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); - NSFontTraitMask traits = [[NSFontManager sharedFontManager] - traitsOfFont:bold_font.GetNativeFont()]; - EXPECT_EQ(NSBoldFontMask, traits); +TEST(PlatformFontMacTest, DeriveFont) { + // |weight_tri| is either -1, 0, or 1 meaning "light", "normal", or "bold". + auto CheckExpected = [](const Font& font, int weight_tri, bool isItalic) { + base::ScopedCFTypeRef<CFDictionaryRef> traits( + CTFontCopyTraits(base::mac::NSToCFCast(font.GetNativeFont()))); + DCHECK(traits); + + CFNumberRef cf_slant = base::mac::GetValueFromDictionary<CFNumberRef>( + traits, kCTFontSlantTrait); + CGFloat slant; + CFNumberGetValue(cf_slant, kCFNumberCGFloatType, &slant); + if (isItalic) + EXPECT_GT(slant, 0); + else + EXPECT_EQ(slant, 0); + + CFNumberRef cf_weight = base::mac::GetValueFromDictionary<CFNumberRef>( + traits, kCTFontWeightTrait); + CGFloat weight; + CFNumberGetValue(cf_weight, kCFNumberCGFloatType, &weight); + if (weight_tri < 0) + EXPECT_LT(weight, 0); + else if (weight_tri == 0) + EXPECT_EQ(weight, 0); + else + EXPECT_GT(weight, 0); + }; + + // Use a base font that support all traits. + Font base_font("Helvetica", 13); + { + SCOPED_TRACE("plain font"); + CheckExpected(base_font, 0, false); + } // Italic - gfx::Font italic_font( - base_font.Derive(0, gfx::Font::ITALIC, gfx::Font::Weight::NORMAL)); - traits = [[NSFontManager sharedFontManager] - traitsOfFont:italic_font.GetNativeFont()]; - EXPECT_EQ(NSItalicFontMask, traits); + Font italic_font(base_font.Derive(0, Font::ITALIC, Weight::NORMAL)); + { + SCOPED_TRACE("italic font"); + CheckExpected(italic_font, 0, true); + } + + // Bold + Font bold_font(base_font.Derive(0, Font::NORMAL, Weight::BOLD)); + { + SCOPED_TRACE("bold font"); + CheckExpected(bold_font, 1, false); + } // Bold italic - gfx::Font bold_italic_font( - base_font.Derive(0, gfx::Font::ITALIC, gfx::Font::Weight::BOLD)); - traits = [[NSFontManager sharedFontManager] - traitsOfFont:bold_italic_font.GetNativeFont()]; - EXPECT_EQ(static_cast<NSFontTraitMask>(NSBoldFontMask | NSItalicFontMask), - traits); + Font bold_italic_font(base_font.Derive(0, Font::ITALIC, Weight::BOLD)); + { + SCOPED_TRACE("bold italic font"); + CheckExpected(bold_italic_font, 1, true); + } + + // Non-existent thin will return the closest weight, light + Font thin_font(base_font.Derive(0, Font::NORMAL, Weight::THIN)); + { + SCOPED_TRACE("thin font"); + CheckExpected(thin_font, -1, false); + } + + // Non-existent black will return the closest weight, bold + Font black_font(base_font.Derive(0, Font::NORMAL, Weight::BLACK)); + { + SCOPED_TRACE("black font"); + CheckExpected(black_font, 1, false); + } } TEST(PlatformFontMacTest, DeriveFontUnderline) { // Create a default font. - gfx::Font base_font; + Font base_font; // Make the font underlined. - gfx::Font derived_font(base_font.Derive( - 0, base_font.GetStyle() | gfx::Font::UNDERLINE, base_font.GetWeight())); + Font derived_font(base_font.Derive(0, base_font.GetStyle() | Font::UNDERLINE, + base_font.GetWeight())); // Validate the derived font properties against its native font instance. NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:derived_font.GetNativeFont()]; - gfx::Font::Weight actual_weight = (traits & NSFontBoldTrait) - ? gfx::Font::Weight::BOLD - : gfx::Font::Weight::NORMAL; + Weight actual_weight = + (traits & NSFontBoldTrait) ? Weight::BOLD : Weight::NORMAL; - int actual_style = gfx::Font::UNDERLINE; + int actual_style = Font::UNDERLINE; if (traits & NSFontItalicTrait) - actual_style |= gfx::Font::ITALIC; + actual_style |= Font::ITALIC; - EXPECT_TRUE(derived_font.GetStyle() & gfx::Font::UNDERLINE); + EXPECT_TRUE(derived_font.GetStyle() & Font::UNDERLINE); EXPECT_EQ(derived_font.GetStyle(), actual_style); EXPECT_EQ(derived_font.GetWeight(), actual_weight); } -// Tests internal methods for extracting gfx::Font properties from the +// Tests internal methods for extracting Font properties from the // underlying CTFont representation. TEST(PlatformFontMacTest, ConstructFromNativeFont) { + Font light_font([NSFont fontWithName:@"Helvetica-Light" size:12]); + EXPECT_EQ(12, light_font.GetFontSize()); + EXPECT_EQ("Helvetica", light_font.GetFontName()); + EXPECT_EQ(Font::NORMAL, light_font.GetStyle()); + EXPECT_EQ(Weight::LIGHT, light_font.GetWeight()); + + Font light_italic_font([NSFont fontWithName:@"Helvetica-LightOblique" + size:14]); + EXPECT_EQ(14, light_italic_font.GetFontSize()); + EXPECT_EQ("Helvetica", light_italic_font.GetFontName()); + EXPECT_EQ(Font::ITALIC, light_italic_font.GetStyle()); + EXPECT_EQ(Weight::LIGHT, light_italic_font.GetWeight()); + Font normal_font([NSFont fontWithName:@"Helvetica" size:12]); EXPECT_EQ(12, normal_font.GetFontSize()); EXPECT_EQ("Helvetica", normal_font.GetFontName()); EXPECT_EQ(Font::NORMAL, normal_font.GetStyle()); - EXPECT_EQ(Font::Weight::NORMAL, normal_font.GetWeight()); - - Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:14]); - EXPECT_EQ(14, bold_font.GetFontSize()); - EXPECT_EQ("Helvetica", bold_font.GetFontName()); - EXPECT_EQ(Font::NORMAL, bold_font.GetStyle()); - EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight()); + EXPECT_EQ(Weight::NORMAL, normal_font.GetWeight()); Font italic_font([NSFont fontWithName:@"Helvetica-Oblique" size:14]); EXPECT_EQ(14, italic_font.GetFontSize()); EXPECT_EQ("Helvetica", italic_font.GetFontName()); EXPECT_EQ(Font::ITALIC, italic_font.GetStyle()); - EXPECT_EQ(Font::Weight::NORMAL, italic_font.GetWeight()); + EXPECT_EQ(Weight::NORMAL, italic_font.GetWeight()); + + Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:12]); + EXPECT_EQ(12, bold_font.GetFontSize()); + EXPECT_EQ("Helvetica", bold_font.GetFontName()); + EXPECT_EQ(Font::NORMAL, bold_font.GetStyle()); + EXPECT_EQ(Weight::BOLD, bold_font.GetWeight()); Font bold_italic_font([NSFont fontWithName:@"Helvetica-BoldOblique" size:14]); EXPECT_EQ(14, bold_italic_font.GetFontSize()); EXPECT_EQ("Helvetica", bold_italic_font.GetFontName()); EXPECT_EQ(Font::ITALIC, bold_italic_font.GetStyle()); - EXPECT_EQ(Font::Weight::BOLD, bold_italic_font.GetWeight()); -} - -// Specific test for the mapping from the NSFont weight API to gfx::Font::Weight -// values. -TEST(PlatformFontMacTest, FontWeightAPIConsistency) { - // Vanilla Helvetica only has bold and normal, so use a system font. - NSFont* ns_font = [NSFont systemFontOfSize:13]; - NSFontManager* manager = [NSFontManager sharedFontManager]; - - // -[NSFontManager convertWeight:ofFont] supposedly steps the font up and down - // in weight values according to a table at - // https://developer.apple.com/reference/appkit/nsfontmanager/1462321-convertweight - // Apple Terminology | ISO Equivalent - // 1. ultralight | none - // 2. thin | W1. ultralight - // 3. light, extralight | W2. extralight - // 4. book | W3. light - // 5. regular, plain, display, roman | W4. semilight - // 6. medium | W5. medium - // 7. demi, demibold | none - // 8. semi, semibold | W6. semibold - // 9. bold | W7. bold - // 10. extra, extrabold | W8. extrabold - // 11. heavy, heavyface | none - // 12. black, super | W9. ultrabold - // 13. ultra, ultrablack, fat | none - // 14. extrablack, obese, nord | none - EXPECT_EQ(Font::Weight::NORMAL, Font(ns_font).GetWeight()); // Row 5. - - // Ensure the Bold "symbolic" trait from the NSFont traits API maps correctly - // to the weight (non-symbolic) trait from the CTFont API. - NSFont* bold_ns_font = - [manager convertFont:ns_font toHaveTrait:NSFontBoldTrait]; - Font bold_font(bold_ns_font); - EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight()); - - // No thin fonts on the lower rows of the table for San Francisco or earlier - // system fonts. - BOOL down = NO; - ns_font = [NSFont systemFontOfSize:13]; - for (int row = 4; row > 0; --row) { - SCOPED_TRACE(testing::Message() << "Row: " << row); - ns_font = [manager convertWeight:down ofFont:ns_font]; - EXPECT_EQ(Font::Weight::NORMAL, Font(ns_font).GetWeight()); - } - - BOOL up = YES; - // That is... unless we first go up by one and then down. A LIGHT and a THIN - // font reveal themselves somehow. Only tested on 10.12. - if (base::mac::IsAtLeastOS10_12()) { - ns_font = [NSFont systemFontOfSize:13]; - ns_font = [manager convertWeight:up ofFont:ns_font]; - ns_font = [manager convertWeight:down ofFont:ns_font]; - EXPECT_EQ(Font::Weight::LIGHT, Font(ns_font).GetWeight()); - ns_font = [manager convertWeight:down ofFont:ns_font]; - EXPECT_EQ(Font::Weight::THIN, Font(ns_font).GetWeight()); - } - - ns_font = [NSFont systemFontOfSize:13]; - - if (base::mac::IsOS10_11()) { - // On 10.11 the API jumps to BOLD, but has heavier weights as well. - ns_font = [manager convertWeight:up ofFont:ns_font]; - EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); - ns_font = [manager convertWeight:up ofFont:ns_font]; - EXPECT_EQ(Font::Weight::EXTRA_BOLD, Font(ns_font).GetWeight()); - ns_font = [manager convertWeight:up ofFont:ns_font]; - EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); - return; - } - - // Each typeface maps weight notches differently, and the weight is actually a - // floating point value that may not map directly to a gfx::Font::Weight. For - // example San Francisco on macOS 10.12 goes up from 0 in the sequence: [0.23, - // 0.23, 0.3, 0.4, 0.56, 0.62, 0.62, ...] and has no "thin" weights. But also - // iterating over weights does weird stuff sometimes - before macOS 10.15, - // occasionally the font goes italic, but going up another step goes back to - // non-italic, at a heavier weight. - - // NSCTFontUIUsageAttribute = CTFontMediumUsage. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.23. - EXPECT_EQ(Font::Weight::MEDIUM, Font(ns_font).GetWeight()); // Row 6. - - // 10.15 fixed the bug where the step up from medium created a medium italic. - if (base::mac::IsAtMostOS10_14()) { - // Goes italic: NSCTFontUIUsageAttribute = CTFontMediumItalicUsage. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.23. - EXPECT_EQ(Font::Weight::MEDIUM, Font(ns_font).GetWeight()); // Row 7. - } - - // NSCTFontUIUsageAttribute = CTFontDemiUsage. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.3. - if (base::mac::IsOS10_10()) { - // 10.10 is Helvetica Neue. It only has NORMAL, MEDIUM, BOLD and BLACK. - EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); // Row 8. - } else { - EXPECT_EQ(Font::Weight::SEMIBOLD, Font(ns_font).GetWeight()); // Row 8. - } - - // NSCTFontUIUsageAttribute = CTFontEmphasizedUsage. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.4 on 10.11+. - - if (base::mac::IsOS10_10()) { - // Remaining rows are all BLACK on 10.10. - for (int row = 9; row <= 14; ++row) { - SCOPED_TRACE(testing::Message() << "Row: " << row); - ns_font = [manager convertWeight:up ofFont:ns_font]; - EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); - } - return; - } - EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); // Row 9. - - // NSCTFontUIUsageAttribute = CTFontHeavyUsage. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.56. - EXPECT_EQ(Font::Weight::EXTRA_BOLD, Font(ns_font).GetWeight()); // Row 10. - - // NSCTFontUIUsageAttribute = CTFontBlackUsage. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. - EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 11. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. - EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 12. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. - EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 13. - ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. - EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 14. + EXPECT_EQ(Weight::BOLD, bold_italic_font.GetWeight()); } // Test font derivation for fine-grained font weights. TEST(PlatformFontMacTest, DerivedFineGrainedFonts) { - // Only test where San Francisco is available. - if (base::mac::IsAtMostOS10_10()) - return; - - using Weight = Font::Weight; - // The resulting, actual font weight after deriving |weight| from |base|. - auto DerivedIntWeight = [](const Font& base, Weight weight) { + auto DerivedIntWeight = [](Weight weight) { + Font base; // The default system font. Font derived(base.Derive(0, 0, weight)); // PlatformFont should always pass the requested weight, not what the OS // could provide. This just checks a constructor argument, so not very // interesting. EXPECT_EQ(static_cast<int>(weight), static_cast<int>(derived.GetWeight())); - // Return the weight int value that PlatformFontMac internally derives from - // the floating point weight given by the kCTFontWeightTrait of |font|. Do - // this by creating a new font based only off the NSFont in |derived|. - return static_cast<int>(Font(derived.GetNativeFont()).GetWeight()); + return static_cast<int>(PlatformFontMac::GetFontWeightFromNSFontForTesting( + derived.GetNativeFont())); }; - // Only use NORMAL or BOLD as a base font. Mac font APIs go wacky otherwise. - // See comments in PlatformFontMac::DeriveFont(). - Font base([NSFont systemFontOfSize:13]); - for (Weight base_weight : {Weight::NORMAL, Weight::BOLD}) { - SCOPED_TRACE(testing::Message() - << "BaseWeight: " << static_cast<int>(base_weight)); - if (base_weight != Weight::NORMAL) { - base = base.Derive(0, 0, base_weight); - EXPECT_EQ(static_cast<int>(base_weight), - static_cast<int>(base.GetWeight())); - } - - // Normal and heavy weights map correctly on 10.11 and 10.12. - EXPECT_EQ(static_cast<int>(Weight::NORMAL), - DerivedIntWeight(base, Weight::NORMAL)); - EXPECT_EQ(static_cast<int>(Weight::BOLD), - DerivedIntWeight(base, Weight::BOLD)); - EXPECT_EQ(static_cast<int>(Weight::EXTRA_BOLD), - DerivedIntWeight(base, Weight::EXTRA_BOLD)); - EXPECT_EQ(static_cast<int>(Weight::BLACK), - DerivedIntWeight(base, Weight::BLACK)); - - if (base::mac::IsAtMostOS10_11()) { - // The fine-grained font weights on 10.11 are incomplete. - EXPECT_EQ(static_cast<int>(Weight::NORMAL), - DerivedIntWeight(base, Weight::THIN)); - EXPECT_EQ(static_cast<int>(Weight::NORMAL), - DerivedIntWeight(base, Weight::EXTRA_LIGHT)); - EXPECT_EQ(static_cast<int>(Weight::NORMAL), - DerivedIntWeight(base, Weight::LIGHT)); - EXPECT_EQ(static_cast<int>(Weight::BOLD), - DerivedIntWeight(base, Weight::MEDIUM)); - EXPECT_EQ(static_cast<int>(Weight::BOLD), - DerivedIntWeight(base, Weight::SEMIBOLD)); - continue; - } - - // San Francisco doesn't offer anything between THIN and LIGHT. - EXPECT_EQ(static_cast<int>(Weight::THIN), - DerivedIntWeight(base, Weight::EXTRA_LIGHT)); - - // All the rest should map correctly. - EXPECT_EQ(static_cast<int>(Weight::THIN), - DerivedIntWeight(base, Weight::THIN)); - EXPECT_EQ(static_cast<int>(Weight::LIGHT), - DerivedIntWeight(base, Weight::LIGHT)); + EXPECT_EQ(static_cast<int>(Weight::THIN), DerivedIntWeight(Weight::THIN)); + EXPECT_EQ(static_cast<int>(Weight::EXTRA_LIGHT), + DerivedIntWeight(Weight::EXTRA_LIGHT)); + EXPECT_EQ(static_cast<int>(Weight::LIGHT), DerivedIntWeight(Weight::LIGHT)); + EXPECT_EQ(static_cast<int>(Weight::NORMAL), DerivedIntWeight(Weight::NORMAL)); + EXPECT_EQ(static_cast<int>(Weight::MEDIUM), DerivedIntWeight(Weight::MEDIUM)); + if (base::mac::IsAtMostOS10_10()) { + // If a SEMIBOLD system font is requested, 10.10 will return the bold system + // font, but somehow bearing a weight number of 0.24, which is really a + // medium weight (0.23). EXPECT_EQ(static_cast<int>(Weight::MEDIUM), - DerivedIntWeight(base, Weight::MEDIUM)); + DerivedIntWeight(Weight::SEMIBOLD)); + } else { EXPECT_EQ(static_cast<int>(Weight::SEMIBOLD), - DerivedIntWeight(base, Weight::SEMIBOLD)); + DerivedIntWeight(Weight::SEMIBOLD)); } + EXPECT_EQ(static_cast<int>(Weight::BOLD), DerivedIntWeight(Weight::BOLD)); + EXPECT_EQ(static_cast<int>(Weight::EXTRA_BOLD), + DerivedIntWeight(Weight::EXTRA_BOLD)); + EXPECT_EQ(static_cast<int>(Weight::BLACK), DerivedIntWeight(Weight::BLACK)); } // Ensures that the Font's reported height is consistent with the native font's @@ -300,16 +195,14 @@ TEST(PlatformFontMacTest, ValidateFontHeight) { // Use the default ResourceBundle system font. E.g. Helvetica Neue in 10.10, // Lucida Grande before that, and San Francisco after. - gfx::Font default_font; - gfx::Font::FontStyle styles[] = {gfx::Font::NORMAL, gfx::Font::ITALIC, - gfx::Font::UNDERLINE}; + Font default_font; + Font::FontStyle styles[] = {Font::NORMAL, Font::ITALIC, Font::UNDERLINE}; for (size_t i = 0; i < base::size(styles); ++i) { SCOPED_TRACE(testing::Message() << "Font::FontStyle: " << styles[i]); // Include the range of sizes used by ResourceBundle::FontStyle (-1 to +8). for (int delta = -1; delta <= 8; ++delta) { - gfx::Font font = - default_font.Derive(delta, styles[i], gfx::Font::Weight::NORMAL); + Font font = default_font.Derive(delta, styles[i], Weight::NORMAL); SCOPED_TRACE(testing::Message() << "FontSize(): " << font.GetFontSize()); NSFont* native_font = font.GetNativeFont(); @@ -343,15 +236,14 @@ // Appkit's bug was detected on macOS 10.10 which uses Helvetica Neue as the // system font. TEST(PlatformFontMacTest, DerivedSemiboldFontIsNotItalic) { - gfx::Font base_font; + Font base_font; { NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:base_font.GetNativeFont()]; ASSERT_FALSE(traits & NSItalicFontMask); } - gfx::Font semibold_font( - base_font.Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::SEMIBOLD)); + Font semibold_font(base_font.Derive(0, Font::NORMAL, Weight::SEMIBOLD)); NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:semibold_font.GetNativeFont()]; EXPECT_FALSE(traits & NSItalicFontMask);
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc index af690237..26aebb5d 100644 --- a/ui/gl/android/android_surface_control_compat.cc +++ b/ui/gl/android/android_surface_control_compat.cc
@@ -50,9 +50,6 @@ using pASurfaceTransaction_apply = int64_t (*)(ASurfaceTransaction*); using pASurfaceTransaction_setOnComplete = void (*)(ASurfaceTransaction*, void* ctx, ASurfaceTransaction_OnComplete); -using pASurfaceTransaction_reparent = void (*)(ASurfaceTransaction*, - ASurfaceControl* surface_control, - ASurfaceControl* new_parent); using pASurfaceTransaction_setVisibility = void (*)(ASurfaceTransaction*, ASurfaceControl*, int8_t visibility); @@ -147,7 +144,6 @@ LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_delete); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_apply); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setOnComplete); - LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_reparent); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setVisibility); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setZOrder); LOAD_FUNCTION(main_dl_handle, ASurfaceTransaction_setBuffer); @@ -179,7 +175,6 @@ pASurfaceTransaction_delete ASurfaceTransaction_deleteFn; pASurfaceTransaction_apply ASurfaceTransaction_applyFn; pASurfaceTransaction_setOnComplete ASurfaceTransaction_setOnCompleteFn; - pASurfaceTransaction_reparent ASurfaceTransaction_reparentFn; pASurfaceTransaction_setVisibility ASurfaceTransaction_setVisibilityFn; pASurfaceTransaction_setZOrder ASurfaceTransaction_setZOrderFn; pASurfaceTransaction_setBuffer ASurfaceTransaction_setBufferFn; @@ -355,14 +350,8 @@ } SurfaceControl::Surface::~Surface() { - if (surface_) { - // It is important to detach the surface from the tree before deleting it. - Transaction transaction; - transaction.SetParent(*this, nullptr); - transaction.Apply(); - + if (surface_) SurfaceControlMethods::Get().ASurfaceControl_releaseFn(surface_); - } } SurfaceControl::SurfaceStats::SurfaceStats() = default; @@ -492,13 +481,6 @@ transaction_, ack_ctx, &OnTransactionCompletedOnAnyThread); } -void SurfaceControl::Transaction::SetParent(const Surface& surface, - const Surface* new_parent) { - SurfaceControlMethods::Get().ASurfaceTransaction_reparentFn( - transaction_, surface.surface(), - new_parent ? new_parent->surface() : nullptr); -} - void SurfaceControl::Transaction::Apply() { TRACE_EVENT_ASYNC_BEGIN0("gpu,benchmark", "SurfaceControlTransaction", id_); SurfaceControlMethods::Get().ASurfaceTransaction_applyFn(transaction_);
diff --git a/ui/gl/android/android_surface_control_compat.h b/ui/gl/android/android_surface_control_compat.h index c5baeb78..2ee53e69 100644 --- a/ui/gl/android/android_surface_control_compat.h +++ b/ui/gl/android/android_surface_control_compat.h
@@ -130,7 +130,6 @@ void SetOnCompleteCb( OnCompleteCb cb, scoped_refptr<base::SingleThreadTaskRunner> task_runner); - void SetParent(const Surface& surface, const Surface* new_parent); void Apply();
diff --git a/ui/views/cocoa/tooltip_manager_mac.mm b/ui/views/cocoa/tooltip_manager_mac.mm index da34d603..113b610c 100644 --- a/ui/views/cocoa/tooltip_manager_mac.mm +++ b/ui/views/cocoa/tooltip_manager_mac.mm
@@ -10,6 +10,7 @@ #include "ui/base/cocoa/cocoa_base_utils.h" #include "ui/gfx/font_list.h" #import "ui/gfx/mac/coordinate_conversion.h" +#include "ui/gfx/platform_font_mac.h" namespace { @@ -32,8 +33,10 @@ } const gfx::FontList& TooltipManagerMac::GetFontList() const { - static base::NoDestructor<gfx::FontList> font_list( - []() { return gfx::Font([NSFont toolTipsFontOfSize:0]); }()); + static base::NoDestructor<gfx::FontList> font_list([]() { + return gfx::Font(new gfx::PlatformFontMac( + gfx::PlatformFontMac::SystemFontType::kToolTip)); + }()); return *font_list; }
diff --git a/ui/views/controls/menu/menu_config_mac.mm b/ui/views/controls/menu/menu_config_mac.mm index 1de2eb9..757cafaf 100644 --- a/ui/views/controls/menu/menu_config_mac.mm +++ b/ui/views/controls/menu/menu_config_mac.mm
@@ -7,6 +7,7 @@ #import <AppKit/AppKit.h> #include "base/mac/mac_util.h" +#include "ui/gfx/platform_font_mac.h" namespace { @@ -42,7 +43,8 @@ namespace views { void MenuConfig::Init() { - font_list = gfx::FontList(gfx::Font([NSFont menuFontOfSize:0.0])); + font_list = gfx::FontList(gfx::Font( + new gfx::PlatformFontMac(gfx::PlatformFontMac::SystemFontType::kMenu))); check_selected_combobox_item = true; arrow_key_selection_wraps = false; use_mnemonics = false;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java index ad8b5eb..78be271 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -703,7 +703,7 @@ "setWebLayerRunningInSameProcess"); setter.invoke(null); } catch (Exception e) { - Log.w(TAG, "Unable to notify WebView running in process", e); + Log.w(TAG, "Unable to notify WebView running in process."); } }
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java index 885dfe5..3889aa3 100644 --- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java +++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
@@ -371,11 +371,11 @@ } }); - // Will be a no-op if this tab is already the active tab. - mBrowser.setActiveTab(mTab); - // Creates and adds a new UrlBarView to |mTopContentsContainer|. createUrlBarView(); + + // Will be a no-op if this tab is already the active tab. + mBrowser.setActiveTab(mTab); } private Fragment getOrCreateBrowserFragment() {