diff --git a/DEPS b/DEPS index 1a727e3..195861f 100644 --- a/DEPS +++ b/DEPS
@@ -195,11 +195,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '532a264c141d7cb7741a20cd7049f4fa03ee1a56', + 'skia_revision': '952f088d41e16c5524d68c4a00c038f24d734102', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '81f3d945e03d8b0d9ae798175dd026d0ba98dd65', + 'v8_revision': '1f2195b49c6d7611165ebd149b2825f27693930c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # 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': '282596778418f1b35c809cdba3dceb778f1d4a26', + 'angle_revision': '1e068e1dbb6250bd45e72c5ef73d5fe563d6ca95', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -258,7 +258,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '788aa6fd2c18c8c4ee84e5c15c86f451def6be07', + 'catapult_revision': 'f9ede33deef5dadb50a3b00cd1607e508c9229a4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # 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': '1fd76f85b10e7b31ef3da29a26a4832011c241bb', + 'devtools_frontend_revision': 'df4b3fe83ab26882e6a38a2ec709548a97b63941', # 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. @@ -322,7 +322,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'd8fb72d5ad9cb8ae3499b07b37b7857d88d26794', + 'quiche_revision': 'e447bc6090479a4b89a2689768a8b05bafffe50c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -1249,7 +1249,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ed2e4739280f8f0971c39966ac6319295b6598e4', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '33a6332a92323279d37beafa0ee8cf181a759672', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1543,7 +1543,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ecf0d2c0f65100694a8a98526969d1e15c454d17', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@cba56d2d3c0923ff8aba635dc5e9b5794714c41d', 'condition': 'checkout_src_internal', },
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 48e25ea..803d4e9 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -2695,15 +2695,9 @@ <message name="IDS_ASH_SCREEN_CAPTURE_MESSAGE" desc="The message shows in the screenshot or screen recording notification."> Show in folder </message> - <message name="IDS_ASH_SCREEN_CAPTURE_BUTTON_SHARE" desc="The share button label for the screen capture notifiction."> - Share - </message> <message name="IDS_ASH_SCREEN_CAPTURE_BUTTON_EDIT" desc="The edit button label for the screen catpure notification."> Edit </message> - <message name="IDS_ASH_SCREEN_CAPTURE_BUTTON_FLOAT_ON_TOP" desc="The float-on-top button label for the screen capture notification."> - Float on top - </message> <message name="IDS_ASH_SCREEN_CAPTURE_BUTTON_DELETE" desc="The delete button label for the screen capture notificaiton."> Delete </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_BUTTON_FLOAT_ON_TOP.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_BUTTON_FLOAT_ON_TOP.png.sha1 deleted file mode 100644 index 57b5c98..0000000 --- a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_BUTTON_FLOAT_ON_TOP.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ac998dc1c50f46552c283f30c1d784b214f3f799 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_BUTTON_SHARE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_BUTTON_SHARE.png.sha1 deleted file mode 100644 index 57b5c98..0000000 --- a/ash/ash_strings_grd/IDS_ASH_SCREEN_CAPTURE_BUTTON_SHARE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ac998dc1c50f46552c283f30c1d784b214f3f799 \ No newline at end of file
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index 631503f..f9322cc 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -33,9 +33,7 @@ // The notification button index. enum NotificationButtonIndex { - BUTTON_SHARE = 0, - BUTTON_EDIT, - BUTTON_FLOAT_ON_TOP, + BUTTON_EDIT = 0, BUTTON_DELETE, }; @@ -111,15 +109,9 @@ l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_MESSAGE); message_center::RichNotificationData optional_field; - message_center::ButtonInfo share_button( - l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_BUTTON_SHARE)); - optional_field.buttons.push_back(share_button); message_center::ButtonInfo edit_button( l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_BUTTON_EDIT)); optional_field.buttons.push_back(edit_button); - message_center::ButtonInfo float_on_top_button( - l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_BUTTON_FLOAT_ON_TOP)); - optional_field.buttons.push_back(float_on_top_button); message_center::ButtonInfo delete_button( l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_BUTTON_DELETE)); optional_field.buttons.push_back(delete_button); @@ -166,12 +158,8 @@ // TODO: fill in here. switch (button_index.value()) { - case NotificationButtonIndex::BUTTON_SHARE: - break; case NotificationButtonIndex::BUTTON_EDIT: break; - case NotificationButtonIndex::BUTTON_FLOAT_ON_TOP: - break; case NotificationButtonIndex::BUTTON_DELETE: break; }
diff --git a/ash/frame/default_frame_header_unittest.cc b/ash/frame/default_frame_header_unittest.cc index 4b57baa..76d6df3 100644 --- a/ash/frame/default_frame_header_unittest.cc +++ b/ash/frame/default_frame_header_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "ash/frame/non_client_frame_view_ash.h" #include "ash/public/cpp/caption_buttons/frame_back_button.h" #include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h" #include "ash/public/cpp/shell_window_ids.h" @@ -13,13 +14,16 @@ #include "ash/test/ash_test_base.h" #include "ash/wm/desks/desks_util.h" #include "base/i18n/rtl.h" +#include "base/stl_util.h" #include "base/test/icu_test_util.h" #include "ui/aura/window.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/gfx/animation/animation_test_api.h" #include "ui/gfx/color_utils.h" #include "ui/views/test/test_views.h" #include "ui/views/widget/widget.h" #include "ui/views/window/non_client_view.h" +#include "ui/wm/core/window_util.h" using views::NonClientFrameView; using views::Widget; @@ -82,70 +86,197 @@ // Ensure the right frame colors are used. TEST_F(DefaultFrameHeaderTest, FrameColors) { - std::unique_ptr<Widget> widget = CreateTestWidget( - nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect(1, 2, 3, 4)); - FrameCaptionButtonContainerView container(widget.get()); - views::StaticSizedView window_icon(gfx::Size(16, 16)); - window_icon.SetBounds(0, 0, 16, 16); - widget->SetBounds(gfx::Rect(0, 0, 500, 500)); - widget->Show(); - - DefaultFrameHeader frame_header( - widget.get(), widget->non_client_view()->frame_view(), &container); + const auto win0_bounds = gfx::Rect{1, 2, 3, 4}; + auto win0 = CreateAppWindow(win0_bounds, AppType::BROWSER); + Widget* widget = Widget::GetWidgetForNativeWindow(win0.get()); + DefaultFrameHeader* frame_header = + static_cast<DefaultFrameHeader*>(FrameHeader::Get(widget)); // Check frame color is sensitive to mode. SkColor active = SkColorSetRGB(70, 70, 70); SkColor inactive = SkColorSetRGB(200, 200, 200); - widget->GetNativeWindow()->SetProperty(kFrameActiveColorKey, active); - widget->GetNativeWindow()->SetProperty(kFrameInactiveColorKey, inactive); - frame_header.UpdateFrameColors(); - frame_header.mode_ = FrameHeader::MODE_ACTIVE; - EXPECT_EQ(active, frame_header.GetCurrentFrameColor()); - frame_header.mode_ = FrameHeader::MODE_INACTIVE; - EXPECT_EQ(inactive, frame_header.GetCurrentFrameColor()); - EXPECT_EQ(active, frame_header.GetActiveFrameColorForPaintForTest()); + win0->SetProperty(kFrameActiveColorKey, active); + win0->SetProperty(kFrameInactiveColorKey, inactive); + frame_header->UpdateFrameColors(); + frame_header->mode_ = FrameHeader::MODE_ACTIVE; + EXPECT_EQ(active, frame_header->GetCurrentFrameColor()); + frame_header->mode_ = FrameHeader::MODE_INACTIVE; + EXPECT_EQ(inactive, frame_header->GetCurrentFrameColor()); + EXPECT_EQ(active, frame_header->GetActiveFrameColorForPaintForTest()); // Update to the new value which has no blue, which should animate. - frame_header.mode_ = FrameHeader::MODE_ACTIVE; + frame_header->mode_ = FrameHeader::MODE_ACTIVE; SkColor new_active = SkColorSetRGB(70, 70, 0); - widget->GetNativeWindow()->SetProperty(kFrameActiveColorKey, new_active); - frame_header.UpdateFrameColors(); - - gfx::SlideAnimation* animation = - frame_header.GetAnimationForActiveFrameColorForTest(); - gfx::AnimationTestApi test_api(animation); - - // animate half way through. - base::TimeTicks now = base::TimeTicks::Now(); - test_api.SetStartTime(now); - test_api.Step(now + base::TimeDelta::FromMilliseconds(120)); - - // GetCurrentFrameColor should return the target color. - EXPECT_EQ(new_active, frame_header.GetCurrentFrameColor()); - - // The color used for paint should be somewhere between 0 and 70. - SkColor new_active_for_paint = - frame_header.GetActiveFrameColorForPaintForTest(); - EXPECT_NE(new_active, new_active_for_paint); - EXPECT_EQ(53u, SkColorGetB(new_active_for_paint)); + win0->SetProperty(kFrameActiveColorKey, new_active); + frame_header->UpdateFrameColors(); // Now update to the new value which is full blue. SkColor new_new_active = SkColorSetRGB(70, 70, 255); - widget->GetNativeWindow()->SetProperty(kFrameActiveColorKey, new_new_active); - frame_header.UpdateFrameColors(); - - now = base::TimeTicks::Now(); - test_api.SetStartTime(now); - test_api.Step(now + base::TimeDelta::FromMilliseconds(20)); + win0->SetProperty(kFrameActiveColorKey, new_new_active); + frame_header->UpdateFrameColors(); // Again, GetCurrentFrameColor should return the target color. - EXPECT_EQ(new_new_active, frame_header.GetCurrentFrameColor()); + EXPECT_EQ(new_new_active, frame_header->GetCurrentFrameColor()); +} - // The start value should be the previous paint color, so it should be - // near 53. - SkColor new_new_active_for_paint = - frame_header.GetActiveFrameColorForPaintForTest(); - EXPECT_NE(new_active_for_paint, new_new_active_for_paint); - EXPECT_EQ(54u, SkColorGetB(new_new_active_for_paint)); +namespace { + +class LayerDestroyedChecker : public ui::LayerObserver { + public: + explicit LayerDestroyedChecker(ui::Layer* layer) { layer->AddObserver(this); } + LayerDestroyedChecker(const LayerDestroyedChecker&) = delete; + LayerDestroyedChecker& operator=(const LayerDestroyedChecker&) = delete; + ~LayerDestroyedChecker() override = default; + + void LayerDestroyed(ui::Layer* layer) override { + layer->RemoveObserver(this); + destroyed_ = true; + } + bool destroyed() const { return destroyed_; } + + private: + bool destroyed_ = false; +}; + +} // namespace + +// A class to wait until hthe frame header is painted. +class FramePaintWaiter : public ui::CompositorObserver { + public: + explicit FramePaintWaiter(aura::Window* window) + : frame_header_( + FrameHeader::Get(Widget::GetWidgetForNativeWindow(window))) { + frame_header_->view()->GetWidget()->GetCompositor()->AddObserver(this); + } + FramePaintWaiter(const FramePaintWaiter&) = delete; + FramePaintWaiter& operator=(FramePaintWaiter&) = delete; + ~FramePaintWaiter() override { + frame_header_->view()->GetWidget()->GetCompositor()->RemoveObserver(this); + } + + // ui::CompositorObserver: + void OnCompositingDidCommit(ui::Compositor* compositor) override { + if (frame_header_->painted_) + run_loop_.Quit(); + } + + void Wait() { run_loop_.Run(); } + + private: + base::RunLoop run_loop_; + FrameHeader* frame_header_ = nullptr; +}; + +TEST_F(DefaultFrameHeaderTest, DeleteDuringAnimation) { + const auto bounds = gfx::Rect(100, 100); + auto win0 = CreateAppWindow(bounds, AppType::BROWSER); + auto win1 = CreateAppWindow(bounds, AppType::BROWSER); + + Widget* widget = Widget::GetWidgetForNativeWindow(win0.get()); + EXPECT_TRUE(FrameHeader::Get(widget)); + + EXPECT_TRUE(wm::IsActiveWindow(win1.get())); + + // A frame will not animate until it is painted first. + FramePaintWaiter(win0.get()).Wait(); + FramePaintWaiter(win1.get()).Wait(); + + ui::ScopedAnimationDurationScaleMode non_zero_duration_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + wm::ActivateWindow(win0.get()); + + auto* header_view = NonClientFrameViewAsh::Get(win0.get())->GetHeaderView(); + ASSERT_TRUE(header_view); + auto* animating_layer_holding_view = header_view->children()[0]; + EXPECT_TRUE(!std::strcmp(animating_layer_holding_view->GetClassName(), + "FrameAnimatorView")); + ASSERT_TRUE(animating_layer_holding_view->layer()); + ASSERT_GT(animating_layer_holding_view->layer()->parent()->children().size(), + 2u); + auto* animating_layer = + animating_layer_holding_view->layer()->parent()->children()[0]; + EXPECT_EQ(ui::LAYER_TEXTURED, animating_layer->type()); + EXPECT_NE(std::string::npos, animating_layer->name().find(":Old", 0)); + EXPECT_TRUE(animating_layer->GetAnimator()->is_animating()); + + LayerDestroyedChecker checker(animating_layer); + + win0.reset(); + + EXPECT_TRUE(checker.destroyed()); +} + +// Make sure that the animation is canceled when resized. +TEST_F(DefaultFrameHeaderTest, ResizeAndReorderDuringAnimation) { + const auto bounds = gfx::Rect(100, 100); + auto win_0 = CreateAppWindow(bounds, AppType::BROWSER); + auto win_1 = CreateAppWindow(bounds, AppType::BROWSER); + + EXPECT_TRUE(wm::IsActiveWindow(win_1.get())); + + // A frame will not animate until it is painted first. + FramePaintWaiter(win_0.get()).Wait(); + FramePaintWaiter(win_1.get()).Wait(); + + ui::ScopedAnimationDurationScaleMode non_zero_duration_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + + auto* header_view_0 = + NonClientFrameViewAsh::Get(win_0.get())->GetHeaderView(); + auto* animating_layer_holding_view_0 = header_view_0->children()[0]; + EXPECT_TRUE(!std::strcmp(animating_layer_holding_view_0->GetClassName(), + "FrameAnimatorView")); + size_t original_layers_count_0 = + animating_layer_holding_view_0->layer()->parent()->children().size(); + + auto* header_view_1 = + NonClientFrameViewAsh::Get(win_1.get())->GetHeaderView(); + auto* animating_layer_holding_view_1 = header_view_1->children()[0]; + EXPECT_TRUE(!std::strcmp(animating_layer_holding_view_1->GetClassName(), + "FrameAnimatorView")); + size_t original_layers_count_1 = + animating_layer_holding_view_1->layer()->parent()->children().size(); + + wm::ActivateWindow(win_0.get()); + + { + // Resize during animation + EXPECT_EQ( + animating_layer_holding_view_0->layer()->parent()->children().size(), + original_layers_count_0 + 1); + auto* animating_layer = + animating_layer_holding_view_0->layer()->parent()->children()[0]; + EXPECT_TRUE(animating_layer->GetAnimator()->is_animating()); + + LayerDestroyedChecker checker(animating_layer); + + win_0->SetBounds(gfx::Rect(200, 200)); + + // Animating layer shuld have been removed. + EXPECT_EQ( + animating_layer_holding_view_0->layer()->parent()->children().size(), + original_layers_count_0); + EXPECT_TRUE(checker.destroyed()); + } + + { + // wind_1 should still be animating. + EXPECT_EQ( + animating_layer_holding_view_1->layer()->parent()->children().size(), + original_layers_count_1 + 1); + auto* animating_layer = + animating_layer_holding_view_1->layer()->parent()->children()[0]; + EXPECT_TRUE(animating_layer->GetAnimator()->is_animating()); + LayerDestroyedChecker checker(animating_layer); + + // Change the view's stacking order should stop the animation. + ASSERT_EQ(3u, header_view_1->children().size()); + header_view_1->ReorderChildView(header_view_1->children()[2], 0); + + EXPECT_EQ( + animating_layer_holding_view_1->layer()->parent()->children().size(), + original_layers_count_1); + EXPECT_TRUE(checker.destroyed()); + } } } // namespace ash
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc index 71a2cfd..053d30f 100644 --- a/ash/frame/header_view.cc +++ b/ash/frame/header_view.cc
@@ -291,13 +291,7 @@ if (!should_paint_ || !target_widget_) return; - bool paint_as_active = - target_widget_->non_client_view()->frame_view()->ShouldPaintAsActive(); - frame_header_->SetPaintAsActive(paint_as_active); - - FrameHeader::Mode header_mode = - paint_as_active ? FrameHeader::MODE_ACTIVE : FrameHeader::MODE_INACTIVE; - frame_header_->PaintHeader(canvas, header_mode); + frame_header_->PaintHeader(canvas); } void HeaderView::UpdateBackButton() {
diff --git a/ash/frame/non_client_frame_view_ash.cc b/ash/frame/non_client_frame_view_ash.cc index f3f7b7b..77c8eb06 100644 --- a/ash/frame/non_client_frame_view_ash.cc +++ b/ash/frame/non_client_frame_view_ash.cc
@@ -410,8 +410,7 @@ } void NonClientFrameViewAsh::PaintAsActiveChanged() { - // The icons differ between active and inactive. - header_view_->SchedulePaint(); + header_view_->GetFrameHeader()->SetPaintAsActive(ShouldPaintAsActive()); frame_->non_client_view()->Layout(); }
diff --git a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc index 882aefb8..9c87699dc 100644 --- a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc +++ b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
@@ -228,6 +228,7 @@ minimize_button_->set_paint_as_active(paint_as_active); size_button_->set_paint_as_active(paint_as_active); close_button_->set_paint_as_active(paint_as_active); + SchedulePaint(); } void FrameCaptionButtonContainerView::SetBackgroundColor(
diff --git a/ash/public/cpp/default_frame_header.cc b/ash/public/cpp/default_frame_header.cc index ab4518f..181707df 100644 --- a/ash/public/cpp/default_frame_header.cc +++ b/ash/public/cpp/default_frame_header.cc
@@ -25,6 +25,10 @@ namespace { +// Duration of animation scheduled when frame color is changed. +constexpr base::TimeDelta kFrameColorChangeAnimationDuration = + base::TimeDelta::FromMilliseconds(240); + // Tiles an image into an area, rounding the top corners. void TileRoundRect(gfx::Canvas* canvas, const cc::PaintFlags& flags, @@ -53,36 +57,6 @@ namespace ash { -DefaultFrameHeader::ColorAnimator::ColorAnimator( - gfx::AnimationDelegate* delegate) - : animation_(delegate) { - animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(240)); - animation_.SetTweenType(gfx::Tween::EASE_IN); - animation_.Reset(1); -} - -DefaultFrameHeader::ColorAnimator::ColorAnimator::~ColorAnimator() = default; - -void DefaultFrameHeader::ColorAnimator::SetTargetColor(SkColor target) { - target_color_ = target; - start_color_ = current_color_; - if (current_color_ == kDefaultFrameColor) { - // Changing from default should be set immediately. - current_color_ = target_color_; - animation_.Reset(1); - } else { - animation_.Reset(0); - } - animation_.Show(); -} - -SkColor DefaultFrameHeader::ColorAnimator::GetCurrentColor() { - current_color_ = - color_utils::AlphaBlend(target_color_, start_color_, - static_cast<float>(animation_.GetCurrentValue())); - return current_color_; -} - /////////////////////////////////////////////////////////////////////////////// // DefaultFrameHeader, public: @@ -90,9 +64,7 @@ views::Widget* target_widget, views::View* header_view, FrameCaptionButtonContainerView* caption_button_container) - : FrameHeader(target_widget, header_view), - active_frame_color_(this), - inactive_frame_color_(this) { + : FrameHeader(target_widget, header_view) { DCHECK(caption_button_container); SetCaptionButtonContainer(caption_button_container); } @@ -114,18 +86,19 @@ target_window->GetProperty(kFrameInactiveColorKey); bool updated = false; - if (active_frame_color_.target_color() != active_frame_color) { - active_frame_color_.SetTargetColor(active_frame_color); - updated = true; + // Update the frame if the frame color for the current active state chagnes. + if (active_frame_color_ != active_frame_color) { + active_frame_color_ = active_frame_color; + updated = mode() == Mode::MODE_ACTIVE; } - if (inactive_frame_color_.target_color() != inactive_frame_color) { - inactive_frame_color_.SetTargetColor(inactive_frame_color); - updated = true; + if (inactive_frame_color_ != inactive_frame_color) { + inactive_frame_color_ = inactive_frame_color; + updated |= mode() == Mode::MODE_INACTIVE; } if (updated) { UpdateCaptionButtonColors(); - view()->SchedulePaint(); + StartTransitionAnimation(kFrameColorChangeAnimationDuration); } } @@ -139,10 +112,8 @@ : 0; cc::PaintFlags flags; - flags.setColor(color_utils::AlphaBlend( - active_frame_color_.GetCurrentColor(), - inactive_frame_color_.GetCurrentColor(), - static_cast<float>(activation_animation().GetCurrentValue()))); + flags.setColor(mode() == Mode::MODE_ACTIVE ? active_frame_color_ + : inactive_frame_color_); flags.setAntiAlias(true); if (width_in_pixels_ > 0) { canvas->Save(); @@ -186,17 +157,11 @@ } SkColor DefaultFrameHeader::GetCurrentFrameColor() const { - return mode() == MODE_ACTIVE ? active_frame_color_.target_color() - : inactive_frame_color_.target_color(); -} - -gfx::SlideAnimation* -DefaultFrameHeader::GetAnimationForActiveFrameColorForTest() { - return active_frame_color_.animation(); + return mode() == MODE_ACTIVE ? active_frame_color_ : inactive_frame_color_; } SkColor DefaultFrameHeader::GetActiveFrameColorForPaintForTest() { - return active_frame_color_.GetCurrentColor(); + return active_frame_color_; } } // namespace ash
diff --git a/ash/public/cpp/default_frame_header.h b/ash/public/cpp/default_frame_header.h index b528ee2..67b8381e6 100644 --- a/ash/public/cpp/default_frame_header.h +++ b/ash/public/cpp/default_frame_header.h
@@ -26,12 +26,8 @@ FrameCaptionButtonContainerView* caption_button_container); ~DefaultFrameHeader() override; - SkColor active_frame_color_for_testing() { - return active_frame_color_.target_color(); - } - SkColor inactive_frame_color_for_testing() { - return inactive_frame_color_.target_color(); - } + SkColor active_frame_color_for_testing() { return active_frame_color_; } + SkColor inactive_frame_color_for_testing() { return inactive_frame_color_; } void SetWidthInPixels(int width_in_pixels); @@ -51,33 +47,10 @@ // Returns the window of the target widget. aura::Window* GetTargetWindow(); - gfx::SlideAnimation* GetAnimationForActiveFrameColorForTest(); SkColor GetActiveFrameColorForPaintForTest(); - // A utility class to animate color value. - class ColorAnimator { - public: - explicit ColorAnimator(gfx::AnimationDelegate* delegate); - ~ColorAnimator(); - - void SetTargetColor(SkColor target); - SkColor target_color() const { return target_color_; } - SkColor GetCurrentColor(); - float get_value() const { return animation_.GetCurrentValue(); } - - gfx::SlideAnimation* animation() { return &animation_; } - - private: - gfx::SlideAnimation animation_; - SkColor start_color_ = kDefaultFrameColor; - SkColor target_color_ = kDefaultFrameColor; - SkColor current_color_ = kDefaultFrameColor; - - DISALLOW_COPY_AND_ASSIGN(ColorAnimator); - }; - - ColorAnimator active_frame_color_; - ColorAnimator inactive_frame_color_; + SkColor active_frame_color_ = kDefaultFrameColor; + SkColor inactive_frame_color_ = kDefaultFrameColor; int width_in_pixels_ = -1;
diff --git a/ash/public/cpp/frame_header.cc b/ash/public/cpp/frame_header.cc index 97ad1644..6b549a4 100644 --- a/ash/public/cpp/frame_header.cc +++ b/ash/public/cpp/frame_header.cc
@@ -11,6 +11,9 @@ #include "ash/public/cpp/window_properties.h" #include "base/logging.h" // DCHECK #include "ui/base/class_property.h" +#include "ui/compositor/layer_animation_observer.h" +#include "ui/compositor/layer_tree_owner.h" +#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/font_list.h" @@ -29,6 +32,9 @@ namespace { +constexpr base::TimeDelta kFrameActivationAnimationDuration = + base::TimeDelta::FromMilliseconds(200); + DEFINE_UI_CLASS_PROPERTY_KEY(FrameHeader*, kFrameHeaderKey, nullptr) // Returns the available bounds for the header's title given the views to the @@ -61,29 +67,6 @@ return gfx::Rect(x, y, width, title_height); } -// Returns true if the header for |widget| can animate to new visuals when the -// widget's activation changes. Returns false if the header should switch to -// new visuals instantaneously. -bool CanAnimateActivation(views::Widget* widget) { - // Do not animate the header if the parent (e.g. the active desk container) is - // already animating. All of the implementers of FrameHeader animate - // activation by continuously painting during the animation. This gives the - // parent's animation a slower frame rate. - // TODO(sky): Expose a better way to determine this rather than assuming the - // parent is a toplevel container. - aura::Window* window = widget->GetNativeWindow(); - // TODO(sky): parent()->layer() is for mash until animations ported. - if (!window || !window->parent() || !window->parent()->layer()) - return true; - - ui::LayerAnimator* parent_layer_animator = - window->parent()->layer()->GetAnimator(); - return !parent_layer_animator->IsAnimatingProperty( - ui::LayerAnimationElement::OPACITY) && - !parent_layer_animator->IsAnimatingProperty( - ui::LayerAnimationElement::VISIBILITY); -} - } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -107,29 +90,102 @@ caption_button_container_->GetMinimumSize().width(); } -void FrameHeader::PaintHeader(gfx::Canvas* canvas, Mode mode) { - Mode old_mode = mode_; - mode_ = mode; - - if (mode_ != old_mode) { - UpdateCaptionButtonColors(); - - if (!initial_paint_ && CanAnimateActivation(target_widget_)) { - activation_animation_.SetSlideDuration( - base::TimeDelta::FromMilliseconds(200)); - if (mode_ == MODE_ACTIVE) - activation_animation_.Show(); - else - activation_animation_.Hide(); - } else { - if (mode_ == MODE_ACTIVE) - activation_animation_.Reset(1); - else - activation_animation_.Reset(0); - } - initial_paint_ = false; +// An invisible view that drives the frame's animation. This holds the animating +// layer as a layer beneath this view so that it's behind all other child layers +// of the window to avoid hiding their contents. +class FrameHeader::FrameAnimatorView : public views::View, + public views::ViewObserver, + public ui::ImplicitAnimationObserver { + public: + FrameAnimatorView(FrameHeader* frame_header, views::View* parent) + : frame_header_(frame_header), parent_(parent) { + SetPaintToLayer(ui::LAYER_NOT_DRAWN); + parent_->AddChildViewAt(this, 0); + parent_->AddObserver(this); + } + FrameAnimatorView(const FrameAnimatorView&) = delete; + FrameAnimatorView& operator=(const FrameAnimatorView&) = delete; + ~FrameAnimatorView() override { + StopAnimation(); + // A child view should always be removed first. + parent_->RemoveObserver(this); } + void StartAnimation(base::TimeDelta duration) { + StopAnimation(); + aura::Window* window = frame_header_->target_widget()->GetNativeWindow(); + + // Make sure the this view is at the bottom of root view's children. + parent_->ReorderChildView(this, 0); + + std::unique_ptr<ui::LayerTreeOwner> old_layer_owner = + std::make_unique<ui::LayerTreeOwner>(window->RecreateLayer()); + ui::Layer* old_layer = old_layer_owner->root(); + ui::Layer* new_layer = window->layer(); + new_layer->SetName(old_layer->name()); + old_layer->SetName(old_layer->name() + ":Old"); + old_layer->SetTransform(gfx::Transform()); + + layer_owner_ = std::move(old_layer_owner); + + AddLayerBeneathView(old_layer); + + // The old layer is on top and should fade out. + old_layer->SetOpacity(1.f); + new_layer->SetOpacity(1.f); + { + ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator()); + settings.SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + settings.AddObserver(this); + settings.SetTransitionDuration(duration); + old_layer->SetOpacity(0.f); + settings.SetTweenType(gfx::Tween::EASE_OUT); + } + } + + // views::Views: + const char* GetClassName() const override { return "FrameAnimatorView"; } + std::unique_ptr<ui::Layer> RecreateLayer() override { + // A layer may be recreated for another animation (maximize/restore). + // Just cancel the animation if that happens during animation. + StopAnimation(); + return views::View::RecreateLayer(); + } + + // ViewObserver:: + void OnChildViewReordered(views::View* observed_view, + views::View* child) override { + // Stop animation if the child view order has changed during animation. + StopAnimation(); + } + void OnViewBoundsChanged(views::View* observed_view) override { + // Stop animation if the frame size changed during animation. + StopAnimation(); + SetBoundsRect(parent_->GetLocalBounds()); + } + + // ui::ImplicitAnimationObserver overrides: + void OnImplicitAnimationsCompleted() override { + RemoveLayerBeneathView(layer_owner_->root()); + layer_owner_ = nullptr; + } + + private: + void StopAnimation() { + if (layer_owner_) { + layer_owner_->root()->GetAnimator()->StopAnimating(); + layer_owner_ = nullptr; + } + } + + FrameHeader* frame_header_; + views::View* parent_; + std::unique_ptr<ui::LayerTreeOwner> layer_owner_; +}; + +void FrameHeader::PaintHeader(gfx::Canvas* canvas) { + painted_ = true; DoPaintHeader(canvas); } @@ -157,6 +213,18 @@ } void FrameHeader::SetPaintAsActive(bool paint_as_active) { + // No need to animate if already active. + const bool already_active = (mode_ == Mode::MODE_ACTIVE); + + if (already_active == paint_as_active) + return; + + mode_ = paint_as_active ? MODE_ACTIVE : MODE_INACTIVE; + + // The frame has no content yet to animatie. + if (painted_) + StartTransitionAnimation(kFrameActivationAnimationDuration); + caption_button_container_->SetPaintAsActive(paint_as_active); if (back_button_) back_button_->set_paint_as_active(paint_as_active); @@ -199,22 +267,14 @@ } /////////////////////////////////////////////////////////////////////////////// -// gfx::AnimationDelegate overrides: - -void FrameHeader::AnimationProgressed(const gfx::Animation* animation) { - view_->SchedulePaintInRect(GetPaintedBounds()); -} - -/////////////////////////////////////////////////////////////////////////////// // FrameHeader, protected: FrameHeader::FrameHeader(views::Widget* target_widget, views::View* view) - : views::AnimationDelegateViews(view), - target_widget_(target_widget), - view_(view) { + : target_widget_(target_widget), view_(view) { DCHECK(target_widget); DCHECK(view); UpdateFrameHeaderKey(); + frame_animator_ = new FrameAnimatorView(this, view); } void FrameHeader::UpdateFrameHeaderKey() { @@ -269,6 +329,18 @@ LayoutHeaderInternal(); } +void FrameHeader::StartTransitionAnimation(base::TimeDelta duration) { + aura::Window* window = target_widget_->GetNativeWindow(); + // Don't start another animation if the window is already animating + // such as maximize/restore/unminimize. + if (window->layer()->GetAnimator()->is_animating()) + return; + + frame_animator_->StartAnimation(duration); + + frame_animator_->SchedulePaint(); +} + /////////////////////////////////////////////////////////////////////////////// // FrameHeader, private:
diff --git a/ash/public/cpp/frame_header.h b/ash/public/cpp/frame_header.h index 6f8165d..89ce587 100644 --- a/ash/public/cpp/frame_header.h +++ b/ash/public/cpp/frame_header.h
@@ -7,11 +7,12 @@ #include "ash/public/cpp/ash_public_export.h" #include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h" +#include "base/callback.h" +#include "base/optional.h" #include "base/strings/string16.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/ui_base_types.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/views/animation/animation_delegate_views.h" +#include "ui/compositor/layer_animation_observer.h" #include "ui/views/window/frame_caption_button.h" namespace gfx { @@ -29,13 +30,13 @@ class CaptionButtonModel; // Helper class for managing the window header. -class ASH_PUBLIC_EXPORT FrameHeader : public views::AnimationDelegateViews { +class ASH_PUBLIC_EXPORT FrameHeader { public: enum Mode { MODE_ACTIVE, MODE_INACTIVE }; static FrameHeader* Get(views::Widget* widget); - ~FrameHeader() override; + virtual ~FrameHeader(); const base::string16& frame_text_override() const { return frame_text_override_; @@ -45,7 +46,7 @@ int GetMinimumHeaderWidth() const; // Paints the header. - void PaintHeader(gfx::Canvas* canvas, Mode mode); + void PaintHeader(gfx::Canvas* canvas); // Performs layout for the header. void LayoutHeader(); @@ -81,9 +82,6 @@ // regardless of what ShouldShowWindowTitle() returns. void SetFrameTextOverride(const base::string16& frame_text_override); - // views::AnimationDelegateViews: - void AnimationProgressed(const gfx::Animation* animation) override; - void UpdateFrameHeaderKey(); views::View* view() { return view_; } @@ -112,19 +110,20 @@ Mode mode() const { return mode_; } - const gfx::SlideAnimation& activation_animation() { - return activation_animation_; - } - virtual void DoPaintHeader(gfx::Canvas* canvas) = 0; virtual views::CaptionButtonLayoutSize GetButtonLayoutSize() const = 0; virtual SkColor GetTitleColor() const = 0; virtual SkColor GetCurrentFrameColor() const = 0; + // Starts fade transition animation with given duration. + void StartTransitionAnimation(base::TimeDelta duration); + private: + class FrameAnimatorView; FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, BackButtonAlignment); FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, TitleIconAlignment); FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, FrameColors); + friend class FramePaintWaiter; void LayoutHeaderInternal(); @@ -139,20 +138,19 @@ views::FrameCaptionButton* back_button_ = nullptr; // May remain nullptr. views::View* left_header_view_ = nullptr; // May remain nullptr. FrameCaptionButtonContainerView* caption_button_container_ = nullptr; + FrameAnimatorView* frame_animator_ = nullptr; // owned by view tree. // The height of the header to paint. int painted_height_ = 0; + // Used to skip animation when the frame hasn't painted yet. + bool painted_ = false; + // Whether the header should be painted as active. Mode mode_ = MODE_INACTIVE; - // Whether the header is painted for the first time. - bool initial_paint_ = true; - base::string16 frame_text_override_; - gfx::SlideAnimation activation_animation_{this}; - DISALLOW_COPY_AND_ASSIGN(FrameHeader); };
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc index 6b5d9005..85b95805 100644 --- a/ash/system/overview/overview_button_tray.cc +++ b/ash/system/overview/overview_button_tray.cc
@@ -10,6 +10,7 @@ #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/style/ash_color_provider.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_container.h" #include "ash/wm/mru_window_tracker.h" @@ -36,7 +37,10 @@ icon_(new views::ImageView()), scoped_session_observer_(this) { gfx::ImageSkia image = gfx::CreateVectorIcon( - kShelfOverviewIcon, ShelfConfig::Get()->shelf_icon_color()); + kShelfOverviewIcon, + AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kButtonIconColor, + AshColorProvider::AshColorMode::kDark)); icon_->SetImage(image); const int vertical_padding = (kTrayItemSize - image.height()) / 2; const int horizontal_padding = (kTrayItemSize - image.width()) / 2;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 876ebc2b..123c099 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -740,6 +740,7 @@ "threading/scoped_thread_priority.cc", "threading/scoped_thread_priority.h", "threading/sequence_bound.h", + "threading/sequence_bound_internal.h", "threading/sequence_local_storage_map.cc", "threading/sequence_local_storage_map.h", "threading/sequence_local_storage_slot.cc",
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm index 001142a..10f2b97 100644 --- a/base/allocator/allocator_interception_mac.mm +++ b/base/allocator/allocator_interception_mac.mm
@@ -77,13 +77,14 @@ MACH_CHECK(result == KERN_SUCCESS, result) << "vm_region_64"; // The kernel always returns a null object for VM_REGION_BASIC_INFO_64, but - // balance it with a deallocate in case this ever changes. See 10.9.2 - // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. + // balance it with a deallocate in case this ever changes. See + // the VM_REGION_BASIC_INFO_64 case in vm_map_region() in 10.15's + // https://opensource.apple.com/source/xnu/xnu-6153.11.26/osfmk/vm/vm_map.c . mach_port_deallocate(mach_task_self(), unused); // Does the region fully enclose the zone pointers? Possibly unwarranted - // simplification used: using the size of a full version 8 malloc zone rather - // than the actual smaller size if the passed-in zone is not version 8. + // simplification used: using the size of a full version 10 malloc zone rather + // than the actual smaller size if the passed-in zone is not version 10. CHECK(*reprotection_start <= reinterpret_cast<vm_address_t>(default_zone)); vm_size_t zone_offset = reinterpret_cast<vm_address_t>(default_zone) - reinterpret_cast<vm_address_t>(*reprotection_start); @@ -147,8 +148,8 @@ size_t size) { void* result = g_old_zone.memalign(zone, alignment, size); // Only die if posix_memalign would have returned ENOMEM, since there are - // other reasons why NULL might be returned (see - // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). + // other reasons why null might be returned. See posix_memalign() in 10.15's + // https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c . if (!result && size && alignment >= sizeof(void*) && base::bits::IsPowerOfTwo(alignment)) { TerminateBecauseOutOfMemory(size); @@ -197,8 +198,8 @@ size_t size) { void* result = g_old_purgeable_zone.memalign(zone, alignment, size); // Only die if posix_memalign would have returned ENOMEM, since there are - // other reasons why NULL might be returned (see - // http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c ). + // other reasons why null might be returned. See posix_memalign() in 10.15's + // https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c . if (!result && size && alignment >= sizeof(void*) && base::bits::IsPowerOfTwo(alignment)) { TerminateBecauseOutOfMemory(size); @@ -363,11 +364,11 @@ // === C malloc/calloc/valloc/realloc/posix_memalign === // This approach is not perfect, as requests for amounts of memory larger than -// MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will -// still fail with a NULL rather than dying (see -// http://opensource.apple.com/source/Libc/Libc-583/gen/malloc.c for details). -// Unfortunately, it's the best we can do. Also note that this does not affect -// allocations from non-default zones. +// MALLOC_ABSOLUTE_MAX_SIZE (currently SIZE_T_MAX - (2 * PAGE_SIZE)) will still +// fail with a NULL rather than dying (see malloc_zone_malloc() in +// https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c for +// details). Unfortunately, it's the best we can do. Also note that this does +// not affect allocations from non-default zones. #if !defined(ADDRESS_SANITIZER) // Don't do anything special on OOM for the malloc zones replaced by
diff --git a/base/allocator/malloc_zone_functions_mac.cc b/base/allocator/malloc_zone_functions_mac.cc index a193cda..6c53042 100644 --- a/base/allocator/malloc_zone_functions_mac.cc +++ b/base/allocator/malloc_zone_functions_mac.cc
@@ -40,6 +40,10 @@ functions->free_definite_size = zone->free_definite_size; } + // Note that zone version 8 introduced a pressure relief callback, and version + // 10 introduced a claimed address callback, but neither are allocation or + // deallocation callbacks and so aren't important to intercept. + functions->context = zone; }
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index 6e41bae0..3fc7620 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h
@@ -325,8 +325,7 @@ constexpr BasicStringPiece substr( size_type pos, size_type n = BasicStringPiece::npos) const { - // TODO(crbug.com/1049498): Be less lenient here and CHECK(pos <= size()). - pos = std::min(pos, size()); + CHECK_LE(pos, size()); return {data() + pos, std::min(n, size() - pos)}; }
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc index 5540baaa..ee4e0cf0 100644 --- a/base/strings/string_piece_unittest.cc +++ b/base/strings/string_piece_unittest.cc
@@ -474,11 +474,7 @@ ASSERT_EQ(a.substr(23, 99), c); ASSERT_EQ(a.substr(0), a); ASSERT_EQ(a.substr(3, 2), TestFixture::as_string("de")); - // empty string nonsense - ASSERT_EQ(a.substr(99, 2), e); - ASSERT_EQ(d.substr(99), e); ASSERT_EQ(d.substr(0, 99), e); - ASSERT_EQ(d.substr(99, 99), e); } TYPED_TEST(CommonStringPieceTest, CheckCustom) { @@ -678,6 +674,11 @@ StringPiece piece; ASSERT_DEATH_IF_SUPPORTED(piece.remove_prefix(1), ""); } + + { + StringPiece piece; + ASSERT_DEATH_IF_SUPPORTED(piece.substr(1), ""); + } } TEST(StringPieceTest, ConstexprData) {
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h index da3fb07..3ec97a7a 100644 --- a/base/strings/string_util_internal.h +++ b/base/strings/string_util_internal.h
@@ -5,6 +5,8 @@ #ifndef BASE_STRINGS_STRING_UTIL_INTERNAL_H_ #define BASE_STRINGS_STRING_UTIL_INTERNAL_H_ +#include <algorithm> + #include "base/logging.h" #include "base/notreached.h" #include "base/strings/string_piece.h" @@ -130,7 +132,7 @@ size_t end = (positions & TRIM_TRAILING) ? input.find_last_not_of(trim_chars) + 1 : input.size(); - return input.substr(begin, end - begin); + return input.substr(std::min(begin, input.size()), end - begin); } template <typename STR>
diff --git a/base/threading/sequence_bound.h b/base/threading/sequence_bound.h index 3ee8ef6..217a1d53 100644 --- a/base/threading/sequence_bound.h +++ b/base/threading/sequence_bound.h
@@ -6,156 +6,196 @@ #define BASE_THREADING_SEQUENCE_BOUND_H_ #include <new> +#include <tuple> #include <type_traits> +#include <utility> #include "base/bind.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/location.h" #include "base/memory/aligned_memory.h" #include "base/memory/ptr_util.h" +#include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" +#include "base/threading/sequence_bound_internal.h" +#include "base/threading/sequenced_task_runner_handle.h" namespace base { -// SequenceBound facilitates owning objects that live on a specified sequence, -// which is potentially different than the owner's sequence. It encapsulates -// the work of posting tasks to the specified sequence to construct T, call -// methods on T, and destroy T. +// Performing blocking work on a different task runner is a common pattern for +// improving responsiveness of foreground task runners. `SequenceBound<T>` +// provides an abstraction for an owner object living on the owner sequence, to +// construct, call methods on, and destroy an object of type T that lives on a +// different sequence (the bound sequence). // -// It does not provide explicit access to the underlying object directly, to -// prevent accidentally using it from the wrong sequence. +// This makes it natural for code running on different sequences to be +// partitioned along class boundaries, e.g.: // -// Like std::unique_ptr<T>, a SequenceBound<T> may be moved between owners, -// and posted across threads. It may also be up-casted (only), to permit -// SequenceBound to be used with interfaces. +// class Tab { +// private: +// void OnScroll() { +// // ... +// io_helper_.AsyncCall(&IOHelper::SaveScrollPosition); +// } +// SequenceBound<IOHelper> io_helper_{GetBackgroundTaskRunner()}; +// }; // -// Basic usage looks like this: +// Note: `SequenceBound<T>` intentionally does not expose a raw pointer to the +// managed `T` to ensure its internal sequence-safety invariants are not +// violated. As a result, `AsyncCall()` cannot simply use `base::OnceCallback` // -// // Some class that lives on |main_task_runner|. -// class MyClass { +// SequenceBound also supports replies: +// +// class Database { // public: -// explicit MyClass(const char* widget_title) {} -// virtual ~MyClass() { ... } -// virtual void DoSomething(int arg) { ... } +// int Query(int value) { +// return value * value; +// } // }; // -// // On any thread... -// scoped_refptr<SequencedTaskRunner> main_task_runner = ...; -// auto widget = SequenceBound<MyClass>(main_task_runner, "My Title"); +// // SequenceBound itself is owned on `SequencedTaskRunnerHandle::Get()`. +// // The managed Database instance managed by it is constructed and owned on +// // `GetDBTaskRunner()`. +// SequenceBound<Database> db(GetDBTaskRunner()); // -// // Execute a single method on the object, on |main_task_runner|. -// widget.Post(FROM_HERE, &MyClass::DoSomething, 1234); -// -// // Execute an arbitrary task on |main_task_runner| with a non-const pointer -// // to the object. -// widget.PostTaskWithThisObject( -// FROM_HERE, -// base::BindOnce([](MyClass* widget) { -// // Unlike with Post, we can issue multiple calls on |widget| within -// // the same stack frame. -// widget->DoSomething(42); -// widget->DoSomething(13); -// })); -// -// // Execute an arbitrary task on |main_task_runner| with a const reference -// // to the object. -// widget.PostTaskWithThisObject( -// FROM_HERE, -// base::BindOnce([](const MyClass& widget) { ... })); -// -// Note that |widget| is constructed asynchronously on |main_task_runner|, -// but calling Post() immediately is safe, since the actual call is posted -// to |main_task_runner| as well. -// -// |widget| will be deleted on |main_task_runner| asynchronously when it goes -// out of scope, or when Reset() is called. -// -// Here is a more complicated example that shows injection and upcasting: -// -// // Some unrelated class that uses a |MyClass| to do something. -// class SomeConsumer { -// public: -// // Note that ownership of |widget| is given to us! -// explicit SomeConsumer(SequenceBound<MyClass> widget) -// : widget_(std::move(widget)) { ... } -// -// ~SomeConsumer() { -// // |widget_| will be destroyed on the associated task runner. -// } -// -// SequenceBound<MyClass> widget_; +// // `Database::Query()` runs on `GetDBTaskRunner()`, but +// // `reply_callback` will run on the owner task runner. +// auto reply_callback = [] (int result) { +// LOG(ERROR) << result; // Prints 25. // }; +// db.AsyncCall(&Database::Query).WithArgs(5) +// .Then(base::BindOnce(reply_callback)); // -// // Implementation of MyClass. -// class MyDerivedClass : public MyClass { ... }; +// // When `db` goes out of scope, the Database instance will also be +// // destroyed via a task posted to `GetDBTaskRunner()`. // -// auto widget = -// SequenceBound<MyDerivedClass>(main_task_runner, ctor args); -// auto c = new SomeConsumer(std::move(widget)); // upcasts to MyClass - +// TODO(dcheng): SequenceBound should only be constructed, used, and destroyed +// on a single sequence. This enforcement will gradually be enabled over time. template <typename T> class SequenceBound { public: - // Allow explicit null. + // Note: on construction, SequenceBound binds to the current sequence. Any + // subsequent SequenceBound calls (including destruction) must run on that + // same sequence. + + // Constructs a null SequenceBound with no managed `T`. + // TODO(dcheng): Add an `Emplace()` method to go with `Reset()`. SequenceBound() = default; - // Construct a new instance of |T| that will be accessed only on - // |task_runner|. One may post calls to it immediately upon return. - // This is marked as NO_SANITIZE because cfi doesn't like that we're casting - // uninitialized memory to a |T*|. However, it's safe since (a) the cast is - // defined (see http://eel.is/c++draft/basic.life#6 for details), and (b) we - // don't use the resulting pointer in any way that requries it to be - // constructed, except by posting such a access to |impl_task_runner_| after - // posting construction there as well. + // Schedules asynchronous construction of a new instance of `T` on + // `task_runner`. + // + // Once the SequenceBound constructor completes, the caller can immediately + // use `AsyncCall()`, et cetera, to schedule work after the construction of + // `T` on `task_runner`. + // + // Marked NO_SANITIZE because cfi doesn't like casting uninitialized memory to + // `T*`. However, this is safe here because: + // + // 1. The cast is well-defined (see https://eel.is/c++draft/basic.life#6) and + // 2. The resulting pointer is only ever dereferenced on `impl_task_runner_`. + // By the time SequenceBound's constructor returns, the task to construct + // `T` will already be posted; thus, subsequent dereference of `t_` on + // `impl_task_runner_` are safe. template <typename... Args> NO_SANITIZE("cfi-unrelated-cast") SequenceBound(scoped_refptr<base::SequencedTaskRunner> task_runner, Args&&... args) : impl_task_runner_(std::move(task_runner)) { - // Allocate space for but do not construct an instance of |T|. + // Allocate space for but do not construct an instance of `T`. // AlignedAlloc() requires alignment be a multiple of sizeof(void*). storage_ = AlignedAlloc( sizeof(T), sizeof(void*) > alignof(T) ? sizeof(void*) : alignof(T)); t_ = reinterpret_cast<T*>(storage_); - // Post construction to the impl thread. + // Ensure that `t_` will be initialized impl_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ConstructOwnerRecord<Args...>, base::Unretained(t_), std::forward<Args>(args)...)); } + // If non-null, destruction of the managed `T` is posted to + // `impl_task_runner_`.` ~SequenceBound() { Reset(); } - // Move construction from the same type can just take the pointer without - // adjusting anything. This is required in addition to the move conversion - // constructor below. + // Disallow copy or assignment. SequenceBound has single ownership of the + // managed `T`. + SequenceBound(const SequenceBound&) = delete; + SequenceBound& operator=(const SequenceBound&) = delete; + + // Move construction and assignment. SequenceBound(SequenceBound&& other) { MoveRecordFrom(other); } - // Move construction is supported from any type that's compatible with |T|. - // This case handles |From| != |T|, so we must adjust the pointer offset. + SequenceBound& operator=(SequenceBound&& other) { + Reset(); + MoveRecordFrom(other); + return *this; + } + + // Move conversion helpers: allows upcasting from SequenceBound<Derived> to + // SequenceBound<Base>. template <typename From> SequenceBound(SequenceBound<From>&& other) { MoveRecordFrom(other); } - SequenceBound& operator=(SequenceBound&& other) { - // Clean up any object we currently own. - Reset(); - MoveRecordFrom(other); - return *this; - } - template <typename From> SequenceBound<T>& operator=(SequenceBound<From>&& other) { - // Clean up any object that we currently own. Reset(); MoveRecordFrom(other); return *this; } - // Post a call to |method| to |impl_task_runner_|. + // Invokes `method` of the managed `T` on `impl_task_runner_`. May only be + // used when `is_null()` is false. + // + // Basic usage: + // + // helper.AsyncCall(&IOHelper::DoWork); + // + // If `method` accepts arguments, use of `WithArgs()` to bind them is + // mandatory: + // + // helper.AsyncCall(&IOHelper::DoWorkWithArgs).WithArgs(args); + // + // Optionally, use `Then()` to chain to a callback on the owner sequence after + // `method` completes. If `method` returns a non-void type, the return value + // will be passed to the chained callback. + // + // helper.AsyncCall(&IOHelper::GetValue).Then(std::move(process_result)); + // + // `WithArgs()` and `Then()` may also be combined: + // + // helper.AsyncCall(&IOHelper::GetValueWithArgs).WithArgs(args) + // .Then(std::move(process_result)); + // + // but note that ordering is strict: `Then()` must always be last. + // + // Note: internally, this is implemented using a series of templated builders. + // Destruction of the builder may trigger task posting; as a result, using the + // builder as anything other than a temporary is not allowed. + // + // Similarly, triggering lifetime extension of the temporary (e.g. by binding + // to a const lvalue reference) is not allowed. + template <typename R, typename... Args> + auto AsyncCall(R (T::*method)(Args...), + const Location& location = Location::Current()) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return AsyncCallBuilder<R (T::*)(Args...)>(this, &location, method); + } + + template <typename R, typename... Args> + auto AsyncCall(R (T::*method)(Args...) const, + const Location& location = Location::Current()) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return AsyncCallBuilder<R (T::*)(Args...) const>(this, &location, method); + } + + // Post a call to `method` to `impl_task_runner_`. + // TODO(dcheng): Deprecate this in favor of `AsyncCall()`. template <typename... MethodArgs, typename... Args> void Post(const base::Location& from_here, void (T::*method)(MethodArgs...), @@ -166,7 +206,7 @@ std::forward<Args>(args)...)); } - // Posts |task| to |impl_task_runner_|, passing it a reference to the wrapped + // Posts `task` to `impl_task_runner_`, passing it a reference to the wrapped // object. This allows arbitrary logic to be safely executed on the object's // task runner. The object is guaranteed to remain alive for the duration of // the task. @@ -194,17 +234,12 @@ // TODO(liberato): Add PostOrCall(), to support cases where synchronous calls // are okay if it's the same task runner. - // TODO(liberato): Add PostAndReply() - - // TODO(liberato): Allow creation of callbacks that bind to a weak pointer, - // and thread-hop to |impl_task_runner_| if needed. - - // Post destruction of any object we own, and return to the null state. + // Resets `this` to null. If `this` is not currently null, posts destruction + // of the managed `T` to `impl_task_runner_`. void Reset() { if (is_null()) return; - // Destruct the object on the impl thread. impl_task_runner_->PostTask( FROM_HERE, base::BindOnce(&DeleteOwnerRecord, base::Unretained(t_), base::Unretained(storage_))); @@ -216,7 +251,12 @@ // Same as above, but allows the caller to provide a closure to be invoked // immediately after destruction. The Closure is invoked on - // |impl_task_runner_|, iff the owned object was non-null. + // `impl_task_runner_`, iff the owned object was non-null. + // + // TODO(dcheng): Consider removing this; this appears to be used for test + // synchronization, but that could be achieved by posting + // `run_loop.QuitClosure()` to the destination sequence after calling + // `Reset()`. void ResetWithCallbackAfterDestruction(base::OnceClosure callback) { if (is_null()) return; @@ -234,66 +274,370 @@ storage_ = nullptr; } - // Return whether we own anything. Note that this does not guarantee that any - // previously owned object has been destroyed. In particular, it will return - // true immediately after a call to Reset(), though the underlying object - // might still be pending destruction on the impl thread. + // Return true if `this` is logically null; otherwise, returns false. + // + // A SequenceBound is logically null if there is no managed `T`; it is only + // valid to call `AsyncCall()` on a non-null SequenceBound. + // + // Note that the concept of 'logically null' here does not exactly match the + // lifetime of `T`, which lives on `impl_task_runner_`. In particular, when + // SequenceBound is first constructed, `is_null()` may return false, even + // though the lifetime of `T` may not have begun yet on `impl_task_runner_`. + // Similarly, after `SequenceBound::Reset()`, `is_null()` may return true, + // even though the lifetime of `T` may not have ended yet on + // `impl_task_runner_`. bool is_null() const { return !t_; } - // True if and only if we have an object, with the same caveats as is_null(). + // True if `this` is not logically null. See `is_null()`. explicit operator bool() const { return !is_null(); } private: - // Move everything from |other|, doing pointer adjustment as needed. - // This method is marked as NO_SANITIZE since (a) it might run before the - // posted ctor runs on |impl_task_runner_|, and (b) implicit conversions to - // non-virtual base classes are allowed before construction by the standard. - // See http://eel.is/c++draft/basic.life#6 for more information. - template <typename From> - void NO_SANITIZE("cfi-unrelated-cast") MoveRecordFrom(From&& other) { - // |other| might be is_null(), but that's okay. - impl_task_runner_ = std::move(other.impl_task_runner_); - - // Note that static_cast<> isn't, in general, safe, since |other| might not - // be constructed yet. Implicit conversion is supported, as long as it - // doesn't convert to a virtual base. Of course, it allows only upcasts. - t_ = other.t_; - - // The original storage is kept unmodified, so we can free it later. - storage_ = other.storage_; - - other.storage_ = nullptr; - other.t_ = nullptr; - } - - // Pointer to the object, Pointer may be modified on the owning thread. - T* t_ = nullptr; - - // Original allocated storage for the object. - void* storage_ = nullptr; - - // The task runner on which all access to |t_| should happen. - scoped_refptr<base::SequencedTaskRunner> impl_task_runner_; - // For move conversion. template <typename U> friend class SequenceBound; - // Run on impl thread to construct |t|'s storage. + // Support helpers for `AsyncCall()` implementation. + // + // Several implementation notes: + // 1. Tasks are posted via destroying the builder or an explicit call to + // `Then()`. + // + // 2. A builder may be consumed by: + // + // - calling `Then()`, which immediately posts the task chain + // - calling `WithArgs()`, which returns a new builder with the captured + // arguments + // + // Builders that are consumed have the internal `sequence_bound_` field + // nulled out; the hope is the compiler can see this and use it to + // eliminate dead branches (e.g. correctness checks that aren't needed + // since the code can be statically proved correct). + // + // 3. Builder methods are rvalue-qualified to try to enforce that the builder + // is only used as a temporary. Note that this only helps so much; nothing + // prevents a determined caller from using `std::move()` to force calls to + // a non-temporary instance. + // + // TODO(dcheng): It might also be possible to use Gmock-style matcher + // composition, e.g. something like: + // + // sb.AsyncCall(&Helper::DoWork, WithArgs(args), + // Then(std::move(process_result)); + // + // In theory, this might allow the elimination of magic destructors and + // better static checking by the compiler. + template <typename MethodPtrType> + class AsyncCallBuilderBase { + protected: + AsyncCallBuilderBase(SequenceBound* sequence_bound, + const Location* location, + MethodPtrType method) + : sequence_bound_(sequence_bound), + location_(location), + method_(method) { + // Common entry point for `AsyncCall()`, so check preconditions here. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_bound_->sequence_checker_); + DCHECK(sequence_bound_->t_); + } + + AsyncCallBuilderBase(AsyncCallBuilderBase&&) = default; + AsyncCallBuilderBase& operator=(AsyncCallBuilderBase&&) = default; + + // `sequence_bound_` is consumed and set to `nullptr` when `Then()` is + // invoked. This is used as a flag for two potential states + // + // - if a method returns void, invoking `Then()` is optional. The destructor + // will check if `sequence_bound_` is null; if it is, `Then()` was + // already invoked and the task chain has already been posted, so the + // destructor does not need to do anything. Otherwise, the destructor + // needs to post the task to make the async call. In theory, the compiler + // should be able to eliminate this branch based on the presence or + // absence of a call to `Then()`. + // + // - if a method returns a non-void type, `Then()` *must* be invoked. The + // destructor will `CHECK()` if `sequence_bound_` is non-null, since that + // indicates `Then()` was not invoked. Similarly, note this branch should + // be eliminated by the optimizer if the code is free of bugs. :) + SequenceBound* sequence_bound_; + // Subtle: this typically points at a Location *temporary*. This is used to + // try to detect errors resulting from lifetime extension of the async call + // factory temporaries, since the factory destructors can perform work. If + // the lifetime of the factory is incorrectly extended, dereferencing + // `location_` will trigger a stack-use-after-scope when running with ASan. + const Location* const location_; + MethodPtrType method_; + }; + + template <typename MethodPtrType, typename ReturnType, typename... Args> + class AsyncCallBuilderImpl; + + // Selected method has no arguments and returns void. + template <typename MethodPtrType> + class AsyncCallBuilderImpl<MethodPtrType, void, std::tuple<>> + : public AsyncCallBuilderBase<MethodPtrType> { + public: + // Note: despite being here, this is actually still protected, since it is + // protected on the base class. + using AsyncCallBuilderBase<MethodPtrType>::AsyncCallBuilderBase; + + ~AsyncCallBuilderImpl() { + if (this->sequence_bound_) { + this->sequence_bound_->impl_task_runner_->PostTask( + *this->location_, + BindOnce(this->method_, Unretained(this->sequence_bound_->t_))); + } + } + + void Then(OnceClosure then_callback) && { + this->sequence_bound_->PostTaskAndThenHelper( + *this->location_, + BindOnce(this->method_, Unretained(this->sequence_bound_->t_)), + std::move(then_callback)); + this->sequence_bound_ = nullptr; + } + + private: + friend SequenceBound; + + AsyncCallBuilderImpl(AsyncCallBuilderImpl&&) = default; + AsyncCallBuilderImpl& operator=(AsyncCallBuilderImpl&&) = default; + }; + + // Selected method has no arguments and returns non-void. + template <typename MethodPtrType, typename ReturnType> + class AsyncCallBuilderImpl<MethodPtrType, ReturnType, std::tuple<>> + : public AsyncCallBuilderBase<MethodPtrType> { + public: + // Note: despite being here, this is actually still protected, since it is + // protected on the base class. + using AsyncCallBuilderBase<MethodPtrType>::AsyncCallBuilderBase; + + ~AsyncCallBuilderImpl() { + // Must use Then() since the method's return type is not void. + // Should be optimized out if the code is bug-free. + CHECK(!this->sequence_bound_) + << "Then() not invoked for a method that returns a non-void type; " + << "make sure to invoke Then() or use base::IgnoreResult()"; + } + + template <template <typename> class CallbackType, + typename ThenArg, + typename = EnableIfIsBaseCallback<CallbackType>> + void Then(CallbackType<void(ThenArg)> then_callback) && { + this->sequence_bound_->PostTaskAndThenHelper( + *this->location_, + BindOnce(this->method_, Unretained(this->sequence_bound_->t_)), + std::move(then_callback)); + this->sequence_bound_ = nullptr; + } + + private: + friend SequenceBound; + + AsyncCallBuilderImpl(AsyncCallBuilderImpl&&) = default; + AsyncCallBuilderImpl& operator=(AsyncCallBuilderImpl&&) = default; + }; + + // Selected method has arguments. Return type can be void or non-void. + template <typename MethodPtrType, typename ReturnType, typename... Args> + class AsyncCallBuilderImpl<MethodPtrType, ReturnType, std::tuple<Args...>> + : public AsyncCallBuilderBase<MethodPtrType> { + public: + // Note: despite being here, this is actually still protected, since it is + // protected on the base class. + using AsyncCallBuilderBase<MethodPtrType>::AsyncCallBuilderBase; + + ~AsyncCallBuilderImpl() { + // Must use WithArgs() since the method takes arguments. + // Should be optimized out if the code is bug-free. + CHECK(!this->sequence_bound_); + } + + template <typename... BoundArgs> + auto WithArgs(BoundArgs&&... bound_args) { + SequenceBound* const sequence_bound = + std::exchange(this->sequence_bound_, nullptr); + return AsyncCallWithBoundArgsBuilder<ReturnType>( + sequence_bound, this->location_, + BindOnce(this->method_, Unretained(sequence_bound->t_), + std::forward<BoundArgs>(bound_args)...)); + } + + private: + friend SequenceBound; + + AsyncCallBuilderImpl(AsyncCallBuilderImpl&&) = default; + AsyncCallBuilderImpl& operator=(AsyncCallBuilderImpl&&) = default; + }; + + template <typename MethodPtrType, + typename R = internal::ExtractMethodReturnType<MethodPtrType>, + typename ArgsTuple = + internal::ExtractMethodArgsTuple<MethodPtrType>> + using AsyncCallBuilder = AsyncCallBuilderImpl<MethodPtrType, R, ArgsTuple>; + + // Support factories when arguments are bound using `WithArgs()`. These + // factories don't need to handle raw method pointers, since everything has + // already been packaged into a base::OnceCallback. + template <typename ReturnType> + class AsyncCallWithBoundArgsBuilderBase { + protected: + AsyncCallWithBoundArgsBuilderBase(SequenceBound* sequence_bound, + const Location* location, + base::OnceCallback<ReturnType()> callback) + : sequence_bound_(sequence_bound), + location_(location), + callback_(std::move(callback)) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_bound_->sequence_checker_); + DCHECK(sequence_bound_->t_); + } + + // Subtle: the internal helpers rely on move elision. Preventing move + // elision (e.g. using `std::move()` when returning the temporary) will + // trigger a `CHECK()` since `sequence_bound_` is not reset to nullptr on + // move. + AsyncCallWithBoundArgsBuilderBase( + AsyncCallWithBoundArgsBuilderBase&&) noexcept = default; + AsyncCallWithBoundArgsBuilderBase& operator=( + AsyncCallWithBoundArgsBuilderBase&&) noexcept = default; + + SequenceBound* sequence_bound_; + const Location* const location_; + base::OnceCallback<ReturnType()> callback_; + }; + + // Note: this doesn't handle a void return type, which has an explicit + // specialization below. + template <typename ReturnType> + class AsyncCallWithBoundArgsBuilder + : public AsyncCallWithBoundArgsBuilderBase<ReturnType> { + public: + ~AsyncCallWithBoundArgsBuilder() { + // Must use Then() since the method's return type is not void. + // Should be optimized out if the code is bug-free. + CHECK(!this->sequence_bound_); + } + + template <template <typename> class CallbackType, + typename ThenArg, + typename = EnableIfIsBaseCallback<CallbackType>> + void Then(CallbackType<void(ThenArg)> then_callback) && { + this->sequence_bound_->PostTaskAndThenHelper(*this->location_, + std::move(this->callback_), + std::move(then_callback)); + this->sequence_bound_ = nullptr; + } + + protected: + using AsyncCallWithBoundArgsBuilderBase< + ReturnType>::AsyncCallWithBoundArgsBuilderBase; + + private: + friend SequenceBound; + + AsyncCallWithBoundArgsBuilder(AsyncCallWithBoundArgsBuilder&&) = default; + AsyncCallWithBoundArgsBuilder& operator=(AsyncCallWithBoundArgsBuilder&&) = + default; + }; + + template <> + class AsyncCallWithBoundArgsBuilder<void> + : public AsyncCallWithBoundArgsBuilderBase<void> { + public: + // Note: despite being here, this is actually still protected, since it is + // protected on the base class. + using AsyncCallWithBoundArgsBuilderBase< + void>::AsyncCallWithBoundArgsBuilderBase; + + ~AsyncCallWithBoundArgsBuilder() { + if (this->sequence_bound_) { + this->sequence_bound_->impl_task_runner_->PostTask( + *this->location_, std::move(this->callback_)); + } + } + + void Then(OnceClosure then_callback) && { + this->sequence_bound_->PostTaskAndThenHelper(*this->location_, + std::move(this->callback_), + std::move(then_callback)); + this->sequence_bound_ = nullptr; + } + + private: + friend SequenceBound; + + AsyncCallWithBoundArgsBuilder(AsyncCallWithBoundArgsBuilder&&) = default; + AsyncCallWithBoundArgsBuilder& operator=(AsyncCallWithBoundArgsBuilder&&) = + default; + }; + + void PostTaskAndThenHelper(const Location& location, + OnceCallback<void()> callback, + OnceClosure then_callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + impl_task_runner_->PostTaskAndReply(location, std::move(callback), + std::move(then_callback)); + } + + template <typename ReturnType, + template <typename> + class CallbackType, + typename ThenArg, + typename = EnableIfIsBaseCallback<CallbackType>> + void PostTaskAndThenHelper(const Location& location, + OnceCallback<ReturnType()> callback, + CallbackType<void(ThenArg)> then_callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnceCallback<void(ThenArg)>&& once_then_callback = std::move(then_callback); + impl_task_runner_->PostTaskAndReplyWithResult( + location, std::move(callback), std::move(once_then_callback)); + } + + // Helper to support move construction and move assignment. + // + // Marked NO_SANITIZE since: + // 1. SequenceBound can be moved before `t_` is constructed on + // `impl_task_runner_` but + // 2. Implicit conversions to non-virtual base classes are allowed before the + // lifetime of `t_` has started (see https://eel.is/c++draft/basic.life#6). + template <typename From> + void NO_SANITIZE("cfi-unrelated-cast") MoveRecordFrom(From&& other) { + // TODO(dcheng): Consider adding a static_assert to provide a friendlier + // error message. + impl_task_runner_ = std::move(other.impl_task_runner_); + + // Subtle: this must not use static_cast<>, since the lifetime of the + // managed `T` may not have begun yet. However, the standard explicitly + // still allows implicit conversion to a non-virtual base class. + t_ = std::exchange(other.t_, nullptr); + storage_ = std::exchange(other.storage_, nullptr); + } + + // Pointer to the managed `T`. This field is only read and written on + // the sequence associated with `sequence_checker_`. + T* t_ = nullptr; + + // Storage originally allocated by `AlignedAlloc()`. Maintained separately + // from `t_` since the original, unadjusted pointer needs to be passed to + // `AlignedFree()`. + void* storage_ = nullptr; + + SEQUENCE_CHECKER(sequence_checker_); + + // Task runner which manages `t_`. `t_` is constructed, destroyed, and + // dereferenced only on this task runner. + scoped_refptr<base::SequencedTaskRunner> impl_task_runner_; + + // Helpers for constructing and destroying `T` on `impl_task_runner_`. template <typename... Args> static void ConstructOwnerRecord(T* t, std::decay_t<Args>&&... args) { new (t) T(std::move(args)...); } - // Destruct the object associated with |t|, and delete |storage|. static void DeleteOwnerRecord(T* t, void* storage) { t->~T(); AlignedFree(storage); } - - // To preserve ownership semantics, we disallow copy construction / copy - // assignment. Move construction / assignment is fine. - DISALLOW_COPY_AND_ASSIGN(SequenceBound); }; } // namespace base
diff --git a/base/threading/sequence_bound_internal.h b/base/threading/sequence_bound_internal.h new file mode 100644 index 0000000..c3d3c3f --- /dev/null +++ b/base/threading/sequence_bound_internal.h
@@ -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. + +#ifndef BASE_THREADING_SEQUENCE_BOUND_INTERNAL_H_ +#define BASE_THREADING_SEQUENCE_BOUND_INTERNAL_H_ + +#include <tuple> + +#include "base/compiler_specific.h" + +namespace base { + +namespace internal { + +// Helpers to simplify sharing templates between non-const and const methods. +// Normally, matching against a method pointer type requires defining both a +// `R (T::*)(Args...)` and a `R (T::*)(Args...) const` overload of the template +// function. Rather than doing that, these helpers allow extraction of `R` and +// `Args...` from a method pointer type deduced as `MethodPointerType`. + +template <typename MethodPtrType> +struct MethodTraits; + +template <typename R, typename T, typename... Args> +struct MethodTraits<R (T::*)(Args...)> { + using ReturnType = R; + using ArgsTuple = std::tuple<Args...>; +}; + +template <typename R, typename T, typename... Args> +struct MethodTraits<R (T::*)(Args...) const> { + using ReturnType = R; + using ArgsTuple = std::tuple<Args...>; +}; + +template <typename MethodPtrType> +using ExtractMethodReturnType = + typename MethodTraits<MethodPtrType>::ReturnType; + +template <typename MethodPtrType> +using ExtractMethodArgsTuple = typename MethodTraits<MethodPtrType>::ArgsTuple; + +} // namespace internal + +} // namespace base + +#endif // BASE_THREADING_SEQUENCE_BOUND_INTERNAL_H_
diff --git a/base/threading/sequence_bound_unittest.cc b/base/threading/sequence_bound_unittest.cc index ecf0e3543..1b75d1b 100644 --- a/base/threading/sequence_bound_unittest.cc +++ b/base/threading/sequence_bound_unittest.cc
@@ -4,11 +4,13 @@ #include "base/threading/sequence_bound.h" +#include <utility> + #include "base/macros.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" #include "base/test/task_environment.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -30,9 +32,13 @@ kOtherDtorValue = 444, }; - void SetUp() override { task_runner_ = base::ThreadTaskRunnerHandle::Get(); } - - void TearDown() override { task_environment_.RunUntilIdle(); } + void TearDown() override { + // Make sure that any objects owned by `SequenceBound` have been destroyed + // to avoid tripping leak detection. + RunLoop run_loop; + task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + } // Do-nothing base class, just so we can test assignment of derived classes. // It introduces a virtual destructor, so that casting derived classes to @@ -66,10 +72,14 @@ MultiplyDerived(Value* ptr1, Value* ptr2) : Other(ptr1), Derived(ptr2) {} }; + // TODO(dcheng): This isn't used, but upcasting to a virtual base class is + // unsafe and is currently unchecked! Add these safety checks back in. struct VirtuallyDerived : public virtual Base {}; base::test::TaskEnvironment task_environment_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> task_runner_ = + base::SequencedTaskRunnerHandle::Get(); + Value value_ = kInitialValue; }; @@ -397,4 +407,275 @@ // Test passes if SequenceBound constructor does not crash in AlignedAlloc(). } +TEST_F(SequenceBoundTest, SelfMoveAssign) { + class EmptyClass {}; + SequenceBound<EmptyClass> value(task_runner_); + EXPECT_FALSE(value.is_null()); + // Clang has a warning for self-move, so be clever. + auto& actually_the_same_value = value; + value = std::move(actually_the_same_value); + // Note: in general, moved-from objects are in a valid but undefined state. + // This is merely a test that self-move doesn't result in something bad + // happening; this is not an assertion that self-move will always have this + // behavior. + EXPECT_TRUE(value.is_null()); +} + +namespace { + +class NoArgsVoidReturn { + public: + void Method() { + if (loop_) + loop_->Quit(); + } + void ConstMethod() const { + if (loop_) + loop_->Quit(); + } + + void set_loop(RunLoop* loop) { loop_ = loop; } + + private: + RunLoop* loop_ = nullptr; +}; + +class NoArgsIntReturn { + public: + int Method() { return 123; } + int ConstMethod() const { return 456; } +}; + +class IntArgVoidReturn { + public: + IntArgVoidReturn(int* method_called_with, int* const_method_called_with) + : method_called_with_(method_called_with), + const_method_called_with_(const_method_called_with) {} + + void Method(int x) { + *method_called_with_ = x; + if (loop_) + loop_->Quit(); + } + void ConstMethod(int x) const { + *const_method_called_with_ = x; + if (loop_) + loop_->Quit(); + } + + void set_loop(RunLoop* loop) { loop_ = loop; } + + private: + int* const method_called_with_; + int* const const_method_called_with_; + + RunLoop* loop_ = nullptr; +}; + +class IntArgIntReturn { + public: + int Method(int x) { return -x; } + int ConstMethod(int x) const { return -x; } +}; + +} // namespace + +TEST_F(SequenceBoundTest, AsyncCallNoArgsNoThen) { + SequenceBound<NoArgsVoidReturn> s(task_runner_); + + { + RunLoop loop; + s.AsyncCall(&NoArgsVoidReturn::set_loop).WithArgs(&loop); + s.AsyncCall(&NoArgsVoidReturn::Method); + loop.Run(); + } + + { + RunLoop loop; + s.AsyncCall(&NoArgsVoidReturn::set_loop).WithArgs(&loop); + s.AsyncCall(&NoArgsVoidReturn::ConstMethod); + loop.Run(); + } +} + +TEST_F(SequenceBoundTest, AsyncCallIntArgNoThen) { + int method_called_with = 0; + int const_method_called_with = 0; + SequenceBound<IntArgVoidReturn> s(task_runner_, &method_called_with, + &const_method_called_with); + + { + RunLoop loop; + s.AsyncCall(&IntArgVoidReturn::set_loop).WithArgs(&loop); + s.AsyncCall(&IntArgVoidReturn::Method).WithArgs(123); + loop.Run(); + EXPECT_EQ(123, method_called_with); + } + + { + RunLoop loop; + s.AsyncCall(&IntArgVoidReturn::set_loop).WithArgs(&loop); + s.AsyncCall(&IntArgVoidReturn::ConstMethod).WithArgs(456); + loop.Run(); + EXPECT_EQ(456, const_method_called_with); + } +} + +TEST_F(SequenceBoundTest, AsyncCallNoArgsVoidThen) { + SequenceBound<NoArgsVoidReturn> s(task_runner_); + + { + RunLoop loop; + s.AsyncCall(&NoArgsVoidReturn::Method).Then(BindLambdaForTesting([&]() { + loop.Quit(); + })); + loop.Run(); + } + + { + RunLoop loop; + s.AsyncCall(&NoArgsVoidReturn::ConstMethod) + .Then(BindLambdaForTesting([&]() { loop.Quit(); })); + loop.Run(); + } +} + +TEST_F(SequenceBoundTest, AsyncCallNoArgsIntThen) { + SequenceBound<NoArgsIntReturn> s(task_runner_); + + { + RunLoop loop; + s.AsyncCall(&NoArgsIntReturn::Method) + .Then(BindLambdaForTesting([&](int result) { + EXPECT_EQ(123, result); + loop.Quit(); + })); + loop.Run(); + } + + { + RunLoop loop; + s.AsyncCall(&NoArgsIntReturn::ConstMethod) + .Then(BindLambdaForTesting([&](int result) { + EXPECT_EQ(456, result); + loop.Quit(); + })); + loop.Run(); + } +} + +TEST_F(SequenceBoundTest, AsyncCallWithArgsVoidThen) { + int method_called_with = 0; + int const_method_called_with = 0; + SequenceBound<IntArgVoidReturn> s(task_runner_, &method_called_with, + &const_method_called_with); + + { + RunLoop loop; + s.AsyncCall(&IntArgVoidReturn::Method) + .WithArgs(123) + .Then(BindLambdaForTesting([&] { loop.Quit(); })); + loop.Run(); + EXPECT_EQ(123, method_called_with); + } + + { + RunLoop loop; + s.AsyncCall(&IntArgVoidReturn::ConstMethod) + .WithArgs(456) + .Then(BindLambdaForTesting([&] { loop.Quit(); })); + loop.Run(); + EXPECT_EQ(456, const_method_called_with); + } +} + +TEST_F(SequenceBoundTest, AsyncCallWithArgsIntThen) { + SequenceBound<IntArgIntReturn> s(task_runner_); + + { + RunLoop loop; + s.AsyncCall(&IntArgIntReturn::Method) + .WithArgs(123) + .Then(BindLambdaForTesting([&](int result) { + EXPECT_EQ(-123, result); + loop.Quit(); + })); + loop.Run(); + } + + { + RunLoop loop; + s.AsyncCall(&IntArgIntReturn::ConstMethod) + .WithArgs(456) + .Then(BindLambdaForTesting([&](int result) { + EXPECT_EQ(-456, result); + loop.Quit(); + })); + loop.Run(); + } +} + +// TODO(dcheng): Maybe use the nocompile harness here instead of being +// "clever"... +TEST_F(SequenceBoundTest, NoCompileTests) { + // TODO(dcheng): Test calling WithArgs() on a method that takes no arguments. + // Given: + // class C { + // void F(); + // }; + // + // Then: + // SequenceBound<C> s(...); + // s.AsyncCall(&C::F).WithArgs(...); + // + // should not compile. + // + // TODO(dcheng): Test calling Then() before calling WithArgs(). + // Given: + // class C { + // void F(int); + // }; + // + // Then: + // SequenceBound<C> s(...); + // s.AsyncCall(&C::F).Then(...).WithArgs(...); + // + // should not compile. + // +} + +class SequenceBoundDeathTest : public ::testing::Test { + protected: + void TearDown() override { + // Make sure that any objects owned by `SequenceBound` have been destroyed + // to avoid tripping leak detection. + RunLoop run_loop; + task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + } + + // Death tests use fork(), which can interact (very) poorly with threads. + test::SingleThreadTaskEnvironment task_environment_; + scoped_refptr<SequencedTaskRunner> task_runner_ = + base::SequencedTaskRunnerHandle::Get(); +}; + +TEST_F(SequenceBoundDeathTest, AsyncCallIntArgNoWithArgsShouldCheck) { + SequenceBound<IntArgIntReturn> s(task_runner_); + EXPECT_DEATH_IF_SUPPORTED(s.AsyncCall(&IntArgIntReturn::Method), ""); +} + +TEST_F(SequenceBoundDeathTest, AsyncCallIntReturnNoThenShouldCheck) { + { + SequenceBound<NoArgsIntReturn> s(task_runner_); + EXPECT_DEATH_IF_SUPPORTED(s.AsyncCall(&NoArgsIntReturn::Method), ""); + } + + { + SequenceBound<IntArgIntReturn> s(task_runner_); + EXPECT_DEATH_IF_SUPPORTED(s.AsyncCall(&IntArgIntReturn::Method).WithArgs(0), + ""); + } +} + } // namespace base
diff --git a/base/util/memory_pressure/BUILD.gn b/base/util/memory_pressure/BUILD.gn index 7d142d6..296ec52 100644 --- a/base/util/memory_pressure/BUILD.gn +++ b/base/util/memory_pressure/BUILD.gn
@@ -44,6 +44,13 @@ "system_memory_pressure_evaluator_fuchsia.h", ] } + + if (is_linux && !is_chromeos) { + sources += [ + "system_memory_pressure_evaluator_linux.cc", + "system_memory_pressure_evaluator_linux.h", + ] + } } source_set("unittests") { @@ -74,6 +81,10 @@ deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.memorypressure" ] sources += [ "system_memory_pressure_evaluator_fuchsia_unittest.cc" ] } + + if (is_linux && !is_chromeos) { + sources += [ "system_memory_pressure_evaluator_linux_unittest.cc" ] + } } static_library("test_support") {
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator.cc b/base/util/memory_pressure/system_memory_pressure_evaluator.cc index 7179fa09..babb4f8 100644 --- a/base/util/memory_pressure/system_memory_pressure_evaluator.cc +++ b/base/util/memory_pressure/system_memory_pressure_evaluator.cc
@@ -14,6 +14,8 @@ #elif defined(OS_WIN) #include "base/util/memory_pressure/system_memory_pressure_evaluator_win.h" #include "base/win/windows_version.h" +#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "base/util/memory_pressure/system_memory_pressure_evaluator_linux.h" #endif namespace util { @@ -43,6 +45,9 @@ evaluator->CreateOSSignalPressureEvaluator(monitor->CreateVoter()); } return evaluator; +#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) + return std::make_unique<util::linux::SystemMemoryPressureEvaluator>( + monitor->CreateVoter()); #endif return nullptr; }
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator_linux.cc b/base/util/memory_pressure/system_memory_pressure_evaluator_linux.cc new file mode 100644 index 0000000..258d983 --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_linux.cc
@@ -0,0 +1,157 @@ +// 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 "base/util/memory_pressure/system_memory_pressure_evaluator_linux.h" + +#include "base/bind.h" +#include "base/process/process_metrics.h" +#include "base/single_thread_task_runner.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" +#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h" + +namespace { + +constexpr int kKiBperMiB = 1024; + +int GetAvailableSystemMemoryMiB(const base::SystemMemoryInfoKB& mem_info) { + // Use 'available' metric if is is present, + // if no (kernels < 3.14), let's make a rough evaluation using free physical + // memory plus buffers and caches (that OS can free in case of low memory + // state) + int mem_available = + mem_info.available ? mem_info.available + : (mem_info.free + mem_info.buffers + mem_info.cached); + // How much physical memory is actively available for use right now, in MBs. + return mem_available / kKiBperMiB; +} + +} // namespace + +namespace util { +namespace linux { + +const base::TimeDelta SystemMemoryPressureEvaluator::kModeratePressureCooldown = + base::TimeDelta::FromSeconds(10); + +const int SystemMemoryPressureEvaluator::kDefaultModerateThresholdPc = 75; +const int SystemMemoryPressureEvaluator::kDefaultCriticalThresholdPc = 85; + +SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( + std::unique_ptr<MemoryPressureVoter> voter) + : util::SystemMemoryPressureEvaluator(std::move(voter)), + moderate_pressure_repeat_count_(0) { + if (InferThresholds()) + StartObserving(); +} + +SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( + int moderate_threshold_mb, + int critical_threshold_mb, + std::unique_ptr<MemoryPressureVoter> voter) + : util::SystemMemoryPressureEvaluator(std::move(voter)), + moderate_threshold_mb_(moderate_threshold_mb), + critical_threshold_mb_(critical_threshold_mb), + moderate_pressure_repeat_count_(0) { + DCHECK_GE(moderate_threshold_mb_, critical_threshold_mb_); + DCHECK_GT(critical_threshold_mb_, 0); + StartObserving(); +} + +void SystemMemoryPressureEvaluator::StartObserving() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + timer_.Start( + FROM_HERE, base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod, + base::BindRepeating(&SystemMemoryPressureEvaluator::CheckMemoryPressure, + base::Unretained(this))); +} + +void SystemMemoryPressureEvaluator::StopObserving() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // If StartObserving failed, StopObserving will still get called. + timer_.Stop(); +} + +bool SystemMemoryPressureEvaluator::GetSystemMemoryInfo( + base::SystemMemoryInfoKB* mem_info) { + return base::GetSystemMemoryInfo(mem_info); +} + +void SystemMemoryPressureEvaluator::CheckMemoryPressure() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Get the previous pressure level and update the current one. + MemoryPressureLevel old_vote = current_vote(); + SetCurrentVote(CalculateCurrentPressureLevel()); + + // |notify| will be set to true if MemoryPressureListeners need to be + // notified of a memory pressure level state change. + bool notify = false; + switch (current_vote()) { + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: + break; + + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: + if (old_vote != current_vote()) { + // This is a new transition to moderate pressure so notify. + moderate_pressure_repeat_count_ = 0; + notify = true; + } else { + // Already in moderate pressure, only notify if sustained over the + // cooldown period. + const int kModeratePressureCooldownCycles = + kModeratePressureCooldown / + base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod; + if (++moderate_pressure_repeat_count_ == + kModeratePressureCooldownCycles) { + moderate_pressure_repeat_count_ = 0; + notify = true; + } + } + break; + + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: + // Always notify of critical pressure levels. + notify = true; + break; + } + + SendCurrentVote(notify); +} + +bool SystemMemoryPressureEvaluator::InferThresholds() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::SystemMemoryInfoKB mem_info; + if (!GetSystemMemoryInfo(&mem_info)) + return false; + critical_threshold_mb_ = + mem_info.total * (100 - kDefaultCriticalThresholdPc) / 100 / kKiBperMiB; + moderate_threshold_mb_ = + mem_info.total * (100 - kDefaultModerateThresholdPc) / 100 / kKiBperMiB; + return true; +} + +base::MemoryPressureListener::MemoryPressureLevel +SystemMemoryPressureEvaluator::CalculateCurrentPressureLevel() { + base::SystemMemoryInfoKB mem_info; + if (GetSystemMemoryInfo(&mem_info)) { + // How much system memory is actively available for use right now, in MBs. + int available = GetAvailableSystemMemoryMiB(mem_info); + + // Determine if the available memory is under critical memory pressure. + if (available <= critical_threshold_mb_) + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; + + // Determine if the available memory is under moderate memory pressure. + if (available <= moderate_threshold_mb_) + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; + } + // No memory pressure was detected. + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; +} + +} // namespace linux +} // namespace util
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator_linux.h b/base/util/memory_pressure/system_memory_pressure_evaluator_linux.h new file mode 100644 index 0000000..0f5c43d8 --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_linux.h
@@ -0,0 +1,112 @@ +// 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 BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_LINUX_H_ +#define BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_LINUX_H_ + +#include "base/memory/memory_pressure_listener.h" +#include "base/process/process_metrics.h" +#include "base/sequence_checker.h" +#include "base/timer/timer.h" +#include "base/util/memory_pressure/memory_pressure_voter.h" +#include "base/util/memory_pressure/system_memory_pressure_evaluator.h" + +namespace util { +namespace linux { + +// Linux memory pressure voter. Because there is no OS provided signal this +// polls at a low frequency, and applies internal hysteresis. +// TODO(https://crbug.com/1119396): use Pressure Stall Information (PSI) on +// kernels >4.20. +class SystemMemoryPressureEvaluator + : public util::SystemMemoryPressureEvaluator { + public: + using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; + + // Constants governing the polling and hysteresis behaviour of the observer. + // The time which should pass between 2 successive moderate memory pressure + // signals. + static const base::TimeDelta kModeratePressureCooldown; + + // Default minimum free memory thresholds, in percents. + static const int kDefaultModerateThresholdPc; + static const int kDefaultCriticalThresholdPc; + + // Default constructor. Will choose thresholds automatically based on the + // actual amount of system memory. + explicit SystemMemoryPressureEvaluator( + std::unique_ptr<MemoryPressureVoter> voter); + + // Constructor with explicit memory thresholds. These represent the amount of + // free memory below which the applicable memory pressure state engages. + SystemMemoryPressureEvaluator(int moderate_threshold_mb, + int critical_threshold_mb, + std::unique_ptr<MemoryPressureVoter> voter); + + ~SystemMemoryPressureEvaluator() override = default; + + SystemMemoryPressureEvaluator(const SystemMemoryPressureEvaluator&) = delete; + SystemMemoryPressureEvaluator& operator=( + const SystemMemoryPressureEvaluator&) = delete; + + // Returns the moderate pressure level free memory threshold, in MB. + int moderate_threshold_mb() const { return moderate_threshold_mb_; } + + // Returns the critical pressure level free memory threshold, in MB. + int critical_threshold_mb() const { return critical_threshold_mb_; } + + protected: + // Internals are exposed for unittests. + + // Starts observing the memory fill level. Calls to StartObserving should + // always be matched with calls to StopObserving. + void StartObserving(); + + // Stop observing the memory fill level. May be safely called if + // StartObserving has not been called. Must be called from the same thread on + // which the monitor was instantiated. + void StopObserving(); + + // Checks memory pressure, storing the current level, applying any hysteresis + // and emitting memory pressure level change signals as necessary. This + // function is called periodically while the monitor is observing memory + // pressure. Must be called from the same thread on which the monitor was + // instantiated. + void CheckMemoryPressure(); + + // Automatically infers threshold values based on system memory. + // Returns 'true' if succeeded. + bool InferThresholds(); + + // Calculates the current instantaneous memory pressure level. This does not + // use any hysteresis and simply returns the result at the current moment. Can + // be called on any thread. + MemoryPressureLevel CalculateCurrentPressureLevel(); + + // This is just a wrapper for base:: function; + // declared as virtual for unit testing + virtual bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* mem_info); + + private: + // Threshold amounts of available memory that trigger pressure levels + int moderate_threshold_mb_; + int critical_threshold_mb_; + + // A periodic timer to check for memory pressure changes. + base::RepeatingTimer timer_; + + // To slow down the amount of moderate pressure event calls, this gets used to + // count the number of events since the last event occurred. This is used by + // |CheckMemoryPressure| to apply hysteresis on the raw results of + // |CalculateCurrentPressureLevel|. + int moderate_pressure_repeat_count_; + + // Ensures that this object is used from a single sequence. + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace linux +} // namespace util + +#endif // BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_LINUX_H_
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator_linux_unittest.cc b/base/util/memory_pressure/system_memory_pressure_evaluator_linux_unittest.cc new file mode 100644 index 0000000..e5db67e --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_linux_unittest.cc
@@ -0,0 +1,261 @@ +// 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 "base/util/memory_pressure/system_memory_pressure_evaluator_linux.h" + +#include "base/bind.h" +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h" +#include "build/build_config.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace util { +namespace linux { + +namespace { + +struct PressureSettings { + int phys_left_mb; + base::MemoryPressureListener::MemoryPressureLevel level; +}; + +} // namespace + +// This is outside of the anonymous namespace so that it can be seen as a friend +// to the evaluator class. +class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator { + public: + using SystemMemoryPressureEvaluator::CalculateCurrentPressureLevel; + using SystemMemoryPressureEvaluator::CheckMemoryPressure; + + static const unsigned long kKiBperMiB = 1024; + static const unsigned long kMemoryTotalMb = 4096; + + TestSystemMemoryPressureEvaluator(bool large_memory, + std::unique_ptr<MemoryPressureVoter> voter) + : SystemMemoryPressureEvaluator(std::move(voter)) { + // Generate a plausible amount of memory. + mem_status_.total = kMemoryTotalMb * kKiBperMiB; + + // Rerun InferThresholds. + InferThresholds(); + // Stop the timer. + StopObserving(); + } + + TestSystemMemoryPressureEvaluator(int system_memory_mb, + int moderate_threshold_mb, + int critical_threshold_mb) + : SystemMemoryPressureEvaluator(moderate_threshold_mb, + critical_threshold_mb, + nullptr) { + // Set the amount of system memory. + mem_status_.total = system_memory_mb * kKiBperMiB; + + // Stop the timer. + StopObserving(); + } + + TestSystemMemoryPressureEvaluator(const TestSystemMemoryPressureEvaluator&) = + delete; + TestSystemMemoryPressureEvaluator& operator=( + const TestSystemMemoryPressureEvaluator&) = delete; + + MOCK_METHOD1(OnMemoryPressure, + void(base::MemoryPressureListener::MemoryPressureLevel level)); + + // Sets up the memory status to reflect the provided absolute memory left. + void SetMemoryFree(int phys_left_mb) { + // ullTotalPhys is set in the constructor and not modified. + + // Set the amount of available memory. + mem_status_.available = phys_left_mb * kKiBperMiB; + DCHECK_LT(mem_status_.available, mem_status_.total); + } + + void SetNone() { SetMemoryFree(moderate_threshold_mb() + 1); } + + void SetModerate() { SetMemoryFree(moderate_threshold_mb() - 1); } + + void SetCritical() { SetMemoryFree(critical_threshold_mb() - 1); } + + bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* mem_info) override { + *mem_info = mem_status_; + return true; + } + + private: + base::SystemMemoryInfoKB mem_status_; +}; + +class LinuxSystemMemoryPressureEvaluatorTest : public testing::Test { + protected: + void CalculateCurrentMemoryPressureLevelTest( + TestSystemMemoryPressureEvaluator* evaluator) { + int mod = evaluator->moderate_threshold_mb(); + evaluator->SetMemoryFree(mod + 1); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, + evaluator->CalculateCurrentPressureLevel()); + + evaluator->SetMemoryFree(mod); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator->CalculateCurrentPressureLevel()); + + evaluator->SetMemoryFree(mod - 1); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator->CalculateCurrentPressureLevel()); + + int crit = evaluator->critical_threshold_mb(); + evaluator->SetMemoryFree(crit + 1); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator->CalculateCurrentPressureLevel()); + + evaluator->SetMemoryFree(crit); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, + evaluator->CalculateCurrentPressureLevel()); + + evaluator->SetMemoryFree(crit - 1); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, + evaluator->CalculateCurrentPressureLevel()); + } + + base::test::SingleThreadTaskEnvironment task_environment_{ + base::test::SingleThreadTaskEnvironment::MainThreadType::UI}; +}; + +// Tests the fundamental direct calculation of memory pressure with manually +// specified threshold levels. +TEST_F(LinuxSystemMemoryPressureEvaluatorTest, + CalculateCurrentMemoryPressureLevelCustom) { + static const int kSystemMb = 512; + static const int kModerateMb = 256; + static const int kCriticalMb = 128; + + TestSystemMemoryPressureEvaluator evaluator(kSystemMb, kModerateMb, + kCriticalMb); + + EXPECT_EQ(kModerateMb, evaluator.moderate_threshold_mb()); + EXPECT_EQ(kCriticalMb, evaluator.critical_threshold_mb()); + + ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&evaluator)); +} + +// This test tests the various transition states from memory pressure, looking +// for the correct behavior on event reposting as well as state updates. +TEST_F(LinuxSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) { + MultiSourceMemoryPressureMonitor monitor; + monitor.ResetSystemEvaluatorForTesting(); + + // Large-memory. + testing::StrictMock<TestSystemMemoryPressureEvaluator> evaluator( + true, monitor.CreateVoter()); + + base::MemoryPressureListener listener( + FROM_HERE, + base::BindRepeating(&TestSystemMemoryPressureEvaluator::OnMemoryPressure, + base::Unretained(&evaluator))); + + // Checking the memory pressure at 0% load should not produce any + // events. + evaluator.SetNone(); + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, + evaluator.current_vote()); + + // Setting the memory level to 80% should produce a moderate pressure level. + EXPECT_CALL( + evaluator, + OnMemoryPressure( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)); + evaluator.SetModerate(); + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + + // Check that the event gets reposted after a while. + const int kModeratePressureCooldownCycles = + evaluator.kModeratePressureCooldown / + base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod; + + for (int i = 0; i < kModeratePressureCooldownCycles; ++i) { + if (i + 1 == kModeratePressureCooldownCycles) { + EXPECT_CALL( + evaluator, + OnMemoryPressure( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)); + } + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + } + + // Setting the memory usage to 99% should produce critical levels. + EXPECT_CALL( + evaluator, + OnMemoryPressure( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)); + evaluator.SetCritical(); + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + + // Calling it again should immediately produce a second call. + EXPECT_CALL( + evaluator, + OnMemoryPressure( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)); + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + + // When lowering the pressure again there should be a notification and the + // pressure should go back to moderate. + EXPECT_CALL( + evaluator, + OnMemoryPressure( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)); + evaluator.SetModerate(); + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + + // Check that the event gets reposted after a while. + for (int i = 0; i < kModeratePressureCooldownCycles; ++i) { + if (i + 1 == kModeratePressureCooldownCycles) { + EXPECT_CALL( + evaluator, + OnMemoryPressure( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)); + } + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + } + + // Going down to no pressure should not produce an notification. + evaluator.SetNone(); + evaluator.CheckMemoryPressure(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, + evaluator.current_vote()); + testing::Mock::VerifyAndClearExpectations(&evaluator); +} + +} // namespace linux +} // namespace util
diff --git a/build/.gitignore b/build/.gitignore index a4a36d9..2e963395 100644 --- a/build/.gitignore +++ b/build/.gitignore
@@ -9,6 +9,7 @@ /cros_cache/ /Debug /Debug_x64 +/fuchsia/internal/ /goma /gomacc.lock /ipch/
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 4a60106..b61dce0 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -4112,9 +4112,6 @@ # will still be verified regardless of the value of this flag. # strip_resources: Whether to ignore android resources found in the .aar. # custom_package: Java package for generated R.java files. - # extract_assets: Whether to extract and include assets found in the .aar. - # If the file contains assets, either extract_assets or ignore_assets - # must be set. # extract_native_libraries: Whether to extract .so files found in the .aar. # If the file contains .so, either extract_native_libraries or # ignore_native_libraries must be set. @@ -4142,7 +4139,6 @@ _unpack_target_name = "${_target_name_without_java_or_junit}__unpack_aar" _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets - _extract_assets = defined(invoker.extract_assets) && invoker.extract_assets _ignore_manifest = defined(invoker.ignore_manifest) && invoker.ignore_manifest _ignore_native_libraries = defined(invoker.ignore_native_libraries) && @@ -4176,7 +4172,7 @@ # rm -r out/tmp _scanned_files = read_file(_info_path, "scope") - _contains_scanned_assets = _scanned_files.assets != [] + _use_scanned_assets = !_ignore_assets && _scanned_files.assets != [] assert(_ignore_aidl || _scanned_files.aidl == [], "android_aar_prebuilt() aidl not yet supported." + @@ -4190,11 +4186,6 @@ assert( !(_ignore_native_libraries && _extract_native_libraries), "ignore_native_libraries and extract_native_libraries cannot both be set.") - assert(!_contains_scanned_assets || (_ignore_assets || _extract_assets), - "android_aar_prebuilt() contains asset files." + - " Please set ignore_assets or extract_assets.") - assert(!(_ignore_assets && _extract_assets), - "ignore_assets and extract_assets cannot both be set.") assert(!_scanned_files.has_native_libraries || _scanned_files.native_libraries != []) assert(_scanned_files.has_classes_jar || _scanned_files.subjars == []) @@ -4252,7 +4243,7 @@ rebase_path(_scanned_files.native_libraries, "", _output_path), "abspath") } - if (_extract_assets && _contains_scanned_assets) { + if (_use_scanned_assets) { outputs += get_path_info(rebase_path(_scanned_files.assets, "", _output_path), "abspath") @@ -4310,10 +4301,8 @@ not_needed(invoker, [ "strip_drawables" ]) } - _should_extract_assets = _extract_assets && _contains_scanned_assets - # Create the android_assets target for assets - if (_should_extract_assets) { + if (_use_scanned_assets) { _assets_target_name = "${target_name}__assets" android_assets(_assets_target_name) { forward_variables_from(invoker, [ "testonly" ])
diff --git a/build/config/fuchsia/generate_runner_scripts.gni b/build/config/fuchsia/generate_runner_scripts.gni index a0bae5e..af5ead3 100644 --- a/build/config/fuchsia/generate_runner_scripts.gni +++ b/build/config/fuchsia/generate_runner_scripts.gni
@@ -104,6 +104,7 @@ # currently always matches the |target_cpu|, rather than for the build host # architecture. data += [ + "//third_party/fuchsia-sdk/sdk/tools/${target_cpu}/device-finder", "//third_party/fuchsia-sdk/sdk/tools/${target_cpu}/fvm", "//third_party/fuchsia-sdk/sdk/tools/${target_cpu}/merkleroot", "//third_party/fuchsia-sdk/sdk/tools/${target_cpu}/pm", @@ -115,6 +116,9 @@ } else { data += [ "${qemu_root}/", + "//third_party/fuchsia-sdk/sdk/bin/fpave.sh", + "//third_party/fuchsia-sdk/sdk/bin/fuchsia-common.sh", + "//third_party/fuchsia-sdk/sdk/meta/manifest.json", "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer", ] } @@ -148,7 +152,7 @@ } executable_args += [ - "--output-directory", + "--output-dir", "@WrappedPath(.)", "--target-cpu", target_cpu,
diff --git a/build/fuchsia/aemu_target.py b/build/fuchsia/aemu_target.py index e997541..a5f1d7e 100644 --- a/build/fuchsia/aemu_target.py +++ b/build/fuchsia/aemu_target.py
@@ -4,6 +4,7 @@ """Implements commands for running and interacting with Fuchsia on AEMU.""" +import emu_target import os import platform import qemu_target @@ -12,14 +13,17 @@ from common import GetEmuRootForPlatform -class AemuTarget(qemu_target.QemuTarget): +def GetTargetType(): + return AemuTarget - def __init__(self, output_dir, target_cpu, system_log_file, emu_type, - cpu_cores, require_kvm, ram_size_mb, enable_graphics, - hardware_gpu): + +class AemuTarget(qemu_target.QemuTarget): + EMULATOR_NAME = 'aemu' + + def __init__(self, output_dir, target_cpu, system_log_file, cpu_cores, + require_kvm, ram_size_mb, enable_graphics, hardware_gpu): super(AemuTarget, self).__init__(output_dir, target_cpu, system_log_file, - emu_type, cpu_cores, require_kvm, - ram_size_mb) + cpu_cores, require_kvm, ram_size_mb) # TODO(crbug.com/1000907): Enable AEMU for arm64. if platform.machine() == 'aarch64': @@ -27,12 +31,27 @@ self._enable_graphics = enable_graphics self._hardware_gpu = hardware_gpu + @staticmethod + def RegisterArgs(arg_parser): + emu_target.EmuTarget.RegisterArgs(arg_parser) + aemu_args = arg_parser.add_argument_group('aemu', 'AEMU Arguments') + aemu_args.add_argument('--enable-graphics', + action='store_true', + default=False, + help='Start AEMU with graphics instead of '\ + 'headless.') + aemu_args.add_argument('--hardware-gpu', + action='store_true', + default=False, + help='Use local GPU hardware instead of '\ + 'Swiftshader.') + def _EnsureEmulatorExists(self, path): assert os.path.exists(path), \ - 'This checkout is missing %s.' % (self._emu_type) + 'This checkout is missing %s.' % (self.EMULATOR_NAME) def _BuildCommand(self): - aemu_folder = GetEmuRootForPlatform(self._emu_type) + aemu_folder = GetEmuRootForPlatform(self.EMULATOR_NAME) self._EnsureEmulatorExists(aemu_folder) aemu_path = os.path.join(aemu_folder, 'emulator') @@ -77,7 +96,7 @@ return aemu_command def _GetVulkanIcdFile(self): - return os.path.join(GetEmuRootForPlatform(self._emu_type), 'lib64', + return os.path.join(GetEmuRootForPlatform(self.EMULATOR_NAME), 'lib64', 'vulkan', 'vk_swiftshader_icd.json') def _SetEnv(self):
diff --git a/build/fuchsia/common.py b/build/fuchsia/common.py index be66d08..5eaefa2b 100644 --- a/build/fuchsia/common.py +++ b/build/fuchsia/common.py
@@ -5,9 +5,12 @@ import logging import os import platform +import signal import socket import subprocess import sys +import time +import threading DIR_SOURCE_ROOT = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) @@ -92,3 +95,42 @@ port = sock.getsockname()[1] sock.close() return port + + +def SubprocessCallWithTimeout(command, silent=False, timeout_secs=None): + """Helper function for running a command. + + Args: + command: The command to run. + silent: If true, stdout and stderr of the command will not be printed. + timeout_secs: Maximum amount of time allowed for the command to finish. + + Returns: + A tuple of (return code, stdout, stderr) of the command. Raises + an exception if the subprocess times out. + """ + + if silent: + devnull = open(os.devnull, 'w') + process = subprocess.Popen(command, stdout=devnull, stderr=devnull) + else: + process = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + timeout_timer = None + if timeout_secs: + + def interrupt_process(): + process.send_signal(signal.SIGKILL) + + timeout_timer = threading.Timer(timeout_secs, interrupt_process) + timeout_timer.start() + + out, err = process.communicate() + if timeout_timer: + timeout_timer.cancel() + + if process.returncode == -9: + raise Exception('Timeout when executing \"%s\".' % ' '.join(command)) + + return process.returncode, out, err
diff --git a/build/fuchsia/common_args.py b/build/fuchsia/common_args.py index 855bc11..12c9df2 100644 --- a/build/fuchsia/common_args.py +++ b/build/fuchsia/common_args.py
@@ -2,16 +2,69 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import argparse +import importlib import logging import os import sys -from aemu_target import AemuTarget -from device_target import DeviceTarget -from qemu_target import QemuTarget from common import GetHostArchFromPlatform +def _AddTargetSpecificationArgs(arg_parser): + """Returns a parser that handles the target type used for the test run.""" + + device_args = arg_parser.add_argument_group( + 'target', 'Arguments specifying the Fuchsia target type.') + device_args.add_argument('--target-cpu', + default=GetHostArchFromPlatform(), + help='GN target_cpu setting for the build. Defaults ' + 'to the same architecture as host cpu.') + device_args.add_argument('--device', + default=None, + choices=['aemu', 'qemu', 'device', 'ext'], + help='Choose to run on aemu|qemu|device. ' + 'By default, Fuchsia will run on AEMU on x64 ' + 'hosts and QEMU on arm64 hosts. Alternatively, ' + 'setting to ext will require specifying the ' + 'subclass of Target class used via the ' + '--ext-device-path flag.') + device_args.add_argument('-d', + action='store_const', + dest='device', + const='device', + help='Run on device instead of emulator.') + device_args.add_argument('--ext-device-path', + default=None, + help='Specify path to file that contains the ' + 'subclass of Target that will be used. Only ' + 'needed if device specific operations such as ' + 'paving is required.') + + +def _GetTargetClass(args): + """Gets the target class to be used for the test run.""" + + if args.device == 'ext': + if not args.ext_device_path: + raise Exception('--ext-device-path flag must be set when device flag ' + 'set to ext.') + target_path = args.ext_device_path + else: + if not args.device: + args.device = 'aemu' if args.target_cpu == 'x64' else 'qemu' + target_path = '%s_target' % args.device + + try: + loaded_target = importlib.import_module(target_path) + except ImportError: + logging.error('Cannot import from %s. Make sure that --ext-device-path ' + 'is pointing to a file containing a target ' + 'module.' % target_path) + raise + return loaded_target.GetTargetType() + + def AddCommonArgs(arg_parser): """Adds command line arguments to |arg_parser| for options which are shared across test and executable target types. @@ -19,6 +72,15 @@ Args: arg_parser: an ArgumentParser object.""" + _AddTargetSpecificationArgs(arg_parser) + + # Parse the args used to specify target + module_args, _ = arg_parser.parse_known_args() + + # Determine the target class and register target specific args. + target_class = _GetTargetClass(module_args) + target_class.RegisterArgs(arg_parser) + package_args = arg_parser.add_argument_group('package', 'Fuchsia Packages') package_args.add_argument( '--package', @@ -30,47 +92,11 @@ help='Name of the package to execute, defined in ' + 'package metadata.') common_args = arg_parser.add_argument_group('common', 'Common arguments') - common_args.add_argument( - '--output-directory', - type=os.path.realpath, - default=None, - help=('Path to the directory in which build files are located. ')) - common_args.add_argument( - '--target-cpu', - default=GetHostArchFromPlatform(), - help=('GN target_cpu setting for the build. Defaults to the same ' - 'architecture as host cpu.')) common_args.add_argument('--target-staging-path', help='target path under which to stage packages ' 'during deployment.', default='/data') - common_args.add_argument('--device', default=None, - choices=['aemu','qemu','device'], - help='Choose to run on aemu|qemu|device. ' + - 'By default, Fuchsia will run in QEMU.') - common_args.add_argument('-d', action='store_const', dest='device', - const='device', - help='Run on device instead of emulator.') - common_args.add_argument('--host', help='The IP of the target device. ' + - 'Optional.') - common_args.add_argument('--node-name', - help='The node-name of the device to boot or deploy ' - 'to. Optional, will use the first discovered ' - 'device if omitted.') - common_args.add_argument('--port', '-p', type=int, default=22, - help='The port of the SSH service running on the ' + - 'device. Optional.') - common_args.add_argument('--ssh-config', '-F', - help='The path to the SSH configuration used for ' - 'connecting to the target device.') - common_args.add_argument('--fuchsia-out-dir', - help='Path to a Fuchsia build output directory. ' - 'Equivalent to setting --ssh_config and ' - '---os-check=ignore') common_args.add_argument('--runner-logs-dir', help='Directory to write test runner logs to.') - common_args.add_argument('--system-log-file', - help='File to write system logs to. Specify - to ' - 'log to stdout.') common_args.add_argument('--exclude-system-logs', action='store_false', dest='include_system_logs', @@ -78,38 +104,6 @@ common_args.add_argument('--verbose', '-v', default=False, action='store_true', help='Enable debug-level logging.') - common_args.add_argument( - '--qemu-cpu-cores', - type=int, - default=4, - help='Sets the number of CPU cores to provide if launching in a VM.') - common_args.add_argument('--memory', type=int, default=2048, - help='Sets the RAM size (MB) if launching in a VM'), - common_args.add_argument( - '--allow-no-kvm', - action='store_false', - dest='require_kvm', - default=True, - help='Do not require KVM acceleration for emulators.') - common_args.add_argument( - '--os_check', choices=['check', 'update', 'ignore'], - default='update', - help='Sets the OS version enforcement policy. If \'check\', then the ' - 'deployment process will halt if the target\'s version doesn\'t ' - 'match. If \'update\', then the target device will automatically ' - 'be repaved. If \'ignore\', then the OS version won\'t be checked.') - - aemu_args = arg_parser.add_argument_group('aemu', 'AEMU Arguments') - aemu_args.add_argument( - '--enable-graphics', - action='store_true', - default=False, - help='Start AEMU with graphics instead of headless.') - aemu_args.add_argument( - '--hardware-gpu', - action='store_true', - default=False, - help='Use local GPU hardware instead of Swiftshader.') def ConfigureLogging(args): @@ -129,47 +123,29 @@ logging.DEBUG if args.verbose else logging.WARN) -def GetDeploymentTargetForArgs(args): - """Constructs a deployment target object using parameters taken from - command line arguments.""" - if args.system_log_file == '-': - system_log_file = sys.stdout - elif args.system_log_file: - system_log_file = open(args.system_log_file, 'w') - else: - system_log_file = None +# TODO(crbug.com/1121763): remove the need for additional_args +def GetDeploymentTargetForArgs(additional_args=None): + """Constructs a deployment target object using command line arguments. + If needed, an additional_args dict can be used to supplement the + command line arguments.""" - # Allow fuchsia to run on emulator if device not explicitly chosen. - # AEMU is the default emulator for x64 Fuchsia, and QEMU for others. - if not args.device: - if args.target_cpu == 'x64': - args.device = 'aemu' - else: - args.device = 'qemu' + # Determine target type from command line arguments. + device_type_parser = argparse.ArgumentParser() + _AddTargetSpecificationArgs(device_type_parser) + module_args, _ = device_type_parser.parse_known_args() + target_class = _GetTargetClass(module_args) - target_args = { 'output_dir':args.output_directory, - 'target_cpu':args.target_cpu, - 'system_log_file':system_log_file } - if args.device == 'device': - target_args.update({ 'host':args.host, - 'node_name':args.node_name, - 'port':args.port, - 'ssh_config':args.ssh_config, - 'fuchsia_out_dir':args.fuchsia_out_dir, - 'os_check':args.os_check }) - return DeviceTarget(**target_args) - else: - target_args.update({ - 'cpu_cores': args.qemu_cpu_cores, - 'require_kvm': args.require_kvm, - 'emu_type': args.device, - 'ram_size_mb': args.memory - }) - if args.device == 'qemu': - return QemuTarget(**target_args) - else: - target_args.update({ - 'enable_graphics': args.enable_graphics, - 'hardware_gpu': args.hardware_gpu - }) - return AemuTarget(**target_args) + # Process command line args needed to initialize target in separate arg + # parser. + target_arg_parser = argparse.ArgumentParser() + target_class.RegisterArgs(target_arg_parser) + known_args, _ = target_arg_parser.parse_known_args() + target_args = vars(known_args) + + # target_cpu is needed to determine target type, so we need to add + # it here to the args used to initialize the Target. + target_args.update({'target_cpu': module_args.target_cpu}) + + if additional_args: + target_args.update(additional_args) + return target_class(**target_args)
diff --git a/build/fuchsia/device_target.py b/build/fuchsia/device_target.py index 4723eee..94cf8058 100644 --- a/build/fuchsia/device_target.py +++ b/build/fuchsia/device_target.py
@@ -23,42 +23,40 @@ # The maximum times to attempt mDNS resolution when connecting to a freshly # booted Fuchsia instance before aborting. -_BOOT_DISCOVERY_ATTEMPTS = 30 +BOOT_DISCOVERY_ATTEMPTS = 30 -# Number of seconds to wait when querying a list of all devices over mDNS. -_LIST_DEVICES_TIMEOUT_SECS = 3 - -#Number of failed connection attempts before redirecting system logs to stdout. +# Number of failed connection attempts before redirecting system logs to stdout. CONNECT_RETRY_COUNT_BEFORE_LOGGING = 10 TARGET_HASH_FILE_PATH = '/data/.hash' +# Number of seconds to wait when querying a list of all devices over mDNS. +_LIST_DEVICES_TIMEOUT_SECS = 3 + +# Time between a reboot command is issued and when connection attempts from the +# host begin. +_REBOOT_SLEEP_PERIOD = 20 + + +def GetTargetType(): + return DeviceTarget + + class DeviceTarget(target.Target): """Prepares a device to be used as a deployment target. Depending on the command line parameters, it automatically handling a number of preparatory - steps relating to address resolution, device provisioning, and SDK - versioning. + steps relating to address resolution. If |_node_name| is unset: - If there is one running device, use it for deployment and execution. The - device's SDK version is checked unless --os-check=ignore is set. - If --os-check=update is set, then the target device is repaved if the SDK - version doesn't match. + If there is one running device, use it for deployment and execution. If there are more than one running devices, then abort and instruct the user to re-run the command with |_node_name| - Otherwise, if there are no running devices, then search for a device - running Zedboot, and pave it. - - If |_node_name| is set: If there is a running device with a matching nodename, then it is used for deployment and execution. - Otherwise, attempt to pave a device with a matching nodename, and use it - for deployment and execution. - If |_host| is set: Deploy to a device at the host IP address as-is.""" @@ -85,7 +83,9 @@ self._port = port if port else 22 self._system_log_file = system_log_file self._host = host - self._fuchsia_out_dir = fuchsia_out_dir + self._fuchsia_out_dir = None + if fuchsia_out_dir: + self._fuchsia_out_dir = os.path.expanduser(fuchsia_out_dir) self._node_name = node_name self._os_check = os_check self._amber_repo = None @@ -113,6 +113,39 @@ boot_data.ProvisionSSH(output_dir) self._ssh_config_path = boot_data.GetSSHConfigPath(output_dir) + @staticmethod + def RegisterArgs(arg_parser): + target.Target.RegisterArgs(arg_parser) + device_args = arg_parser.add_argument_group('device', 'Device Arguments') + device_args.add_argument('--host', + help='The IP of the target device. Optional.') + device_args.add_argument('--node-name', + help='The node-name of the device to boot or ' + 'deploy to. Optional, will use the first ' + 'discovered device if omitted.') + device_args.add_argument('--port', + '-p', + type=int, + default=22, + help='The port of the SSH service running on the ' + 'device. Optional.') + device_args.add_argument('--ssh-config', + '-F', + help='The path to the SSH configuration used for ' + 'connecting to the target device.') + device_args.add_argument('--fuchsia-out-dir', + help='Path to a Fuchsia build output directory. ' + 'Equivalent to setting --ssh_config and ' + '--os-check=ignore') + device_args.add_argument( + '--os_check', + choices=['check', 'update', 'ignore'], + default='update', + help="Sets the OS version enforcement policy. If 'check', then the " + "deployment process will halt if the target\'s version doesn\'t " + "match. If 'update', then the target device will automatically " + "be repaved. If 'ignore', then the OS version won\'t be checked.") + def _SDKHashMatches(self): """Checks if /data/.hash on the device matches SDK_ROOT/.hash. @@ -127,7 +160,10 @@ return filecmp.cmp(tmp.name, os.path.join(SDK_ROOT, '.hash'), False) - def __Discover(self): + def _ProvisionDeviceIfNecessary(self): + pass + + def _Discover(self): """Queries mDNS for the IP address of a booted Fuchsia instance whose name matches |_node_name| on the local area network. If |_node_name| isn't specified, and there is only one device on the network, then returns the @@ -186,33 +222,11 @@ def Start(self): if self._host: self._WaitUntilReady() - else: - should_provision = False - - if self.__Discover(): - self._WaitUntilReady() - - if self._os_check != 'ignore': - if self._SDKHashMatches(): - if self._os_check == 'update': - logging.info( 'SDK hash does not match; rebooting and repaving.') - self.RunCommand(['dm', 'reboot']) - should_provision = True - elif self._os_check == 'check': - raise Exception('Target device SDK version does not match.') - - else: - should_provision = True - - if should_provision: - boot_data.AssertBootImagesExist(self._GetTargetSdkArch(), 'generic') - self.__ProvisionDevice() - + self._ProvisionDeviceIfNecessary() assert self._node_name assert self._host - def GetAmberRepo(self): if not self._amber_repo: if self._fuchsia_out_dir: @@ -226,39 +240,9 @@ return self._amber_repo - - def __ProvisionDevice(self): - """Netboots a device with Fuchsia. If |_node_name| is set, then only a - device with a matching node name is used. - - The device is up and reachable via SSH when the function is successfully - completes.""" - - bootserver_path = GetHostToolPathFromPlatform('bootserver') - bootserver_command = [ - bootserver_path, - '-1', - '--fvm', - EnsurePathExists( - boot_data.GetTargetFile('storage-sparse.blk', - self._GetTargetSdkArch(), - boot_data.TARGET_TYPE_GENERIC)), - EnsurePathExists(boot_data.GetBootImage(self._output_dir, - self._GetTargetSdkArch(), - boot_data.TARGET_TYPE_GENERIC))] - - if self._node_name: - bootserver_command += ['-n', self._node_name] - - bootserver_command += ['--'] - bootserver_command += boot_data.GetKernelArgs(self._output_dir) - - logging.debug(' '.join(bootserver_command)) - stdout = subprocess.check_output(bootserver_command, - stderr=subprocess.STDOUT) - + def _ParseNodename(self, output): # Parse the nodename from bootserver stdout. - m = re.search(r'.*Proceeding with nodename (?P<nodename>.*)$', stdout, + m = re.search(r'.*Proceeding with nodename (?P<nodename>.*)$', output, re.MULTILINE) if not m: raise Exception('Couldn\'t parse nodename from bootserver output.') @@ -286,3 +270,10 @@ def _GetSshConfigPath(self): return self._ssh_config_path + + def Restart(self): + """Restart the device.""" + + self.RunCommandPiped('dm reboot') + time.sleep(_REBOOT_SLEEP_PERIOD) + self.Start()
diff --git a/build/fuchsia/emu_target.py b/build/fuchsia/emu_target.py index d6136d63..49a8791 100644 --- a/build/fuchsia/emu_target.py +++ b/build/fuchsia/emu_target.py
@@ -14,17 +14,38 @@ import target import tempfile + class EmuTarget(target.Target): def __init__(self, output_dir, target_cpu, system_log_file): """output_dir: The directory which will contain the files that are generated to support the emulator deployment. target_cpu: The emulated target CPU architecture. Can be 'x64' or 'arm64'.""" + super(EmuTarget, self).__init__(output_dir, target_cpu) self._emu_process = None self._system_log_file = system_log_file self._amber_repo = None + @staticmethod + def RegisterArgs(arg_parser): + target.Target.RegisterArgs(arg_parser) + emu_args = arg_parser.add_argument_group('emu', 'Emulator arguments') + emu_args.add_argument('--cpu-cores', + type=int, + default=4, + help='Sets the number of CPU cores to provide.') + emu_args.add_argument('--ram-size-mb', + type=int, + default=2048, + help='Sets the RAM size (MB) if launching in a VM'), + emu_args.add_argument('--allow-no-kvm', + action='store_false', + dest='require_kvm', + default=True, + help='Do not require KVM acceleration for ' + 'emulators.') + def __enter__(self): return self
diff --git a/build/fuchsia/generic_x64_target.py b/build/fuchsia/generic_x64_target.py new file mode 100644 index 0000000..5c56faa --- /dev/null +++ b/build/fuchsia/generic_x64_target.py
@@ -0,0 +1,97 @@ +# 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. +"""Implements commands for running and interacting with Fuchsia generic +build on devices.""" + +import boot_data +import device_target +import logging +import os + +from common import SDK_ROOT, EnsurePathExists, \ + GetHostToolPathFromPlatform, SubprocessCallWithTimeout + + +def GetTargetType(): + return GenericX64Target + + +class GenericX64Target(device_target.DeviceTarget): + """In addition to the functionality provided by DeviceTarget, this class + automatically handles paving of x64 devices that use generic Fuchsia build. + + If there are no running devices, then search for a device running Zedboot + and pave it. + + If there's only one running device, or |_node_name| is set, then the + device's SDK version is checked unless --os-check=ignore is set. + If --os-check=update is set, then the target device is repaved if the SDK + version doesn't match.""" + + def _ProvisionDeviceIfNecessary(self): + should_provision = False + + if self._Discover(): + self._WaitUntilReady() + + if self._os_check != 'ignore': + if self._SDKHashMatches(): + if self._os_check == 'update': + logging.info('SDK hash does not match; rebooting and repaving.') + self.RunCommand(['dm', 'reboot']) + should_provision = True + elif self._os_check == 'check': + raise Exception('Target device SDK version does not match.') + else: + should_provision = True + + if should_provision: + self._ProvisionDevice() + + def _ProvisionDevice(self): + """Pave a device with a generic image of Fuchsia.""" + bootserver_path = GetHostToolPathFromPlatform('bootserver') + bootserver_command = [ + bootserver_path, '-1', '--fvm', + EnsurePathExists( + boot_data.GetTargetFile('storage-sparse.blk', + self._GetTargetSdkArch(), + boot_data.TARGET_TYPE_GENERIC)), + EnsurePathExists( + boot_data.GetBootImage(self._output_dir, self._GetTargetSdkArch(), + boot_data.TARGET_TYPE_GENERIC)) + ] + + if self._node_name: + bootserver_command += ['-n', self._node_name] + + bootserver_command += ['--'] + bootserver_command += boot_data.GetKernelArgs(self._output_dir) + + logging.debug(' '.join(bootserver_command)) + _, stdout = SubprocessCallWithTimeout(bootserver_command, + silent=False, + timeout_secs=300) + + self._ParseNodename(stdout) + + # Start loglistener to save system logs. + if self._system_log_file: + self._StartLoglistener() + + # Repeatdly query mDNS until we find the device, or we hit + # BOOT_DISCOVERY_ATTEMPTS + logging.info('Waiting for device to join network.') + for _ in xrange(device_target.BOOT_DISCOVERY_ATTEMPTS): + if self.__Discover(): + break + + if not self._host: + raise Exception("Device %s couldn't be discovered via mDNS." % + self._node_name) + + self._WaitUntilReady() + + # Update the target's hash to match the current tree's. + self.PutFile(os.path.join(SDK_ROOT, '.hash'), TARGET_HASH_FILE_PATH)
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 3af3507..f375043 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200826.2.2 +0.20200827.3.2
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 3af3507..f375043 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200826.2.2 +0.20200827.3.2
diff --git a/build/fuchsia/qemu_target.py b/build/fuchsia/qemu_target.py index ad6f4de..895d2e0 100644 --- a/build/fuchsia/qemu_target.py +++ b/build/fuchsia/qemu_target.py
@@ -33,19 +33,21 @@ EXTENDED_BLOBSTORE_SIZE = 1073741824 # 1GB +def GetTargetType(): + return QemuTarget + + class QemuTarget(emu_target.EmuTarget): - def __init__(self, output_dir, target_cpu, system_log_file, - emu_type, cpu_cores, require_kvm, ram_size_mb): + EMULATOR_NAME = 'qemu' + + def __init__(self, output_dir, target_cpu, system_log_file, cpu_cores, + require_kvm, ram_size_mb): super(QemuTarget, self).__init__(output_dir, target_cpu, system_log_file) - self._emu_type=emu_type self._cpu_cores=cpu_cores self._require_kvm=require_kvm self._ram_size_mb=ram_size_mb - def _GetEmulatorName(self): - return self._emu_type - def _IsKvmEnabled(self): kvm_supported = sys.platform.startswith('linux') and \ os.access('/dev/kvm', os.R_OK | os.W_OK) @@ -60,8 +62,8 @@ kvm_error = 'File /dev/kvm does not exist. Please install KVM first.' else: kvm_error = 'To use KVM acceleration, add user to the kvm group '\ - 'through editing /etc/groups. Log out and back in for '\ - 'the change to take effect.' + 'with "sudo usermod -a -G kvm $USER". Log out and back '\ + 'in for the change to take effect.' raise FuchsiaTargetException(kvm_error) else: raise FuchsiaTargetException('KVM unavailable when CPU architecture of'\ @@ -131,8 +133,7 @@ kvm_command.append('host,migratable=no,+invtsc') else: logging.warning('Unable to launch %s with KVM acceleration.' - % (self._emu_type) + - 'The guest VM will be slow.') + 'The guest VM will be slow.' % (self.EMULATOR_NAME)) if self._target_cpu == 'arm64': kvm_command = ['-cpu', 'cortex-a53'] else: @@ -158,8 +159,10 @@ def _BuildCommand(self): qemu_exec = 'qemu-system-'+self._GetTargetSdkLegacyArch() - qemu_command = [os.path.join(GetEmuRootForPlatform(self._emu_type), 'bin', - qemu_exec)] + qemu_command = [ + os.path.join(GetEmuRootForPlatform(self.EMULATOR_NAME), 'bin', + qemu_exec) + ] qemu_command.extend(self._BuildQemuConfig()) qemu_command.append('-nographic') return qemu_command
diff --git a/build/fuchsia/remote_cmd.py b/build/fuchsia/remote_cmd.py index 019c2dc9..4c950a0 100644 --- a/build/fuchsia/remote_cmd.py +++ b/build/fuchsia/remote_cmd.py
@@ -7,6 +7,8 @@ import subprocess import threading +from common import SubprocessCallWithTimeout + _SSH = ['ssh'] _SCP = ['scp', '-C'] # Use gzip compression. _SSH_LOGGER = logging.getLogger('ssh') @@ -54,29 +56,8 @@ ssh_command = self._GetSshCommandLinePrefix() + command _SSH_LOGGER.debug('ssh exec: ' + ' '.join(ssh_command)) - if silent: - devnull = open(os.devnull, 'w') - process = subprocess.Popen(ssh_command, stdout=devnull, stderr=devnull) - else: - process = subprocess.Popen(ssh_command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - timeout_timer = None - if timeout_secs: - timeout_timer = threading.Timer(timeout_secs, process.kill) - timeout_timer.start() - - if not silent: - for line in process.stdout: - print(line) - - process.wait() - if timeout_timer: - timeout_timer.cancel() - if process.returncode == -9: - raise Exception('Timeout when executing \"%s\".' % ' '.join(command)) - - return process.returncode + retval, _, _ = SubprocessCallWithTimeout(ssh_command, silent, timeout_secs) + return retval def RunCommandPiped(self, command, stdout, stderr, ssh_args = None, **kwargs):
diff --git a/build/fuchsia/target.py b/build/fuchsia/target.py index 254c5fd..c030206 100644 --- a/build/fuchsia/target.py +++ b/build/fuchsia/target.py
@@ -2,17 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import boot_data import common import json import logging import os import remote_cmd import runner_logs -import shutil import subprocess -import sys -import tempfile import time @@ -71,6 +67,20 @@ self._target_cpu = target_cpu self._command_runner = None + @staticmethod + def RegisterArgs(arg_parser): + common_args = arg_parser.add_argument_group( + 'target', 'Arguments that apply to all targets.') + common_args.add_argument( + '--output-dir', + type=os.path.realpath, + default=os.getcwd(), + help=('Path to the directory in which build files are located. ' + 'Defaults to current directory.')) + common_args.add_argument('--system-log-file', + help='File to write system logs to. Specify ' + '- to log to stdout.') + # Functions used by the Python context manager for teardown. def __enter__(self): return self
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py index 5033a245..eac7f6f 100755 --- a/build/fuchsia/test_runner.py +++ b/build/fuchsia/test_runner.py
@@ -7,15 +7,9 @@ """Deploys and runs a test package on a Fuchsia target.""" import argparse -import json -import logging import os import runner_logs -import socket -import subprocess import sys -import tempfile -import time from common_args import AddCommonArgs, ConfigureLogging, GetDeploymentTargetForArgs from net_test_server import SetupTestServer @@ -63,7 +57,7 @@ type=int, help='Sets the limit of test batch to run in a single ' 'process.') - # --test-launcher-filter-file is specified relative to --output-directory, + # --test-launcher-filter-file is specified relative to --output-dir, # so specifying type=os.path.* will break it. parser.add_argument('--test-launcher-filter-file', default=None, @@ -87,9 +81,9 @@ help='Arguments for the test process.') args = parser.parse_args() - # Flag output_directory is required for tests launched with this script. - if not args.output_directory: - raise ValueError("output-directory must be specified.") + # Flag output_dir is required for tests launched with this script. + if not args.output_dir: + raise ValueError("output-dir must be specified.") ConfigureLogging(args) @@ -120,7 +114,7 @@ if args.device == 'device': test_concurrency = DEFAULT_TEST_SERVER_CONCURRENCY else: - test_concurrency = args.qemu_cpu_cores + test_concurrency = args.cpu_cores if test_concurrency: child_args.append('--test-launcher-jobs=%d' % test_concurrency) @@ -143,7 +137,7 @@ child_args.extend(args.child_args) try: - with GetDeploymentTargetForArgs(args) as target, \ + with GetDeploymentTargetForArgs() as target, \ SystemLogReader() as system_logger, \ RunnerLogManager(args.runner_logs_dir, BuildIdsPaths(args.package)): target.Start() @@ -163,9 +157,8 @@ args.package_name) run_package_args = RunPackageArgs.FromCommonArgs(args) - returncode = RunPackage( - args.output_directory, target, args.package, args.package_name, - child_args, run_package_args) + returncode = RunPackage(args.output_dir, target, args.package, + args.package_name, child_args, run_package_args) if test_server: test_server.Stop()
diff --git a/build/linux/sysroot_scripts/libwayland-client-symbols b/build/linux/sysroot_scripts/libwayland-client-symbols index d6bffeb..6e8a01f 100644 --- a/build/linux/sysroot_scripts/libwayland-client-symbols +++ b/build/linux/sysroot_scripts/libwayland-client-symbols
@@ -1,74 +1,75 @@ libwayland-client.so.0 libwayland-client0 #MINVER# - wl_array_add@Base 1.4.0 - wl_array_copy@Base 1.4.0 - wl_array_init@Base 1.4.0 - wl_array_release@Base 1.4.0 - wl_buffer_interface@Base 1.4.0 - wl_callback_interface@Base 1.4.0 - wl_compositor_interface@Base 1.4.0 - wl_data_device_interface@Base 1.4.0 - wl_data_device_manager_interface@Base 1.4.0 - wl_data_offer_interface@Base 1.4.0 - wl_data_source_interface@Base 1.4.0 - wl_display_cancel_read@Base 1.4.0 - wl_display_connect@Base 1.4.0 - wl_display_connect_to_fd@Base 1.4.0 - wl_display_create_queue@Base 1.4.0 - wl_display_disconnect@Base 1.4.0 - wl_display_dispatch@Base 1.4.0 - wl_display_dispatch_pending@Base 1.4.0 - wl_display_dispatch_queue@Base 1.4.0 - wl_display_dispatch_queue_pending@Base 1.4.0 - wl_display_flush@Base 1.4.0 - wl_display_get_error@Base 1.4.0 - wl_display_get_fd@Base 1.4.0 - wl_display_get_protocol_error@Base 1.4.0 - wl_display_interface@Base 1.4.0 - wl_display_prepare_read@Base 1.4.0 - wl_display_prepare_read_queue@Base 1.4.0 - wl_display_read_events@Base 1.4.0 - wl_display_roundtrip@Base 1.4.0 - wl_display_roundtrip_queue@Base 1.4.0 - wl_event_queue_destroy@Base 1.4.0 - wl_keyboard_interface@Base 1.4.0 - wl_list_empty@Base 1.4.0 - wl_list_init@Base 1.4.0 - wl_list_insert@Base 1.4.0 - wl_list_insert_list@Base 1.4.0 - wl_list_length@Base 1.4.0 - wl_list_remove@Base 1.4.0 - wl_log_set_handler_client@Base 1.4.0 - wl_output_interface@Base 1.4.0 - wl_pointer_interface@Base 1.4.0 - wl_proxy_add_dispatcher@Base 1.4.0 - wl_proxy_add_listener@Base 1.4.0 - wl_proxy_create@Base 1.4.0 - wl_proxy_create_wrapper@Base 1.4.0 - wl_proxy_destroy@Base 1.4.0 - wl_proxy_get_class@Base 1.4.0 - wl_proxy_get_id@Base 1.4.0 - wl_proxy_get_listener@Base 1.4.0 - wl_proxy_get_tag@Base 1.4.0 - wl_proxy_get_user_data@Base 1.4.0 - wl_proxy_get_version@Base 1.4.0 - wl_proxy_marshal@Base 1.4.0 - wl_proxy_marshal_array@Base 1.4.0 - wl_proxy_marshal_array_constructor@Base 1.4.0 - wl_proxy_marshal_array_constructor_versioned@Base 1.4.0 - wl_proxy_marshal_constructor@Base 1.4.0 - wl_proxy_marshal_constructor_versioned@Base 1.4.0 - wl_proxy_set_queue@Base 1.4.0 - wl_proxy_set_tag@Base 1.4.0 - wl_proxy_set_user_data@Base 1.4.0 - wl_proxy_wrapper_destroy@Base 1.4.0 - wl_region_interface@Base 1.4.0 - wl_registry_interface@Base 1.4.0 - wl_seat_interface@Base 1.4.0 - wl_shell_interface@Base 1.4.0 - wl_shell_surface_interface@Base 1.4.0 - wl_shm_interface@Base 1.4.0 - wl_shm_pool_interface@Base 1.4.0 - wl_subcompositor_interface@Base 1.4.0 - wl_subsurface_interface@Base 1.4.0 - wl_surface_interface@Base 1.4.0 - wl_touch_interface@Base 1.4.0 +* Build-Depends-Package: libwayland-dev + wl_array_add@Base 1.0.2 + wl_array_copy@Base 1.0.2 + wl_array_init@Base 1.0.2 + wl_array_release@Base 1.0.2 + wl_buffer_interface@Base 1.0.2 + wl_callback_interface@Base 1.0.2 + wl_compositor_interface@Base 1.0.2 + wl_data_device_interface@Base 1.0.2 + wl_data_device_manager_interface@Base 1.0.2 + wl_data_offer_interface@Base 1.0.2 + wl_data_source_interface@Base 1.0.2 + wl_display_cancel_read@Base 1.2.0 + wl_display_connect@Base 1.0.2 + wl_display_connect_to_fd@Base 1.0.2 + wl_display_create_queue@Base 1.0.2 + wl_display_disconnect@Base 1.0.2 + wl_display_dispatch@Base 1.0.2 + wl_display_dispatch_pending@Base 1.0.2 + wl_display_dispatch_queue@Base 1.0.2 + wl_display_dispatch_queue_pending@Base 1.0.2 + wl_display_flush@Base 1.0.2 + wl_display_get_error@Base 1.0.2 + wl_display_get_fd@Base 1.0.2 + wl_display_get_protocol_error@Base 1.5.91 + wl_display_interface@Base 1.0.2 + wl_display_prepare_read@Base 1.2.0 + wl_display_prepare_read_queue@Base 1.2.0 + wl_display_read_events@Base 1.2.0 + wl_display_roundtrip@Base 1.0.2 + wl_display_roundtrip_queue@Base 1.5.91 + wl_event_queue_destroy@Base 1.0.2 + wl_keyboard_interface@Base 1.0.2 + wl_list_empty@Base 1.0.2 + wl_list_init@Base 1.0.2 + wl_list_insert@Base 1.0.2 + wl_list_insert_list@Base 1.0.2 + wl_list_length@Base 1.0.2 + wl_list_remove@Base 1.0.2 + wl_log_set_handler_client@Base 1.0.2 + wl_output_interface@Base 1.0.2 + wl_pointer_interface@Base 1.0.2 + wl_proxy_add_dispatcher@Base 1.3.0 + wl_proxy_add_listener@Base 1.0.2 + wl_proxy_create@Base 1.0.2 + wl_proxy_create_wrapper@Base 1.11.0 + wl_proxy_destroy@Base 1.0.2 + wl_proxy_get_class@Base 1.1.0 + wl_proxy_get_id@Base 1.0.2 + wl_proxy_get_listener@Base 1.3.0 + wl_proxy_get_tag@Base 1.17.93 + wl_proxy_get_user_data@Base 1.0.2 + wl_proxy_get_version@Base 1.9.91 + wl_proxy_marshal@Base 1.0.2 + wl_proxy_marshal_array@Base 1.3.0 + wl_proxy_marshal_array_constructor@Base 1.3.92 + wl_proxy_marshal_array_constructor_versioned@Base 1.9.91 + wl_proxy_marshal_constructor@Base 1.3.92 + wl_proxy_marshal_constructor_versioned@Base 1.9.91 + wl_proxy_set_queue@Base 1.0.2 + wl_proxy_set_tag@Base 1.17.93 + wl_proxy_set_user_data@Base 1.0.2 + wl_proxy_wrapper_destroy@Base 1.11.0 + wl_region_interface@Base 1.0.2 + wl_registry_interface@Base 1.0.2 + wl_seat_interface@Base 1.0.2 + wl_shell_interface@Base 1.0.2 + wl_shell_surface_interface@Base 1.0.2 + wl_shm_interface@Base 1.0.2 + wl_shm_pool_interface@Base 1.0.2 + wl_subcompositor_interface@Base 1.3.92 + wl_subsurface_interface@Base 1.3.92 + wl_surface_interface@Base 1.0.2 + wl_touch_interface@Base 1.0.2
diff --git a/build/linux/sysroot_scripts/sysroots.json b/build/linux/sysroot_scripts/sysroots.json index aaa3eda..e7a9b326 100644 --- a/build/linux/sysroot_scripts/sysroots.json +++ b/build/linux/sysroot_scripts/sysroots.json
@@ -1,36 +1,36 @@ { "sid_amd64": { - "Sha1Sum": "cc396d2ee91286924b377c2124b1efbcad7df8f2", + "Sha1Sum": "5f64b417e1018dcf8fcc81dc2714e0f264b9b911", "SysrootDir": "debian_sid_amd64-sysroot", "Tarball": "debian_sid_amd64_sysroot.tar.xz" }, "sid_arm": { - "Sha1Sum": "019d07229d7cc18fd808e210a25a307e9c52c81b", + "Sha1Sum": "c2e54f675b83a61301dcdb22e8e7a2b85c01d58c", "SysrootDir": "debian_sid_arm-sysroot", "Tarball": "debian_sid_arm_sysroot.tar.xz" }, "sid_arm64": { - "Sha1Sum": "dc0edfa18ab4467282be4ca4b3b7df7d1a4ff81c", + "Sha1Sum": "ef67b6ca8fd6e2e51515a243d043d1ea4caf45e6", "SysrootDir": "debian_sid_arm64-sysroot", "Tarball": "debian_sid_arm64_sysroot.tar.xz" }, "sid_armel": { - "Sha1Sum": "c76dc40268302fc585ecfb8677aebd6eb4473d41", + "Sha1Sum": "4ccbe0db925a5ab39ba52cbe601535f97be05372", "SysrootDir": "debian_sid_armel-sysroot", "Tarball": "debian_sid_armel_sysroot.tar.xz" }, "sid_i386": { - "Sha1Sum": "328009b4502a9e45df905115d79582ed8cd60a0e", + "Sha1Sum": "d967bcef40477dbc39acef141ff22bf73f3e7cdb", "SysrootDir": "debian_sid_i386-sysroot", "Tarball": "debian_sid_i386_sysroot.tar.xz" }, "sid_mips": { - "Sha1Sum": "d5db6c30ec4f0cd12033eeacad04f42f505ff48f", + "Sha1Sum": "2758d766faa0c73da18128a4d46580ade68d3eea", "SysrootDir": "debian_sid_mips-sysroot", "Tarball": "debian_sid_mips_sysroot.tar.xz" }, "sid_mips64el": { - "Sha1Sum": "abe00d71ee077ba492a82229d87cd10d6b6a9026", + "Sha1Sum": "0edb979c932d207076c3986403a198387a4a8aa9", "SysrootDir": "debian_sid_mips64el-sysroot", "Tarball": "debian_sid_mips64el_sysroot.tar.xz" }
diff --git a/cc/input/scrollbar.h b/cc/input/scrollbar.h index 4fc7a3e..cbfdd310 100644 --- a/cc/input/scrollbar.h +++ b/cc/input/scrollbar.h
@@ -27,9 +27,9 @@ namespace cc { -enum ScrollbarOrientation { HORIZONTAL, VERTICAL }; +enum class ScrollbarOrientation { HORIZONTAL, VERTICAL }; -enum ScrollbarPart { +enum class ScrollbarPart { THUMB, TRACK_BUTTONS_TICKMARKS, // for PartNeedsRepaint() and PaintPart() only. BACK_BUTTON,
diff --git a/cc/input/scrollbar_animation_controller.cc b/cc/input/scrollbar_animation_controller.cc index 39d3ec0..89861d6 100644 --- a/cc/input/scrollbar_animation_controller.cc +++ b/cc/input/scrollbar_animation_controller.cc
@@ -50,7 +50,7 @@ fade_duration_(fade_duration), need_trigger_scrollbar_fade_in_(false), is_animating_(false), - animation_change_(NONE), + animation_change_(AnimationChange::NONE), scroll_element_id_(scroll_element_id), opacity_(initial_opacity), show_scrollbars_on_scroll_gesture_(false), @@ -70,7 +70,7 @@ fade_duration_(fade_duration), need_trigger_scrollbar_fade_in_(false), is_animating_(false), - animation_change_(NONE), + animation_change_(AnimationChange::NONE), scroll_element_id_(scroll_element_id), opacity_(initial_opacity), show_scrollbars_on_scroll_gesture_(true), @@ -102,7 +102,7 @@ } void ScrollbarAnimationController::StartAnimation() { - DCHECK(animation_change_ != NONE); + DCHECK(animation_change_ != AnimationChange::NONE); delayed_scrollbar_animation_.Cancel(); need_trigger_scrollbar_fade_in_ = false; is_animating_ = true; @@ -114,7 +114,7 @@ delayed_scrollbar_animation_.Cancel(); need_trigger_scrollbar_fade_in_ = false; is_animating_ = false; - animation_change_ = NONE; + animation_change_ = AnimationChange::NONE; } void ScrollbarAnimationController::PostDelayedAnimation( @@ -137,7 +137,7 @@ } if (is_animating_) { - DCHECK(animation_change_ != NONE); + DCHECK(animation_change_ != AnimationChange::NONE); if (last_awaken_time_.is_null()) last_awaken_time_ = now; @@ -166,8 +166,8 @@ void ScrollbarAnimationController::RunAnimationFrame(float progress) { float opacity; - DCHECK(animation_change_ != NONE); - if (animation_change_ == FADE_IN) { + DCHECK(animation_change_ != AnimationChange::NONE); + if (animation_change_ == AnimationChange::FADE_IN) { opacity = std::max(progress, opacity_); } else { opacity = std::min(1.f - progress, opacity_); @@ -194,9 +194,9 @@ // Overlay) and mouse is near or tickmarks show. if (need_thinning_animation_) { if (!MouseIsNearAnyScrollbar() && !tickmarks_showing_) - PostDelayedAnimation(FADE_OUT); + PostDelayedAnimation(AnimationChange::FADE_OUT); } else { - PostDelayedAnimation(FADE_OUT); + PostDelayedAnimation(AnimationChange::FADE_OUT); } if (need_thinning_animation_) { @@ -251,7 +251,7 @@ if (!Captured()) { if (MouseIsNearAnyScrollbar() && ScrollbarsHidden()) { - PostDelayedAnimation(FADE_IN); + PostDelayedAnimation(AnimationChange::FADE_IN); need_trigger_scrollbar_fade_in_ = true; } return; @@ -261,7 +261,7 @@ horizontal_controller_->DidMouseUp(); if (!MouseIsNearAnyScrollbar() && !ScrollbarsHidden() && !tickmarks_showing_) - PostDelayedAnimation(FADE_OUT); + PostDelayedAnimation(AnimationChange::FADE_OUT); } void ScrollbarAnimationController::DidMouseLeave() { @@ -277,7 +277,7 @@ if (ScrollbarsHidden() || Captured() || tickmarks_showing_) return; - PostDelayedAnimation(FADE_OUT); + PostDelayedAnimation(AnimationChange::FADE_OUT); } void ScrollbarAnimationController::DidMouseMove( @@ -304,7 +304,7 @@ if (need_trigger_scrollbar_fade_in_before != need_trigger_scrollbar_fade_in_) { if (need_trigger_scrollbar_fade_in_) { - PostDelayedAnimation(FADE_IN); + PostDelayedAnimation(AnimationChange::FADE_IN); } else { delayed_scrollbar_animation_.Cancel(); } @@ -314,7 +314,7 @@ Show(); StopAnimation(); } else if (!is_animating_) { - PostDelayedAnimation(FADE_OUT); + PostDelayedAnimation(AnimationChange::FADE_OUT); } } } @@ -352,8 +352,10 @@ bool ScrollbarAnimationController::Captured() const { DCHECK(need_thinning_animation_); - return GetScrollbarAnimationController(VERTICAL).captured() || - GetScrollbarAnimationController(HORIZONTAL).captured(); + return GetScrollbarAnimationController(ScrollbarOrientation::VERTICAL) + .captured() || + GetScrollbarAnimationController(ScrollbarOrientation::HORIZONTAL) + .captured(); } void ScrollbarAnimationController::Show() {
diff --git a/cc/input/scrollbar_animation_controller.h b/cc/input/scrollbar_animation_controller.h index 1f2c22a..f47fe8f 100644 --- a/cc/input/scrollbar_animation_controller.h +++ b/cc/input/scrollbar_animation_controller.h
@@ -95,7 +95,7 @@ private: // Describes whether the current animation should FadeIn or FadeOut. - enum AnimationChange { NONE, FADE_IN, FADE_OUT }; + enum class AnimationChange { NONE, FADE_IN, FADE_OUT }; ScrollbarAnimationController(ElementId scroll_element_id, ScrollbarAnimationControllerClient* client,
diff --git a/cc/input/scrollbar_animation_controller_unittest.cc b/cc/input/scrollbar_animation_controller_unittest.cc index 985f45b..53c2252 100644 --- a/cc/input/scrollbar_animation_controller_unittest.cc +++ b/cc/input/scrollbar_animation_controller_unittest.cc
@@ -79,9 +79,11 @@ scroll_layer_ = AddLayer<LayerImpl>(); h_scrollbar_layer_ = AddLayer<SolidColorScrollbarLayerImpl>( - HORIZONTAL, kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); + ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar); v_scrollbar_layer_ = AddLayer<SolidColorScrollbarLayerImpl>( - VERTICAL, kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); + ScrollbarOrientation::VERTICAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar); SetElementIdsForTesting(); clip_layer_ = root_layer(); @@ -1341,7 +1343,9 @@ base::TimeDelta::FromSeconds(3), 0.0f); } - virtual ScrollbarOrientation orientation() const { return HORIZONTAL; } + virtual ScrollbarOrientation orientation() const { + return ScrollbarOrientation::HORIZONTAL; + } std::unique_ptr<ScrollbarAnimationController> scrollbar_controller_; LayerImpl* scroll_layer_; @@ -1356,7 +1360,9 @@ class VerticalScrollbarAnimationControllerAndroidTest : public ScrollbarAnimationControllerAndroidTest { protected: - ScrollbarOrientation orientation() const override { return VERTICAL; } + ScrollbarOrientation orientation() const override { + return ScrollbarOrientation::VERTICAL; + } }; TEST_F(ScrollbarAnimationControllerAndroidTest, HiddenInBegin) { @@ -1403,7 +1409,7 @@ TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnResize) { EXPECT_EQ(gfx::Size(200, 200), scroll_layer_->bounds()); - EXPECT_EQ(HORIZONTAL, scrollbar_layer_->orientation()); + EXPECT_EQ(ScrollbarOrientation::HORIZONTAL, scrollbar_layer_->orientation()); // Shrink along X axis, horizontal scrollbar should appear. GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(100, 200); @@ -1426,7 +1432,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnResize) { EXPECT_EQ(gfx::Size(200, 200), scroll_layer_->bounds()); - EXPECT_EQ(VERTICAL, scrollbar_layer_->orientation()); + EXPECT_EQ(ScrollbarOrientation::VERTICAL, scrollbar_layer_->orientation()); // Shrink along X axis, vertical scrollbar should remain invisible. GetScrollNode(scroll_layer_)->container_bounds = gfx::Size(100, 200); @@ -1446,7 +1452,7 @@ } TEST_F(ScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableHorz) { - EXPECT_EQ(HORIZONTAL, scrollbar_layer_->orientation()); + EXPECT_EQ(ScrollbarOrientation::HORIZONTAL, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_)->user_scrollable_horizontal = false; UpdateActiveTreeDrawProperties(); @@ -1456,7 +1462,7 @@ } TEST_F(ScrollbarAnimationControllerAndroidTest, ShowOnUserNonScrollableVert) { - EXPECT_EQ(HORIZONTAL, scrollbar_layer_->orientation()); + EXPECT_EQ(ScrollbarOrientation::HORIZONTAL, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_)->user_scrollable_vertical = false; UpdateActiveTreeDrawProperties(); @@ -1467,7 +1473,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, HideOnUserNonScrollableVert) { - EXPECT_EQ(VERTICAL, scrollbar_layer_->orientation()); + EXPECT_EQ(ScrollbarOrientation::VERTICAL, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_)->user_scrollable_vertical = false; UpdateActiveTreeDrawProperties(); @@ -1478,7 +1484,7 @@ TEST_F(VerticalScrollbarAnimationControllerAndroidTest, ShowOnUserNonScrollableHorz) { - EXPECT_EQ(VERTICAL, scrollbar_layer_->orientation()); + EXPECT_EQ(ScrollbarOrientation::VERTICAL, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_)->user_scrollable_horizontal = false; UpdateActiveTreeDrawProperties();
diff --git a/cc/input/scrollbar_controller.h b/cc/input/scrollbar_controller.h index 9551131..6a9ccb4 100644 --- a/cc/input/scrollbar_controller.h +++ b/cc/input/scrollbar_controller.h
@@ -152,7 +152,7 @@ // "Autoscroll" here means the continuous scrolling that occurs when the // pointer is held down on a hit-testable area of the scrollbar such as an // arrows of the track itself. - enum AutoScrollDirection { AUTOSCROLL_FORWARD, AUTOSCROLL_BACKWARD }; + enum class AutoScrollDirection { AUTOSCROLL_FORWARD, AUTOSCROLL_BACKWARD }; struct CC_EXPORT AutoScrollState { // Can only be either AUTOSCROLL_FORWARD or AUTOSCROLL_BACKWARD.
diff --git a/cc/input/single_scrollbar_animation_controller_thinning.cc b/cc/input/single_scrollbar_animation_controller_thinning.cc index 9cc85ab..75a4586 100644 --- a/cc/input/single_scrollbar_animation_controller_thinning.cc +++ b/cc/input/single_scrollbar_animation_controller_thinning.cc
@@ -61,7 +61,7 @@ mouse_is_over_scrollbar_thumb_(false), mouse_is_near_scrollbar_thumb_(false), mouse_is_near_scrollbar_track_(false), - thickness_change_(NONE), + thickness_change_(AnimationChange::NONE), thinning_duration_(thinning_duration) { ApplyThumbThicknessScale(kIdleThicknessScale); } @@ -112,7 +112,7 @@ client_->SetNeedsRedrawForScrollbarAnimation(); if (progress == 1.f) { StopAnimation(); - thickness_change_ = NONE; + thickness_change_ = AnimationChange::NONE; } } @@ -143,10 +143,10 @@ StopAnimation(); if (!mouse_is_near_scrollbar_thumb_) { - thickness_change_ = DECREASE; + thickness_change_ = AnimationChange::DECREASE; StartAnimation(); } else { - thickness_change_ = NONE; + thickness_change_ = AnimationChange::NONE; } } @@ -161,7 +161,7 @@ if (captured_) return; - thickness_change_ = DECREASE; + thickness_change_ = AnimationChange::DECREASE; StartAnimation(); } @@ -188,7 +188,9 @@ if (!captured_ && mouse_is_near_scrollbar_thumb != mouse_is_near_scrollbar_thumb_) { - thickness_change_ = mouse_is_near_scrollbar_thumb ? INCREASE : DECREASE; + thickness_change_ = mouse_is_near_scrollbar_thumb + ? AnimationChange::INCREASE + : AnimationChange::DECREASE; StartAnimation(); } mouse_is_near_scrollbar_thumb_ = mouse_is_near_scrollbar_thumb; @@ -197,9 +199,11 @@ float SingleScrollbarAnimationControllerThinning::ThumbThicknessScaleAt( float progress) { - if (thickness_change_ == NONE) + if (thickness_change_ == AnimationChange::NONE) return mouse_is_near_scrollbar_thumb_ ? 1.f : kIdleThicknessScale; - float factor = thickness_change_ == INCREASE ? progress : (1.f - progress); + float factor = thickness_change_ == AnimationChange::INCREASE + ? progress + : (1.f - progress); return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale; } @@ -210,9 +214,11 @@ float min_value, float max_value) { float result; - if (animation_change == INCREASE && current_value > new_value) + if (animation_change == AnimationChange::INCREASE && + current_value > new_value) result = current_value; - else if (animation_change == DECREASE && current_value < new_value) + else if (animation_change == AnimationChange::DECREASE && + current_value < new_value) result = current_value; else result = new_value;
diff --git a/cc/input/single_scrollbar_animation_controller_thinning.h b/cc/input/single_scrollbar_animation_controller_thinning.h index 96fe980..6f9d03d 100644 --- a/cc/input/single_scrollbar_animation_controller_thinning.h +++ b/cc/input/single_scrollbar_animation_controller_thinning.h
@@ -73,7 +73,7 @@ // Describes whether the current animation should INCREASE (thicken) // a bar or DECREASE it (thin). - enum AnimationChange { NONE, INCREASE, DECREASE }; + enum class AnimationChange { NONE, INCREASE, DECREASE }; float ThumbThicknessScaleAt(float progress); float AdjustScale(float new_value,
diff --git a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc index a14ae213..2bf4672 100644 --- a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc +++ b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc
@@ -71,7 +71,8 @@ const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer_ = AddLayer<SolidColorScrollbarLayerImpl>( - HORIZONTAL, kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); + ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar); scrollbar_layer_->SetBounds(gfx::Size(kThumbThickness, kTrackLength)); scrollbar_layer_->SetScrollElementId(scroll_layer->element_id()); @@ -86,7 +87,8 @@ UpdateActiveTreeDrawProperties(); scrollbar_controller_ = SingleScrollbarAnimationControllerThinning::Create( - scroll_layer->element_id(), HORIZONTAL, &client_, kThinningDuration); + scroll_layer->element_id(), ScrollbarOrientation::HORIZONTAL, &client_, + kThinningDuration); } std::unique_ptr<SingleScrollbarAnimationControllerThinning>
diff --git a/cc/layers/painted_overlay_scrollbar_layer.cc b/cc/layers/painted_overlay_scrollbar_layer.cc index 2014160a6..a6cfc88 100644 --- a/cc/layers/painted_overlay_scrollbar_layer.cc +++ b/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -66,7 +66,7 @@ PaintedOverlayScrollbarLayerImpl* scrollbar_layer = static_cast<PaintedOverlayScrollbarLayerImpl*>(layer); - if (orientation() == HORIZONTAL) { + if (orientation() == ScrollbarOrientation::HORIZONTAL) { scrollbar_layer->SetThumbThickness(thumb_size_.height()); scrollbar_layer->SetThumbLength(thumb_size_.width()); scrollbar_layer->SetTrackStart(track_rect_.x()); @@ -130,7 +130,7 @@ } bool PaintedOverlayScrollbarLayer::PaintThumbIfNeeded() { - if (!scrollbar_->NeedsRepaintPart(THUMB) && thumb_resource_) + if (!scrollbar_->NeedsRepaintPart(ScrollbarPart::THUMB) && thumb_resource_) return false; gfx::Size paint_size = scrollbar_->NinePatchThumbCanvasSize(); @@ -142,7 +142,7 @@ SkiaPaintCanvas canvas(skbitmap); canvas.clear(SK_ColorTRANSPARENT); - scrollbar_->PaintPart(&canvas, THUMB, gfx::Rect(paint_size)); + scrollbar_->PaintPart(&canvas, ScrollbarPart::THUMB, gfx::Rect(paint_size)); // Make sure that the pixels are no longer mutable to unavoid unnecessary // allocation and copying. skbitmap.setImmutable(); @@ -175,7 +175,7 @@ SkiaPaintCanvas canvas(skbitmap); canvas.clear(SK_ColorTRANSPARENT); - scrollbar_->PaintPart(&canvas, TRACK_BUTTONS_TICKMARKS, + scrollbar_->PaintPart(&canvas, ScrollbarPart::TRACK_BUTTONS_TICKMARKS, gfx::Rect(paint_size)); // Make sure that the pixels are no longer mutable to unavoid unnecessary // allocation and copying.
diff --git a/cc/layers/painted_overlay_scrollbar_layer_impl.cc b/cc/layers/painted_overlay_scrollbar_layer_impl.cc index ba485239..2706da80 100644 --- a/cc/layers/painted_overlay_scrollbar_layer_impl.cc +++ b/cc/layers/painted_overlay_scrollbar_layer_impl.cc
@@ -222,7 +222,9 @@ } float PaintedOverlayScrollbarLayerImpl::TrackLength() const { - return track_length_ + (orientation() == VERTICAL ? vertical_adjust() : 0); + return track_length_ + (orientation() == ScrollbarOrientation::VERTICAL + ? vertical_adjust() + : 0); } bool PaintedOverlayScrollbarLayerImpl::IsThumbResizable() const {
diff --git a/cc/layers/painted_overlay_scrollbar_layer_unittest.cc b/cc/layers/painted_overlay_scrollbar_layer_unittest.cc index d7ce388..92a0d76 100644 --- a/cc/layers/painted_overlay_scrollbar_layer_unittest.cc +++ b/cc/layers/painted_overlay_scrollbar_layer_unittest.cc
@@ -24,7 +24,7 @@ } void PaintPart(PaintCanvas*, ScrollbarPart part, const gfx::Rect&) override { - if (part == TRACK_BUTTONS_TICKMARKS) + if (part == ScrollbarPart::TRACK_BUTTONS_TICKMARKS) paint_tickmarks_called_ = true; }
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc index 1a3e05aa..8b682c5 100644 --- a/cc/layers/painted_scrollbar_layer.cc +++ b/cc/layers/painted_scrollbar_layer.cc
@@ -64,7 +64,7 @@ scrollbar_layer->SetBackButtonRect(back_button_rect_); scrollbar_layer->SetForwardButtonRect(forward_button_rect_); scrollbar_layer->SetTrackRect(track_rect_); - if (orientation() == HORIZONTAL) { + if (orientation() == ScrollbarOrientation::HORIZONTAL) { scrollbar_layer->SetThumbThickness(thumb_size_.height()); scrollbar_layer->SetThumbLength(thumb_size_.width()); } else { @@ -176,21 +176,24 @@ } if (!track_resource_ || - scrollbar_->NeedsRepaintPart(TRACK_BUTTONS_TICKMARKS)) { + scrollbar_->NeedsRepaintPart(ScrollbarPart::TRACK_BUTTONS_TICKMARKS)) { track_resource_ = ScopedUIResource::Create( layer_tree_host()->GetUIResourceManager(), - RasterizeScrollbarPart(size, scaled_size, TRACK_BUTTONS_TICKMARKS)); + RasterizeScrollbarPart(size, scaled_size, + ScrollbarPart::TRACK_BUTTONS_TICKMARKS)); SetNeedsPushProperties(); updated = true; } gfx::Size scaled_thumb_size = LayerSizeToContentSize(thumb_size_); if (has_thumb_ && !scaled_thumb_size.IsEmpty()) { - if (!thumb_resource_ || scrollbar_->NeedsRepaintPart(THUMB) || + if (!thumb_resource_ || + scrollbar_->NeedsRepaintPart(ScrollbarPart::THUMB) || scaled_thumb_size != thumb_resource_->GetBitmap(0, false).GetSize()) { thumb_resource_ = ScopedUIResource::Create( layer_tree_host()->GetUIResourceManager(), - RasterizeScrollbarPart(thumb_size_, scaled_thumb_size, THUMB)); + RasterizeScrollbarPart(thumb_size_, scaled_thumb_size, + ScrollbarPart::THUMB)); SetNeedsPushProperties(); updated = true; }
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc index 6d36154..b5f60854 100644 --- a/cc/layers/painted_scrollbar_layer_impl.cc +++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -210,7 +210,8 @@ } int PaintedScrollbarLayerImpl::TrackStart() const { - return orientation() == VERTICAL ? track_rect_.y() : track_rect_.x(); + return orientation() == ScrollbarOrientation::VERTICAL ? track_rect_.y() + : track_rect_.x(); } void PaintedScrollbarLayerImpl::SetBackButtonRect(gfx::Rect back_button_rect) { @@ -240,7 +241,7 @@ const gfx::Rect thumb_rect = ComputeThumbQuadRect(); const int rect_x = track_rect_.x(); const int rect_y = track_rect_.y(); - if (orientation() == HORIZONTAL) { + if (orientation() == ScrollbarOrientation::HORIZONTAL) { int width = thumb_rect.x() - rect_x; int height = track_rect_.height(); return gfx::Rect(rect_x, rect_y, width, height); @@ -254,7 +255,7 @@ gfx::Rect PaintedScrollbarLayerImpl::ForwardTrackRect() const { const gfx::Rect thumb_rect = ComputeThumbQuadRect(); const int track_end = TrackStart() + TrackLength(); - if (orientation() == HORIZONTAL) { + if (orientation() == ScrollbarOrientation::HORIZONTAL) { int rect_x = thumb_rect.right(); int rect_y = track_rect_.y(); int width = track_end - rect_x; @@ -277,7 +278,7 @@ } float PaintedScrollbarLayerImpl::TrackLength() const { - if (orientation() == VERTICAL) + if (orientation() == ScrollbarOrientation::VERTICAL) return track_rect_.height() + vertical_adjust(); else return track_rect_.width();
diff --git a/cc/layers/painted_scrollbar_layer_impl_unittest.cc b/cc/layers/painted_scrollbar_layer_impl_unittest.cc index a3805ba..11f47b40 100644 --- a/cc/layers/painted_scrollbar_layer_impl_unittest.cc +++ b/cc/layers/painted_scrollbar_layer_impl_unittest.cc
@@ -38,7 +38,7 @@ UIResourceBitmap track_bitmap(track_sk_bitmap); impl.host_impl()->CreateUIResource(track_uid, track_bitmap); - ScrollbarOrientation orientation = VERTICAL; + ScrollbarOrientation orientation = ScrollbarOrientation::VERTICAL; PaintedScrollbarLayerImpl* scrollbar_layer_impl = impl.AddLayer<PaintedScrollbarLayerImpl>(orientation, false, false);
diff --git a/cc/layers/painted_scrollbar_layer_unittest.cc b/cc/layers/painted_scrollbar_layer_unittest.cc index 6bb0855..0777fc0 100644 --- a/cc/layers/painted_scrollbar_layer_unittest.cc +++ b/cc/layers/painted_scrollbar_layer_unittest.cc
@@ -59,28 +59,36 @@ // yet been initialized. scrollbar->set_needs_repaint_thumb(false); scrollbar->set_needs_repaint_track(false); - EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(1); - EXPECT_CALL(*scrollbar, PaintPart(_, TRACK_BUTTONS_TICKMARKS, _)).Times(1); + EXPECT_CALL(*scrollbar, PaintPart(_, ScrollbarPart::THUMB, _)).Times(1); + EXPECT_CALL(*scrollbar, + PaintPart(_, ScrollbarPart::TRACK_BUTTONS_TICKMARKS, _)) + .Times(1); scrollbar_layer->Update(); Mock::VerifyAndClearExpectations(scrollbar.get()); // The next update will paint nothing because the first update caused a paint. - EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(0); - EXPECT_CALL(*scrollbar, PaintPart(_, TRACK_BUTTONS_TICKMARKS, _)).Times(0); + EXPECT_CALL(*scrollbar, PaintPart(_, ScrollbarPart::THUMB, _)).Times(0); + EXPECT_CALL(*scrollbar, + PaintPart(_, ScrollbarPart::TRACK_BUTTONS_TICKMARKS, _)) + .Times(0); scrollbar_layer->Update(); Mock::VerifyAndClearExpectations(scrollbar.get()); // Enable the thumb. - EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(1); - EXPECT_CALL(*scrollbar, PaintPart(_, TRACK_BUTTONS_TICKMARKS, _)).Times(0); + EXPECT_CALL(*scrollbar, PaintPart(_, ScrollbarPart::THUMB, _)).Times(1); + EXPECT_CALL(*scrollbar, + PaintPart(_, ScrollbarPart::TRACK_BUTTONS_TICKMARKS, _)) + .Times(0); scrollbar->set_needs_repaint_thumb(true); scrollbar->set_needs_repaint_track(false); scrollbar_layer->Update(); Mock::VerifyAndClearExpectations(scrollbar.get()); // Enable the track. - EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(0); - EXPECT_CALL(*scrollbar, PaintPart(_, TRACK_BUTTONS_TICKMARKS, _)).Times(1); + EXPECT_CALL(*scrollbar, PaintPart(_, ScrollbarPart::THUMB, _)).Times(0); + EXPECT_CALL(*scrollbar, + PaintPart(_, ScrollbarPart::TRACK_BUTTONS_TICKMARKS, _)) + .Times(1); scrollbar->set_needs_repaint_thumb(false); scrollbar->set_needs_repaint_track(true); scrollbar_layer->Update();
diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc index 787f339..3d9e48d 100644 --- a/cc/layers/scrollbar_layer_impl_base.cc +++ b/cc/layers/scrollbar_layer_impl_base.cc
@@ -227,7 +227,7 @@ thumb_thickness * (1.f - thumb_thickness_scale_factor); gfx::RectF thumb_rect; - if (orientation_ == HORIZONTAL) { + if (orientation_ == ScrollbarOrientation::HORIZONTAL) { thumb_rect = gfx::RectF(thumb_offset, vertical_adjust_ + thumb_thickness_adjustment, thumb_length,
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index 6da184e2..ee02df5 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -315,7 +315,8 @@ base::MakeRefCounted<FakeNinePatchScrollbar>()); painted_overlay_scrollbar_layer->SetScrollElementId(layer_a->element_id()); scoped_refptr<SolidColorScrollbarLayer> solid_color_scrollbar_layer = - SolidColorScrollbarLayer::Create(VERTICAL, 1, 1, false); + SolidColorScrollbarLayer::Create(ScrollbarOrientation::VERTICAL, 1, 1, + false); solid_color_scrollbar_layer->SetScrollElementId(layer_a->element_id()); layer_tree_host_->SetRootLayer(layer_tree_root); @@ -553,8 +554,9 @@ scoped_refptr<Layer> root_layer = Layer::Create(); // Create an overlay left side vertical scrollbar. scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer = - FakePaintedScrollbarLayer::Create(false, true, VERTICAL, true, true, - root_layer->element_id()); + FakePaintedScrollbarLayer::Create(false, true, + ScrollbarOrientation::VERTICAL, true, + true, root_layer->element_id()); root_layer->SetScrollable(gfx::Size(20, 50)); root_layer->SetBounds(gfx::Size(50, 100)); @@ -603,8 +605,8 @@ scoped_refptr<Layer> root = Layer::Create(); scoped_refptr<Layer> child = Layer::Create(); scoped_refptr<ScrollbarLayerBase> scrollbar_layer = - SolidColorScrollbarLayer::Create(HORIZONTAL, kThumbThickness, - kTrackStart, false); + SolidColorScrollbarLayer::Create(ScrollbarOrientation::HORIZONTAL, + kThumbThickness, kTrackStart, false); root->AddChild(child); root->AddChild(scrollbar_layer); layer_tree_host_->SetRootLayer(root); @@ -673,7 +675,8 @@ scoped_refptr<Layer> child1 = Layer::Create(); const bool kIsLeftSideVerticalScrollbar = false; scoped_refptr<SolidColorScrollbarLayer> child2 = - SolidColorScrollbarLayer::Create(HORIZONTAL, kThumbThickness, kTrackStart, + SolidColorScrollbarLayer::Create(ScrollbarOrientation::HORIZONTAL, + kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); child2->SetScrollElementId(scroll_layer->element_id()); scroll_layer->AddChild(child1); @@ -728,7 +731,8 @@ scoped_refptr<SolidColorScrollbarLayer> scrollbar_layer; const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( - HORIZONTAL, kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); + ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar); scrollbar_layer->SetScrollElementId(scroll_layer->element_id()); scrollbar_layer->SetElementId(ElementId(300)); scroll_layer->AddChild(child1); @@ -802,7 +806,8 @@ scoped_refptr<Layer> child1 = Layer::Create(); const bool kIsLeftSideVerticalScrollbar = false; scoped_refptr<SolidColorScrollbarLayer> scrollbar_layer = - SolidColorScrollbarLayer::Create(HORIZONTAL, kThumbThickness, kTrackStart, + SolidColorScrollbarLayer::Create(ScrollbarOrientation::HORIZONTAL, + kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); scrollbar_layer->SetScrollElementId(scroll_layer->element_id()); scroll_layer->AddChild(child1); @@ -847,9 +852,9 @@ const bool kIsLeftSideVerticalScrollbar = false; SolidColorScrollbarLayerImpl* scrollbar_layer = - impl.AddLayer<SolidColorScrollbarLayerImpl>(HORIZONTAL, kThumbThickness, - kTrackStart, - kIsLeftSideVerticalScrollbar); + impl.AddLayer<SolidColorScrollbarLayerImpl>( + ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar); scrollbar_layer->SetScrollElementId(scroll_layer->element_id()); scroll_layer->SetBounds(gfx::Size(980, 980)); @@ -887,9 +892,9 @@ const int kThumbThickness = 10; const bool kIsLeftSideVerticalScrollbar = false; SolidColorScrollbarLayerImpl* scrollbar_layer = - impl.AddLayer<SolidColorScrollbarLayerImpl>(HORIZONTAL, kThumbThickness, - kTrackStart, - kIsLeftSideVerticalScrollbar); + impl.AddLayer<SolidColorScrollbarLayerImpl>( + ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart, + kIsLeftSideVerticalScrollbar); scrollbar_layer->SetScrollElementId(scroll_layer->element_id()); EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); @@ -991,7 +996,8 @@ host_impl->ActivateSyncTree(); scoped_refptr<SolidColorScrollbarLayer> scrollbar_layer = - SolidColorScrollbarLayer::Create(HORIZONTAL, kThumbThickness, kTrackStart, + SolidColorScrollbarLayer::Create(ScrollbarOrientation::HORIZONTAL, + kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); scrollbar_layer->SetScrollElementId(scroll_layer->element_id()); scroll_layer->InsertChild(scrollbar_layer, 1); @@ -1021,11 +1027,11 @@ const bool kIsLeftSideVerticalScrollbar = false; horizontal_scrollbar_layer_ = SolidColorScrollbarLayerImpl::Create( - host_impl_->active_tree(), 1, HORIZONTAL, kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar); + host_impl_->active_tree(), 1, ScrollbarOrientation::HORIZONTAL, + kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); vertical_scrollbar_layer_ = SolidColorScrollbarLayerImpl::Create( - host_impl_->active_tree(), 2, VERTICAL, kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar); + host_impl_->active_tree(), 2, ScrollbarOrientation::VERTICAL, + kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); } protected: @@ -1116,7 +1122,7 @@ const int kTrackStart = 0; const bool kIsLeftSideVerticalScrollbar = false; scrollbar_layer = SolidColorScrollbarLayer::Create( - HORIZONTAL, kThumbThickness, kTrackStart, + ScrollbarOrientation::HORIZONTAL, kThumbThickness, kTrackStart, kIsLeftSideVerticalScrollbar); } else { auto scrollbar = base::MakeRefCounted<FakeScrollbar>();
diff --git a/cc/layers/solid_color_scrollbar_layer.cc b/cc/layers/solid_color_scrollbar_layer.cc index d446a39f..8fe21528 100644 --- a/cc/layers/solid_color_scrollbar_layer.cc +++ b/cc/layers/solid_color_scrollbar_layer.cc
@@ -22,7 +22,8 @@ scoped_refptr<Scrollbar> scrollbar, SolidColorScrollbarLayer* existing_layer) { DCHECK(scrollbar->IsOverlay()); - bool is_horizontal = scrollbar->Orientation() == HORIZONTAL; + bool is_horizontal = + scrollbar->Orientation() == ScrollbarOrientation::HORIZONTAL; gfx::Rect thumb_rect = scrollbar->ThumbRect(); int thumb_thickness = is_horizontal ? thumb_rect.height() : thumb_rect.width();
diff --git a/cc/layers/solid_color_scrollbar_layer_impl.cc b/cc/layers/solid_color_scrollbar_layer_impl.cc index e37741c..7c86df34 100644 --- a/cc/layers/solid_color_scrollbar_layer_impl.cc +++ b/cc/layers/solid_color_scrollbar_layer_impl.cc
@@ -58,7 +58,7 @@ if (thumb_thickness_ != -1) return thumb_thickness_; - if (orientation() == HORIZONTAL) + if (orientation() == ScrollbarOrientation::HORIZONTAL) return bounds().height(); else return bounds().width(); @@ -73,7 +73,7 @@ } float SolidColorScrollbarLayerImpl::TrackLength() const { - if (orientation() == HORIZONTAL) + if (orientation() == ScrollbarOrientation::HORIZONTAL) return bounds().width() - TrackStart() * 2; else return bounds().height() + vertical_adjust() - TrackStart() * 2;
diff --git a/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc b/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc index 8544ce17..7e87232 100644 --- a/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc +++ b/cc/layers/solid_color_scrollbar_layer_impl_unittest.cc
@@ -18,7 +18,7 @@ LayerTreeImplTestBase impl; - ScrollbarOrientation orientation = VERTICAL; + ScrollbarOrientation orientation = ScrollbarOrientation::VERTICAL; int thumb_thickness = layer_size.width(); int track_start = 0; bool is_left_side_vertical_scrollbar = false;
diff --git a/cc/test/fake_painted_scrollbar_layer.cc b/cc/test/fake_painted_scrollbar_layer.cc index 8dfb65d..2ee5547d 100644 --- a/cc/test/fake_painted_scrollbar_layer.cc +++ b/cc/test/fake_painted_scrollbar_layer.cc
@@ -13,7 +13,8 @@ bool paint_during_update, bool has_thumb, ElementId scrolling_element_id) { - return Create(paint_during_update, has_thumb, HORIZONTAL, false, false, + return Create(paint_during_update, has_thumb, + ScrollbarOrientation::HORIZONTAL, false, false, scrolling_element_id); }
diff --git a/cc/test/fake_scrollbar.cc b/cc/test/fake_scrollbar.cc index 0b63a1b..9613adb5 100644 --- a/cc/test/fake_scrollbar.cc +++ b/cc/test/fake_scrollbar.cc
@@ -62,7 +62,7 @@ } bool FakeScrollbar::NeedsRepaintPart(ScrollbarPart part) const { - if (part == THUMB) + if (part == ScrollbarPart::THUMB) return needs_repaint_thumb_; return needs_repaint_track_; }
diff --git a/cc/test/fake_scrollbar.h b/cc/test/fake_scrollbar.h index 6923618..37ddbad2 100644 --- a/cc/test/fake_scrollbar.h +++ b/cc/test/fake_scrollbar.h
@@ -72,7 +72,7 @@ bool should_paint_ = false; bool has_thumb_ = false; bool has_tickmarks_ = false; - ScrollbarOrientation orientation_ = HORIZONTAL; + ScrollbarOrientation orientation_ = ScrollbarOrientation::HORIZONTAL; bool is_left_side_vertical_scrollbar_ = false; bool is_solid_color_ = false; bool is_overlay_ = false;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 8a6918b..790258aa 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -489,7 +489,7 @@ squash2->SetOffsetToTransformParent(gfx::Vector2dF(220, 300)); auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, false, true); + layer_tree_impl, ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayer(scroll, scrollbar); scrollbar->SetBounds(scrollbar_size); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); @@ -1595,7 +1595,7 @@ content_size, scroll_content_size); auto* drawn_scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, false, true); + layer_tree_impl, ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayer(scroll, drawn_scrollbar); drawn_scrollbar->SetBounds(scrollbar_size); drawn_scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); @@ -3534,10 +3534,10 @@ // Add scrollbars. They will always exist - even if unscrollable - but their // visibility will be determined by whether the content can be scrolled. - auto* v_scrollbar = - AddLayer<PaintedScrollbarLayerImpl>(active_tree, VERTICAL, false, true); - auto* h_scrollbar = - AddLayer<PaintedScrollbarLayerImpl>(active_tree, HORIZONTAL, false, true); + auto* v_scrollbar = AddLayer<PaintedScrollbarLayerImpl>( + active_tree, ScrollbarOrientation::VERTICAL, false, true); + auto* h_scrollbar = AddLayer<PaintedScrollbarLayerImpl>( + active_tree, ScrollbarOrientation::HORIZONTAL, false, true); SetupScrollbarLayer(scroll, v_scrollbar); SetupScrollbarLayer(scroll, h_scrollbar); @@ -4968,7 +4968,8 @@ host_impl_->active_tree()->PushPageScaleFromMainThread(1, 1, 4); auto* scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 10, 0, false); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 10, 0, + false); SetupScrollbarLayer(OuterViewportScrollLayer(), scrollbar); host_impl_->active_tree()->DidBecomeActive(); @@ -5193,7 +5194,8 @@ LayerImpl* scroll = host_impl_->pending_tree()->OuterViewportScrollLayerForTesting(); auto* scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->pending_tree(), VERTICAL, 10, 0, false); + host_impl_->pending_tree(), ScrollbarOrientation::VERTICAL, 10, 0, + false); SetupScrollbarLayer(scroll, scrollbar); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(90, 0)); @@ -5297,7 +5299,7 @@ // scrollbar_1 on root scroll. scrollbar_1_ = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 15, 0, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 15, 0, true); SetupScrollbarLayer(root_scroll, scrollbar_1_); scrollbar_1_->SetBounds(scrollbar_size_1); TouchActionRegion touch_action_region; @@ -5310,7 +5312,7 @@ GetTransformNode(child)->post_translation = gfx::Vector2dF(50, 50); scrollbar_2_ = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 15, 0, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 15, 0, true); SetupScrollbarLayer(child, scrollbar_2_); scrollbar_2_->SetBounds(scrollbar_size_2); @@ -5429,7 +5431,7 @@ // scrollbar_1 on root scroll. auto* scrollbar_1 = AddLayer<PaintedScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, true, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, true, true); SetupScrollbarLayer(root_scroll, scrollbar_1); scrollbar_1->SetBounds(scrollbar_size_1); TouchActionRegion touch_action_region; @@ -5442,7 +5444,7 @@ // scrollbar_2 on child. auto* scrollbar_2 = AddLayer<PaintedScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, true, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, true, true); SetupScrollbarLayer(child, scrollbar_2); scrollbar_2->SetBounds(scrollbar_size_2); scrollbar_2->SetOffsetToTransformParent(gfx::Vector2dF(50, 50)); @@ -5515,7 +5517,7 @@ LayerImpl* scroll = host_impl_->pending_tree()->OuterViewportScrollLayerForTesting(); auto* scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->pending_tree(), VERTICAL, 10, 0, false); + host_impl_->pending_tree(), ScrollbarOrientation::VERTICAL, 10, 0, false); SetupScrollbarLayer(scroll, scrollbar); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(90, 0)); @@ -5580,7 +5582,7 @@ outer_viewport_size, content_size); LayerImpl* root_scroll = OuterViewportScrollLayer(); auto* horiz_scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - host_impl_->active_tree(), HORIZONTAL, true, true); + host_impl_->active_tree(), ScrollbarOrientation::HORIZONTAL, true, true); SetupScrollbarLayer(root_scroll, horiz_scrollbar); LayerImpl* child = AddLayer(); child->SetBounds(content_size); @@ -5606,19 +5608,19 @@ auto* container = InnerViewportScrollLayer(); auto* root_scroll = OuterViewportScrollLayer(); auto* vert_1_scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 5, 5, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 5, 5, true); CopyProperties(container, vert_1_scrollbar); auto* horiz_1_scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), HORIZONTAL, 5, 5, true); + host_impl_->active_tree(), ScrollbarOrientation::HORIZONTAL, 5, 5, true); CopyProperties(container, horiz_1_scrollbar); auto* vert_2_scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 5, 5, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 5, 5, true); CopyProperties(container, vert_2_scrollbar); auto* horiz_2_scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), HORIZONTAL, 5, 5, true); + host_impl_->active_tree(), ScrollbarOrientation::HORIZONTAL, 5, 5, true); CopyProperties(container, horiz_2_scrollbar); UpdateDrawProperties(host_impl_->active_tree()); @@ -5700,7 +5702,8 @@ const int kScrollbarThickness = 5; auto* vert_scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, kScrollbarThickness, 0, false); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, + kScrollbarThickness, 0, false); SetupScrollbarLayer(root_scroll, vert_scrollbar); vert_scrollbar->SetBounds(gfx::Size(10, 200)); vert_scrollbar->SetOffsetToTransformParent( @@ -5721,11 +5724,13 @@ // Move the mouse near the thumb while its at the viewport top. auto near_thumb_at_top = gfx::Point(295, kDistanceToTriggerThumb - 1); host_impl_->MouseMoveAt(near_thumb_at_top); - EXPECT_TRUE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); // Move the mouse away from the thumb. host_impl_->MouseMoveAt(gfx::Point(295, kDistanceToTriggerThumb + 1)); - EXPECT_FALSE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); // Scroll the page down which moves the thumb down to the viewport bottom. host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 800), @@ -5739,7 +5744,8 @@ // Move the mouse near the thumb in the top position. host_impl_->MouseMoveAt(near_thumb_at_top); - EXPECT_FALSE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); // Scroll the page up which moves the thumb back up. host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, -800), @@ -5753,7 +5759,8 @@ // Move the mouse near the thumb in the top position. host_impl_->MouseMoveAt(near_thumb_at_top); - EXPECT_TRUE(scrollbar_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); } void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( @@ -5773,7 +5780,7 @@ LayerImpl* root_scroll = OuterViewportScrollLayer(); // The scrollbar is on the left side. auto* scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 15, 0, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 15, 0, true); SetupScrollbarLayer(root_scroll, scrollbar); scrollbar->SetBounds(scrollbar_size); TouchActionRegion touch_action_region; @@ -5796,34 +5803,37 @@ host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerFadeIn, 1)); - EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerExpand - 1, 10)); - EXPECT_TRUE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerFadeIn, 100)); - EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); did_request_redraw_ = false; - EXPECT_FALSE( - scrollbar_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 10)); - EXPECT_TRUE( - scrollbar_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 0)); - EXPECT_TRUE( - scrollbar_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(150, 120)); - EXPECT_FALSE( - scrollbar_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); } TEST_P(ScrollUnifiedLayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) { @@ -6845,7 +6855,8 @@ // Create a horizontal scrollbar. gfx::Size scrollbar_size(gfx::Size(50, 15)); auto* scrollbar_layer = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), HORIZONTAL, 3, 20, false); + host_impl_->active_tree(), ScrollbarOrientation::HORIZONTAL, 3, 20, + false); SetupScrollbarLayer(OuterViewportScrollLayer(), scrollbar_layer); scrollbar_layer->SetBounds(scrollbar_size); TouchActionRegion touch_action_region; @@ -13544,8 +13555,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); - auto* scrollbar = AddLayer<PaintedOverlayScrollbarLayerImpl>(layer_tree_impl, - VERTICAL, false); + auto* scrollbar = AddLayer<PaintedOverlayScrollbarLayerImpl>( + layer_tree_impl, ScrollbarOrientation::VERTICAL, false); SetupScrollbarLayerCommon(scroll_layer, scrollbar); scrollbar->SetHitTestable(true); @@ -13610,8 +13621,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); - auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(layer_tree_impl, - VERTICAL, false, true); + auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( + layer_tree_impl, ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayerCommon(scroll_layer, scrollbar); scrollbar->SetHitTestable(true); @@ -13682,8 +13693,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); - auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(layer_tree_impl, - VERTICAL, false, true); + auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( + layer_tree_impl, ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayerCommon(scroll_layer, scrollbar); scrollbar->SetHitTestable(true); @@ -13732,8 +13743,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); - auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(layer_tree_impl, - VERTICAL, false, true); + auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( + layer_tree_impl, ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayer(scroll_layer, scrollbar); const gfx::Size scrollbar_size = gfx::Size(15, 600); scrollbar->SetBounds(scrollbar_size); @@ -13870,7 +13881,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, /*is_left_side_vertical_scrollbar*/ false, + layer_tree_impl, ScrollbarOrientation::VERTICAL, + /*is_left_side_vertical_scrollbar*/ false, /*is_overlay*/ false); SetupScrollbarLayer(scroll_layer, scrollbar); @@ -13942,7 +13954,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, /*is_left_side_vertical_scrollbar*/ false, + layer_tree_impl, ScrollbarOrientation::VERTICAL, + /*is_left_side_vertical_scrollbar*/ false, /*is_overlay*/ false); SetupScrollbarLayer(scroll_layer, scrollbar); @@ -14039,7 +14052,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, /*is_left_side_vertical_scrollbar*/ false, + layer_tree_impl, ScrollbarOrientation::VERTICAL, + /*is_left_side_vertical_scrollbar*/ false, /*is_overlay*/ false); // TODO(arakeri): crbug.com/1070063 Setting the dimensions for scrollbar parts @@ -14148,7 +14162,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, /*is_left_side_vertical_scrollbar*/ false, + layer_tree_impl, ScrollbarOrientation::VERTICAL, + /*is_left_side_vertical_scrollbar*/ false, /*is_overlay*/ false); // TODO(arakeri): crbug.com/1070063 Setting the dimensions for scrollbar parts @@ -14248,8 +14263,8 @@ // Set up the scrollbar and its dimensions. LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); - auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>(layer_tree_impl, - VERTICAL, false, true); + auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( + layer_tree_impl, ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayer(scroll_layer, scrollbar); const gfx::Size scrollbar_size = gfx::Size(15, 600); scrollbar->SetBounds(scrollbar_size); @@ -15548,7 +15563,7 @@ // scrollbar_1 on root scroll. auto* scrollbar_1 = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 15, 0, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 15, 0, true); SetupScrollbarLayer(root_scroll, scrollbar_1); scrollbar_1->SetBounds(scrollbar_size_1); TouchActionRegion touch_action_region; @@ -15576,64 +15591,69 @@ // moves back to where it was. host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerFadeIn, 0)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerExpand, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseMoveDistanceToTriggerExpand, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseMoveDistanceToTriggerExpand, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerExpand, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(15 + kMouseMoveDistanceToTriggerFadeIn, 0)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); // scrollbar_2 on child. auto* scrollbar_2 = AddLayer<SolidColorScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, 15, 0, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, 15, 0, true); LayerImpl* child = AddScrollableLayer(root_scroll, gfx::Size(100, 100), child_layer_size); child->SetOffsetToTransformParent(gfx::Vector2dF(50, 50)); @@ -15657,56 +15677,60 @@ // Mouse goes over scrollbar_2, moves close to scrollbar_2, moves close to // scrollbar_1, goes over scrollbar_1. host_impl_->MouseMoveAt(gfx::Point(60, 60)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); - EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(64 + kMouseMoveDistanceToTriggerExpand, 50)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); - EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_2_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_2_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt( gfx::Point(14 + kMouseMoveDistanceToTriggerExpand, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); host_impl_->MouseMoveAt(gfx::Point(10, 0)); - EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_TRUE( - scrollbar_1_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsNearScrollbar(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsNearScrollbarThumb(VERTICAL)); - EXPECT_FALSE( - scrollbar_2_animation_controller->MouseIsOverScrollbarThumb(VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_TRUE(scrollbar_1_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsNearScrollbar( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsNearScrollbarThumb( + ScrollbarOrientation::VERTICAL)); + EXPECT_FALSE(scrollbar_2_animation_controller->MouseIsOverScrollbarThumb( + ScrollbarOrientation::VERTICAL)); // Capture scrollbar_1, then move mouse to scrollbar_2's layer); animation_task_.Reset(); @@ -16815,7 +16839,7 @@ viewport_size, scroll_content_size); auto* scrollbar = AddLayer<SolidColorScrollbarLayerImpl>( - layer_tree_impl, VERTICAL, 10, 0, false); + layer_tree_impl, ScrollbarOrientation::VERTICAL, 10, 0, false); SetupScrollbarLayer(content, scrollbar); scrollbar->SetBounds(scrollbar_size); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); @@ -17024,7 +17048,7 @@ content_layer, gfx::Size(185, 500), gfx::Size(185, 3800)); auto* scrollbar = AddLayer<PaintedScrollbarLayerImpl>( - host_impl_->active_tree(), VERTICAL, false, true); + host_impl_->active_tree(), ScrollbarOrientation::VERTICAL, false, true); SetupScrollbarLayer(scroll_layer, scrollbar); scrollbar->SetBounds(gfx::Size(15, 500));
diff --git a/cc/trees/layer_tree_host_pixeltest_scrollbars.cc b/cc/trees/layer_tree_host_pixeltest_scrollbars.cc index 6677811b..2e45a74 100644 --- a/cc/trees/layer_tree_host_pixeltest_scrollbars.cc +++ b/cc/trees/layer_tree_host_pixeltest_scrollbars.cc
@@ -213,7 +213,7 @@ PaintedOverlayScrollbar() { set_should_paint(true); set_has_thumb(true); - set_orientation(VERTICAL); + set_orientation(ScrollbarOrientation::VERTICAL); set_is_overlay(true); set_thumb_size(gfx::Size(15, 50)); set_track_rect(gfx::Rect(0, 0, 15, 400));
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 0536e70..494475d 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -312,7 +312,7 @@ } for (auto* scrollbar : ScrollbarsFor(scrolling_element_id)) { - if (scrollbar->orientation() == HORIZONTAL) { + if (scrollbar->orientation() == ScrollbarOrientation::HORIZONTAL) { scrollbar->SetCurrentPos(current_offset.x()); scrollbar->SetClipLayerLength(bounds_size.width()); scrollbar->SetScrollLayerLength(scrolling_size.width()); @@ -675,7 +675,7 @@ return; for (ScrollbarLayerImplBase* scrollbar : controller->Scrollbars()) { - if (scrollbar->orientation() != VERTICAL) + if (scrollbar->orientation() != ScrollbarOrientation::VERTICAL) continue; // Android Overlay Scrollbar don't have FindInPage Tickmarks. @@ -1917,9 +1917,10 @@ return; auto* scrollbar_ids = &element_id_to_scrollbar_layer_ids_[scroll_element_id]; - int* scrollbar_layer_id = scrollbar_layer->orientation() == HORIZONTAL - ? &scrollbar_ids->horizontal - : &scrollbar_ids->vertical; + int* scrollbar_layer_id = + scrollbar_layer->orientation() == ScrollbarOrientation::HORIZONTAL + ? &scrollbar_ids->horizontal + : &scrollbar_ids->vertical; // We used to DCHECK this was not the case but this can occur on Android: as // the visual viewport supplies scrollbars for the outer viewport, if the @@ -1932,9 +1933,10 @@ // The scrollbar_ids could have been erased above so get it again. scrollbar_ids = &element_id_to_scrollbar_layer_ids_[scroll_element_id]; - scrollbar_layer_id = scrollbar_layer->orientation() == HORIZONTAL - ? &scrollbar_ids->horizontal - : &scrollbar_ids->vertical; + scrollbar_layer_id = + scrollbar_layer->orientation() == ScrollbarOrientation::HORIZONTAL + ? &scrollbar_ids->horizontal + : &scrollbar_ids->vertical; } *scrollbar_layer_id = scrollbar_layer->id(); @@ -1957,7 +1959,7 @@ return; auto& scrollbar_ids = element_id_to_scrollbar_layer_ids_[scroll_element_id]; - if (scrollbar_layer->orientation() == HORIZONTAL) + if (scrollbar_layer->orientation() == ScrollbarOrientation::HORIZONTAL) scrollbar_ids.horizontal = Layer::INVALID_ID; else scrollbar_ids.vertical = Layer::INVALID_ID;
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index d029559..ca09cd7c 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -168,7 +168,7 @@ # are currently duplicated in system_webview_apk_tmpl.gni. # Used only by alert dialog on tiny screens. - _material_package = "com_google_android_material_material.*" + _material_package = "com_google_android_material.*" resource_exclusion_regex += "|${_material_package}values-small" # Used only by date picker (which chrome doesn't use). @@ -182,7 +182,7 @@ resource_exclusion_regex += "|${_material_package}/drawable.*design_snackbar" resource_exclusion_regex += "|${_material_package}/xml.*badge_" - _material_package = "*com_google_android_material_material*" + _material_package = "*com_google_android_material*" resource_exclusion_exceptions += [ # AppBarLayout "${_material_package}design_appbar_*",
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java index 427db8d..1edafed8 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
@@ -1077,6 +1077,7 @@ @Test @MediumTest @CommandLineFlags.Add({BASE_PARAMS}) + @DisabledTest(message = "https://crbug.com/1122657") public void testThumbnailAspectRatio_default() { prepareTabs(2, 0, mUrl); enterTabSwitcher(mActivityTestRule.getActivity()); @@ -1087,6 +1088,7 @@ @Test @MediumTest @CommandLineFlags.Add({BASE_PARAMS + "/thumbnail_aspect_ratio/0.75"}) + @DisabledTest(message = "https://crbug.com/1122657") public void testThumbnailAspectRatio_point75() { prepareTabs(2, 0, mUrl); enterTabSwitcher(mActivityTestRule.getActivity());
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 ad4a4d5..58b5140 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
@@ -184,12 +184,12 @@ @Override public void addOnContentChangedListener(ContentChangedListener listener) { - // Not longer needed. + mFeedStreamSurface.addContentChangedListener(listener); } @Override public void removeOnContentChangedListener(ContentChangedListener listener) { - // Not longer needed. + mFeedStreamSurface.removeContentChangedListener(listener); } @Override
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 988ce1b..c141331 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
@@ -6,6 +6,7 @@ import android.app.Activity; import android.content.Context; +import android.os.Handler; import android.view.ContextThemeWrapper; import android.view.View; import android.view.ViewParent; @@ -14,10 +15,12 @@ import androidx.annotation.VisibleForTesting; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.ItemAnimator.ItemAnimatorFinishedListener; import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -27,6 +30,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.AppHooks; import org.chromium.chrome.browser.feed.shared.ScrollTracker; +import org.chromium.chrome.browser.feed.shared.stream.Stream.ContentChangedListener; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; @@ -105,6 +109,10 @@ private final NativePageNavigationDelegate mPageNavigationDelegate; private final HelpAndFeedback mHelpAndFeedback; private final ScrollReporter mScrollReporter = new ScrollReporter(); + private final ObserverList<ContentChangedListener> mContentChangedListeners = + new ObserverList<ContentChangedListener>(); + private final RecyclerViewAnimationFinishDetector mRecyclerViewAnimationFinishDetector = + new RecyclerViewAnimationFinishDetector(); // True after onSurfaceOpened(), and before onSurfaceClosed(). private boolean mOpened; private boolean mStreamContentVisible; @@ -518,9 +526,12 @@ private void updateContentsInPlace( ArrayList<FeedListContentManager.FeedContent> newContentList) { + boolean hasContentChange = false; + // 1) Builds the hash set based on keys of new contents. HashSet<String> newContentKeySet = new HashSet<String>(); for (int i = 0; i < newContentList.size(); ++i) { + hasContentChange = true; newContentKeySet.add(newContentList.get(i).getKey()); } @@ -536,6 +547,7 @@ for (int i = mContentManager.getItemCount() - 1; i >= 0; --i) { String key = mContentManager.getContent(i).getKey(); if (!newContentKeySet.contains(key)) { + hasContentChange = true; mContentManager.removeContents(i, 1); existingContentMap.remove(key); } @@ -549,6 +561,7 @@ // If this is an existing content, moves it to new position. if (existingContentMap.containsKey(content.getKey())) { + hasContentChange = true; mContentManager.moveContent( mContentManager.findContentPositionByKey(content.getKey()), i); ++i; @@ -561,8 +574,21 @@ && !existingContentMap.containsKey(newContentList.get(i).getKey())) { ++i; } + hasContentChange = true; mContentManager.addContents(startIndex, newContentList.subList(startIndex, i)); } + + if (hasContentChange) { + mRecyclerViewAnimationFinishDetector.asyncWait(); + } + } + + private void notifyContentChanged() { + for (ContentChangedListener listener : mContentChangedListeners) { + // For Feed v2, we only need to report if the content has changed. All other callbacks + // are not used at this point. + listener.onContentChanged(); + } } private FeedListContentManager.FeedContent createContentFromSlice(Slice slice) { @@ -896,6 +922,7 @@ int feedCount = mContentManager.getItemCount() - mHeaderCount; if (feedCount > 0) { mContentManager.removeContents(mHeaderCount, feedCount); + mRecyclerViewAnimationFinishDetector.asyncWait(); } mScrollReporter.onUnbind(); @@ -928,6 +955,14 @@ } } + public void addContentChangedListener(ContentChangedListener listener) { + mContentChangedListeners.addObserver(listener); + } + + public void removeContentChangedListener(ContentChangedListener listener) { + mContentChangedListeners.removeObserver(listener); + } + // Called when the stream is scrolled. void streamScrolled(int dx, int dy) { FeedStreamSurfaceJni.get().reportStreamScrollStart( @@ -935,6 +970,51 @@ mScrollReporter.trackScroll(dx, dy); } + // Detects animation finishes in RecyclerView. + // https://stackoverflow.com/questions/33710605/detect-animation-finish-in-androids-recyclerview + private class RecyclerViewAnimationFinishDetector implements ItemAnimatorFinishedListener { + private boolean mWaitingStarted; + + /** Asynchronousy waits for the animation to finish. */ + public void asyncWait() { + if (mWaitingStarted) { + return; + } + mWaitingStarted = true; + + // The RecyclerView has not started animating yet, so post a message to the + // message queue that will be run after the RecyclerView has started animating. + new Handler().post(() -> { checkFinish(); }); + } + + private void checkFinish() { + if (mRootView.isAnimating()) { + // The RecyclerView is still animating, try again when the animation has finished. + mRootView.getItemAnimator().isRunning(this); + return; + } + + // The RecyclerView has animated all it's views. + onFinished(); + } + + private void onFinished() { + mWaitingStarted = false; + + // This works around the bug that the out-of-screen toolbar is not brought back together + // with the new tab page view when it slides down. This is because the RecyclerView + // animation may not finish when content changed event is triggered and thus the new tab + // page layout view may still be partially off screen. + notifyContentChanged(); + } + + @Override + public void onAnimationsFinished() { + // There might still be more items that will be animated after this one. + new Handler().post(() -> { checkFinish(); }); + } + } + // Ingests scroll events and reports scroll completion back to native. private class ScrollReporter extends ScrollTracker { @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java index f0595cd..af55186 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java
@@ -72,9 +72,9 @@ private String mUrl; private int mCurrentMaxSheetHeight; - private Profile mProfile; - private boolean mOpened; - private boolean mFullStateLogged; + private boolean mPeeked; + private boolean mViewed; // Moved up from peek state by user + private boolean mFullyOpened; /** * Constructor. @@ -114,7 +114,7 @@ * Checks if the preview tab is in open (peek) state. */ public boolean isOpened() { - return mOpened; + return mPeeked; } /** @@ -146,25 +146,33 @@ public void onSheetContentChanged(BottomSheetContent newContent) { if (newContent != mSheetContent) { mMetrics.recordMetricsForClosed(mCloseReason); - mOpened = false; + mPeeked = false; destroyWebContents(); } } @Override + public void onSheetOpened(@StateChangeReason int reason) { + if (!mViewed) { + mMetrics.recordMetricsForViewed(); + mViewed = true; + } + } + + @Override public void onSheetStateChanged(int newState) { if (mSheetContent == null) return; switch (newState) { case SheetState.PEEK: - if (!mOpened) { + if (!mPeeked) { mMetrics.recordMetricsForPeeked(); - mOpened = true; + mPeeked = true; } break; case SheetState.FULL: - if (!mFullStateLogged) { + if (!mFullyOpened) { mMetrics.recordMetricsForOpened(); - mFullStateLogged = true; + mFullyOpened = true; } break; } @@ -190,8 +198,9 @@ mLayoutView.addOnLayoutChangeListener(this); } - mOpened = false; - mFullStateLogged = false; + mPeeked = false; + mViewed = false; + mFullyOpened = false; mMediator.requestShowContent(url, title); Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMetrics.java index e787370..66fc0cb1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabMetrics.java
@@ -19,7 +19,7 @@ /** The timestamp when the panel entered the peeking state for the first time. */ private long mPanelPeekedNanoseconds; - /** Remembers whether the panel was opened beyond the peeking state. */ + /** Remembers whether the panel was opened fully. */ private boolean mDidRecordFirstOpen; /** The timestamp when the panel entered the opened state for the first time. */ @@ -28,6 +28,9 @@ /** Whether the panel is in any visible state. */ private boolean mIsVisible; + /** Whether the panel was opened beyond peeking state. */ + private boolean mIsViewed; + /** Records metrics for the peeked panel state. */ public void recordMetricsForPeeked() { mIsVisible = true; @@ -36,6 +39,12 @@ finishOpenTimer(); } + /** Records metrics when the panel has gone beyond peek state. */ + public void recordMetricsForViewed() { + mIsViewed = true; + finishPeekTimer(); + } + /** Records metrics when the panel has been fully opened. */ public void recordMetricsForOpened() { mIsVisible = true; @@ -49,6 +58,7 @@ finishPeekTimer(); finishOpenTimer(); + RecordHistogram.recordBooleanHistogram("EphemeralTab.CtrPeek", mIsViewed); RecordHistogram.recordBooleanHistogram("EphemeralTab.Ctr", mDidRecordFirstOpen); RecordHistogram.recordEnumeratedHistogram("EphemeralTab.BottomSheet.CloseReason", stateChangeReason, StateChangeReason.MAX_VALUE + 1); @@ -73,6 +83,7 @@ mDidRecordFirstOpen = false; mPanelOpenedNanoseconds = 0; mIsVisible = false; + mIsViewed = false; } /** Starts timing the peek state if it's not already been started. */
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 03921ea..3f1aa6a 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
@@ -55,6 +55,7 @@ import org.chromium.base.test.util.MetricsUtils.HistogramDelta; import org.chromium.chrome.browser.AppHooks; import org.chromium.chrome.browser.AppHooksImpl; +import org.chromium.chrome.browser.feed.shared.stream.Stream.ContentChangedListener; import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; import org.chromium.chrome.browser.ntp.NewTabPageUma; @@ -80,6 +81,19 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE, shadows = {ShadowPostTask.class, ShadowRecordHistogram.class}) public class FeedStreamSurfaceTest { + class ContentChangeWatcher implements ContentChangedListener { + @Override + public void onContentChanged() { + mContentChanged = true; + } + + @Override + public void onAddStarting() {} + + @Override + public void onAddFinished() {} + } + private static final String TEST_DATA = "test"; private static final String TEST_URL = "https://www.chromium.org"; private static final int LOAD_MORE_TRIGGER_LOOKAHEAD = 5; @@ -89,6 +103,7 @@ private LinearLayout mParent; private FakeLinearLayoutManager mLayoutManager; private FeedListContentManager mContentManager; + private boolean mContentChanged; @Mock private SnackbarManager mSnackbarManager; @@ -146,6 +161,7 @@ mRecyclerView = mFeedStreamSurface.mRootView; mLayoutManager = new FakeLinearLayoutManager(mActivity); mRecyclerView.setLayoutManager(mLayoutManager); + mFeedStreamSurface.addContentChangedListener(new ContentChangeWatcher()); // Since we use a mockito spy, we need to replace the entry in sSurfaces. FeedStreamSurface.sSurfaces.clear(); @@ -164,6 +180,39 @@ @Test @SmallTest + public void testContentChangedOnStreamUpdated() { + startupAndSetVisible(); + + // Add 1 slice. + StreamUpdate update = StreamUpdate.newBuilder() + .addUpdatedSlices(createSliceUpdateForNewXSurfaceSlice("a")) + .build(); + mContentChanged = false; + mFeedStreamSurface.onStreamUpdated(update.toByteArray()); + assertTrue(mContentChanged); + assertEquals(1, mContentManager.getItemCount()); + + // Remove 1 slice. + update = StreamUpdate.newBuilder().build(); + mContentChanged = false; + mFeedStreamSurface.onStreamUpdated(update.toByteArray()); + assertTrue(mContentChanged); + assertEquals(0, mContentManager.getItemCount()); + } + + @Test + @SmallTest + public void testContentChangedOnSetHeaderViews() { + startupAndSetVisible(); + + mContentChanged = false; + mFeedStreamSurface.setHeaderViews(Arrays.asList(new View(mActivity))); + assertTrue(mContentChanged); + assertEquals(1, mContentManager.getItemCount()); + } + + @Test + @SmallTest public void testAddSlicesOnStreamUpdated() { startupAndSetVisible(); // Add 3 new slices at first. @@ -529,7 +578,9 @@ assertEquals(headers + 3, mContentManager.getItemCount()); // Closing the surface should remove all non-header contents. + mContentChanged = false; mFeedStreamSurface.setStreamVisibility(false); + assertTrue(mContentChanged); assertEquals(headers, mContentManager.getItemCount()); assertEquals(v0, getNativeView(0)); assertEquals(v1, getNativeView(1));
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn index 5c1c646..79d6fad 100644 --- a/chrome/android/webapk/shell_apk/BUILD.gn +++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -105,6 +105,7 @@ _generated_res_background_dir = "${target_gen_dir}/${_generate_res_background_xml_target_name}/res" _resources_target_name = "${target_name}_resources" + _app_icon_resources_target_name = "${target_name}_app_icon_resources" if (defined(invoker.manifest_output)) { _manifest_output = invoker.manifest_output @@ -136,6 +137,17 @@ output = "${_generated_res_background_dir}/values/background_color.xml" } + android_resources(_app_icon_resources_target_name) { + create_srcjar = false + sources = [ + "res_app_icon/mipmap-hdpi/app_icon.xml", + "res_app_icon/mipmap-mdpi/app_icon.xml", + "res_app_icon/mipmap-xhdpi/app_icon.xml", + "res_app_icon/mipmap-xxhdpi/app_icon.xml", + "res_app_icon/mipmap-xxxhdpi/app_icon.xml", + ] + } + android_resources(_resources_target_name) { create_srcjar = false sources = [ @@ -173,10 +185,8 @@ "res/layout/choose_host_browser_dialog.xml", "res/layout/host_browser_list_item.xml", "res/mipmap-anydpi-v26/ic_launcher.xml", - "res/mipmap-hdpi/app_icon.xml", "res/mipmap-hdpi/ic_launcher.xml", "res/mipmap-hdpi/maskable_app_icon.xml", - "res/mipmap-mdpi/app_icon.xml", "res/mipmap-mdpi/ic_launcher.xml", "res/mipmap-mdpi/ic_launcher_background.png", "res/mipmap-mdpi/ic_launcher_foreground.png", @@ -195,13 +205,10 @@ "res/mipmap-nodpi/maskable_splash_icon_xxxhdpi.png", "res/mipmap-nodpi/splash_icon_xxhdpi.png", "res/mipmap-nodpi/splash_icon_xxxhdpi.png", - "res/mipmap-xhdpi/app_icon.xml", "res/mipmap-xhdpi/ic_launcher.xml", "res/mipmap-xhdpi/maskable_app_icon.xml", - "res/mipmap-xxhdpi/app_icon.xml", "res/mipmap-xxhdpi/ic_launcher.xml", "res/mipmap-xxhdpi/maskable_app_icon.xml", - "res/mipmap-xxxhdpi/app_icon.xml", "res/mipmap-xxxhdpi/ic_launcher.xml", "res/mipmap-xxxhdpi/maskable_app_icon.xml", "res/values-hdpi/is_splash_icon_maskable_bool.xml", @@ -244,7 +251,10 @@ "apk_name", "testonly", ]) - deps = [ ":$_java_with_services_target_name" ] + deps = [ + ":$_app_icon_resources_target_name", + ":$_java_with_services_target_name", + ] android_manifest = _manifest_output android_manifest_dep = ":$_manifest_target_name"
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni index 92feb52..85d57b4 100644 --- a/chrome/android/webapk/shell_apk/current_version/current_version.gni +++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@ # //chrome/android/webapk/shell_apk:webapk is changed. This includes # Java files, Android resource files and AndroidManifest.xml. Does not affect # Chrome.apk -current_shell_apk_version = 131 +current_shell_apk_version = 132
diff --git a/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn b/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn index a4bc1ca4..e391ed8 100644 --- a/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn +++ b/chrome/android/webapk/shell_apk/prepare_upload_dir/BUILD.gn
@@ -28,6 +28,11 @@ destination_dir = "${upload_dir}/res" } +copy_dir("copy_res_app_icon_to_upload_dir") { + source_dir = "//chrome/android/webapk/shell_apk/res_app_icon" + destination_dir = "${upload_dir}/res" +} + copy_dir("copy_res_template_to_upload_dir") { source_dir = "//chrome/android/webapk/shell_apk/res_template" destination_dir = "${upload_dir}/res" @@ -63,6 +68,7 @@ deps = [ ":copy_extra_files_to_upload_dir", ":copy_libs_common_res_splash_to_upload_dir", + ":copy_res_app_icon_to_upload_dir", ":copy_res_template_to_upload_dir", ":copy_res_to_upload_dir", ]
diff --git a/chrome/android/webapk/shell_apk/res/layout/choose_host_browser_dialog.xml b/chrome/android/webapk/shell_apk/res/layout/choose_host_browser_dialog.xml index 2f63747..b9b98994 100644 --- a/chrome/android/webapk/shell_apk/res/layout/choose_host_browser_dialog.xml +++ b/chrome/android/webapk/shell_apk/res/layout/choose_host_browser_dialog.xml
@@ -13,8 +13,8 @@ android:id="@+id/desc" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textSize="@dimen/text_size_large" - android:textColor="@color/black_alpha_54" + android:textSize="@dimen/webapk_text_size_large" + android:textColor="@color/webapk_black_alpha_54" android:layout_marginBottom="12dp" /> <ListView @@ -25,4 +25,4 @@ android:dividerHeight="0dp" android:layout_marginTop="4dp" /> -</LinearLayout> \ No newline at end of file +</LinearLayout>
diff --git a/chrome/android/webapk/shell_apk/res/layout/host_browser_list_item.xml b/chrome/android/webapk/shell_apk/res/layout/host_browser_list_item.xml index 05f3c61..f9d0726 100644 --- a/chrome/android/webapk/shell_apk/res/layout/host_browser_list_item.xml +++ b/chrome/android/webapk/shell_apk/res/layout/host_browser_list_item.xml
@@ -25,8 +25,8 @@ android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textColor="@color/black_alpha_87" - android:textSize="@dimen/text_size_large" + android:textColor="@color/webapk_black_alpha_87" + android:textSize="@dimen/webapk_text_size_large" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" /> -</LinearLayout> \ No newline at end of file +</LinearLayout>
diff --git a/chrome/android/webapk/shell_apk/res/values/colors.xml b/chrome/android/webapk/shell_apk/res/values/colors.xml index 6b398373..8df8d0b 100644 --- a/chrome/android/webapk/shell_apk/res/values/colors.xml +++ b/chrome/android/webapk/shell_apk/res/values/colors.xml
@@ -5,8 +5,8 @@ <resources> <!-- Common colors--> - <color name="black_alpha_38">#61000000</color> - <color name="black_alpha_54">#8A000000</color> - <color name="black_alpha_87">#DE000000</color> + <color name="webapk_black_alpha_38">#61000000</color> + <color name="webapk_black_alpha_54">#8A000000</color> + <color name="webapk_black_alpha_87">#DE000000</color> <color name="white_adaptive_ic_launcher_background">#FFFFFF</color> </resources>
diff --git a/chrome/android/webapk/shell_apk/res/values/dimens.xml b/chrome/android/webapk/shell_apk/res/values/dimens.xml index 7924682..98429aa7 100644 --- a/chrome/android/webapk/shell_apk/res/values/dimens.xml +++ b/chrome/android/webapk/shell_apk/res/values/dimens.xml
@@ -6,8 +6,8 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Common text sizes --> <dimen name="headline_size_medium">20sp</dimen> - <dimen name="text_size_large">16sp</dimen> - <dimen name="text_size_medium_dense">12sp</dimen> + <dimen name="webapk_text_size_large">16sp</dimen> + <dimen name="webapk_text_size_medium_dense">12sp</dimen> <!-- Refers to https://material.googleplex.com/components/dialogs.html#dialogs-specs. --> <dimen name="dialog_content_padding">24dp</dimen>
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-hdpi/app_icon.xml b/chrome/android/webapk/shell_apk/res_app_icon/mipmap-hdpi/app_icon.xml similarity index 100% rename from chrome/android/webapk/shell_apk/res/mipmap-hdpi/app_icon.xml rename to chrome/android/webapk/shell_apk/res_app_icon/mipmap-hdpi/app_icon.xml
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-mdpi/app_icon.xml b/chrome/android/webapk/shell_apk/res_app_icon/mipmap-mdpi/app_icon.xml similarity index 100% rename from chrome/android/webapk/shell_apk/res/mipmap-mdpi/app_icon.xml rename to chrome/android/webapk/shell_apk/res_app_icon/mipmap-mdpi/app_icon.xml
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-xhdpi/app_icon.xml b/chrome/android/webapk/shell_apk/res_app_icon/mipmap-xhdpi/app_icon.xml similarity index 100% rename from chrome/android/webapk/shell_apk/res/mipmap-xhdpi/app_icon.xml rename to chrome/android/webapk/shell_apk/res_app_icon/mipmap-xhdpi/app_icon.xml
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-xxhdpi/app_icon.xml b/chrome/android/webapk/shell_apk/res_app_icon/mipmap-xxhdpi/app_icon.xml similarity index 100% rename from chrome/android/webapk/shell_apk/res/mipmap-xxhdpi/app_icon.xml rename to chrome/android/webapk/shell_apk/res_app_icon/mipmap-xxhdpi/app_icon.xml
diff --git a/chrome/android/webapk/shell_apk/res/mipmap-xxxhdpi/app_icon.xml b/chrome/android/webapk/shell_apk/res_app_icon/mipmap-xxxhdpi/app_icon.xml similarity index 100% rename from chrome/android/webapk/shell_apk/res/mipmap-xxxhdpi/app_icon.xml rename to chrome/android/webapk/shell_apk/res_app_icon/mipmap-xxxhdpi/app_icon.xml
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java index 44226d2..f4ee46e 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java
@@ -212,19 +212,20 @@ name.setEnabled(item.enable()); if (item.enable()) { name.setText(item.getApplicationName()); - name.setTextColor(WebApkUtils.getColor(res, R.color.black_alpha_87)); + name.setTextColor(WebApkUtils.getColor(res, R.color.webapk_black_alpha_87)); icon.setAlpha(SUPPORTED_ICON_OPACITY); } else { String text = mContext.getString(R.string.host_browser_item_not_supporting_webapks, item.getApplicationName()); SpannableString spannableName = new SpannableString(text); - float descriptionProportion = res.getDimension(R.dimen.text_size_medium_dense) - / res.getDimension(R.dimen.text_size_large); + float descriptionProportion = + res.getDimension(R.dimen.webapk_text_size_medium_dense) + / res.getDimension(R.dimen.webapk_text_size_large); spannableName.setSpan(new RelativeSizeSpan(descriptionProportion), item.getApplicationName().length() + 1, spannableName.length(), 0); name.setText(spannableName); name.setSingleLine(false); - name.setTextColor(WebApkUtils.getColor(res, R.color.black_alpha_38)); + name.setTextColor(WebApkUtils.getColor(res, R.color.webapk_black_alpha_38)); icon.setAlpha(UNSUPPORTED_ICON_OPACITY); } icon.setImageDrawable(item.getApplicationIcon());
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java index 4dd530c..155b0fb6 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
@@ -162,7 +162,7 @@ public static void applyAlertDialogContentStyle( Context context, View contentView, TextView titleView) { Resources res = context.getResources(); - titleView.setTextColor(getColor(res, R.color.black_alpha_87)); + titleView.setTextColor(getColor(res, R.color.webapk_black_alpha_87)); titleView.setTextSize( TypedValue.COMPLEX_UNIT_PX, res.getDimension(R.dimen.headline_size_medium)); int dialogContentPadding = res.getDimensionPixelSize(R.dimen.dialog_content_padding);
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d09ace6b..360b7ab 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -210,6 +210,7 @@ #endif // OS_CHROMEOS #if defined(OS_MAC) +#include "base/mac/mac_util.h" #include "chrome/browser/ui/browser_dialogs.h" #endif // OS_MAC @@ -1430,11 +1431,9 @@ {features::kPromoBrowserCommandIdParam, "1"}}; const FeatureEntry::FeatureVariation kPromoBrowserCommandsVariations[] = { {"- Unknown Command", kPromoBrowserCommandUnknownCommandParam, - base::size(kPromoBrowserCommandUnknownCommandParam), - "t4237555" /* variation_id */}, + base::size(kPromoBrowserCommandUnknownCommandParam), nullptr}, {"- Open Safety Check", kPromoBrowserCommandOpenSafetyCheckCommandParam, - base::size(kPromoBrowserCommandOpenSafetyCheckCommandParam), - "t4237555" /* variation_id */}}; + base::size(kPromoBrowserCommandOpenSafetyCheckCommandParam), nullptr}}; #if defined(OS_ANDROID) const FeatureEntry::FeatureParam kTranslateForceTriggerOnEnglishHeuristic[] = { @@ -5372,7 +5371,7 @@ FEATURE_VALUE_TYPE(features::kFormControlsRefresh)}, {"color-picker-eye-dropper", flag_descriptions::kColorPickerEyeDropperName, - flag_descriptions::kColorPickerEyeDropperDescription, kOsWin, + flag_descriptions::kColorPickerEyeDropperDescription, kOsWin | kOsMac, FEATURE_VALUE_TYPE(features::kEyeDropper)}, #if defined(OS_CHROMEOS) @@ -6534,6 +6533,15 @@ } #endif // OS_ANDROID +#if defined(OS_MAC) + // The Eye Dropper relies on the NSColorSampler API, which is available + // starting with macOS 10.15. + if (!strcmp("color-picker-eye-dropper", entry.internal_name) && + !base::mac::IsAtLeastOS10_15()) { + return true; + } +#endif // OS_MAC + if (flags::IsFlagExpired(storage, entry.internal_name)) return true;
diff --git a/chrome/browser/apps/app_service/app_service_proxy_factory.cc b/chrome/browser/apps/app_service/app_service_proxy_factory.cc index e1dbd0a1..4f8e086 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_factory.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_factory.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" @@ -50,7 +51,17 @@ // static AppServiceProxy* AppServiceProxyFactory::GetForProfile(Profile* profile) { - DCHECK(IsAppServiceAvailableForProfile(profile)); + // TODO(https://crbug.com/1122463): remove this and convert back to a DCHECK + // once we have audited and removed code paths that call here with a profile + // that doesn't have an App Service. + if (!IsAppServiceAvailableForProfile(profile)) { + DVLOG(1) << "Called AppServiceProxyFactory::GetForProfile() on a profile " + "which does not contain an AppServiceProxy. Please check " + "whether this is appropriate as you may be leaking information " + "out of this profile. Returning the AppServiceProxy attached " + "to the parent profile instead."; + base::debug::DumpWithoutCrashing(); + } auto* proxy = static_cast<AppServiceProxy*>( AppServiceProxyFactory::GetInstance()->GetServiceForBrowserContext( @@ -99,13 +110,16 @@ } // We must have a proxy in guest mode to ensure default extension-based apps - // are served. Otherwise, don't create the app service for incognito profiles. + // are served. if (profile->IsGuestSession()) { return chrome::GetBrowserContextOwnInstanceInIncognito(context); } #endif // OS_CHROMEOS - return BrowserContextKeyedServiceFactory::GetBrowserContextToUse(context); + // TODO(https://crbug.com/1122463): replace this with + // BrowserContextKeyedServiceFactory::GetBrowserContextToUse(context) once + // all non-guest incognito accesses have been removed. + return chrome::GetBrowserContextRedirectedInIncognito(context); } bool AppServiceProxyFactory::ServiceIsCreatedWithBrowserContext() const {
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc index 22cfb83..ef2c893 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -2,11 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <utility> #include <vector> #include "base/callback.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image_skia_rep.h" @@ -81,6 +85,8 @@ int NumOuterFinishedCallbacks() { return num_outer_finished_callbacks_; } int num_outer_finished_callbacks_ = 0; + + content::BrowserTaskEnvironment task_environment_; }; TEST_F(AppServiceProxyTest, IconCache) { @@ -181,3 +187,30 @@ EXPECT_EQ(3, fake.NumInnerFinishedCallbacks()); EXPECT_EQ(6, NumOuterFinishedCallbacks()); } + +TEST_F(AppServiceProxyTest, ProxyAccessPerProfile) { + TestingProfile::Builder profile_builder; + + // We expect an App Service in a regular profile. + auto profile = profile_builder.Build(); + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile.get()); + EXPECT_TRUE(proxy); + + // We expect the same App Service in the incognito profile branched from that + // regular profile. + // TODO(https://crbug.com/1122463): this should be nullptr once we address all + // incognito access to the App Service. + TestingProfile::Builder incognito_builder; + auto* incognito_proxy = apps::AppServiceProxyFactory::GetForProfile( + incognito_builder.BuildIncognito(profile.get())); + EXPECT_EQ(proxy, incognito_proxy); + + // We expect a different App Service in the Guest Session profile. + TestingProfile::Builder guest_builder; + guest_builder.SetGuestSession(); + auto guest_profile = guest_builder.Build(); + auto* guest_proxy = + apps::AppServiceProxyFactory::GetForProfile(guest_profile.get()); + EXPECT_TRUE(guest_proxy); + EXPECT_NE(guest_proxy, proxy); +}
diff --git a/chrome/browser/chromeos/crosapi/browser_loader.cc b/chrome/browser/chromeos/crosapi/browser_loader.cc index efacabf6..393e8fd 100644 --- a/chrome/browser/chromeos/crosapi/browser_loader.cc +++ b/chrome/browser/chromeos/crosapi/browser_loader.cc
@@ -15,6 +15,7 @@ #include "base/task/thread_pool.h" #include "chrome/browser/chromeos/crosapi/browser_util.h" #include "chromeos/constants/chromeos_switches.h" +#include "chromeos/cryptohome/system_salt_getter.h" namespace crosapi { @@ -82,7 +83,7 @@ FROM_HERE, {base::MayBlock()}, base::BindOnce(&CheckInstalledAndMaybeRemoveUserDirectory, component_manager_), - base::BindOnce(&BrowserLoader::UnloadAfterCleanUp, + base::BindOnce(&BrowserLoader::OnCheckInstalled, weak_factory_.GetWeakPtr())); } @@ -101,9 +102,22 @@ std::move(callback).Run(success ? path : base::FilePath()); } -void BrowserLoader::UnloadAfterCleanUp(bool was_installed) { - if (was_installed) - component_manager_->Unload(kLacrosComponentName); +void BrowserLoader::OnCheckInstalled(bool was_installed) { + if (!was_installed) + return; + + // Workaround for login crash when the user un-sets the LacrosSupport flag. + // CrOSComponentManager::Unload() calls into code in MetadataTable that + // assumes that system salt is available. This isn't always true when chrome + // restarts to apply non-owner flags. It's hard to make MetadataTable async. + // Ensure salt is available before unloading. https://crbug.com/1122674 + chromeos::SystemSaltGetter::Get()->GetSystemSalt(base::BindOnce( + &BrowserLoader::UnloadAfterCleanUp, weak_factory_.GetWeakPtr())); +} + +void BrowserLoader::UnloadAfterCleanUp(const std::string& ignored_salt) { + CHECK(chromeos::SystemSaltGetter::Get()->GetRawSalt()); + component_manager_->Unload(kLacrosComponentName); } } // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/browser_loader.h b/chrome/browser/chromeos/crosapi/browser_loader.h index 69c8598..d06d065 100644 --- a/chrome/browser/chromeos/crosapi/browser_loader.h +++ b/chrome/browser/chromeos/crosapi/browser_loader.h
@@ -42,9 +42,12 @@ component_updater::CrOSComponentManager::Error error, const base::FilePath& path); - // Unloading hops threads. This is called after possible user directory - // removal. - void UnloadAfterCleanUp(bool was_installed); + // Unloading hops threads. This is called after we check whether Lacros was + // installed and maybe clean up the user directory. + void OnCheckInstalled(bool was_installed); + + // Unloads the component. Called after system salt is available. + void UnloadAfterCleanUp(const std::string& ignored_salt); // May be null in tests. scoped_refptr<component_updater::CrOSComponentManager> component_manager_;
diff --git a/chrome/browser/chromeos/input_method/ui/candidate_window_view.cc b/chrome/browser/chromeos/input_method/ui/candidate_window_view.cc index d8ff2644..ed91ca6 100644 --- a/chrome/browser/chromeos/input_method/ui/candidate_window_view.cc +++ b/chrome/browser/chromeos/input_method/ui/candidate_window_view.cc
@@ -152,6 +152,15 @@ set_parent_window(parent); set_margins(gfx::Insets()); + // When BubbleDialogDelegateView creates its frame view it will create a + // bubble border with a non-zero corner radius by default. + // This class replaces the frame view's bubble border later on with its own + // |CandidateWindowBorder| with a radius of 0. + // We want to disable the use of round corners here to ensure that the radius + // of the frame view created by the BubbleDialogDelegateView is consistent + // with what CandidateWindowView expects. + set_use_round_corners(false); + SetBorder(views::CreateSolidBorder( 1, GetNativeTheme()->GetSystemColor( ui::NativeTheme::kColorId_MenuBorderColor)));
diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc index 6526f7b..a3390896 100644 --- a/chrome/browser/extensions/execute_script_apitest.cc +++ b/chrome/browser/extensions/execute_script_apitest.cc
@@ -32,6 +32,8 @@ public testing::WithParamInterface<ContextType> { protected: ExecuteScriptApiTest() { + // Service Workers are currently only available on certain channels, so set + // the channel for those tests. if (GetParam() == ContextType::kServiceWorker) current_channel_ = std::make_unique<ScopedWorkerBasedExtensionsChannel>(); } @@ -87,14 +89,7 @@ ASSERT_TRUE(RunTest("executescript/frame_id")) << message_; } -// Fails often on Windows. -// http://crbug.com/174715 -#if defined(OS_WIN) -#define MAYBE_ExecuteScriptPermissions DISABLED_ExecuteScriptPermissions -#else -#define MAYBE_ExecuteScriptPermissions ExecuteScriptPermissions -#endif // defined(OS_WIN) -IN_PROC_BROWSER_TEST_P(ExecuteScriptApiTest, MAYBE_ExecuteScriptPermissions) { +IN_PROC_BROWSER_TEST_P(ExecuteScriptApiTest, ExecuteScriptPermissions) { // TODO(https://crbug.com/1115182): Flaky for SW-based extensions. if (GetParam() == ContextType::kServiceWorker) return;
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 93ae78b..f36faa5 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -231,6 +231,7 @@ &net::features::kCookiesWithoutSameSiteMustBeSecure, &paint_preview::kPaintPreviewDemo, &paint_preview::kPaintPreviewShowOnStartup, + &language::kDetailedLanguageSettings, &language::kExplicitLanguageAsk, &ntp_snippets::kArticleSuggestionsFeature, &offline_pages::kOfflineIndicatorFeature,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index abd6c601..bf47395 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -280,6 +280,7 @@ "DarkenWebsitesCheckboxInThemesSetting"; public static final String DECOUPLE_SYNC_FROM_ANDROID_MASTER_SYNC = "DecoupleSyncFromAndroidMasterSync"; + public static final String DETAILED_LANGUAGE_SETTINGS = "DetailedLanguageSettings"; public static final String DIRECT_ACTIONS = "DirectActions"; public static final String DNS_OVER_HTTPS = "DnsOverHttps"; public static final String DOWNLOAD_FILE_PROVIDER = "DownloadFileProvider";
diff --git a/chrome/browser/metrics/cros_healthd_metrics_provider.cc b/chrome/browser/metrics/cros_healthd_metrics_provider.cc index 80ca54eb..cc76bfe0 100644 --- a/chrome/browser/metrics/cros_healthd_metrics_provider.cc +++ b/chrome/browser/metrics/cros_healthd_metrics_provider.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "chrome/common/chrome_features.h" #include "chromeos/services/cros_healthd/public/cpp/service_connection.h" #include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h" #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h" @@ -43,6 +44,12 @@ init_callback_ = std::move(done_callback); initialized_ = false; + if (!base::FeatureList::IsEnabled(::features::kUmaStorageDimensions)) { + DVLOG(1) << "cros_healthd metrics provider is not enabled"; + std::move(init_callback_).Run(); + return; + } + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&CrosHealthdMetricsProvider::OnProbeTimeout, @@ -177,6 +184,8 @@ void CrosHealthdMetricsProvider::ProvideSystemProfileMetrics( metrics::SystemProfileProto* system_profile_proto) { + if (!initialized_) + return; auto* mutable_hardware_proto = system_profile_proto->mutable_hardware(); mutable_hardware_proto->clear_internal_storage_devices();
diff --git a/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc b/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc index fe704f2..e06c42f 100644 --- a/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/cros_healthd_metrics_provider_unittest.cc
@@ -10,8 +10,10 @@ #include "base/bind.h" #include "base/test/bind_test_util.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" +#include "chrome/common/chrome_features.h" #include "chromeos/dbus/cros_healthd/cros_healthd_client.h" #include "chromeos/dbus/cros_healthd/fake_cros_healthd_client.h" #include "chromeos/services/cros_healthd/public/cpp/service_connection.h" @@ -22,6 +24,10 @@ class CrosHealthdMetricsProviderTest : public testing::Test { public: + CrosHealthdMetricsProviderTest() { + scoped_feature_list_.InitAndEnableFeature(features::kUmaStorageDimensions); + } + void SetUp() override { chromeos::CrosHealthdClient::InitializeFake(); } void TearDown() override { @@ -34,6 +40,9 @@ base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + protected: + base::test::ScopedFeatureList scoped_feature_list_; }; TEST_F(CrosHealthdMetricsProviderTest, EndToEnd) { @@ -123,3 +132,17 @@ run_loop.Run(); ASSERT_FALSE(provider.IsInitialized()); } + +TEST_F(CrosHealthdMetricsProviderTest, EndToEndNoFeature) { + scoped_feature_list_.Reset(); + scoped_feature_list_.Init(); + + base::RunLoop run_loop; + CrosHealthdMetricsProvider provider; + provider.AsyncInit(base::BindOnce( + [](base::OnceClosure callback) { std::move(callback).Run(); }, + run_loop.QuitClosure())); + + run_loop.Run(); + ASSERT_FALSE(provider.IsInitialized()); +}
diff --git a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc index b1f0632..99f2e48 100644 --- a/chrome/browser/payments/secure_payment_confirmation_browsertest.cc +++ b/chrome/browser/payments/secure_payment_confirmation_browsertest.cc
@@ -9,10 +9,13 @@ #include <vector> #include "base/command_line.h" +#include "base/files/file_util.h" #include "base/memory/ref_counted.h" +#include "base/path_service.h" #include "base/strings/strcat.h" #include "base/strings/string16.h" #include "base/strings/stringprintf.h" +#include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_data_service_factory.h" @@ -46,6 +49,22 @@ return base::StringPrintf("getStatusForMethodData(%s)", kTestMethodData); } +std::vector<uint8_t> GetEncodedIcon(const std::string& icon_file_name) { + base::FilePath base_path; + CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &base_path)); + std::string icon_as_string; + base::FilePath icon_file_path = + base_path.AppendASCII("components/test/data/payments") + .AppendASCII(icon_file_name); + { + base::ScopedAllowBlockingForTesting allow_blocking; + CHECK(base::PathExists(icon_file_path)); + CHECK(base::ReadFileToString(icon_file_path, &icon_as_string)); + } + + return std::vector<uint8_t>(icon_as_string.begin(), icon_as_string.end()); +} + #if !defined(OS_ANDROID) std::string getPaymentCreationOptions(const std::string& icon_url) { return base::StrCat( @@ -138,7 +157,7 @@ test_controller()->SetHasAuthenticator(true); NavigateTo("a.com", "/payment_handler_status.html"); std::vector<uint8_t> credential_id = {'c', 'r', 'e', 'd'}; - std::vector<uint8_t> icon = {0, 1, 2, 3}; + std::vector<uint8_t> icon = GetEncodedIcon("icon.png"); WebDataServiceFactory::GetPaymentManifestWebDataForProfile( Profile::FromBrowserContext(GetActiveWebContents()->GetBrowserContext()), ServiceAccessType::EXPLICIT_ACCESS)
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 8782ac43..07a8866 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -759,9 +759,9 @@ PDFExtensionLoadTest, testing::Range(0, kNumberLoadTestParts)); -class PDFExtensionJSTest : public PDFExtensionTest { +class PDFExtensionJSTestBase : public PDFExtensionTest { public: - ~PDFExtensionJSTest() override = default; + ~PDFExtensionJSTestBase() override = default; protected: void RunTestsInJsModule(const std::string& filename, @@ -809,104 +809,137 @@ } }; -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Basic) { +class PDFExtensionJSUpdatesDisabledTest : public PDFExtensionJSTestBase { + public: + ~PDFExtensionJSUpdatesDisabledTest() override = default; + + protected: + const std::vector<base::Feature> GetDisabledFeatures() const override { + return {chrome_pdf::features::kPDFViewerUpdate}; + } +}; + +// Zoom toolbar doesn't exist and the top toolbar is sticky with the new PDF +// viewer updates, so run this test only with the updates disabled. +IN_PROC_BROWSER_TEST_F(PDFExtensionJSUpdatesDisabledTest, ToolbarManager) { + RunTestsInJsModule("toolbar_manager_test.js", "test.pdf"); +} + +class PDFExtensionJSTest : public PDFExtensionJSTestBase, + public testing::WithParamInterface<bool> { + public: + ~PDFExtensionJSTest() override = default; + + protected: + const std::vector<base::Feature> GetEnabledFeatures() const override { + if (GetParam()) { + return {chrome_pdf::features::kPDFViewerUpdate}; + } + return {}; + } + + const std::vector<base::Feature> GetDisabledFeatures() const override { + if (GetParam()) { + return {}; + } + return {chrome_pdf::features::kPDFViewerUpdate}; + } +}; + +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Basic) { RunTestsInJsModule("basic_test.js", "test.pdf"); // Ensure it loaded in a PPAPI process. EXPECT_EQ(1, CountPDFProcesses()); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, BasicPlugin) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, BasicPlugin) { RunTestsInJsModule("basic_plugin_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Viewport) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Viewport) { RunTestsInJsModule("viewport_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Layout3) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Layout3) { RunTestsInJsModule("layout_test.js", "test-layout3.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Layout4) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Layout4) { RunTestsInJsModule("layout_test.js", "test-layout4.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Bookmark) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Bookmark) { RunTestsInJsModule("bookmarks_test.js", "test-bookmarks-with-zoom.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Navigator) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Navigator) { RunTestsInJsModule("navigator_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ParamsParser) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ParamsParser) { RunTestsInJsModule("params_parser_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ZoomManager) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ZoomManager) { RunTestsInJsModule("zoom_manager_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, GestureDetector) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, GestureDetector) { RunTestsInJsModule("gesture_detector_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, TouchHandling) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, TouchHandling) { RunTestsInJsModule("touch_handling_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Elements) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Elements) { // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("material_elements_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, DownloadControls) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, DownloadControls) { // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("download_controls_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ViewerPdfToolbarNew) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerPdfToolbarNew) { // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_pdf_toolbar_new_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ViewerPdfSidenav) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerPdfSidenav) { // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_pdf_sidenav_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ViewerThumbnailBar) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ViewerThumbnailBar) { // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult. RunTestsInJsModule("viewer_thumbnail_bar_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ToolbarManager) { - RunTestsInJsModule("toolbar_manager_test.js", "test.pdf"); -} - -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Title) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Title) { RunTestsInJsModule("title_test.js", "test-title.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, WhitespaceTitle) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, WhitespaceTitle) { RunTestsInJsModule("whitespace_title_test.js", "test-whitespace-title.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, PageChange) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, PageChange) { RunTestsInJsModule("page_change_test.js", "test-bookmarks.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Metrics) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Metrics) { RunTestsInJsModule("metrics_test.js", "test.pdf"); } -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, ArrayBufferAllocator) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, ArrayBufferAllocator) { // Run several times to see if there are issues with unloading. RunTestsInJsModule("beep_test.js", "array_buffer.pdf"); RunTestsInJsModule("beep_test.js", "array_buffer.pdf"); @@ -916,12 +949,12 @@ // Test that if the plugin tries to load a URL that redirects then it will fail // to load. This is to avoid the source origin of the document changing during // the redirect, which can have security implications. https://crbug.com/653749. -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, RedirectsFailInPlugin) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, RedirectsFailInPlugin) { RunTestsInJsModule("redirects_fail_test.js", "test.pdf"); } #if defined(OS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, Printing) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, Printing) { RunTestsInJsModule("printing_icon_test.js", "test.pdf"); } @@ -932,13 +965,15 @@ #else #define MAYBE_AnnotationsFeatureEnabled AnnotationsFeatureEnabled #endif -IN_PROC_BROWSER_TEST_F(PDFExtensionJSTest, MAYBE_AnnotationsFeatureEnabled) { +IN_PROC_BROWSER_TEST_P(PDFExtensionJSTest, MAYBE_AnnotationsFeatureEnabled) { RunTestsInJsModule("annotations_feature_enabled_test.js", "test.pdf"); } #endif // defined(OS_CHROMEOS) +INSTANTIATE_TEST_SUITE_P(/* no prefix */, PDFExtensionJSTest, testing::Bool()); + class PDFExtensionContentSettingJSTest - : public PDFExtensionJSTest, + : public PDFExtensionJSTestBase, public testing::WithParamInterface<bool> { public: ~PDFExtensionContentSettingJSTest() override = default; @@ -1017,7 +1052,7 @@ // Service worker tests are regression tests for // https://crbug.com/916514. -class PDFExtensionServiceWorkerJSTest : public PDFExtensionJSTest { +class PDFExtensionServiceWorkerJSTest : public PDFExtensionJSTestBase { public: ~PDFExtensionServiceWorkerJSTest() override = default;
diff --git a/chrome/browser/resources/chromeos/accessibility/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/BUILD.gn index 1998283..db57d5a 100644 --- a/chrome/browser/resources/chromeos/accessibility/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/BUILD.gn
@@ -148,7 +148,6 @@ "common/rect_util_unittest.js", "select_to_speak/node_utils_unittest.js", "select_to_speak/paragraph_utils_unittest.js", - "select_to_speak/rect_utils_unittest.js", "select_to_speak/select_to_speak_unittest.js", "select_to_speak/word_utils_unittest.js", ] @@ -156,7 +155,6 @@ "braille_ime/braille_ime.js", "common/rect_util.js", "select_to_speak/paragraph_utils.js", - "select_to_speak/rect_utils.js", "select_to_speak/select_to_speak.js", "select_to_speak/test_support.js", "select_to_speak/word_utils.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/common/rect_util.js b/chrome/browser/resources/chromeos/accessibility/common/rect_util.js index ed3e63db..b3e901d 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/rect_util.js +++ b/chrome/browser/resources/chromeos/accessibility/common/rect_util.js
@@ -14,6 +14,24 @@ ZERO_RECT: {top: 0, left: 0, width: 0, height: 0}, /** + * Return the rect that encloses two points. + * @param {number} x1 The first x coordinate. + * @param {number} y1 The first y coordinate. + * @param {number} x2 The second x coordinate. + * @param {number} y2 The second x coordinate. + * @return {!ScreenRect} + */ + rectFromPoints: (x1, y1, x2, y2) => { + const left = Math.min(x1, x2); + const right = Math.max(x1, x2); + const top = Math.min(y1, y2); + const bottom = Math.max(y1, y2); + const width = right - left; + const height = bottom - top; + return {left, top, width, height}; + }, + + /** * @param {!ScreenRect} rect1 * @param {!ScreenRect} rect2 * @return {boolean} @@ -92,10 +110,7 @@ return outer; } - if (outer.left >= RectUtil.right(subtrahend) || - RectUtil.right(outer) <= subtrahend.left || - outer.top >= RectUtil.bottom(subtrahend) || - RectUtil.bottom(outer) <= subtrahend.top) { + if (!RectUtil.overlaps(outer, subtrahend)) { // If the rectangles do not overlap, return the outer rect. return outer; } @@ -241,6 +256,19 @@ }, /** + * Returns true if |rect1| and |rect2| overlap. + * @param {!ScreenRect} rect1 + * @param {!ScreenRect} rect2 + * @return {boolean} True if the rects overlap. + */ + overlaps: (rect1, rect2) => { + return rect1.left < RectUtil.right(rect2) && + rect2.left < RectUtil.right(rect1) && + rect1.top < RectUtil.bottom(rect2) && + rect2.top < RectUtil.bottom(rect1); + }, + + /** * Finds the right edge of a rect. * @param {!ScreenRect} rect * @return {number}
diff --git a/chrome/browser/resources/chromeos/accessibility/common/rect_util_unittest.js b/chrome/browser/resources/chromeos/accessibility/common/rect_util_unittest.js index 1bbfa19..202a273 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/rect_util_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/common/rect_util_unittest.js
@@ -363,3 +363,36 @@ RectUtil.equal(expected, RectUtil.intersection(rect2, rect1)), 'Intersection should be symmetric'); }); + +TEST_F('RectUtilUnitTest', 'Overlaps', function() { + var rect1 = {left: 0, top: 0, width: 100, height: 100}; + var rect2 = {left: 80, top: 0, width: 100, height: 20}; + var rect3 = {left: 0, top: 80, width: 20, height: 100}; + + assertTrue(RectUtil.overlaps(rect1, rect1)); + assertTrue(RectUtil.overlaps(rect2, rect2)); + assertTrue(RectUtil.overlaps(rect3, rect3)); + assertTrue(RectUtil.overlaps(rect1, rect2)); + assertTrue(RectUtil.overlaps(rect1, rect3)); + assertFalse(RectUtil.overlaps(rect2, rect3)); +}); + +TEST_F('RectUtilUnitTest', 'RectFromPoints', function() { + var rect = {left: 10, top: 20, width: 50, height: 60}; + + assertNotEquals( + JSON.stringify(rect), + JSON.stringify(RectUtil.rectFromPoints(0, 0, 10, 10))); + assertEquals( + JSON.stringify(rect), + JSON.stringify(RectUtil.rectFromPoints(10, 20, 60, 80))); + assertEquals( + JSON.stringify(rect), + JSON.stringify(RectUtil.rectFromPoints(60, 20, 10, 80))); + assertEquals( + JSON.stringify(rect), + JSON.stringify(RectUtil.rectFromPoints(10, 80, 60, 20))); + assertEquals( + JSON.stringify(rect), + JSON.stringify(RectUtil.rectFromPoints(60, 80, 10, 20))); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js index d60d71b..c2bb7fd9 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_event_handler.js
@@ -52,9 +52,18 @@ /** @private {boolean} */ this.capture_ = options.capture || false; + /** @private {boolean} */ + this.listening_ = false; + /** @private {!function(!chrome.automation.AutomationEvent)} */ this.handler_ = this.onEvent_.bind(this); + this.startListening(); + } + + /** Starts listening or handling events. */ + startListening() { + this.listening_ = true; for (const node of this.nodes_) { node.addEventListener(this.type_, this.handler_, this.capture_); } @@ -62,6 +71,7 @@ /** Stops listening or handling future events. */ stopListening() { + this.listening_ = false; for (const node of this.nodes_) { node.removeEventListener(this.type_, this.handler_, this.capture_); } @@ -78,7 +88,7 @@ /** @private */ handleEvent_() { - if (this.eventStack_.length === 0) { + if (!this.listening_ || this.eventStack_.length === 0) { return; }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn index bc257dc..f429300 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
@@ -34,7 +34,6 @@ "options.html", "paragraph_utils.js", "prefs_manager.js", - "rect_utils.js", "select_to_speak-2x.svg", "select_to_speak.js", "select_to_speak_gdocs_script.js", @@ -111,7 +110,6 @@ ":node_utils", ":paragraph_utils", ":prefs_manager", - ":rect_utils", ":select_to_speak", ":select_to_speak_options", ":word_utils", @@ -119,6 +117,7 @@ "../common:automation_util", "../common:closure_shim", "../common:constants", + "../common:rect_util", "../common:tree_walker", ] } @@ -130,10 +129,10 @@ ":node_utils", ":paragraph_utils", ":prefs_manager", - ":rect_utils", ":word_utils", "../common:automation_util", "../common:constants", + "../common:rect_util", ] externs_list = [ "$externs_path/accessibility_private.js", @@ -158,7 +157,7 @@ js_library("node_utils") { deps = [ ":paragraph_utils", - ":rect_utils", + "../common:rect_util", ] externs_list = [ "$externs_path/automation.js" ] } @@ -177,10 +176,7 @@ } js_library("input_handler") { - deps = [ ":rect_utils" ] -} - -js_library("rect_utils") { + deps = [ "../common:rect_util" ] } js_library("prefs_manager") {
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js index 41426b4..ecb14ec 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js
@@ -92,7 +92,7 @@ return false; } - var rect = RectUtils.rectFromPoints( + var rect = RectUtil.rectFromPoints( this.mouseStart_.x, this.mouseStart_.y, evt.screenX, evt.screenY); this.callbacks_.onSelectionChanged(rect); return false; @@ -179,7 +179,7 @@ * @public */ getMouseRect() { - return RectUtils.rectFromPoints( + return RectUtil.rectFromPoints( this.mouseStart_.x, this.mouseStart_.y, this.mouseEnd_.x, this.mouseEnd_.y); }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js index 1d24339..17321d88 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js
@@ -168,7 +168,7 @@ return false; } - if (RectUtils.overlaps(node.location, rect)) { + if (RectUtil.overlaps(node.location, rect)) { if (!node.children || node.children.length == 0 || node.children[0].role != RoleType.INLINE_TEXT_BOX) { // Only add a node if it has no inlineTextBox children. If
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js index 66d5d827..8feac02 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js
@@ -13,7 +13,7 @@ 'paragraph_utils.js', 'node_utils.js', 'word_utils.js', - 'rect_utils.js', + '../common/rect_util.js', ];
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/rect_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/rect_utils.js deleted file mode 100644 index 37d278c..0000000 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/rect_utils.js +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2018 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. - -// Utilities for processing rectangles and coordinates. - -class RectUtils { - constructor() {} - - /** - * Return the rect that encloses two points. - * @param {number} x1 The first x coordinate. - * @param {number} y1 The first y coordinate. - * @param {number} x2 The second x coordinate. - * @param {number} y2 The second x coordinate. - * @return {{left: number, top: number, width: number, height: number}} - */ - static rectFromPoints(x1, y1, x2, y2) { - var left = Math.min(x1, x2); - var right = Math.max(x1, x2); - var top = Math.min(y1, y2); - var bottom = Math.max(y1, y2); - return {left, top, width: right - left, height: bottom - top}; - } - - /** - * Returns true if |rect1| and |rect2| overlap. The rects must define - * left, top, width, and height. - * @param {{left: number, top: number, width: number, height: number}} rect1 - * @param {{left: number, top: number, width: number, height: number}} rect2 - * @return {boolean} True if the rects overlap. - */ - static overlaps(rect1, rect2) { - var l1 = rect1.left; - var r1 = rect1.left + rect1.width; - var t1 = rect1.top; - var b1 = rect1.top + rect1.height; - var l2 = rect2.left; - var r2 = rect2.left + rect2.width; - var t2 = rect2.top; - var b2 = rect2.top + rect2.height; - return (l1 < r2 && r1 > l2 && t1 < b2 && b1 > t2); - } -}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/rect_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/rect_utils_unittest.js deleted file mode 100644 index 5ac0194..0000000 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/rect_utils_unittest.js +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2018 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. - -/** - * Test fixture for rect_utils.js. - */ -SelectToSpeakRectUtilsUnitTest = class extends testing.Test {}; - -/** @override */ -SelectToSpeakRectUtilsUnitTest.prototype.extraLibraries = [ - 'rect_utils.js', -]; - - -TEST_F('SelectToSpeakRectUtilsUnitTest', 'Overlaps', function() { - var rect1 = {left: 0, top: 0, width: 100, height: 100}; - var rect2 = {left: 80, top: 0, width: 100, height: 20}; - var rect3 = {left: 0, top: 80, width: 20, height: 100}; - - assertTrue(RectUtils.overlaps(rect1, rect1)); - assertTrue(RectUtils.overlaps(rect2, rect2)); - assertTrue(RectUtils.overlaps(rect3, rect3)); - assertTrue(RectUtils.overlaps(rect1, rect2)); - assertTrue(RectUtils.overlaps(rect1, rect3)); - assertFalse(RectUtils.overlaps(rect2, rect3)); -}); - -TEST_F('SelectToSpeakRectUtilsUnitTest', 'RectFromPoints', function() { - var rect = {left: 10, top: 20, width: 50, height: 60}; - - assertNotEquals( - JSON.stringify(rect), - JSON.stringify(RectUtils.rectFromPoints(0, 0, 10, 10))); - assertEquals( - JSON.stringify(rect), - JSON.stringify(RectUtils.rectFromPoints(10, 20, 60, 80))); - assertEquals( - JSON.stringify(rect), - JSON.stringify(RectUtils.rectFromPoints(60, 20, 10, 80))); - assertEquals( - JSON.stringify(rect), - JSON.stringify(RectUtils.rectFromPoints(10, 80, 60, 20))); - assertEquals( - JSON.stringify(rect), - JSON.stringify(RectUtils.rectFromPoints(60, 80, 10, 20))); -});
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2 b/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2 index 91b01f9..fc06737 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2
@@ -14,6 +14,7 @@ "common/closure_shim.js", "common/constants.js", "common/automation_predicate.js", + "common/rect_util.js", "common/tree_walker.js", "common/automation_util.js", "select_to_speak/input_handler.js", @@ -22,7 +23,6 @@ "select_to_speak/paragraph_utils.js", "select_to_speak/prefs_manager.js", "select_to_speak/word_utils.js", - "select_to_speak/rect_utils.js", "select_to_speak/select_to_speak.js", "select_to_speak/select_to_speak_main.js" ]
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/background.js b/chrome/browser/resources/chromeos/accessibility/switch_access/background.js index 90f8d65e..19854c19 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/background.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/background.js
@@ -2,4 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// In 'split' manifest mode, the extension system runs two copies of the +// extension. One in an incognito context; the other not. In guest mode, the +// extension system runs only the extension in an incognito context. To prevent +// doubling of this extension, only continue for one context. +const manifest = + /** @type {{incognito: (string|undefined)}} */ ( + chrome.runtime.getManifest()); +if (manifest.incognito == 'split' && !chrome.extension.inIncognitoContext) { + window.close(); +} SwitchAccess.initialize();
diff --git a/chrome/browser/resources/new_tab_page/BUILD.gn b/chrome/browser/resources/new_tab_page/BUILD.gn index c83b365..1a808a6 100644 --- a/chrome/browser/resources/new_tab_page/BUILD.gn +++ b/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -48,6 +48,7 @@ deps = [ ":background_manager", ":browser_proxy", + ":middle_slot_promo", ":module_wrapper", ":modules", ":most_visited", @@ -66,6 +67,13 @@ ] } +js_library("middle_slot_promo") { + deps = [ + ":browser_proxy", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + js_library("most_visited") { deps = [ ":browser_proxy", @@ -258,6 +266,7 @@ "doodle_share_dialog.js", "fakebox.js", "logo.js", + "middle_slot_promo.js", "mini_page.js", "most_visited.js", "realbox_button.js",
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html index d1f83b7..fc569cf 100644 --- a/chrome/browser/resources/new_tab_page/app.html +++ b/chrome/browser/resources/new_tab_page/app.html
@@ -94,13 +94,9 @@ --tile-hover-color: rgba(255, 255, 255, .1); } - #promo { + ntp-middle-slot-promo { bottom: 16px; - height: 32px; - left: 0; position: fixed; - right: 0; - width: 100%; } ntp-module-wrapper + ntp-module-wrapper { @@ -280,9 +276,9 @@ </ntp-most-visited> <dom-if if="[[lazyRender_]]" on-dom-change="onLazyRendered_"> <template> - <ntp-iframe id="promo" hidden$="[[!promoLoaded_]]" - src="chrome-untrusted://new-tab-page/promo"> - </ntp-iframe> + <ntp-middle-slot-promo + on-ntp-middle-slot-promo-loaded="onMiddleSlotPromoLoaded_"> + </ntp-middle-slot-promo> <template is="dom-repeat" items="[[moduleDescriptors_]]" id="modules"> <ntp-module-wrapper descriptor="[[item]]"></ntp-module-wrapper> </template>
diff --git a/chrome/browser/resources/new_tab_page/app.js b/chrome/browser/resources/new_tab_page/app.js index e0f6989..40a36e2 100644 --- a/chrome/browser/resources/new_tab_page/app.js +++ b/chrome/browser/resources/new_tab_page/app.js
@@ -3,6 +3,7 @@ // found in the LICENSE file. import './strings.m.js'; +import './middle_slot_promo.js'; import './most_visited.js'; import './customize_dialog.js'; import './voice_search_overlay.js'; @@ -106,12 +107,6 @@ lazyRender_)`, }, - /** @private */ - promoLoaded_: { - type: Boolean, - value: false, - }, - /** @private {!newTabPage.mojom.Theme} */ theme_: { observer: 'onThemeChange_', @@ -251,12 +246,8 @@ if (typeof data !== 'object') { return; } - if ('frameType' in data) { - if (data.frameType === 'promo') { - this.handlePromoMessage_(event); - } else if (data.frameType === 'one-google-bar') { - this.handleOneGoogleBarMessage_(event); - } + if ('frameType' in data && data.frameType === 'one-google-bar') { + this.handleOneGoogleBarMessage_(event); } }); this.eventTracker_.add(window, 'keydown', e => this.onWindowKeydown_(e)); @@ -728,35 +719,7 @@ $$(this, '#oneGoogleBar').style.zIndex = '0'; } else if (data.messageType === 'execute-browser-command') { this.executePromoBrowserCommand_( - /** @type CommandData */ (data), event.source, event.origin); - } - } - - /** - * Handle messages from promo iframe. This shows the promo on load and sets - * up the show/hide logic (in case there is an overlap with most-visited - * tiles). - * @param {!MessageEvent} event - * @private - */ - handlePromoMessage_(event) { - /** @type {!Object} */ - const data = event.data; - if (data.messageType === 'loaded') { - this.promoLoaded_ = true; - const onResize = () => { - const hidePromo = this.$.mostVisited.getBoundingClientRect().bottom >= - $$(this, '#promo').offsetTop; - $$(this, '#promo').style.opacity = hidePromo ? 0 : 1; - }; - this.eventTracker_.add(window, 'resize', onResize); - onResize(); - this.pageHandler_.onPromoRendered(BrowserProxy.getInstance().now()); - } else if (data.messageType === 'link-clicked') { - this.pageHandler_.onPromoLinkClicked(); - } else if (data.messageType === 'execute-browser-command') { - this.executePromoBrowserCommand_( - /** @type CommandData */ (data), event.source, event.origin); + /** @type {!CommandData} */ (data.data), event.source, event.origin); } } @@ -768,6 +731,18 @@ } } + /** @private */ + onMiddleSlotPromoLoaded_() { + const onResize = () => { + const promoElement = $$(this, 'ntp-middle-slot-promo'); + const hidePromo = this.$.mostVisited.getBoundingClientRect().bottom >= + promoElement.offsetTop; + promoElement.style.visibility = hidePromo ? 'hidden' : 'visible'; + }; + this.eventTracker_.add(window, 'resize', onResize); + onResize(); + } + /** * During a shortcut drag, an iframe behind ntp-most-visited will prevent * 'dragover' events from firing. To workaround this, 'pointer-events: none'
diff --git a/chrome/browser/resources/new_tab_page/middle_slot_promo.html b/chrome/browser/resources/new_tab_page/middle_slot_promo.html new file mode 100644 index 0000000..3c39838 --- /dev/null +++ b/chrome/browser/resources/new_tab_page/middle_slot_promo.html
@@ -0,0 +1,57 @@ +<style include="cr-hidden-style"> + :host { + font-size: 12px; + max-width: 537px; + white-space: pre; + } + + #container { + align-items: center; + background-color: var(--cr-card-background-color); + border: 1px solid var(--ntp-border-color); + border-radius: 16px; + box-sizing: border-box; + color: var(--cr-primary-text-color); + display: flex; + flex-direction: row; + height: 32px; + padding: 0 16px; + } + + a { + color: var(--cr-link-color); + cursor: pointer; + text-decoration: none; + } + + a:focus { + border-radius: 2px; + box-shadow: var(--ntp-focus-shadow); + outline: none; + } + + .image { + margin-inline-end: 8px; + margin-inline-start: -12px; + } + + img { + border-radius: 50%; + height: 24px; + pointer-events: none; + width: 24px; + } + + @media (prefers-color-scheme: dark) { + img { + background-color: var(--google-grey-200); + } + } + + #container > :last-child { + overflow: hidden; + text-overflow: ellipsis; + } +</style> +<!-- The #container is hidden until the promo parts are added by the JS. --> +<div id="container" hidden></div>
diff --git a/chrome/browser/resources/new_tab_page/middle_slot_promo.js b/chrome/browser/resources/new_tab_page/middle_slot_promo.js new file mode 100644 index 0000000..4c3c9b4d --- /dev/null +++ b/chrome/browser/resources/new_tab_page/middle_slot_promo.js
@@ -0,0 +1,117 @@ +// 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 'chrome://resources/cr_elements/hidden_style_css.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {BrowserProxy} from './browser_proxy.js'; +import {PromoBrowserCommandProxy} from './promo_browser_command_proxy.js'; + +// Element that requests and renders the middle-slot promo. The element is +// hidden until the promo is rendered, If no promo exists or the promo is empty, +// the element remains hidden. +class MiddleSlotPromoElement extends PolymerElement { + static get is() { + return 'ntp-middle-slot-promo'; + } + + static get template() { + return html`{__html_template__}`; + } + + constructor() { + super(); + /** @private {newTabPage.mojom.PageHandlerRemote} */ + this.pageHandler_ = BrowserProxy.getInstance().handler; + } + + /** @override */ + connectedCallback() { + super.connectedCallback(); + this.pageHandler_.getPromo().then(({promo}) => { + if (!promo) { + return; + } + promo.middleSlotParts.forEach(({image, link, text}) => { + let el; + if (image) { + el = document.createElement('img'); + el.src = image.imageUrl.url.startsWith('data:') ? + image.imageUrl.url : + `chrome://image?${image.imageUrl.url}`; + if (image.target) { + const anchor = this.createAnchor_(image.target); + if (anchor) { + anchor.appendChild(el); + el = anchor; + } + } + el.classList.add('image'); + } else if (link) { + el = this.createAnchor_(link.url); + } else if (text) { + el = document.createElement('span'); + } + const linkOrText = link || text; + if (el && linkOrText) { + el.innerText = linkOrText.text; + if (linkOrText.color) { + el.style.color = linkOrText.color; + } + } + if (el) { + this.$.container.appendChild(el); + } + }); + this.$.container.hidden = false; + this.pageHandler_.onPromoRendered( + BrowserProxy.getInstance().now(), promo.logUrl || null); + this.dispatchEvent(new Event( + 'ntp-middle-slot-promo-loaded', {bubbles: true, composed: true})); + }); + } + + /** + * @param {!url.mojom.Url} target + * @return {HTMLAnchorElement} + * @private + */ + createAnchor_(target) { + const commandIdMatch = /^command:(\d+)$/.exec(target.url); + if (!commandIdMatch && !target.url.startsWith('https://')) { + return null; + } + const el = /** @type {!HTMLAnchorElement} */ (document.createElement('a')); + if (!commandIdMatch) { + el.href = target.url; + } + const onClick = event => { + if (commandIdMatch) { + let commandId = +commandIdMatch[1]; + // Make sure we don't send unsupported commands to the browser. + if (!Object.values(promoBrowserCommand.mojom.Command) + .includes(commandId)) { + commandId = promoBrowserCommand.mojom.Command.kUnknownCommand; + } + PromoBrowserCommandProxy.getInstance().handler.executeCommand( + commandId, { + middleButton: event.button === 1, + altKey: event.altKey, + ctrlKey: event.ctrlKey, + metaKey: event.metaKey, + shiftKey: event.shiftKey, + }); + } + this.pageHandler_.onPromoLinkClicked(); + }; + // 'auxclick' handles the middle mouse button which does not trigger a + // 'click' event. + el.addEventListener('auxclick', onClick); + el.addEventListener('click', onClick); + return el; + } +} + +customElements.define(MiddleSlotPromoElement.is, MiddleSlotPromoElement);
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd b/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd index 871c434..5d1a0858 100644 --- a/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd +++ b/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
@@ -18,6 +18,9 @@ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/app.js" use_base_dir="false" type="BINDATA" compress="false" preprocess="true" /> + <include name="IDR_NEW_TAB_PAGE_MIDDLE_SLOT_PROMO_JS" + file="${root_gen_dir}/chrome/browser/resources/new_tab_page/middle_slot_promo.js" + use_base_dir="false" type="BINDATA" compress="false" /> <include name="IDR_NEW_TAB_PAGE_MOST_VISITED_JS" file="${root_gen_dir}/chrome/browser/resources/new_tab_page/most_visited.js" use_base_dir="false" type="BINDATA" compress="false" />
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp b/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp index 8d0effd..012b9e8 100644 --- a/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp +++ b/chrome/browser/resources/new_tab_page/new_tab_page_resources_common.grdp
@@ -55,10 +55,6 @@ file="untrusted/one_google_bar.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_JS" file="untrusted/one_google_bar.js" type="BINDATA" /> - <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_HTML" - file="untrusted/promo.html" type="BINDATA" /> - <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_JS" - file="untrusted/promo.js" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_IMAGE_HTML" file="untrusted/image.html" type="BINDATA" /> <include name="IDR_NEW_TAB_PAGE_UNTRUSTED_BACKGROUND_IMAGE_HTML"
diff --git a/chrome/browser/resources/new_tab_page/untrusted/promo.html b/chrome/browser/resources/new_tab_page/untrusted/promo.html deleted file mode 100644 index 04cd935..0000000 --- a/chrome/browser/resources/new_tab_page/untrusted/promo.html +++ /dev/null
@@ -1,107 +0,0 @@ -<!doctype html> -<html dir="$i18n{textdirection}"> - <head> - <meta charset="utf-8"> - <style> - html { - --google-blue-400-rgb: 107, 165, 237; /* #6ba5ed */ - --google-blue-400: rgb(var(--google-blue-400-rgb)); - --google-blue-600-rgb: 26, 115, 232; /* #1a73e8 */ - --google-blue-600: rgb(var(--google-blue-600-rgb)); - --google-grey-200-rgb: 232, 234, 237; /* #e8eaed */ - --google-grey-200: rgb(var(--google-grey-200-rgb)); - --google-grey-900-rgb: 32, 33, 36; /* #202124 */ - --google-grey-900: rgb(var(--google-grey-900-rgb)); - --google-blue-refresh-300-rgb: 138, 180, 248; /* #8ab4f8 */ - --google-blue-refresh-300: rgb(var(--google-blue-refresh-300-rgb)); - --google-grey-refresh-300-rgb: 218, 220, 224; /* #dadce0 */ - --google-grey-refresh-300: rgb(var(--google-grey-refresh-300-rgb)); - --google-grey-refresh-700-rgb: 95, 99, 104; /* #5f6368 */ - --google-grey-refresh-700: rgb(var(--google-grey-refresh-700-rgb)); - } - - body { - margin: auto; - overflow: hidden; - width: fit-content; - } - - body * { - font-family: Roboto, arial, sans-serif; - } - - body > div { - background-color: white; - border: 1px solid var(--google-grey-refresh-300); - border-radius: 16px; - box-sizing: border-box; - color: var(--google-grey-refresh-700); - display: inline-block; - font-size: 12px; - height: 32px; - line-height: 30px; - margin-bottom: 0; - max-width: 537px; - overflow: hidden; - padding: 0 16px; - pointer-events: all; - position: relative; - text-overflow: ellipsis; - white-space: nowrap; - } - - @media (prefers-color-scheme: dark) { - body > div { - background-color: var(--google-grey-900); - border-color: rgba(0, 0, 0, .1); - color: var(--google-grey-200); - } - } - - body > div > a { - color: var(--google-blue-600); - text-decoration: none; - } - - body > div > a:focus { - outline: solid 2px rgba(var(--google-blue-600-rgb), .4); - } - - @media (prefers-color-scheme: dark) { - body > div > a { - color: var(--google-blue-400); - } - - body > div > a:focus { - outline: solid 2px rgba(var(--google-blue-refresh-300-rgb), .5); - } - } - - body > div > img { - border-radius: 50%; - height: 24px; - margin-bottom: 2px; - margin-inline-end: 8px; - margin-inline-start: -12px; - object-fit: cover; - vertical-align: middle; - width: 24px; - } - - @media (prefers-color-scheme: dark) { - body > div > img { - background-color: var(--google-grey-200); - } - } - </style> - </head> - <body> - <!-- - This is the promo HTML which includes a <style> and <div> tags. The - <style> element is removed since the styling needs to be overridden. - The <div> contains one or more <span>, <a> and <img> elements. - --> - $i18nRaw{data} - <script src="promo.js"></script> - </body> -</html>
diff --git a/chrome/browser/resources/new_tab_page/untrusted/promo.js b/chrome/browser/resources/new_tab_page/untrusted/promo.js deleted file mode 100644 index 18a6190..0000000 --- a/chrome/browser/resources/new_tab_page/untrusted/promo.js +++ /dev/null
@@ -1,48 +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. - -// TODO(crbug.com/1057147): add tests for chrome-untrusted://new-tab-page files. -document.addEventListener('DOMContentLoaded', () => { - // Remove the <style> from the raw promo since we want to style the promo - // ourselves. - const styleElement = document.querySelector('body > style'); - if (styleElement) { - styleElement.remove(); - } - // The <a> elements need to open in the top frame since the promo is loaded - // in an <iframe>. - document.body.querySelectorAll('a').forEach(el => { - if (el.target !== '_blank') { - el.target = '_top'; - } - el.addEventListener('click', (event) => { - const browserCommandFound = - event.target.getAttribute('href').match(/^command:(\d+)$/); - if (browserCommandFound) { - event.preventDefault(); // Prevent navigation attempt. - window.parent.postMessage( - { - frameType: 'promo', - messageType: 'execute-browser-command', - commandId: parseInt(browserCommandFound[1], 10), - clickInfo: { - middleButton: event.button === 1, - altKey: event.altKey, - ctrlKey: event.ctrlKey, - metaKey: event.metaKey, - shiftKey: event.shiftKey - } - }, - 'chrome://new-tab-page'); - } - - window.parent.postMessage( - {frameType: 'promo', messageType: 'link-clicked'}, - 'chrome://new-tab-page'); - }); - }); - // Inform the embedder that the promo has loaded and can be displayed. - window.parent.postMessage( - {frameType: 'promo', messageType: 'loaded'}, 'chrome://new-tab-page'); -});
diff --git a/chrome/browser/resources/pdf/elements/viewer-annotations-bar.js b/chrome/browser/resources/pdf/elements/viewer-annotations-bar.js index f502a1441..d483280 100644 --- a/chrome/browser/resources/pdf/elements/viewer-annotations-bar.js +++ b/chrome/browser/resources/pdf/elements/viewer-annotations-bar.js
@@ -40,10 +40,16 @@ annotationTool_: Object, /** @private */ - canUndoAnnotation_: Boolean, + canUndoAnnotation_: { + type: Boolean, + value: false, + }, /** @private */ - canRedoAnnotation_: Boolean, + canRedoAnnotation_: { + type: Boolean, + value: false, + }, }; }
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index d2300291..37d7e012 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -540,7 +540,10 @@ * @private */ onScroll_(e) { - this.pluginController.updateScroll(e.target.scrollLeft, e.target.scrollTop); + if (this.currentController === this.pluginController) { + this.pluginController.updateScroll( + e.target.scrollLeft, e.target.scrollTop); + } } /** @override */
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index 5a4870f..3eae2fd 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -752,6 +752,11 @@ if (this.shouldShowDeprecatedPrinterWarning) { return 'print-preview:printer-not-supported'; } + // <if expr="chromeos"> + if (this.id_ === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { + return 'print-preview:save-to-drive'; + } + // </if> if (this.id_ === Destination.GooglePromotedId.DOCS) { return 'print-preview:save-to-drive'; }
diff --git a/chrome/browser/resources/print_preview/data/destination_match.js b/chrome/browser/resources/print_preview/data/destination_match.js index e5404fe..3d71593 100644 --- a/chrome/browser/resources/print_preview/data/destination_match.js +++ b/chrome/browser/resources/print_preview/data/destination_match.js
@@ -43,6 +43,12 @@ * @return {!PrinterType} Map the destination to a PrinterType. */ export function getPrinterTypeForDestination(destination) { + // <if expr="chromeos"> + if (destination.id === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { + return PrinterType.PDF_PRINTER; + } + // </if> + if (destination.id === Destination.GooglePromotedId.SAVE_AS_PDF) { return PrinterType.PDF_PRINTER; } @@ -123,10 +129,14 @@ * @private */ isVirtualDestination_(destination) { - if (destination.origin === DestinationOrigin.LOCAL) { - return destination.id === Destination.GooglePromotedId.SAVE_AS_PDF; + // <if expr="chromeos"> + if (destination.id === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { + return true; } - return destination.id === Destination.GooglePromotedId.DOCS; + // </if> + + return destination.id === Destination.GooglePromotedId.DOCS || + destination.id === Destination.GooglePromotedId.SAVE_AS_PDF; } /**
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index 874a1ad..93cd45ec 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -414,8 +414,7 @@ const serializedSystemDefault = { id: this.systemDefaultDestinationId_, - origin: this.systemDefaultDestinationId_ === - Destination.GooglePromotedId.SAVE_AS_PDF ? + origin: this.isDestinationLocal_(this.systemDefaultDestinationId_) ? DestinationOrigin.LOCAL : this.platformOrigin_, account: '', @@ -436,6 +435,20 @@ serializedSystemDefault, /*autoselect=*/ true); } + /** + * @param {?string} destinationId + * @return {boolean} + */ + isDestinationLocal_(destinationId) { + // <if expr="chromeos"> + if (destinationId === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { + return true; + } + // </if> + + return destinationId === Destination.GooglePromotedId.SAVE_AS_PDF; + } + /** Removes all events being tracked from the tracker. */ resetTracker() { this.tracker_.removeAll();
diff --git a/chrome/browser/resources/print_preview/data/model.js b/chrome/browser/resources/print_preview/data/model.js index b0a3948..4deab39 100644 --- a/chrome/browser/resources/print_preview/data/model.js +++ b/chrome/browser/resources/print_preview/data/model.js
@@ -11,7 +11,7 @@ import {BackgroundGraphicsModeRestriction, Policies} from '../native_layer.js'; import {Cdd, CddCapabilities, Destination, DestinationOrigin, DestinationType, RecentDestination, VendorCapability} from './destination.js'; -import {getPrinterTypeForDestination} from './destination_match.js'; +import {getPrinterTypeForDestination, PrinterType} from './destination_match.js'; // <if expr="chromeos"> import {ColorModeRestriction, DuplexModeRestriction, PinModeRestriction} from './destination_policies.js'; // </if> @@ -475,7 +475,7 @@ value: false, }, - /** @type {Destination} */ + /** @type {!Destination} */ destination: Object, /** @type {!DocumentSettings} */ @@ -708,8 +708,8 @@ /** @private */ updateSettingsAvailabilityFromDestinationAndDocumentSettings_() { - const isSaveAsPDF = - this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF; + const isSaveAsPDF = getPrinterTypeForDestination(this.destination) === + PrinterType.PDF_PRINTER; const knownSizeToSaveAsPdf = isSaveAsPDF && (!this.documentSettings.isModifiable || this.documentSettings.hasCssMediaStyles); @@ -1357,6 +1357,10 @@ pageHeight: this.pageSize.height, showSystemDialog: showSystemDialog, }; + // <if expr="chromeos"> + ticket.printToGoogleDrive = ticket.printToGoogleDrive || + destination.id === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS; + // </if> // Set 'cloudPrintID' only if the destination is not local. if (!destination.isLocal) {
diff --git a/chrome/browser/resources/print_preview/print_preview_resources.grd b/chrome/browser/resources/print_preview/print_preview_resources.grd index 80cdb82..5e3f125 100644 --- a/chrome/browser/resources/print_preview/print_preview_resources.grd +++ b/chrome/browser/resources/print_preview/print_preview_resources.grd
@@ -186,7 +186,8 @@ <structure name="IDR_PRINT_PREVIEW_DATA_DESTINATION_MATCH_JS" file="data/destination_match.js" compress="false" - type="chrome_html" /> + type="chrome_html" + preprocess="true" /> <if expr="chromeos"> <structure name="IDR_PRINT_PREVIEW_DATA_DESTINATION_POLICIES_JS" file="data/destination_policies.js"
diff --git a/chrome/browser/resources/print_preview/ui/app.js b/chrome/browser/resources/print_preview/ui/app.js index b638a9d5..6f856097 100644 --- a/chrome/browser/resources/print_preview/ui/app.js +++ b/chrome/browser/resources/print_preview/ui/app.js
@@ -19,6 +19,7 @@ import {CloudPrintInterface, CloudPrintInterfaceErrorEventDetail, CloudPrintInterfaceEventType} from '../cloud_print_interface.js'; import {CloudPrintInterfaceImpl} from '../cloud_print_interface_impl.js'; import {Destination, DestinationOrigin} from '../data/destination.js'; +import {getPrinterTypeForDestination, PrinterType} from '../data/destination_match.js'; import {DocumentSettings} from '../data/document_info.js'; import {Margins} from '../data/margins.js'; import {MeasurementSystem} from '../data/measurement_system.js'; @@ -442,7 +443,8 @@ this.nativeLayer_.dialogClose(this.cancelled_); } else if (this.state === State.HIDDEN) { if (this.destination_.isLocal && - this.destination_.id !== Destination.GooglePromotedId.SAVE_AS_PDF) { + getPrinterTypeForDestination(this.destination_) !== + PrinterType.PDF_PRINTER) { // Only hide the preview for local, non PDF destinations. this.nativeLayer_.hidePreview(); } @@ -453,8 +455,8 @@ destination, this.openPdfInPreview_, this.showSystemDialogBeforePrint_)); if (destination.isLocal) { - const onError = - destination.id === Destination.GooglePromotedId.SAVE_AS_PDF ? + const onError = getPrinterTypeForDestination(destination) === + PrinterType.PDF_PRINTER ? this.onFileSelectionCancel_.bind(this) : this.onPrintFailed_.bind(this); whenPrintDone.then(this.close_.bind(this), onError);
diff --git a/chrome/browser/resources/print_preview/ui/button_strip.js b/chrome/browser/resources/print_preview/ui/button_strip.js index 46244702..107df18 100644 --- a/chrome/browser/resources/print_preview/ui/button_strip.js +++ b/chrome/browser/resources/print_preview/ui/button_strip.js
@@ -13,6 +13,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination} from '../data/destination.js'; +import {getPrinterTypeForDestination, PrinterType} from '../data/destination_match.js'; import {State} from '../data/state.js'; Polymer({ @@ -83,7 +84,8 @@ */ isPdfOrDrive_() { return this.destination && - (this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF || + (getPrinterTypeForDestination(this.destination) === + PrinterType.PDF_PRINTER || this.destination.id === Destination.GooglePromotedId.DOCS); },
diff --git a/chrome/browser/resources/print_preview/ui/destination_select_cros.js b/chrome/browser/resources/print_preview/ui/destination_select_cros.js index 0c0ccee..db1c793 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select_cros.js +++ b/chrome/browser/resources/print_preview/ui/destination_select_cros.js
@@ -174,6 +174,11 @@ // Check for the Docs or Save as PDF ids first. const keyParams = this.selectedValue.split('/'); + // <if expr="chromeos"> + if (keyParams[0] === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { + return 'print-preview:save-to-drive'; + } + // </if> if (keyParams[0] === Destination.GooglePromotedId.DOCS) { return 'print-preview:save-to-drive'; }
diff --git a/chrome/browser/resources/print_preview/ui/destination_settings.js b/chrome/browser/resources/print_preview/ui/destination_settings.js index bdc1874c..e461abf 100644 --- a/chrome/browser/resources/print_preview/ui/destination_settings.js +++ b/chrome/browser/resources/print_preview/ui/destination_settings.js
@@ -22,12 +22,12 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {beforeNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CloudPrintInterfaceImpl} from '../cloud_print_interface_impl.js'; import {createDestinationKey, createRecentDestinationKey, Destination, DestinationOrigin, makeRecentDestination, RecentDestination} from '../data/destination.js'; +import {getPrinterTypeForDestination, PrinterType} from '../data/destination_match.js'; import {DestinationErrorType, DestinationStore} from '../data/destination_store.js'; import {InvitationStore} from '../data/invitation_store.js'; import {Error, State} from '../data/state.js'; @@ -153,17 +153,6 @@ /** @private {!Array<string>} */ users_: Array, - - // <if expr="chromeos"> - /** @private */ - saveToDriveFlagEnabled_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('printSaveToDrive'); - }, - readOnly: true, - }, - // </if> }, /** @private {string} */ @@ -384,8 +373,7 @@ */ destinationIsDriveOrPdf_(destination) { // <if expr="chromeos"> - if (this.saveToDriveFlagEnabled_ && - destination.id === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { + if (destination.id === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { return true; } // </if> @@ -470,7 +458,8 @@ this.destinationState === DestinationState.UPDATED || (this.destinationState === DestinationState.SET && !!this.destination && (!!this.destination.capabilities || - this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF)); + getPrinterTypeForDestination(this.destination) === + PrinterType.PDF_PRINTER)); }, // <if expr="chromeos">
diff --git a/chrome/browser/resources/print_preview/ui/header.js b/chrome/browser/resources/print_preview/ui/header.js index 8f90333a..df4c2d24 100644 --- a/chrome/browser/resources/print_preview/ui/header.js +++ b/chrome/browser/resources/print_preview/ui/header.js
@@ -13,6 +13,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination} from '../data/destination.js'; +import {getPrinterTypeForDestination, PrinterType} from '../data/destination_match.js'; import {Error, State} from '../data/state.js'; import {SettingsBehavior} from './settings_behavior.js'; @@ -53,7 +54,8 @@ */ isPdfOrDrive_() { return this.destination && - (this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF || + (getPrinterTypeForDestination(this.destination) === + PrinterType.PDF_PRINTER || this.destination.id === Destination.GooglePromotedId.DOCS); },
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn index f635bda..c1ce423 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
@@ -19,6 +19,7 @@ js_library("android_apps_subpage") { deps = [ ":android_apps_browser_proxy", + "..:deep_linking_behavior", "..:os_route", "../..:router", "../../prefs:prefs_behavior", @@ -32,6 +33,7 @@ deps = [ ":android_apps_browser_proxy", ":android_apps_subpage", + "..:deep_linking_behavior", "..:os_route", "../../:router", "../../prefs:prefs_behavior",
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.html b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.html index 7fcc517b..41ce64fc 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.html
@@ -9,6 +9,7 @@ <link rel="import" href="android_apps_browser_proxy.html"> <link rel="import" href="../../i18n_setup.html"> <link rel="import" href="../../prefs/prefs_behavior.html"> +<link rel="import" href="../deep_linking_behavior.html"> <link rel="import" href="../os_route.html"> <link rel="import" href="../../router.html"> <link rel="import" href="../../settings_shared_css.html"> @@ -19,7 +20,9 @@ <template is="dom-if" if="[[androidAppsInfo.settingsAppAvailable]]" restamp> <cr-link-row id="manageApps" label="$i18n{androidAppsManageApps}" - on-click="onManageAndroidAppsTap_" external></cr-link-row> + on-click="onManageAndroidAppsTap_" external + deep-link-focus-id$="[[Setting.kManageAndroidPreferences]]"> + </cr-link-row> </template> <!-- Use 'restamp' so tests can check if the row exists. --> @@ -29,7 +32,8 @@ $i18n{androidAppsRemove} </div> <cr-button on-click="onRemoveTap_" - aria-labelledby="androidRemoveLabel"> + aria-labelledby="androidRemoveLabel" + deep-link-focus-id$="[[Setting.kRemovePlayStore]]"> $i18n{androidAppsRemoveButton} </cr-button> </div>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js index 3a78ec1..42f9b5d 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js
@@ -10,7 +10,12 @@ Polymer({ is: 'settings-android-apps-subpage', - behaviors: [I18nBehavior, PrefsBehavior], + behaviors: [ + DeepLinkingBehavior, + I18nBehavior, + PrefsBehavior, + settings.RouteObserverBehavior, + ], properties: { /** Preferences state. */ @@ -36,7 +41,32 @@ 'androidAppsDisableDialogMessage', {substitutions: [], tags: ['br']}); } + }, + + /** + * Used by DeepLinkingBehavior to focus this page's deep links. + * @type {!Set<!chromeos.settings.mojom.Setting>} + */ + supportedSettingIds: { + type: Object, + value: () => new Set([ + chromeos.settings.mojom.Setting.kManageAndroidPreferences, + chromeos.settings.mojom.Setting.kRemovePlayStore, + ]), + }, + }, + + /** + * @param {!settings.Route} route + * @param {!settings.Route} oldRoute + */ + currentRouteChanged(route, oldRoute) { + // Does not apply to this page. + if (route !== settings.routes.ANDROID_APPS_DETAILS) { + return; } + + this.attemptDeepLink(); }, /** @private */
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html index 69c36a9..86c567b 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.html
@@ -7,6 +7,7 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="../../i18n_setup.html"> <link rel="import" href="../../prefs/prefs_behavior.html"> +<link rel="import" href="../deep_linking_behavior.html"> <link rel="import" href="../os_route.html"> <link rel="import" href="../../router.html"> <link rel="import" href="../../settings_page/settings_animated_pages.html"> @@ -66,7 +67,8 @@ disabled="[[isEnforced_(prefs.arc.enabled)]]" on-click="onEnableAndroidAppsTap_" aria-label="$i18n{androidAppsPageTitle}" - aria-describedby="secondaryText"> + aria-describedby="secondaryText" + deep-link-focus-id$="[[Setting.kTurnOnPlayStore]]"> $i18n{androidAppsEnable} </cr-button> </template> @@ -74,7 +76,8 @@ </template> <template is="dom-if" if="[[!havePlayStoreApp]]" restamp> <cr-link-row id="manageApps" label="$i18n{androidAppsManageApps}" - on-click="onManageAndroidAppsTap_" external> + on-click="onManageAndroidAppsTap_" external + deep-link-focus-id$="[[Setting.kManageAndroidPreferences]]"> </cr-link-row> </template> </template>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js index 8d4834d..75cfec0c 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
@@ -12,8 +12,10 @@ behaviors: [ app_management.StoreClient, + DeepLinkingBehavior, I18nBehavior, PrefsBehavior, + settings.RouteObserverBehavior, ], properties: { @@ -74,6 +76,18 @@ * @private */ app_: Object, + + /** + * Used by DeepLinkingBehavior to focus this page's deep links. + * @type {!Set<!chromeos.settings.mojom.Setting>} + */ + supportedSettingIds: { + type: Object, + value: () => new Set([ + chromeos.settings.mojom.Setting.kManageAndroidPreferences, + chromeos.settings.mojom.Setting.kTurnOnPlayStore, + ]), + }, }, attached() { @@ -81,6 +95,19 @@ }, /** + * @param {!settings.Route} route + * @param {!settings.Route} oldRoute + */ + currentRouteChanged(route, oldRoute) { + // Does not apply to this page. + if (route !== settings.routes.APPS) { + return; + } + + this.attemptDeepLink(); + }, + + /** * @param {App} app * @return {string} * @private
diff --git a/chrome/browser/search/promos/promo_data.cc b/chrome/browser/search/promos/promo_data.cc index 7132b318..8169aa7 100644 --- a/chrome/browser/search/promos/promo_data.cc +++ b/chrome/browser/search/promos/promo_data.cc
@@ -14,6 +14,7 @@ bool operator==(const PromoData& lhs, const PromoData& rhs) { return lhs.promo_html == rhs.promo_html && + lhs.middle_slot_json == rhs.middle_slot_json && lhs.promo_log_url == rhs.promo_log_url && lhs.promo_id == rhs.promo_id; }
diff --git a/chrome/browser/search/promos/promo_data.h b/chrome/browser/search/promos/promo_data.h index 7d02987..ac89199 100644 --- a/chrome/browser/search/promos/promo_data.h +++ b/chrome/browser/search/promos/promo_data.h
@@ -23,6 +23,9 @@ // The main HTML for the promo. May be empty when nothing to show. std::string promo_html; + // The structured JSON data of the middle slot promo. + std::string middle_slot_json; + // URL to ping to log a promo impression. May be invalid. GURL promo_log_url;
diff --git a/chrome/browser/search/promos/promo_service.cc b/chrome/browser/search/promos/promo_service.cc index b435d0f..317c487 100644 --- a/chrome/browser/search/promos/promo_service.cc +++ b/chrome/browser/search/promos/promo_service.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/feature_list.h" +#include "base/json/json_string_value_serializer.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/strings/strcat.h" @@ -95,6 +96,13 @@ return false; } + const base::Value* middle_announce_payload = promos->FindKeyOfType( + "middle_announce_payload", base::Value::Type::DICTIONARY); + if (middle_announce_payload) { + JSONStringValueSerializer serializer(&result.middle_slot_json); + serializer.Serialize(*middle_announce_payload); + } + std::string log_url; // Emergency promos don't have these, so it's OK if this key is missing. promos->GetString("log_url", &log_url);
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java index 16f780a..0b37fc9 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
@@ -9,6 +9,7 @@ import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; +import org.chromium.base.TraceEvent; import org.chromium.base.UserData; import org.chromium.base.UserDataHost; import org.chromium.base.metrics.RecordHistogram; @@ -188,7 +189,10 @@ abstract byte[] serialize(); private byte[] serializeAndLog() { - byte[] res = serialize(); + byte[] res; + try (TraceEvent e = TraceEvent.scoped("PersistedTabData.Serialize")) { + res = serialize(); + } RecordHistogram.recordBooleanHistogram( "Tabs.PersistedTabData.Serialize." + getUmaTag(), res != null); return res; @@ -202,7 +206,10 @@ abstract boolean deserialize(@Nullable byte[] bytes); private void deserializeAndLog(@Nullable byte[] bytes) { - boolean success = deserialize(bytes); + boolean success; + try (TraceEvent e = TraceEvent.scoped("PersistedTabData.Deserialize")) { + success = deserialize(bytes); + } RecordHistogram.recordBooleanHistogram( "Tabs.PersistedTabData.Deserialize." + getUmaTag(), success); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 0fe15b66..f462bfd 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1287,6 +1287,8 @@ "unload_controller.h", "views/eye_dropper/eye_dropper.cc", "views/eye_dropper/eye_dropper.h", + "views/eye_dropper/eye_dropper_view_mac.h", + "views/eye_dropper/eye_dropper_view_mac.mm", "webui/app_launcher_login_handler.cc", "webui/app_launcher_login_handler.h", "webui/app_management/app_management_page_handler.cc", @@ -3023,8 +3025,6 @@ "views/color_chooser_win.cc", "views/critical_notification_bubble_view.cc", "views/critical_notification_bubble_view.h", - "views/eye_dropper/eye_dropper_win.cc", - "views/eye_dropper/eye_dropper_win.h", "views/frame/browser_desktop_window_tree_host.h", "views/frame/browser_desktop_window_tree_host_win.cc", "views/frame/browser_desktop_window_tree_host_win.h", @@ -3880,6 +3880,8 @@ "views/tabs/tab_hover_card_bubble_view.h", "views/tabs/tab_icon.cc", "views/tabs/tab_icon.h", + "views/tabs/tab_search_button.cc", + "views/tabs/tab_search_button.h", "views/tabs/tab_slot_view.cc", "views/tabs/tab_slot_view.h", "views/tabs/tab_strip.cc", @@ -4139,13 +4141,6 @@ if (is_chrome_branded) { deps += [ "//chrome/browser/ui/media_router/internal/vector_icons" ] } - - if (enable_tab_search) { - sources += [ - "views/tabs/tab_search_button.cc", - "views/tabs/tab_search_button.h", - ] - } } if (use_aura) { @@ -4164,6 +4159,8 @@ "views/apps/shaped_app_window_targeter.cc", "views/apps/shaped_app_window_targeter.h", "views/dropdown_bar_host_aura.cc", + "views/eye_dropper/eye_dropper_view_aura.cc", + "views/eye_dropper/eye_dropper_view_aura.h", "views/renderer_context_menu/render_view_context_menu_views.cc", "views/renderer_context_menu/render_view_context_menu_views.h", "views/tab_contents/chrome_web_contents_view_delegate_views.cc",
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.cc b/chrome/browser/ui/app_list/search/omnibox_provider.cc index 5ad1fdd9..c44c9b6 100644 --- a/chrome/browser/ui/app_list/search/omnibox_provider.cc +++ b/chrome/browser/ui/app_list/search/omnibox_provider.cc
@@ -20,6 +20,15 @@ #include "url/gurl.h" namespace app_list { +namespace { + +bool IsDriveUrl(const GURL& url) { + // Returns true if the |url| points to a Drive Web host. + const std::string& host = url.host(); + return host == "drive.google.com" || host == "docs.google.com"; +} + +} // namespace OmniboxProvider::OmniboxProvider(Profile* profile, AppListControllerDelegate* list_controller) @@ -72,12 +81,22 @@ SearchProvider::Results new_results; new_results.reserve(result.size()); for (const AutocompleteMatch& match : result) { - if (!match.destination_url.is_valid()) + // Do not return a match in any of these cases: + // - The URL is invalid. + // - The URL points to Drive Web. The LauncherSearchProvider surfaces Drive + // results. + // - The URL points to a local file. The LauncherSearchProvider also handles + // files results, even if they've been opened in the browser. + if (!match.destination_url.is_valid() || + IsDriveUrl(match.destination_url) || + match.destination_url.SchemeIsFile()) { continue; + } new_results.emplace_back(std::make_unique<OmniboxResult>( profile_, list_controller_, controller_.get(), match, is_zero_state_input_)); } + SwapResults(&new_results); }
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper.cc b/chrome/browser/ui/views/eye_dropper/eye_dropper.cc index aa3ebb75..f0abe81b 100644 --- a/chrome/browser/ui/views/eye_dropper/eye_dropper.cc +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper.cc
@@ -7,11 +7,11 @@ #include "build/build_config.h" #include "content/public/browser/eye_dropper.h" -#if !defined(OS_WIN) +#if !defined(USE_AURA) && !defined(OS_MAC) // Used for the platforms that don't support an eye dropper. std::unique_ptr<content::EyeDropper> ShowEyeDropper( content::RenderFrameHost* frame, content::EyeDropperListener* listener) { return nullptr; } -#endif // !defined(OS_WIN) +#endif // !defined(USE_AURA) && !defined(OS_MAC)
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_browsertest.cc b/chrome/browser/ui/views/eye_dropper/eye_dropper_browsertest.cc index 181fbe38..93f73ec 100644 --- a/chrome/browser/ui/views/eye_dropper/eye_dropper_browsertest.cc +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_browsertest.cc
@@ -18,7 +18,7 @@ #include "ui/display/display_switches.h" #if defined(OS_WIN) -#include "chrome/browser/ui/views/eye_dropper/eye_dropper_win.h" +#include "chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.h" #endif class EyeDropperBrowserTest : public UiBrowserTest, @@ -33,9 +33,11 @@ // UiBrowserTest: void ShowUi(const std::string& name) override { +#if defined(OS_WIN) content::RenderFrameHost* parent_frame = browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(); eye_dropper_ = ShowEyeDropper(parent_frame, /*listener=*/nullptr); +#endif } bool VerifyUi() override { @@ -44,7 +46,7 @@ return false; views::Widget* widget = - static_cast<EyeDropperWin*>(eye_dropper_.get())->GetWidget(); + static_cast<EyeDropperViewAura*>(eye_dropper_.get())->GetWidget(); auto* test_info = testing::UnitTest::GetInstance()->current_test_info(); const std::string screenshot_name = base::StrCat({test_info->test_case_name(), "_", test_info->name()});
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_win.cc b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.cc similarity index 80% rename from chrome/browser/ui/views/eye_dropper/eye_dropper_win.cc rename to chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.cc index 7cbfaf4..481bedd 100644 --- a/chrome/browser/ui/views/eye_dropper/eye_dropper_win.cc +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/eye_dropper/eye_dropper_win.h" +#include "chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.h" #include "base/time/time.h" #include "chrome/browser/ui/views/eye_dropper/eye_dropper.h" @@ -19,9 +19,9 @@ #include "ui/gfx/native_widget_types.h" #include "ui/views/widget/widget.h" -class EyeDropperWin::PreEventDispatchHandler : public ui::EventHandler { +class EyeDropperViewAura::PreEventDispatchHandler : public ui::EventHandler { public: - explicit PreEventDispatchHandler(aura::Window* owner, EyeDropperWin* view); + explicit PreEventDispatchHandler(EyeDropperViewAura* view); PreEventDispatchHandler(const PreEventDispatchHandler&) = delete; PreEventDispatchHandler& operator=(const PreEventDispatchHandler&) = delete; ~PreEventDispatchHandler() override; @@ -29,35 +29,37 @@ private: void OnMouseEvent(ui::MouseEvent* event) override; - aura::Window* owner_; - EyeDropperWin* view_; + EyeDropperViewAura* view_; }; -EyeDropperWin::PreEventDispatchHandler::PreEventDispatchHandler( - aura::Window* owner, - EyeDropperWin* view) - : owner_(owner), view_(view) { +EyeDropperViewAura::PreEventDispatchHandler::PreEventDispatchHandler( + EyeDropperViewAura* view) + : view_(view) { // Ensure that this handler is called before color popup handler by using // a higher priority. - owner_->AddPreTargetHandler(this, ui::EventTarget::Priority::kSystem); + view->GetWidget()->GetNativeWindow()->AddPreTargetHandler( + this, ui::EventTarget::Priority::kSystem); } -EyeDropperWin::PreEventDispatchHandler::~PreEventDispatchHandler() { - owner_->RemovePreTargetHandler(this); +EyeDropperViewAura::PreEventDispatchHandler::~PreEventDispatchHandler() { + view_->GetWidget()->GetNativeWindow()->RemovePreTargetHandler(this); } -void EyeDropperWin::PreEventDispatchHandler::OnMouseEvent( +void EyeDropperViewAura::PreEventDispatchHandler::OnMouseEvent( ui::MouseEvent* event) { if (event->type() == ui::ET_MOUSE_PRESSED) { // Avoid closing the color popup when the eye dropper is clicked. + event->StopPropagation(); + } + if (event->type() == ui::ET_MOUSE_RELEASED) { view_->OnColorSelected(); event->StopPropagation(); } } -class EyeDropperWin::ViewPositionHandler { +class EyeDropperViewAura::ViewPositionHandler { public: - explicit ViewPositionHandler(EyeDropperWin* owner); + explicit ViewPositionHandler(EyeDropperViewAura* owner); ViewPositionHandler(const ViewPositionHandler&) = delete; ViewPositionHandler& operator=(const ViewPositionHandler&) = delete; ~ViewPositionHandler(); @@ -68,27 +70,29 @@ // Timer used for updating the window location. base::RepeatingTimer timer_; - EyeDropperWin* owner_; + EyeDropperViewAura* owner_; }; -EyeDropperWin::ViewPositionHandler::ViewPositionHandler(EyeDropperWin* owner) +EyeDropperViewAura::ViewPositionHandler::ViewPositionHandler( + EyeDropperViewAura* owner) : owner_(owner) { // Use a value close to the refresh rate @60hz. // TODO(iopopesc): Use SetCapture instead of a timer when support for // activating the eye dropper without closing the color popup is added. timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(16), this, - &EyeDropperWin::ViewPositionHandler::UpdateViewPosition); + &EyeDropperViewAura::ViewPositionHandler::UpdateViewPosition); } -EyeDropperWin::ViewPositionHandler::~ViewPositionHandler() { +EyeDropperViewAura::ViewPositionHandler::~ViewPositionHandler() { timer_.AbandonAndStop(); } -void EyeDropperWin::ViewPositionHandler::UpdateViewPosition() { +void EyeDropperViewAura::ViewPositionHandler::UpdateViewPosition() { owner_->UpdatePosition(); } -class EyeDropperWin::ScreenCapturer : public webrtc::DesktopCapturer::Callback { +class EyeDropperViewAura::ScreenCapturer + : public webrtc::DesktopCapturer::Callback { public: ScreenCapturer(); ScreenCapturer(const ScreenCapturer&) = delete; @@ -106,7 +110,7 @@ SkBitmap frame_; }; -EyeDropperWin::ScreenCapturer::ScreenCapturer() { +EyeDropperViewAura::ScreenCapturer::ScreenCapturer() { // TODO(iopopesc): Update the captured frame after a period of time to match // latest content on screen. capturer_ = content::desktop_capture::CreateScreenCapturer(); @@ -114,7 +118,7 @@ capturer_->CaptureFrame(); } -void EyeDropperWin::ScreenCapturer::OnCaptureResult( +void EyeDropperViewAura::ScreenCapturer::OnCaptureResult( webrtc::DesktopCapturer::Result result, std::unique_ptr<webrtc::DesktopFrame> frame) { if (result != webrtc::DesktopCapturer::Result::SUCCESS) @@ -126,12 +130,12 @@ frame_.setImmutable(); } -SkBitmap EyeDropperWin::ScreenCapturer::GetBitmap() const { +SkBitmap EyeDropperViewAura::ScreenCapturer::GetBitmap() const { return frame_; } -EyeDropperWin::EyeDropperWin(content::RenderFrameHost* frame, - content::EyeDropperListener* listener) +EyeDropperViewAura::EyeDropperViewAura(content::RenderFrameHost* frame, + content::EyeDropperListener* listener) : render_frame_host_(frame), listener_(listener), view_position_handler_(std::make_unique<ViewPositionHandler>(this)), @@ -154,8 +158,7 @@ widget->Init(std::move(params)); widget->SetContentsView(this); - pre_dispatch_handler_ = std::make_unique<PreEventDispatchHandler>( - widget->GetNativeWindow(), this); + pre_dispatch_handler_ = std::make_unique<PreEventDispatchHandler>(this); auto* cursor_client = aura::client::GetCursorClient(widget->GetNativeWindow()->GetRootWindow()); @@ -164,21 +167,21 @@ widget->Show(); } -EyeDropperWin::~EyeDropperWin() { +EyeDropperViewAura::~EyeDropperViewAura() { if (GetWidget()) GetWidget()->CloseNow(); } -void EyeDropperWin::OnPaint(gfx::Canvas* view_canvas) { +void EyeDropperViewAura::OnPaint(gfx::Canvas* view_canvas) { if (screen_capturer_->GetBitmap().drawsNothing()) return; constexpr float kDiameter = 90; constexpr float kPixelSize = 10; - - // Clip circle for magnified projection. const gfx::Size padding((size().width() - kDiameter) / 2, (size().height() - kDiameter) / 2); + + // Clip circle for magnified projection. SkPath clip_path; clip_path.addOval(SkRect::MakeXYWH(padding.width(), padding.height(), kDiameter, kDiameter)); @@ -240,23 +243,23 @@ OnPaintBorder(view_canvas); } -void EyeDropperWin::WindowClosing() { +void EyeDropperViewAura::WindowClosing() { aura::client::GetCursorClient(GetWidget()->GetNativeWindow()->GetRootWindow()) ->UnlockCursor(); pre_dispatch_handler_.reset(); } -ui::ModalType EyeDropperWin::GetModalType() const { +ui::ModalType EyeDropperViewAura::GetModalType() const { return ui::MODAL_TYPE_SYSTEM; } -void EyeDropperWin::OnWidgetMove() { +void EyeDropperViewAura::OnWidgetMove() { // Trigger a repaint since because the widget was moved, the content of the // view needs to be updated. SchedulePaint(); } -void EyeDropperWin::UpdatePosition() { +void EyeDropperViewAura::UpdatePosition() { if (screen_capturer_->GetBitmap().drawsNothing() || !GetWidget()) return; @@ -271,7 +274,7 @@ size())); } -void EyeDropperWin::OnColorSelected() { +void EyeDropperViewAura::OnColorSelected() { if (!selected_color_.has_value()) { listener_->ColorSelectionCanceled(); return; @@ -284,5 +287,5 @@ std::unique_ptr<content::EyeDropper> ShowEyeDropper( content::RenderFrameHost* frame, content::EyeDropperListener* listener) { - return std::make_unique<EyeDropperWin>(frame, listener); + return std::make_unique<EyeDropperViewAura>(frame, listener); }
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_win.h b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.h similarity index 68% rename from chrome/browser/ui/views/eye_dropper/eye_dropper_win.h rename to chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.h index ed32a3e4..7413262 100644 --- a/chrome/browser/ui/views/eye_dropper/eye_dropper_win.h +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_aura.h
@@ -2,8 +2,8 @@ // 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_EYE_DROPPER_EYE_DROPPER_WIN_H_ -#define CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_WIN_H_ +#ifndef CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_VIEW_AURA_H_ +#define CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_VIEW_AURA_H_ #include <memory> @@ -15,14 +15,14 @@ #include "ui/gfx/geometry/point.h" #include "ui/views/widget/widget_delegate.h" -class EyeDropperWin : public content::EyeDropper, - public views::WidgetDelegateView { +class EyeDropperViewAura : public content::EyeDropper, + public views::WidgetDelegateView { public: - EyeDropperWin(content::RenderFrameHost* frame, - content::EyeDropperListener* listener); - EyeDropperWin(const EyeDropperWin&) = delete; - EyeDropperWin& operator=(const EyeDropperWin&) = delete; - ~EyeDropperWin() override; + EyeDropperViewAura(content::RenderFrameHost* frame, + content::EyeDropperListener* listener); + EyeDropperViewAura(const EyeDropperViewAura&) = delete; + EyeDropperViewAura& operator=(const EyeDropperViewAura&) = delete; + ~EyeDropperViewAura() override; protected: // views::WidgetDelegateView: @@ -53,4 +53,4 @@ base::Optional<SkColor> selected_color_; }; -#endif // CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_WIN_H_ +#endif // CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_VIEW_AURA_H_
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h new file mode 100644 index 0000000..bd9f82c --- /dev/null +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.h
@@ -0,0 +1,28 @@ +// 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_EYE_DROPPER_EYE_DROPPER_VIEW_MAC_H_ +#define CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_VIEW_MAC_H_ + +#include "base/mac/scoped_nsobject.h" +#include "content/public/browser/eye_dropper.h" +#include "content/public/browser/eye_dropper_listener.h" + +@class NSColorSampler; + +class EyeDropperViewMac : public content::EyeDropper { + public: + EyeDropperViewMac(content::EyeDropperListener* listener); + EyeDropperViewMac(const EyeDropperViewMac&) = delete; + EyeDropperViewMac& operator=(const EyeDropperViewMac&) = delete; + ~EyeDropperViewMac() override; + + private: + // Receives the color selection. + content::EyeDropperListener* listener_; + + base::scoped_nsobject<NSColorSampler> color_sampler_; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_EYE_DROPPER_EYE_DROPPER_VIEW_MAC_H_
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm new file mode 100644 index 0000000..a4c27352d --- /dev/null +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm
@@ -0,0 +1,37 @@ +// 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/eye_dropper/eye_dropper_view_mac.h" + +#import <Cocoa/Cocoa.h> + +#include "content/public/browser/render_frame_host.h" +#include "skia/ext/skia_utils_mac.h" + +EyeDropperViewMac::EyeDropperViewMac(content::EyeDropperListener* listener) + : listener_(listener) { + if (!listener_) + return; + if (@available(macOS 10.15, *)) { + color_sampler_.reset([[NSColorSampler alloc] init]); + [color_sampler_ showSamplerWithSelectionHandler:^(NSColor* selectedColor) { + if (!selectedColor) { + listener_->ColorSelectionCanceled(); + } else { + listener_->ColorSelected(skia::NSSystemColorToSkColor(selectedColor)); + } + }]; + } +} + +EyeDropperViewMac::~EyeDropperViewMac() {} + +std::unique_ptr<content::EyeDropper> ShowEyeDropper( + content::RenderFrameHost* frame, + content::EyeDropperListener* listener) { + if (@available(macOS 10.15, *)) { + return std::make_unique<EyeDropperViewMac>(listener); + } + return nullptr; +}
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc b/chrome/browser/ui/views/frame/browser_frame_header_ash.cc index b437f7b..07064be 100644 --- a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc +++ b/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
@@ -34,39 +34,31 @@ SkColor background_color, const gfx::Rect& bounds, int image_inset_x, - int image_inset_y, - int alpha) { + int image_inset_y) { SkColor opaque_background_color = SkColorSetA(background_color, SK_AlphaOPAQUE); - // When no images are used, just draw a color, with the animation |alpha| - // applied. + // When no images are used, just draw a color. if (frame_image.isNull() && frame_overlay_image.isNull()) { - // We use kPlus blending mode so that between the active and inactive - // background colors, the result is 255 alpha (i.e. opaque). - canvas->DrawColor(SkColorSetA(opaque_background_color, alpha), - SkBlendMode::kPlus); + canvas->DrawColor(opaque_background_color); return; } // This handles the case where blending is required between one or more images // and the background color. In this case we use a SaveLayerWithFlags() call - // to draw all 2-3 components into a single layer then apply the alpha to them - // together. + // to draw all 2-3 components into a single layer. const bool blending_required = - alpha < 0xFF || (!frame_image.isNull() && !frame_overlay_image.isNull()); + !frame_image.isNull() && !frame_overlay_image.isNull(); if (blending_required) { cc::PaintFlags flags; // We use kPlus blending mode so that between the active and inactive // background colors, the result is 255 alpha (i.e. opaque). flags.setBlendMode(SkBlendMode::kPlus); - flags.setAlpha(alpha); canvas->SaveLayerWithFlags(flags); } // Images can be transparent and we expect the background color to be present - // behind them. Here the |alpha| will be applied to the background color by - // the SaveLayer call, so use |opaque_background_color|. + // behind them. canvas->DrawColor(opaque_background_color); if (!frame_image.isNull()) { canvas->TileImageInt(frame_image, image_inset_x, image_inset_y, 0, 0, @@ -89,7 +81,6 @@ const gfx::Rect& bounds, int image_inset_x, int image_inset_y, - int alpha, int corner_radius) { const SkScalar sk_corner_radius = SkIntToScalar(corner_radius); const SkScalar radii[8] = {sk_corner_radius, @@ -109,7 +100,7 @@ canvas->ClipPath(frame_path, antialias); PaintThemedFrame(canvas, frame_image, frame_overlay_image, background_color, - bounds, image_inset_x, image_inset_y, alpha); + bounds, image_inset_x, image_inset_y); } } // namespace @@ -147,8 +138,7 @@ // BrowserFrameHeaderAsh, protected: void BrowserFrameHeaderAsh::DoPaintHeader(gfx::Canvas* canvas) { - PaintFrameImages(canvas, false /* active */); - PaintFrameImages(canvas, true /* active */); + PaintFrameImages(canvas); PaintTitleBar(canvas); } @@ -178,13 +168,8 @@ /////////////////////////////////////////////////////////////////////////////// // BrowserFrameHeaderAsh, private: -void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) { - int alpha = activation_animation().CurrentValueBetween(0, 0xFF); - if (!active) - alpha = 0xFF - alpha; - - if (alpha == 0) - return; +void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas) { + const bool active = mode() == Mode::MODE_ACTIVE; gfx::ImageSkia frame_image = appearance_provider_->GetFrameHeaderImage(active); @@ -201,5 +186,5 @@ appearance_provider_->GetFrameHeaderColor(active), GetPaintedBounds(), GetThemeBackgroundXInset(), appearance_provider_->GetFrameHeaderImageYInset(), - alpha, corner_radius); + corner_radius); }
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.h b/chrome/browser/ui/views/frame/browser_frame_header_ash.h index c1ea091c..842c76d 100644 --- a/chrome/browser/ui/views/frame/browser_frame_header_ash.h +++ b/chrome/browser/ui/views/frame/browser_frame_header_ash.h
@@ -49,9 +49,8 @@ SkColor GetCurrentFrameColor() const override; private: - // Paints the frame image for the |active| state based on the current value of - // the activation animation. - void PaintFrameImages(gfx::Canvas* canvas, bool active); + // Paints the frame image. + void PaintFrameImages(gfx::Canvas* canvas); AppearanceProvider* appearance_provider_ = nullptr;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 8bd3e26..8bb685c8 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -326,11 +326,8 @@ if (!ShouldPaint()) return; - const ash::FrameHeader::Mode header_mode = - ShouldPaintAsActive() ? ash::FrameHeader::MODE_ACTIVE - : ash::FrameHeader::MODE_INACTIVE; if (frame_header_) - frame_header_->PaintHeader(canvas, header_mode); + frame_header_->PaintHeader(canvas); } void BrowserNonClientFrameViewAsh::Layout() {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 14ffedb7..471b856 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -122,6 +122,7 @@ #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/browser/ui/views/tabs/tab.h" +#include "chrome/browser/ui/views/tabs/tab_search_button.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" #include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h" @@ -2621,6 +2622,8 @@ } void BrowserView::CreateTabSearchBubble() { + // TODO(tluk): This should be triggering the TabSearchButton in the tab strip + // rather than creating the Tab Search bubble directly. TabSearchBubbleView::CreateTabSearchBubble(browser_->profile(), tabstrip_->tab_search_button()); base::UmaHistogramEnumeration("Tabs.TabSearch.OpenAction",
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index ba9873e..4a7ee3d27 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -2040,8 +2040,17 @@ void OmniboxViewViews::OnFocusChangedInPage( content::FocusedNodeDetails* details) { - if (details->is_editable_node) + // Elide the URL to the simplified domain (the most security-critical + // information) when the user focuses a form text field, which is a key moment + // for making security decisions. Ignore the focus event if it didn't come + // from a mouse click/tap. Focus via keyboard will trigger elision from + // DidGetUserInteraction(), and we want to ignore focuses that aren't from an + // explicit user action (e.g., input fields that are autofocused on page + // load). + if (details->is_editable_node && + details->focus_type == blink::mojom::FocusType::kMouse) { MaybeElideURLWithAnimationFromInteraction(); + } } base::string16 OmniboxViewViews::GetSelectionClipboardText() const { @@ -2267,10 +2276,11 @@ break; case ui::VKEY_SPACE: { - if (!control && !alt && !shift && SelectionAtEnd()) { - OmniboxPopupModel* popup_model = model()->popup_model(); - if (popup_model && popup_model->TriggerSelectionAction( - popup_model->selection(), event.time_stamp())) { + OmniboxPopupModel* popup_model = model()->popup_model(); + if (popup_model && !control && !alt && !shift && + popup_model->selection().IsButtonFocused()) { + if (popup_model->TriggerSelectionAction(popup_model->selection(), + event.time_stamp())) { return true; } }
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 889506f9..e319c804 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -2232,13 +2232,33 @@ // Focusing a non-editable node should not run the fade-out animation. content::FocusedNodeDetails details; details.is_editable_node = false; + details.focus_type = blink::mojom::FocusType::kMouse; omnibox_view()->OnFocusChangedInPage(&details); OmniboxViewViews::ElideAnimation* elide_animation = omnibox_view()->GetElideAfterInteractionAnimationForTesting(); EXPECT_FALSE(elide_animation); + // Focusing via keypress should not run the fade-out animation. + details.is_editable_node = true; + details.focus_type = blink::mojom::FocusType::kForward; + omnibox_view()->OnFocusChangedInPage(&details); + elide_animation = + omnibox_view()->GetElideAfterInteractionAnimationForTesting(); + EXPECT_FALSE(elide_animation); + + // Other ways that an element can be focused, such as element.focus() in + // JavaScript, have a focus type of kNone and should not run the fade-out + // animation. + details.is_editable_node = true; + details.focus_type = blink::mojom::FocusType::kNone; + omnibox_view()->OnFocusChangedInPage(&details); + elide_animation = + omnibox_view()->GetElideAfterInteractionAnimationForTesting(); + EXPECT_FALSE(elide_animation); + // Focusing an editable node should run the fade-out animation. details.is_editable_node = true; + details.focus_type = blink::mojom::FocusType::kMouse; omnibox_view()->OnFocusChangedInPage(&details); elide_animation = omnibox_view()->GetElideAfterInteractionAnimationForTesting();
diff --git a/chrome/browser/ui/views/tabs/tab_search_button.cc b/chrome/browser/ui/views/tabs/tab_search_button.cc index 8f80daa5..63beef1 100644 --- a/chrome/browser/ui/views/tabs/tab_search_button.cc +++ b/chrome/browser/ui/views/tabs/tab_search_button.cc
@@ -71,6 +71,11 @@ observed_bubble_widget_.Remove(bubble_); bubble_ = nullptr; pressed_lock_.reset(); + tab_strip()->OnTabSearchBubbleClosed(); +} + +bool TabSearchButton::IsBubbleVisible() const { + return bubble_ && bubble_->IsVisible(); } void TabSearchButton::PaintIcon(gfx::Canvas* canvas) {
diff --git a/chrome/browser/ui/views/tabs/tab_search_button.h b/chrome/browser/ui/views/tabs/tab_search_button.h index aeb696c..d0f199d 100644 --- a/chrome/browser/ui/views/tabs/tab_search_button.h +++ b/chrome/browser/ui/views/tabs/tab_search_button.h
@@ -45,6 +45,10 @@ // views::WidgetObserver: void OnWidgetClosing(views::Widget* widget) override; + bool IsBubbleVisible() const; + + views::Widget* bubble_for_testing() { return bubble_; } + protected: // NewTabButton: void PaintIcon(gfx::Canvas* canvas) override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 03979210..bfb1cb5f 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -38,6 +38,7 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tab_search/tab_search_bubble_view.h" #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h" @@ -48,6 +49,7 @@ #include "chrome/browser/ui/views/tabs/tab_group_underline.h" #include "chrome/browser/ui/views/tabs/tab_group_views.h" #include "chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h" +#include "chrome/browser/ui/views/tabs/tab_search_button.h" #include "chrome/browser/ui/views/tabs/tab_slot_view.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/tab_strip_layout_helper.h" @@ -106,12 +108,6 @@ #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" -#include "chrome/browser/ui/views/tabs/tab_search_button.h" -#endif - namespace { // Distance from the next/previous stacked before before we consider the tab @@ -1447,6 +1443,11 @@ ShiftGroupRelative(group, 1); } +void TabStrip::OnTabSearchBubbleClosed() { + UpdateIdealBounds(); + AnimateToIdealBounds(); +} + bool TabStrip::ShouldTabBeVisible(const Tab* tab) const { // Detached tabs should always be invisible (as they close). if (tab->detached()) @@ -2333,12 +2334,13 @@ } gfx::Size TabStrip::CalculatePreferredSize() const { - if (tab_count() == 0) { - return gfx::Size(GetRightSideReservedWidth(), - GetLayoutConstant(TAB_HEIGHT)); + // The tabs might be out of order due to an active animation or drag, so + // we have to check all of them to find the visually trailing-most one. + int max_x = 0; + for (auto* tab : layout_helper_->GetTabs()) { + max_x = std::max(max_x, tab->bounds().right()); } - return gfx::Size(layout_helper_->GetTabs().back()->bounds().right() + - GetRightSideReservedWidth(), + return gfx::Size(max_x + GetRightSideReservedWidth(), GetLayoutConstant(TAB_HEIGHT)); } @@ -2451,7 +2453,6 @@ new_tab_button_ = tab_controls_container_->AddChildView(std::move(new_tab_button)); -#if BUILDFLAG(ENABLE_TAB_SEARCH) if (base::FeatureList::IsEnabled(features::kTabSearch) && !controller_->GetProfile()->IsIncognitoProfile()) { auto tab_search_button = std::make_unique<TabSearchButton>(this, this); @@ -2466,7 +2467,6 @@ tab_search_button_ = tab_controls_container_->AddChildView(std::move(tab_search_button)); } -#endif UpdateNewTabButtonBorder(); tab_controls_container_ideal_bounds_.set_size( @@ -3373,9 +3373,13 @@ base::FeatureList::IsEnabled(features::kScrollableTabStrip) ? trailing_x : std::min(available_width_for_tabs, trailing_x); - - tab_controls_container_ideal_bounds_.set_origin( - gfx::Point(ntb_x_offset + TabToNewTabButtonSpacing(), 0)); + // We want to lock the |tab_controls_container_| in place if the Tab Search + // bubble is open to prevent the UI sliding across the screen as the tab + // strip changes. + if (!tab_search_button_ || !tab_search_button_->IsBubbleVisible()) { + tab_controls_container_ideal_bounds_.set_origin( + gfx::Point(ntb_x_offset + TabToNewTabButtonSpacing(), 0)); + } } }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 83c438c..466d62b 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -45,6 +45,7 @@ class StackedTabStripLayout; class Tab; class TabHoverCardBubbleView; +class TabSearchButton; class TabStripController; class TabStripObserver; class TabStripLayoutHelper; @@ -201,6 +202,12 @@ // Attempts to move the specified group to the right. void ShiftGroupRight(const tab_groups::TabGroupId& group); + // While the Tab Search bubble is open, the |tab_controls_container_| is kept + // in a fixed position in the tab strip. This is called when the bubble is + // closed to allow the |tab_controls_container_| to animate to the correct + // position. + void OnTabSearchBubbleClosed(); + // Returns true if the tab is not partly or fully clipped (due to overflow), // and the tab couldn't become partly clipped due to changing the selected tab // (for example, if currently the strip has the last tab selected, and @@ -238,7 +245,7 @@ NewTabButton* new_tab_button() { return new_tab_button_; } // Returns the TabSearchButton. - NewTabButton* tab_search_button() { return tab_search_button_; } + TabSearchButton* tab_search_button() { return tab_search_button_; } // Returns the index of the specified view in the model coordinate system, or // -1 if view is closing or not a tab. @@ -700,7 +707,7 @@ NewTabButton* new_tab_button_ = nullptr; // |tab_search_button_| will be null if features::kTabSearch is disabled or if // the current profile is an incognito profile. - NewTabButton* tab_search_button_ = nullptr; + TabSearchButton* tab_search_button_ = nullptr; // Ideal bounds of container holding the tab controls. gfx::Rect tab_controls_container_ideal_bounds_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc b/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc index b207e9b1..ad3b16af 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc
@@ -6,17 +6,27 @@ #include <vector> +#include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_group_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/tab_search_button.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/tab_groups/tab_group_id.h" #include "content/public/test/browser_test.h" #include "url/gurl.h" +namespace { +ui::MouseEvent GetDummyEvent() { + return ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), + base::TimeTicks::Now(), 0, 0); +} +} // namespace + // Integration tests for interactions between TabStripModel and TabStrip. class TabStripBrowsertest : public InProcessBrowserTest { public: @@ -741,10 +751,7 @@ AppendTab(); tab_groups::TabGroupId group = AddTabToNewGroup(0); - ui::MouseEvent dummy_event = - ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), - base::TimeTicks::Now(), 0, 0); - tab_strip()->SelectTab(tab_strip()->tab_at(0), dummy_event); + tab_strip()->SelectTab(tab_strip()->tab_at(0), GetDummyEvent()); ASSERT_EQ(0, tab_strip()->controller()->GetActiveIndex()); ASSERT_FALSE(tab_strip()->controller()->IsGroupCollapsed(group)); tab_strip()->controller()->ToggleTabGroupCollapsedState(group); @@ -758,10 +765,7 @@ AppendTab(); tab_groups::TabGroupId group = AddTabToNewGroup(1); - ui::MouseEvent dummy_event = - ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), - base::TimeTicks::Now(), 0, 0); - tab_strip()->SelectTab(tab_strip()->tab_at(1), dummy_event); + tab_strip()->SelectTab(tab_strip()->tab_at(1), GetDummyEvent()); ASSERT_EQ(1, tab_strip()->controller()->GetActiveIndex()); ASSERT_FALSE(tab_strip()->controller()->IsGroupCollapsed(group)); tab_strip()->controller()->ToggleTabGroupCollapsedState(group); @@ -776,10 +780,7 @@ AppendTab(); tab_groups::TabGroupId group = AddTabToNewGroup(0); - ui::MouseEvent dummy_event = - ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), - base::TimeTicks::Now(), 0, 0); - tab_strip()->SelectTab(tab_strip()->tab_at(1), dummy_event); + tab_strip()->SelectTab(tab_strip()->tab_at(1), GetDummyEvent()); ASSERT_EQ(1, tab_strip()->controller()->GetActiveIndex()); ASSERT_FALSE(tab_strip()->controller()->IsGroupCollapsed(group)); tab_strip()->controller()->ToggleTabGroupCollapsedState(group); @@ -809,9 +810,31 @@ ASSERT_TRUE(tab_strip()->controller()->IsGroupCollapsed(group)); ASSERT_EQ(1, tab_strip()->controller()->GetActiveIndex()); - ui::MouseEvent dummy_event = - ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), - base::TimeTicks::Now(), 0, 0); - tab_strip()->SelectTab(tab_strip()->tab_at(0), dummy_event); + tab_strip()->SelectTab(tab_strip()->tab_at(0), GetDummyEvent()); EXPECT_FALSE(tab_strip()->controller()->IsGroupCollapsed(group)); } + +class TabSearchButtonTest : public TabStripBrowsertest { + public: + void SetUp() override { + scoped_feature_list_.InitWithFeatureState(features::kTabSearch, true); + TabStripBrowsertest::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(TabSearchButtonTest, TabSearchBubble_CreateAndClose) { + TabSearchButton* tab_search_button = tab_strip()->tab_search_button(); + + DCHECK_EQ(nullptr, tab_search_button->bubble_for_testing()); + tab_search_button->ButtonPressed(tab_search_button, GetDummyEvent()); + DCHECK_NE(nullptr, tab_search_button->bubble_for_testing()); + + // Close the tab search bubble widget, the bubble should be cleared from the + // TabSearchButton. + tab_search_button->bubble_for_testing()->CloseWithReason( + views::Widget::ClosedReason::kUnspecified); + DCHECK_EQ(nullptr, tab_search_button->bubble_for_testing()); +}
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom index a28efd40..4e2f01cb 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
@@ -4,12 +4,13 @@ module new_tab_page.mojom; +import "chrome/common/search/omnibox.mojom"; +import "mojo/public/mojom/base/string16.mojom"; import "mojo/public/mojom/base/text_direction.mojom"; import "mojo/public/mojom/base/time.mojom"; import "skia/public/mojom/skcolor.mojom"; import "url/mojom/url.mojom"; -import "mojo/public/mojom/base/string16.mojom"; -import "chrome/common/search/omnibox.mojom"; + struct OneGoogleBarParts { string bar_html; @@ -251,6 +252,38 @@ kLinkCopy, }; +struct PromoImagePart { + url.mojom.Url image_url; + url.mojom.Url target; +}; + +struct PromoLinkPart { + string? color; + string text; + url.mojom.Url url; +}; + +struct PromoTextPart { + string? color; + string text; +}; + +union PromoPart { + PromoImagePart image; + PromoLinkPart link; + PromoTextPart text; +}; + +// Homepage promo used to display a message with a link on the NTP. +struct Promo { + // A unique identifier for this promo. + string? id; + // URL to ping to log a promo impression. May be invalid. + url.mojom.Url? log_url; + // Middle slot promo data. + array<PromoPart> middle_slot_parts; +}; + // Action the user performed while using the customize dialog. Used for metrics // logging only. Actions correspond to items in NTPLoggingEventType. enum CustomizeDialogAction { @@ -360,6 +393,8 @@ // parameters to the endpoint that serves the OneGoogleBar parts with // |query_params|. GetOneGoogleBarParts(string query_params) => (OneGoogleBarParts? parts); + // Get the middle slot promo if it exists. + GetPromo() => (Promo? promo); // ======= METRICS ======= // Logs that |tiles| were displayed / updated at |time|. The first instance of @@ -368,8 +403,9 @@ // Logs that the One Google Bar was added to the DOM / loaded in an iframe at // |time|. OnOneGoogleBarRendered(double time); - // Logs that the promo iframe was loaded at |time|. - OnPromoRendered(double time); + // Logs that the promo iframe was loaded at |time| and pings |log_url| for + // promo metrics logging. + OnPromoRendered(double time, url.mojom.Url? log_url); // Logs that |tile| at position |index| was triggered to navigate to that // most visited entry. OnMostVisitedTileNavigation(MostVisitedTile tile, uint32 index);
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc index 8c872e06..f030459 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -10,6 +10,8 @@ #include "base/files/file_path.h" #include "base/i18n/rtl.h" #include "base/json/json_reader.h" +#include "base/json/json_string_value_serializer.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" @@ -22,6 +24,7 @@ #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/predictors/autocomplete_action_predictor.h" @@ -34,6 +37,7 @@ #include "chrome/browser/search/chrome_colors/chrome_colors_service.h" #include "chrome/browser/search/instant_service.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" +#include "chrome/browser/search/promos/promo_service_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/search_provider_logos/logo_service_factory.h" #include "chrome/browser/ui/bookmarks/bookmark_stats.h" @@ -287,6 +291,76 @@ return doodle; } +new_tab_page::mojom::PromoPtr MakePromo(const PromoData& data) { + // |data.middle_slot_json| is safe to be decoded here. The JSON string is part + // of a larger JSON initially decoded using the data decoder utility in the + // PromoService to base::Value. The middle-slot promo part is then reencoded + // from base::Value to a JSON string stored in |data.middle_slot_json|. + auto middle_slot = base::JSONReader::Read(data.middle_slot_json); + if (!middle_slot.has_value() || + middle_slot.value().FindBoolPath("hidden").value_or(false)) { + return nullptr; + } + auto promo = new_tab_page::mojom::Promo::New(); + promo->id = data.promo_id; + if (middle_slot.has_value()) { + auto* parts = middle_slot.value().FindListPath("part"); + if (parts) { + std::vector<new_tab_page::mojom::PromoPartPtr> mojom_parts; + for (const base::Value& part : parts->GetList()) { + if (part.FindKey("image")) { + auto mojom_image = new_tab_page::mojom::PromoImagePart::New(); + auto* image_url = part.FindStringPath("image.image_url"); + if (!image_url || image_url->empty()) { + continue; + } + mojom_image->image_url = GURL(*image_url); + auto* target = part.FindStringPath("image.target"); + if (target && !target->empty()) { + mojom_image->target = GURL(*target); + } + mojom_parts.push_back( + new_tab_page::mojom::PromoPart::NewImage(std::move(mojom_image))); + } else if (part.FindKey("link")) { + auto mojom_link = new_tab_page::mojom::PromoLinkPart::New(); + auto* url = part.FindStringPath("link.url"); + if (!url || url->empty()) { + continue; + } + mojom_link->url = GURL(*url); + auto* text = part.FindStringPath("link.text"); + if (!text || text->empty()) { + continue; + } + mojom_link->text = *text; + auto* color = part.FindStringPath("link.color"); + if (color && !color->empty()) { + mojom_link->color = *color; + } + mojom_parts.push_back( + new_tab_page::mojom::PromoPart::NewLink(std::move(mojom_link))); + } else if (part.FindKey("text")) { + auto mojom_text = new_tab_page::mojom::PromoTextPart::New(); + auto* text = part.FindStringPath("text.text"); + if (!text || text->empty()) { + continue; + } + mojom_text->text = *text; + auto* color = part.FindStringPath("text.color"); + if (color && !color->empty()) { + mojom_text->color = *color; + } + mojom_parts.push_back( + new_tab_page::mojom::PromoPart::NewText(std::move(mojom_text))); + } + } + promo->middle_slot_parts = std::move(mojom_parts); + } + } + promo->log_url = data.promo_log_url; + return promo; +} + } // namespace NewTabPageHandler::NewTabPageHandler( @@ -318,11 +392,14 @@ web_contents_(web_contents), ntp_navigation_start_time_(ntp_navigation_start_time), logger_(logger), + promo_service_(PromoServiceFactory::GetForProfile(profile)), page_{std::move(pending_page)}, receiver_{this, std::move(pending_page_handler)} { CHECK(instant_service_); CHECK(ntp_background_service_); CHECK(logo_service_); + CHECK(one_google_bar_service_); + CHECK(promo_service_); CHECK(web_contents_); CHECK(logger_); instant_service_->AddObserver(this); @@ -330,11 +407,8 @@ instant_service_->UpdateNtpTheme(); OmniboxTabHelper::CreateForWebContents(web_contents); OmniboxTabHelper::FromWebContents(web_contents_)->AddObserver(this); - // |one_google_bar_service_| is null in incognito, or when the feature is - // disabled. - if (one_google_bar_service_) { - one_google_bar_service_observer_.Add(one_google_bar_service_); - } + promo_service_observer_.Add(promo_service_); + one_google_bar_service_observer_.Add(one_google_bar_service_); } NewTabPageHandler::~NewTabPageHandler() { @@ -613,6 +687,79 @@ one_google_bar_service_->Refresh(); } +void NewTabPageHandler::GetPromo(GetPromoCallback callback) { + // Replace the promo URL with "command:<id>" if such a command ID is set + // via the feature params. + const std::string command_id = base::GetFieldTrialParamValueByFeature( + features::kPromoBrowserCommands, features::kPromoBrowserCommandIdParam); + if (!command_id.empty()) { + auto promo = new_tab_page::mojom::Promo::New(); + std::vector<new_tab_page::mojom::PromoPartPtr> parts; + auto image = new_tab_page::mojom::PromoImagePart::New(); + // Warning symbol used as the test image. + image->image_url = GURL( + "data:image/" + "svg+xml;base64," + "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii01IC" + "01IDU4IDU4IiBmaWxsPSIjZmRkNjMzIj48cGF0aCBkPSJNMiA0Mmg0NEwyNCA0IDIgNDJ6" + "bTI0LTZoLTR2LTRoNHY0em0wLThoLTR2LThoNHY4eiIvPjwvc3ZnPg=="); + image->target = GURL("command:" + command_id); + parts.push_back(new_tab_page::mojom::PromoPart::NewImage(std::move(image))); + auto link = new_tab_page::mojom::PromoLinkPart::New(); + link->url = GURL("command:" + command_id); + link->text = "Test command: " + command_id; + parts.push_back(new_tab_page::mojom::PromoPart::NewLink(std::move(link))); + promo->middle_slot_parts = std::move(parts); + std::move(callback).Run(std::move(promo)); + return; + } + + promo_callbacks_.push_back(std::move(callback)); + if (promo_service_->promo_data().has_value()) { + OnPromoDataUpdated(); + } + promo_load_start_time_ = base::TimeTicks::Now(); + promo_service_->Refresh(); +} + +void NewTabPageHandler::OnPromoDataUpdated() { + if (promo_load_start_time_.has_value()) { + base::TimeDelta duration = base::TimeTicks::Now() - *promo_load_start_time_; + UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency2", duration); + if (promo_service_->promo_status() == PromoService::Status::OK_WITH_PROMO) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "NewTabPage.Promos.RequestLatency2.SuccessWithPromo", duration); + } else if (promo_service_->promo_status() == + PromoService::Status::OK_BUT_BLOCKED) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "NewTabPage.Promos.RequestLatency2.SuccessButBlocked", duration); + } else if (promo_service_->promo_status() == + PromoService::Status::OK_WITHOUT_PROMO) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "NewTabPage.Promos.RequestLatency2.SuccessWithoutPromo", duration); + } else { + UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency2.Failure", + duration); + } + promo_load_start_time_ = base::nullopt; + } + + const auto& data = promo_service_->promo_data(); + for (auto& callback : promo_callbacks_) { + if (data.has_value() && !data->promo_html.empty()) { + std::move(callback).Run(MakePromo(data.value())); + } else { + std::move(callback).Run(nullptr); + } + } + promo_callbacks_.clear(); +} + +void NewTabPageHandler::OnPromoServiceShuttingDown() { + promo_service_observer_.RemoveAll(); + promo_service_ = nullptr; +} + void NewTabPageHandler::OnMostVisitedTilesRendered( std::vector<new_tab_page::mojom::MostVisitedTilePtr> tiles, double time) { @@ -630,9 +777,13 @@ base::Time::FromJsTime(time) - ntp_navigation_start_time_); } -void NewTabPageHandler::OnPromoRendered(double time) { +void NewTabPageHandler::OnPromoRendered(double time, + const base::Optional<GURL>& log_url) { logger_->LogEvent(NTP_MIDDLE_SLOT_PROMO_SHOWN, base::Time::FromJsTime(time) - ntp_navigation_start_time_); + if (log_url.has_value() && log_url->is_valid()) { + Fetch(*log_url, base::BindOnce([](bool, std::unique_ptr<std::string>) {})); + } } void NewTabPageHandler::OnMostVisitedTileNavigation( @@ -1342,13 +1493,13 @@ net::DefineNetworkTrafficAnnotation("new_tab_page_handler", R"( semantics { sender: "New Tab Page" - description: "Logs impression and interaction with the doodle." + description: "Logs impression and interaction with doodle or promo." trigger: - "Showing or clicking on the doodle on the New Tab Page. Desktop " - "only." + "Showing or clicking on the doodle or promo on the New Tab Page. " + "Desktop only." data: - "String identifiying todays doodle and token identifying a single " - "doodle interaction session. Data does not contain PII." + "String identifiying todays doodle or promo and token identifying " + "a single interaction session. Data does not contain PII." destination: GOOGLE_OWNED_SERVICE } policy {
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h index 21c0258..bc4c231 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
@@ -6,9 +6,11 @@ #define CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_HANDLER_H_ #include <unordered_map> +#include <vector> #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/scoped_observer.h" #include "base/time/time.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" @@ -16,6 +18,8 @@ #include "chrome/browser/search/instant_service_observer.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_observer.h" +#include "chrome/browser/search/promos/promo_service.h" +#include "chrome/browser/search/promos/promo_service_observer.h" #include "chrome/browser/ui/omnibox/omnibox_tab_helper.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h" #include "chrome/common/search/instant_types.h" @@ -54,7 +58,8 @@ public OmniboxTabHelper::Observer, public OneGoogleBarServiceObserver, public ui::SelectFileDialog::Listener, - public AutocompleteController::Observer { + public AutocompleteController::Observer, + public PromoServiceObserver { public: NewTabPageHandler(mojo::PendingReceiver<new_tab_page::mojom::PageHandler> pending_page_handler, @@ -103,11 +108,13 @@ ChooseLocalCustomBackgroundCallback callback) override; void GetOneGoogleBarParts(const std::string& ogdeb_value, GetOneGoogleBarPartsCallback callback) override; + void GetPromo(GetPromoCallback callback) override; void OnMostVisitedTilesRendered( std::vector<new_tab_page::mojom::MostVisitedTilePtr> tiles, double time) override; void OnOneGoogleBarRendered(double time) override; - void OnPromoRendered(double time) override; + void OnPromoRendered(double time, + const base::Optional<GURL>& log_url) override; void OnMostVisitedTileNavigation(new_tab_page::mojom::MostVisitedTilePtr tile, uint32_t index) override; void OnCustomizeDialogAction( @@ -161,6 +168,10 @@ void OnOneGoogleBarDataUpdated() override; void OnOneGoogleBarServiceShuttingDown() override; + // PromoServiceObserver: + void OnPromoDataUpdated() override; + void OnPromoServiceShuttingDown() override; + // SelectFileDialog::Listener: void FileSelected(const base::FilePath& path, int index, @@ -225,6 +236,11 @@ std::unordered_map<const network::SimpleURLLoader*, std::unique_ptr<network::SimpleURLLoader>> loader_map_; + std::vector<GetPromoCallback> promo_callbacks_; + PromoService* promo_service_; + ScopedObserver<PromoService, PromoServiceObserver> promo_service_observer_{ + this}; + base::Optional<base::TimeTicks> promo_load_start_time_; // These are located at the end of the list of member variables to ensure the // WebUI page is disconnected before other members are destroyed.
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index e0f74b9..6eb933e 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h" #include "chrome/browser/ui/webui/new_tab_page/promo_browser_command/promo_browser_command_handler.h" #include "chrome/browser/ui/webui/new_tab_page/untrusted_source.h" +#include "chrome/browser/ui/webui/sanitized_image_source.h" #include "chrome/browser/ui/webui/theme_source.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" @@ -269,6 +270,8 @@ instant_service_->IsCustomBackgroundDisabledByPolicy()); content::WebUIDataSource::Add(profile_, source); + content::URLDataSource::Add(profile_, + std::make_unique<SanitizedImageSource>(profile_)); content::URLDataSource::Add( profile_, std::make_unique<FaviconSource>( profile_, chrome::FaviconUrlFormat::kFavicon2));
diff --git a/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc b/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc index c583b9c..e868748e 100644 --- a/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc +++ b/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
@@ -12,7 +12,6 @@ #include "base/i18n/rtl.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" -#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "base/strings/string_piece.h" @@ -20,13 +19,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" -#include "chrome/browser/browser_features.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/ntp_features.h" #include "chrome/browser/search/one_google_bar/one_google_bar_data.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" -#include "chrome/browser/search/promos/promo_data.h" -#include "chrome/browser/search/promos/promo_service_factory.h" #include "chrome/browser/ui/search/ntp_user_data_logger.h" #include "chrome/common/url_constants.h" #include "chrome/grit/new_tab_page_resources.h" @@ -71,14 +67,7 @@ UntrustedSource::UntrustedSource(Profile* profile) : one_google_bar_service_( OneGoogleBarServiceFactory::GetForProfile(profile)), - profile_(profile), - promo_service_(PromoServiceFactory::GetForProfile(profile)) { - // |promo_service_| is null in incognito, or when the feature is - // disabled. - if (promo_service_) { - promo_service_observer_.Add(promo_service_); - } - + profile_(profile) { // |one_google_bar_service_| is null in incognito, or when the feature is // disabled. if (one_google_bar_service_) { @@ -147,21 +136,6 @@ bundle.LoadDataResourceBytes(IDR_NEW_TAB_PAGE_ONE_GOOGLE_BAR_API_JS)); return; } - if (path == "promo" && promo_service_) { - promo_callbacks_.push_back(std::move(callback)); - if (promo_service_->promo_data().has_value()) { - OnPromoDataUpdated(); - } - promo_load_start_time_ = base::TimeTicks::Now(); - promo_service_->Refresh(); - return; - } - if (path == "promo.js") { - ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - std::move(callback).Run( - bundle.LoadDataResourceBytes(IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_JS)); - return; - } if (path == "image" && url_param.is_valid() && (url_param.SchemeIs(url::kHttpsScheme) || url_param.SchemeIs(content::kChromeUIUntrustedScheme))) { @@ -255,10 +229,9 @@ } const std::string path = url.path().substr(1); return path == "one-google-bar" || path == "one_google_bar.js" || - path == "promo" || path == "promo.js" || path == "image" || - path == "background_image" || path == "custom_background_image" || - path == "background_image.js" || path == "background.jpg" || - path == "one_google_bar_api.js"; + path == "image" || path == "background_image" || + path == "custom_background_image" || path == "background_image.js" || + path == "background.jpg" || path == "one_google_bar_api.js"; } void UntrustedSource::OnOneGoogleBarDataUpdated() { @@ -300,59 +273,6 @@ one_google_bar_service_ = nullptr; } -void UntrustedSource::OnPromoDataUpdated() { - if (promo_load_start_time_.has_value()) { - base::TimeDelta duration = base::TimeTicks::Now() - *promo_load_start_time_; - UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency2", duration); - if (promo_service_->promo_status() == PromoService::Status::OK_WITH_PROMO) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "NewTabPage.Promos.RequestLatency2.SuccessWithPromo", duration); - } else if (promo_service_->promo_status() == - PromoService::Status::OK_BUT_BLOCKED) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "NewTabPage.Promos.RequestLatency2.SuccessButBlocked", duration); - } else if (promo_service_->promo_status() == - PromoService::Status::OK_WITHOUT_PROMO) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "NewTabPage.Promos.RequestLatency2.SuccessWithoutPromo", duration); - } else { - UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency2.Failure", - duration); - } - promo_load_start_time_ = base::nullopt; - } - - const auto& data = promo_service_->promo_data(); - std::string html; - if (data.has_value() && !data->promo_html.empty()) { - std::string promo_html = data->promo_html; - - // Replace the promo URL with "command:<id>" if such a command ID is set - // via the feature params. - const std::string command_id = base::GetFieldTrialParamValueByFeature( - features::kPromoBrowserCommands, features::kPromoBrowserCommandIdParam); - if (!command_id.empty()) { - re2::RE2::GlobalReplace(&promo_html, re2::RE2("href=\"([^\\s]+)\""), - "href=\"command:" + command_id + "\""); - } - - ui::TemplateReplacements replacements; - replacements["textdirection"] = base::i18n::IsRTL() ? "rtl" : "ltr"; - replacements["data"] = promo_html; - - html = FormatTemplate(IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_HTML, replacements); - } - for (auto& callback : promo_callbacks_) { - std::move(callback).Run(base::RefCountedString::TakeString(&html)); - } - promo_callbacks_.clear(); -} - -void UntrustedSource::OnPromoServiceShuttingDown() { - promo_service_observer_.RemoveAll(); - promo_service_ = nullptr; -} - void UntrustedSource::ServeBackgroundImage( const GURL& url, const GURL& url_2x,
diff --git a/chrome/browser/ui/webui/new_tab_page/untrusted_source.h b/chrome/browser/ui/webui/new_tab_page/untrusted_source.h index 1caf16a..420a55c 100644 --- a/chrome/browser/ui/webui/new_tab_page/untrusted_source.h +++ b/chrome/browser/ui/webui/new_tab_page/untrusted_source.h
@@ -11,8 +11,6 @@ #include "base/scoped_observer.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_observer.h" -#include "chrome/browser/search/promos/promo_service.h" -#include "chrome/browser/search/promos/promo_service_observer.h" #include "content/public/browser/url_data_source.h" class Profile; @@ -41,8 +39,7 @@ // * positionY: (optional) CSS background-position-y property. // Each of those helpers only accept URLs with HTTPS or chrome-untrusted:. class UntrustedSource : public content::URLDataSource, - public OneGoogleBarServiceObserver, - public PromoServiceObserver { + public OneGoogleBarServiceObserver { public: explicit UntrustedSource(Profile* profile); ~UntrustedSource() override; @@ -70,10 +67,6 @@ void OnOneGoogleBarDataUpdated() override; void OnOneGoogleBarServiceShuttingDown() override; - // PromoServiceObserver: - void OnPromoDataUpdated() override; - void OnPromoServiceShuttingDown() override; - void ServeBackgroundImage(const GURL& url, const GURL& url_2x, const std::string& size, @@ -90,11 +83,6 @@ one_google_bar_service_observer_{this}; base::Optional<base::TimeTicks> one_google_bar_load_start_time_; Profile* profile_; - std::vector<content::URLDataSource::GotDataCallback> promo_callbacks_; - PromoService* promo_service_; - ScopedObserver<PromoService, PromoServiceObserver> promo_service_observer_{ - this}; - base::Optional<base::TimeTicks> promo_load_start_time_; }; #endif // CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_UNTRUSTED_SOURCE_H_
diff --git a/chrome/test/data/pdf/annotations_feature_enabled_test.js b/chrome/test/data/pdf/annotations_feature_enabled_test.js index d5a422d..52dad0c9 100644 --- a/chrome/test/data/pdf/annotations_feature_enabled_test.js +++ b/chrome/test/data/pdf/annotations_feature_enabled_test.js
@@ -59,11 +59,21 @@ viewer.viewport.setZoom(2); chrome.test.assertEq(2, cameras.length); - window.scrollTo(100, 100); + const updateEnabled = + document.documentElement.hasAttribute('pdf-viewer-update-enabled'); + const scrollingContainer = + updateEnabled ? viewer.shadowRoot.querySelector('#main') : window; + scrollingContainer.scrollTo(100, 100); await animationFrame(); chrome.test.assertEq(3, cameras.length); + if (updateEnabled) { + // TODO (https://crbug.com/1120279): Determine what the expectations + // below should be for the new UI and fix if needed to meet them. + return; + } + const expectations = [ {top: 44.25, left: -106.5, right: 718.5, bottom: -448.5}, {top: 23.25, left: -3.75, right: 408.75, bottom: -223.125}, @@ -87,8 +97,7 @@ inkHost.ink_.setAnnotationTool = value => tool = value; // Pen defaults. - const viewerPdfToolbar = - viewer.shadowRoot.querySelector('viewer-pdf-toolbar'); + const viewerPdfToolbar = viewer.shadowRoot.querySelector('#toolbar'); const viewerAnnotationsBar = viewerPdfToolbar.shadowRoot.querySelector('viewer-annotations-bar'); const pen = viewerAnnotationsBar.shadowRoot.querySelector('#pen'); @@ -148,8 +157,7 @@ function testStrokeUndoRedo() { testAsync(async () => { const inkHost = contentElement(); - const viewerPdfToolbar = - viewer.shadowRoot.querySelector('viewer-pdf-toolbar'); + const viewerPdfToolbar = viewer.shadowRoot.querySelector('#toolbar'); const viewerAnnotationsBar = viewerPdfToolbar.shadowRoot.querySelector('viewer-annotations-bar'); const undo = viewerAnnotationsBar.shadowRoot.querySelector('#undo');
diff --git a/chrome/test/data/pdf/basic_plugin_test.js b/chrome/test/data/pdf/basic_plugin_test.js index 3910002..92d19d1 100644 --- a/chrome/test/data/pdf/basic_plugin_test.js +++ b/chrome/test/data/pdf/basic_plugin_test.js
@@ -18,6 +18,14 @@ // Verify that the initial zoom is less than or equal to 100%. chrome.test.assertTrue(viewer.viewport.getZoom() <= 1); + // TODO (https://crbug.com/1120279): Currently, calling setZoom() on the + // viewport with the new UI enabled triggers a crash in Blink. Fix this + // issue and remove the lines below. + if (document.documentElement.hasAttribute('pdf-viewer-update-enabled')) { + chrome.test.succeed(); + return; + } + viewer.viewport.setZoom(1); const sizer = viewer.shadowRoot.querySelector('#sizer'); chrome.test.assertEq(826, sizer.offsetWidth);
diff --git a/chrome/test/data/pdf/basic_test.js b/chrome/test/data/pdf/basic_test.js index e803f137..b415fc7 100644 --- a/chrome/test/data/pdf/basic_test.js +++ b/chrome/test/data/pdf/basic_test.js
@@ -14,12 +14,11 @@ function testHasElements() { const viewer = /** @type {!PDFViewerElement} */ ( document.body.querySelector('pdf-viewer')); - const elementNames = [ - 'viewer-pdf-toolbar', - 'viewer-zoom-toolbar', - 'viewer-password-screen', - 'viewer-error-screen', - ]; + const commonElements = ['viewer-password-screen', 'viewer-error-screen']; + const elementNames = + document.documentElement.hasAttribute('pdf-viewer-update-enabled') ? + ['viewer-pdf-toolbar-new', 'viewer-pdf-sidenav', ...commonElements] : + ['viewer-pdf-toolbar', 'viewer-zoom-toolbar', ...commonElements]; for (let i = 0; i < elementNames.length; i++) { const elements = viewer.shadowRoot.querySelectorAll(elementNames[i]); chrome.test.assertEq(1, elements.length); @@ -52,11 +51,17 @@ document.body.querySelector('pdf-viewer')); const toolbar = /** @type {!ViewerPdfToolbarElement} */ ( viewer.shadowRoot.querySelector('#toolbar')); - toolbar.$$('#pageselector').pageSelector.focus(); + toolbar.shadowRoot.querySelector('viewer-page-selector') + .pageSelector.focus(); chrome.test.assertTrue(shouldIgnoreKeyEvents(toolbar)); // Test case where the active element has a shadow root of its own. - toolbar.$['rotate-right'].focus(); + const rotateButton = + document.documentElement.hasAttribute('pdf-viewer-update-enabled') ? + toolbar.shadowRoot.querySelector( + 'cr-icon-button[iron-icon=\'pdf:rotate-left\']') : + toolbar.$['rotate-right']; + rotateButton.focus(); chrome.test.assertFalse(shouldIgnoreKeyEvents(toolbar)); chrome.test.assertFalse( @@ -70,6 +75,13 @@ * pressing escape. */ function testOpenCloseBookmarks() { + // Test is not relevant for the new viewer, as bookmarks are no longer in a + // dropdown. + if (document.documentElement.hasAttribute('pdf-viewer-update-enabled')) { + chrome.test.succeed(); + return; + } + const viewer = /** @type {!PDFViewerElement} */ ( document.body.querySelector('pdf-viewer')); const toolbar = /** @type {!ViewerPdfToolbarElement} */ (
diff --git a/chrome/test/data/pdf/page_change_test.js b/chrome/test/data/pdf/page_change_test.js index 0473456d..59d2935 100644 --- a/chrome/test/data/pdf/page_change_test.js +++ b/chrome/test/data/pdf/page_change_test.js
@@ -21,7 +21,6 @@ function resetDocument() { const viewer = getViewer(); viewer.viewport.goToPage(0); - viewer.viewport.setZoom(1); simulateFormFocusChange(false); }
diff --git a/chrome/test/data/webui/new_tab_page/app_test.js b/chrome/test/data/webui/new_tab_page/app_test.js index e3efe75..6d27da31 100644 --- a/chrome/test/data/webui/new_tab_page/app_test.js +++ b/chrome/test/data/webui/new_tab_page/app_test.js
@@ -51,6 +51,7 @@ testProxy.handler.setResultFor('getOneGoogleBarParts', Promise.resolve({ parts: null, })); + testProxy.handler.setResultFor('getPromo', Promise.resolve({promo: null})); testProxy.setResultMapperFor('matchMedia', () => ({ addListener() {}, removeListener() {}, @@ -411,8 +412,10 @@ data: { frameType: 'one-google-bar', messageType: 'execute-browser-command', - commandId, - clickInfo, + data: { + commandId, + clickInfo, + }, }, source: window, origin: window.origin,
diff --git a/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.js b/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.js new file mode 100644 index 0000000..3998639 --- /dev/null +++ b/chrome/test/data/webui/new_tab_page/middle_slot_promo_test.js
@@ -0,0 +1,120 @@ +// 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 {BrowserProxy, PromoBrowserCommandProxy} from 'chrome://new-tab-page/new_tab_page.js'; +import {createTestProxy} from 'chrome://test/new_tab_page/test_support.js'; +import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; +import {eventToPromise, flushTasks} from 'chrome://test/test_util.m.js'; + +suite('NewTabPageMiddleSlotPromoTest', () => { + /** @type {!MiddleSlotPromoElement} */ + let middleSlotPromo; + + /** + * @implements {BrowserProxy} + * @extends {TestBrowserProxy} + */ + let testProxy; + + setup(async () => { + PolymerTest.clearBody(); + testProxy = createTestProxy(); + testProxy.handler.setResultFor('getPromo', Promise.resolve({ + promo: { + middleSlotParts: [ + {image: {imageUrl: {url: 'https://image'}}}, + { + image: { + imageUrl: {url: 'https://image'}, + target: {url: 'https://link'}, + } + }, + { + image: { + imageUrl: {url: 'https://image'}, + target: {url: 'command:123'}, + } + }, + {text: {text: 'text', color: 'red'}}, + { + link: { + url: {url: 'https://link'}, + text: 'link', + color: 'green', + } + }, + { + link: { + url: {url: 'command:123'}, + text: 'command', + color: 'blue', + } + }, + ], + }, + })); + BrowserProxy.instance_ = testProxy; + const loaded = + eventToPromise('ntp-middle-slot-promo-loaded', document.body); + middleSlotPromo = document.createElement('ntp-middle-slot-promo'); + document.body.appendChild(middleSlotPromo); + await loaded; + }); + + test('render', () => { + const parts = middleSlotPromo.$.container.children; + assertEquals(6, parts.length); + const [image, imageWithLink, imageWithCommand, text, link, command] = parts; + + assertEquals('chrome://image/?https://image', image.src); + + assertEquals('https://link/', imageWithLink.href); + assertEquals( + 'chrome://image/?https://image', imageWithLink.children[0].src); + + assertEquals('', imageWithCommand.href); + assertEquals( + 'chrome://image/?https://image', imageWithCommand.children[0].src); + + assertEquals('text', text.innerText); + assertEquals('red', text.style.color); + + assertEquals('https://link/', link.href); + assertEquals('link', link.innerText); + assertEquals('green', link.style.color); + + assertEquals('', command.href); + assertEquals('command', command.text); + assertEquals('blue', command.style.color); + }); + + test('clicking on command', async () => { + const testProxy = PromoBrowserCommandProxy.getInstance(); + testProxy.handler = TestBrowserProxy.fromClass( + promoBrowserCommand.mojom.CommandHandlerRemote); + testProxy.handler.setResultFor('executeCommand', Promise.resolve()); + const imageWithCommand = middleSlotPromo.$.container.children[2]; + const command = middleSlotPromo.$.container.children[5]; + await Promise.all([imageWithCommand, command].map(async el => { + testProxy.handler.reset(); + el.click(); + // Make sure the command and click information are sent to the browser. + const [expectedCommand, expectedClickInfo] = + await testProxy.handler.whenCalled('executeCommand'); + // Unsupported commands get resolved to the default command before being + // sent to the browser. + assertEquals( + promoBrowserCommand.mojom.Command.kUnknownCommand, expectedCommand); + assertDeepEquals( + { + middleButton: false, + altKey: false, + ctrlKey: false, + metaKey: false, + shiftKey: false, + }, + expectedClickInfo); + })); + }); +});
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js index 807cb8e..7b1e4b3 100644 --- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js +++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
@@ -226,3 +226,15 @@ TEST_F('NewTabPageModulesDummyModuleTest', 'All', function() { mocha.run(); }); + +// eslint-disable-next-line no-var +var NewTabPageMiddleSlotPromoTest = class extends NewTabPageBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://new-tab-page/test_loader.html?module=new_tab_page/middle_slot_promo_test.js'; + } +}; + +TEST_F('NewTabPageMiddleSlotPromoTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/print_preview/destination_select_test_cros.js b/chrome/test/data/webui/print_preview/destination_select_test_cros.js index 519a6093..4e785c3 100644 --- a/chrome/test/data/webui/print_preview/destination_select_test_cros.js +++ b/chrome/test/data/webui/print_preview/destination_select_test_cros.js
@@ -415,7 +415,11 @@ compareIcon(selectEl, 'print'); destinationSelect.driveDestinationKey = driveKey; - return selectOption(destinationSelect, driveKey); + return selectOption( + destinationSelect, + loadTimeData.getBoolean('printSaveToDrive') ? + SAVE_TO_DRIVE_CROS_DESTINATION_KEY : + driveKey); }) .then(() => { // Icon updates early based on the ID.
diff --git a/chrome/test/data/webui/print_preview/model_test.js b/chrome/test/data/webui/print_preview/model_test.js index 6cc4ae1..af81b39 100644 --- a/chrome/test/data/webui/print_preview/model_test.js +++ b/chrome/test/data/webui/print_preview/model_test.js
@@ -17,7 +17,8 @@ SetPolicySettings: 'set policy settings', GetPrintTicket: 'get print ticket', GetCloudPrintTicket: 'get cloud print ticket', - ChangeDestination: 'change destination' + ChangeDestination: 'change destination', + PrintToGoogleDriveCros: 'print to google drive cros', }; suite(model_test.suiteName, function() { @@ -525,4 +526,17 @@ assertEquals(400, model.getSettingValue('dpi').horizontal_dpi); assertEquals(false, model.getSettingValue('duplex')); }); + + // Tests that printToGoogleDrive is set correctly on the print ticket for Save + // to Drive CrOS. + test(assert(model_test.TestNames.PrintToGoogleDriveCros), function() { + const driveDestination = new Destination( + Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS, DestinationType.LOCAL, + DestinationOrigin.LOCAL, 'Save to Google Drive', + DestinationConnectionStatus.ONLINE); + initializeModel(); + model.destination = driveDestination; + const ticket = model.createPrintTicket(driveDestination, false, false); + assertTrue(JSON.parse(ticket).printToGoogleDrive); + }); });
diff --git a/chrome/test/data/webui/print_preview/native_layer_stub.js b/chrome/test/data/webui/print_preview/native_layer_stub.js index 00a7b0c..674e6b3 100644 --- a/chrome/test/data/webui/print_preview/native_layer_stub.js +++ b/chrome/test/data/webui/print_preview/native_layer_stub.js
@@ -187,7 +187,8 @@ this.multipleCapabilitiesPromise_ = null; } } - if (printerId === Destination.GooglePromotedId.SAVE_AS_PDF) { + if (printerId === Destination.GooglePromotedId.SAVE_AS_PDF || + printerId === Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS) { return Promise.resolve(getPdfPrinter()); } if (type !== PrinterType.LOCAL_PRINTER) {
diff --git a/chrome/test/data/webui/print_preview/print_button_test.js b/chrome/test/data/webui/print_preview/print_button_test.js index 2da30e3..35c492797 100644 --- a/chrome/test/data/webui/print_preview/print_button_test.js +++ b/chrome/test/data/webui/print_preview/print_button_test.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {NativeLayer, NativeLayerImpl, PluginProxyImpl} from 'chrome://print/print_preview.js'; +import {Destination, NativeLayer, NativeLayerImpl, PluginProxyImpl} from 'chrome://print/print_preview.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {NativeLayerStub} from 'chrome://test/print_preview/native_layer_stub.js'; import {getDefaultInitialSettings} from 'chrome://test/print_preview/print_preview_test_utils.js'; @@ -14,6 +14,7 @@ print_button_test.TestNames = { LocalPrintHidePreview: 'local print hide preview', PDFPrintVisiblePreview: 'pdf print visible preview', + SaveToDriveVisiblePreviewCros: 'save to drive visible preview cros', }; suite(print_button_test.suiteName, function() { @@ -131,4 +132,45 @@ return nativeLayer.whenCalled('dialogClose'); }); }); + + // Tests that hidePreview() is not called if Save to Drive is selected on + // Chrome OS and the user clicks print while the preview is loading because + // when the flag |kPrintSaveToDrive| is enabled, Save to Drive needs to be + // treated like Save as PDF. + test( + assert(print_button_test.TestNames.SaveToDriveVisiblePreviewCros), + function() { + printBeforePreviewReady = false; + + return waitForInitialPreview() + .then(function() { + nativeLayer.reset(); + // Setup to print before the preview loads. + printBeforePreviewReady = true; + + // Select Save as PDF destination + const destinationSettings = + page.$$('print-preview-sidebar') + .$$('print-preview-destination-settings'); + const driveDestination = + destinationSettings.destinationStore_.destinations().find( + d => d.id === + Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS); + assertTrue(!!driveDestination); + destinationSettings.destinationStore_.selectDestination( + driveDestination); + + // Reload preview and wait for print. + return nativeLayer.whenCalled('print'); + }) + .then(function(printTicket) { + assertFalse(previewHidden); + + // Verify that the printer name is correct. + assertEquals( + Destination.GooglePromotedId.SAVE_TO_DRIVE_CROS, + JSON.parse(printTicket).deviceName); + return nativeLayer.whenCalled('dialogClose'); + }); + }); });
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js index 9ef5f4a1..c7ac4fd8 100644 --- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -293,6 +293,35 @@ this.runMochaTest(model_test.TestNames.ChangeDestination); }); +GEN('#if defined(OS_CHROMEOS)'); +// eslint-disable-next-line no-var +var PrintPreviewModelTestCros = class extends PrintPreviewTest { + /** @override */ + get browsePreload() { + return 'chrome://print/test_loader.html?module=print_preview/model_test.js'; + } + + /** @override */ + get suiteName() { + return model_test.suiteName; + } + + /** @override */ + get featureList() { + const kPrintSaveToDrive = ['chromeos::features::kPrintSaveToDrive']; + const featureList = super.featureList || []; + featureList.enabled = featureList.enabled ? + featureList.enabled.concat(kPrintSaveToDrive) : + kPrintSaveToDrive; + return featureList; + } +}; + +TEST_F('PrintPreviewModelTestCros', 'PrintToGoogleDriveCros', function() { + this.runMochaTest(model_test.TestNames.PrintToGoogleDriveCros); +}); +GEN('#endif'); + // eslint-disable-next-line no-var var PrintPreviewModelSettingsAvailabilityTest = class extends PrintPreviewTest { /** @override */ @@ -1076,6 +1105,38 @@ this.runMochaTest(print_button_test.TestNames.PDFPrintVisiblePreview); }); +GEN('#if defined(OS_CHROMEOS)'); +// eslint-disable-next-line no-var +var PrintPreviewPrintButtonTestCros = class extends PrintPreviewTest { + /** @override */ + get browsePreload() { + return 'chrome://print/test_loader.html?module=print_preview/print_button_test.js'; + } + + /** @override */ + get suiteName() { + return print_button_test.suiteName; + } + + /** @override */ + get featureList() { + const kPrintSaveToDrive = ['chromeos::features::kPrintSaveToDrive']; + const featureList = super.featureList || []; + featureList.enabled = featureList.enabled ? + featureList.enabled.concat(kPrintSaveToDrive) : + kPrintSaveToDrive; + return featureList; + } +}; + +TEST_F( + 'PrintPreviewPrintButtonTestCros', 'SaveToDriveVisiblePreviewCros', + function() { + this.runMochaTest( + print_button_test.TestNames.SaveToDriveVisiblePreviewCros); + }); +GEN('#endif'); + // eslint-disable-next-line no-var var PrintPreviewKeyEventTest = class extends PrintPreviewTest { /** @override */ @@ -1219,6 +1280,19 @@ destination_select_test_cros.TestNames.SelectDriveDestination); }); +TEST_F( + 'PrintPreviewDestinationSelectTestCrOSSaveToDriveEnabled', 'ChangeIcon', + function() { + this.runMochaTest(destination_select_test_cros.TestNames.ChangeIcon); + }); + +TEST_F( + 'PrintPreviewDestinationSelectTestCrOSSaveToDriveEnabled', + 'ChangeIconDeprecationWarnings', function() { + this.runMochaTest( + destination_select_test_cros.TestNames.ChangeIconDeprecationWarnings); + }); + // eslint-disable-next-line no-var var PrintPreviewPrinterStatusTestCros = class extends PrintPreviewTest { /** @override */
diff --git a/chrome/test/data/webui/settings/chromeos/apps_page_test.js b/chrome/test/data/webui/settings/chromeos/apps_page_test.js index 4c1c15b..19b8e72c 100644 --- a/chrome/test/data/webui/settings/chromeos/apps_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/apps_page_test.js
@@ -21,6 +21,7 @@ teardown(function() { appsPage.remove(); appsPage = null; + settings.Router.getInstance().resetRouteForTesting(); }); suite('Page Combinations', function() { @@ -78,6 +79,41 @@ assertTrue(!!appsPage.$$('.subpage-arrow')); }); + test('Deep link to manage android prefs', async () => { + loadTimeData.overrideValues({ + isDeepLinkingEnabled: true, + }); + + appsPage.havePlayStoreApp = false; + Polymer.dom.flush(); + + const params = new URLSearchParams; + params.append('settingId', '700'); + settings.Router.getInstance().navigateTo(settings.routes.APPS, params); + + const deepLinkElement = appsPage.$$('#manageApps').$$('cr-icon-button'); + await test_util.waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Manage android prefs button should be focused for settingId=700.'); + }); + + test('Deep link to turn on Play Store', async () => { + loadTimeData.overrideValues({ + isDeepLinkingEnabled: true, + }); + + const params = new URLSearchParams; + params.append('settingId', '702'); + settings.Router.getInstance().navigateTo(settings.routes.APPS, params); + + const deepLinkElement = appsPage.$$('#enable'); + await test_util.waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Turn on play store button should be focused for settingId=702.'); + }); + // TODO(crbug.com/1006662): Test that setting playStoreEnabled to false // navigates back to the main apps section. }); @@ -93,6 +129,13 @@ document.body.appendChild(subpage); testing.Test.disableAnimationsAndTransitions(); + // Because we can't simulate the loadTimeData value androidAppsVisible, + // this route doesn't exist for tests. Add it in for testing. + if (!settings.routes.ANDROID_APPS_DETAILS) { + settings.routes.ANDROID_APPS_DETAILS = settings.routes.APPS.createChild( + '/' + chromeos.settings.mojom.GOOGLE_PLAY_STORE_SUBPAGE_PATH); + } + subpage.prefs = {arc: {enabled: {value: true}}}; subpage.androidAppsInfo = { playStoreEnabled: true, @@ -192,5 +235,45 @@ Polymer.dom.flush(); return promise; }); + + test('Deep link to manage android prefs - subpage', async () => { + loadTimeData.overrideValues({ + isDeepLinkingEnabled: true, + }); + + subpage.androidAppsInfo = { + playStoreEnabled: false, + settingsAppAvailable: true, + }; + Polymer.dom.flush(); + + const params = new URLSearchParams; + params.append('settingId', '700'); + settings.Router.getInstance().navigateTo( + settings.routes.ANDROID_APPS_DETAILS, params); + + const deepLinkElement = subpage.$$('#manageApps').$$('cr-icon-button'); + await test_util.waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Manage android prefs button should be focused for settingId=700.'); + }); + + test('Deep link to remove play store', async () => { + loadTimeData.overrideValues({ + isDeepLinkingEnabled: true, + }); + + const params = new URLSearchParams; + params.append('settingId', '701'); + settings.Router.getInstance().navigateTo( + settings.routes.ANDROID_APPS_DETAILS, params); + + const deepLinkElement = subpage.$$('#remove cr-button'); + await test_util.waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Remove play store button should be focused for settingId=701.'); + }); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js index 9075336c..7543ea1 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -302,6 +302,7 @@ return super.extraLibraries.concat([ '//ui/webui/resources/js/promise_resolver.js', BROWSER_SETTINGS_PATH + '../test_browser_proxy.js', + BROWSER_SETTINGS_PATH + '../test_util.js', BROWSER_SETTINGS_PATH + 'chromeos/test_android_apps_browser_proxy.js', 'apps_page_test.js', ]);
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index fd043250..5ffcecf 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -104,6 +104,8 @@ "installer.cc", "installer.h", "lib_util.h", + "policy_service.cc", + "policy_service.h", "prefs.cc", "prefs.h", "prefs_impl.h", @@ -183,6 +185,7 @@ if (is_mac) { deps += [ "//chrome/updater/app/server/mac:protocol", + "//chrome/updater/mac:enterprise", "//chrome/updater/mac:installer_sources", "//chrome/updater/mac:network_fetcher_sources", "//chrome/updater/mac:updater_setup_sources", @@ -290,6 +293,7 @@ "lib_util_unittest.cc", "persisted_data_unittest.cc", "policy_manager_unittest.cc", + "policy_service_unittest.cc", "prefs_unittest.cc", "run_all_unittests.cc", "service_scope_unittest.cc",
diff --git a/chrome/updater/device_management/dm_policy_manager.cc b/chrome/updater/device_management/dm_policy_manager.cc index be2d4fa..4fac804 100644 --- a/chrome/updater/device_management/dm_policy_manager.cc +++ b/chrome/updater/device_management/dm_policy_manager.cc
@@ -202,6 +202,16 @@ return true; } +bool DMPolicyManager::GetTargetChannel(const std::string& app_id, + std::string* channel) const { + const auto* app_settings = GetAppSettings(app_id); + if (!app_settings || !app_settings->has_target_channel()) + return false; + + *channel = app_settings->target_channel(); + return true; +} + bool DMPolicyManager::IsRollbackToTargetVersionAllowed( const std::string& app_id, bool* rollback_allowed) const {
diff --git a/chrome/updater/device_management/dm_policy_manager.h b/chrome/updater/device_management/dm_policy_manager.h index 62f4b9e..e6a69e3 100644 --- a/chrome/updater/device_management/dm_policy_manager.h +++ b/chrome/updater/device_management/dm_policy_manager.h
@@ -47,6 +47,8 @@ bool GetTargetVersionPrefix( const std::string& app_id, std::string* target_version_prefix) const override; + bool GetTargetChannel(const std::string& app_id, + std::string* channel) const override; bool IsRollbackToTargetVersionAllowed(const std::string& app_id, bool* rollback_allowed) const override;
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc index 2794f6d..b029c74 100644 --- a/chrome/updater/installer.cc +++ b/chrome/updater/installer.cc
@@ -17,6 +17,7 @@ #include "build/build_config.h" #include "chrome/updater/action_handler.h" #include "chrome/updater/constants.h" +#include "chrome/updater/policy_service.h" #include "chrome/updater/util.h" #include "components/crx_file/crx_verifier.h" #include "components/update_client/update_client_errors.h" @@ -78,6 +79,13 @@ component.name = app_id_; component.version = pv_; component.fingerprint = fingerprint_; + + // In case we fail at getting the target channel, make sure that + // |component.channel| is an empty string. Possible failure cases are if the + // machine is not managed, the policy was not set or any other unexpected + // error. + if (!GetUpdaterPolicyService()->GetTargetChannel(app_id_, &component.channel)) + component.channel.clear(); return component; }
diff --git a/chrome/updater/mac/managed_preference_policy_manager.mm b/chrome/updater/mac/managed_preference_policy_manager.mm index bb8d78b6..ffe9169 100644 --- a/chrome/updater/mac/managed_preference_policy_manager.mm +++ b/chrome/updater/mac/managed_preference_policy_manager.mm
@@ -52,6 +52,8 @@ bool GetProxyMode(std::string* proxy_mode) const override; bool GetProxyPacUrl(std::string* proxy_pac_url) const override; bool GetProxyServer(std::string* proxy_server) const override; + bool GetTargetChannel(const std::string& app_id, + std::string* channel) const override; private: base::scoped_nsobject<CRUManagedPreferencePolicyManager> impl_; @@ -188,6 +190,18 @@ return false; } +bool ManagedPreferencePolicyManager::GetTargetChannel( + const std::string& app_id, + std::string* channel) const { + NSString* value = [impl_ targetChannel:base::SysUTF8ToNSString(app_id)]; + if (value) { + *channel = base::SysNSStringToUTF8(value); + return true; + } + + return false; +} + NSDictionary* ReadManagedPreferencePolicyDictionary() { base::ScopedCFTypeRef<CFPropertyListRef> policies(CFPreferencesCopyAppValue( (__bridge CFStringRef)kManagedPreferencesUpdatePolicies,
diff --git a/chrome/updater/mac/managed_preference_policy_manager_impl.h b/chrome/updater/mac/managed_preference_policy_manager_impl.h index f0a57cb..8626a8c 100644 --- a/chrome/updater/mac/managed_preference_policy_manager_impl.h +++ b/chrome/updater/mac/managed_preference_policy_manager_impl.h
@@ -67,6 +67,7 @@ // App-level policies. - (int)appUpdatePolicy:(nonnull NSString*)appid; +- (nullable NSString*)targetChannel:(nonnull NSString*)appid; - (nullable NSString*)targetVersionPrefix:(nonnull NSString*)appid; - (int)rollbackToTargetVersion:(nonnull NSString*)appid;
diff --git a/chrome/updater/mac/managed_preference_policy_manager_impl.mm b/chrome/updater/mac/managed_preference_policy_manager_impl.mm index 2e5cbaa3..ad70f97 100644 --- a/chrome/updater/mac/managed_preference_policy_manager_impl.mm +++ b/chrome/updater/mac/managed_preference_policy_manager_impl.mm
@@ -16,6 +16,7 @@ @"UpdatesSuppressedStartMin"; static NSString* kUpdatesSuppressedDurationMinuteKey = @"UpdatesSuppressedDurationMin"; +static NSString* kTargetChannelKey = @"TargetChannel"; static NSString* kTargetVersionPrefixKey = @"TargetVersionPrefix"; static NSString* kRollbackToTargetVersionKey = @"RollbackToTargetVersion"; @@ -119,11 +120,13 @@ /// Class that manages policies for a single App. @interface CRUManagedPreferenceAppPolicySettings : NSObject { + base::scoped_nsobject<NSString> _targetChannel; base::scoped_nsobject<NSString> _targetVersionPrefix; } @property(nonatomic, readonly) int updatePolicy; @property(nonatomic, readonly) int rollbackToTargetVersion; +@property(nonatomic, readonly, nullable) NSString* targetChannel; @property(nonatomic, readonly, nullable) NSString* targetVersionPrefix; @end @@ -137,6 +140,8 @@ if (([super init])) { _updatePolicy = updater::ReadPolicyInteger([policyDict objectForKey:kUpdateDefaultKey]); + _targetChannel = + updater::ReadPolicyString([policyDict objectForKey:kTargetChannelKey]); _targetVersionPrefix = updater::ReadPolicyString( [policyDict objectForKey:kTargetVersionPrefixKey]); _rollbackToTargetVersion = updater::ReadPolicyInteger( @@ -146,6 +151,14 @@ return self; } +- (NSString*)targetChannel { + if (_targetChannel) { + return [NSString stringWithString:_targetChannel]; + } else { + return nil; + } +} + - (NSString*)targetVersionPrefix { if (_targetVersionPrefix) { return [NSString stringWithString:_targetVersionPrefix]; @@ -233,6 +246,11 @@ return [_appPolicies objectForKey:appid].updatePolicy; } +- (NSString*)targetChannel:(NSString*)appid { + appid = appid.lowercaseString; + return [_appPolicies objectForKey:appid].targetChannel; +} + - (NSString*)targetVersionPrefix:(NSString*)appid { appid = appid.lowercaseString; return [_appPolicies objectForKey:appid].targetVersionPrefix;
diff --git a/chrome/updater/policy_manager.cc b/chrome/updater/policy_manager.cc index 04ff5626f..3038ca4 100644 --- a/chrome/updater/policy_manager.cc +++ b/chrome/updater/policy_manager.cc
@@ -44,6 +44,8 @@ bool GetProxyMode(std::string* proxy_mode) const override; bool GetProxyPacUrl(std::string* proxy_pac_url) const override; bool GetProxyServer(std::string* proxy_server) const override; + bool GetTargetChannel(const std::string& app_id, + std::string* channel) const override; }; DefaultPolicyManager::DefaultPolicyManager() = default; @@ -119,6 +121,11 @@ return false; } +bool DefaultPolicyManager::GetTargetChannel(const std::string& app_id, + std::string* channel) const { + return false; +} + std::unique_ptr<PolicyManagerInterface> GetPolicyManager() { return std::make_unique<DefaultPolicyManager>(); }
diff --git a/chrome/updater/policy_manager.h b/chrome/updater/policy_manager.h index 39f275e..cc5fa27c 100644 --- a/chrome/updater/policy_manager.h +++ b/chrome/updater/policy_manager.h
@@ -84,6 +84,10 @@ // Returns a proxy server. virtual bool GetProxyServer(std::string* proxy_server) const = 0; + + // Returns a channel, for example {stable|beta|dev}. + virtual bool GetTargetChannel(const std::string& app_id, + std::string* channel) const = 0; }; std::unique_ptr<PolicyManagerInterface> GetPolicyManager();
diff --git a/chrome/updater/policy_service.cc b/chrome/updater/policy_service.cc new file mode 100644 index 0000000..c26b77b --- /dev/null +++ b/chrome/updater/policy_service.cc
@@ -0,0 +1,183 @@ +// 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/updater/policy_service.h" + +#include "base/check.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include "chrome/updater/win/group_policy_manager.h" +#elif defined(OS_MAC) +#include "chrome/updater/mac/managed_preference_policy_manager.h" +#endif + +namespace updater { + +// Only policy manager that are enterprise managed are used by the policy +// service. +PolicyService::PolicyService() : default_policy_manager_(GetPolicyManager()) { +#if defined(OS_WIN) + auto group_policy_manager = std::make_unique<GroupPolicyManager>(); + if (group_policy_manager->IsManaged()) + policy_managers_.emplace_back(std::move(group_policy_manager)); +#endif + // TODO (crbug/1122118): Inject the DMPolicyManager here. +#if defined(OS_MAC) + auto mac_policy_manager = CreateManagedPreferencePolicyManager(); + if (mac_policy_manager->IsManaged()) + policy_managers_.emplace_back(std::move(mac_policy_manager)); +#endif + UpdateActivePolicyManager(); +} + +PolicyService::~PolicyService() = default; + +void PolicyService::SetPolicyManagersForTesting( + std::vector<std::unique_ptr<PolicyManagerInterface>> managers) { + policy_managers_ = std::move(managers); + UpdateActivePolicyManager(); +} + +std::string PolicyService::source() const { + return active_policy_manager_->source(); +} + +bool PolicyService::IsManaged() const { + return active_policy_manager_->IsManaged(); +} + +bool PolicyService::GetLastCheckPeriodMinutes(int* minutes) const { + return active_policy_manager_->GetLastCheckPeriodMinutes(minutes) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetLastCheckPeriodMinutes(minutes)); +} + +bool PolicyService::GetUpdatesSuppressedTimes(int* start_hour, + int* start_min, + int* duration_min) const { + return active_policy_manager_->GetUpdatesSuppressedTimes( + start_hour, start_min, duration_min) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetUpdatesSuppressedTimes( + start_hour, start_min, duration_min)); +} + +bool PolicyService::GetDownloadPreferenceGroupPolicy( + std::string* download_preference) const { + return active_policy_manager_->GetDownloadPreferenceGroupPolicy( + download_preference) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetDownloadPreferenceGroupPolicy( + download_preference)); +} + +bool PolicyService::GetPackageCacheSizeLimitMBytes( + int* cache_size_limit) const { + return active_policy_manager_->GetPackageCacheSizeLimitMBytes( + cache_size_limit) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetPackageCacheSizeLimitMBytes( + cache_size_limit)); +} + +bool PolicyService::GetPackageCacheExpirationTimeDays( + int* cache_life_limit) const { + return active_policy_manager_->GetPackageCacheExpirationTimeDays( + cache_life_limit) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetPackageCacheExpirationTimeDays( + cache_life_limit)); +} + +bool PolicyService::GetEffectivePolicyForAppInstalls( + const std::string& app_id, + int* install_policy) const { + return active_policy_manager_->GetEffectivePolicyForAppInstalls( + app_id, install_policy) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetEffectivePolicyForAppInstalls( + app_id, install_policy)); +} + +bool PolicyService::GetEffectivePolicyForAppUpdates(const std::string& app_id, + int* update_policy) const { + return active_policy_manager_->GetEffectivePolicyForAppUpdates( + app_id, update_policy) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetEffectivePolicyForAppUpdates( + app_id, update_policy)); +} + +bool PolicyService::GetTargetChannel(const std::string& app_id, + std::string* channel) const { + return active_policy_manager_->GetTargetChannel(app_id, channel) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetTargetChannel(app_id, channel)); +} + +bool PolicyService::GetTargetVersionPrefix( + const std::string& app_id, + std::string* target_version_prefix) const { + return active_policy_manager_->GetTargetVersionPrefix( + app_id, target_version_prefix) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetTargetVersionPrefix( + app_id, target_version_prefix)); +} + +bool PolicyService::IsRollbackToTargetVersionAllowed( + const std::string& app_id, + bool* rollback_allowed) const { + return active_policy_manager_->IsRollbackToTargetVersionAllowed( + app_id, rollback_allowed) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->IsRollbackToTargetVersionAllowed( + app_id, rollback_allowed)); +} + +bool PolicyService::GetProxyMode(std::string* proxy_mode) const { + return active_policy_manager_->GetProxyMode(proxy_mode) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetProxyMode(proxy_mode)); +} + +bool PolicyService::GetProxyPacUrl(std::string* proxy_pac_url) const { + return active_policy_manager_->GetProxyPacUrl(proxy_pac_url) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetProxyPacUrl(proxy_pac_url)); +} + +bool PolicyService::GetProxyServer(std::string* proxy_server) const { + return active_policy_manager_->GetProxyServer(proxy_server) || + (ShouldFallbackToDefaultManager() && + default_policy_manager_->GetProxyServer(proxy_server)); +} + +const PolicyManagerInterface& PolicyService::GetActivePolicyManager() { + DCHECK(active_policy_manager_); + return *active_policy_manager_; +} + +bool PolicyService::ShouldFallbackToDefaultManager() const { + return active_policy_manager_ != default_policy_manager_.get(); +} + +void PolicyService::UpdateActivePolicyManager() { + // The active policy manager is either the default policy manager or the + // manager with the highest level that is managed. + active_policy_manager_ = default_policy_manager_.get(); + for (const auto& manager : policy_managers_) { + if (manager->IsManaged()) { + active_policy_manager_ = manager.get(); + return; + } + } +} + +std::unique_ptr<PolicyService> GetUpdaterPolicyService() { + return std::make_unique<PolicyService>(); +} + +} // namespace updater
diff --git a/chrome/updater/policy_service.h b/chrome/updater/policy_service.h new file mode 100644 index 0000000..055c62b --- /dev/null +++ b/chrome/updater/policy_service.h
@@ -0,0 +1,81 @@ +// 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_UPDATER_POLICY_SERVICE_H_ +#define CHROME_UPDATER_POLICY_SERVICE_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "chrome/updater/policy_manager.h" + +namespace updater { + +// The PolicyService returns policies for enterprise managed machines from the +// source with the highest priority where the policy available. +class PolicyService : public PolicyManagerInterface { + public: + PolicyService(); + PolicyService(const PolicyService&) = delete; + PolicyService& operator=(const PolicyService&) = delete; + ~PolicyService() override; + + // Overrides for PolicyManagerInterface. + std::string source() const override; + + bool IsManaged() const override; + + bool GetLastCheckPeriodMinutes(int* minutes) const override; + bool GetUpdatesSuppressedTimes(int* start_hour, + int* start_min, + int* duration_min) const override; + bool GetDownloadPreferenceGroupPolicy( + std::string* download_preference) const override; + bool GetPackageCacheSizeLimitMBytes(int* cache_size_limit) const override; + bool GetPackageCacheExpirationTimeDays(int* cache_life_limit) const override; + + bool GetEffectivePolicyForAppInstalls(const std::string& app_id, + int* install_policy) const override; + bool GetEffectivePolicyForAppUpdates(const std::string& app_id, + int* update_policy) const override; + bool GetTargetChannel(const std::string& app_id, + std::string* channel) const override; + bool GetTargetVersionPrefix( + const std::string& app_id, + std::string* target_version_prefix) const override; + bool IsRollbackToTargetVersionAllowed(const std::string& app_id, + bool* rollback_allowed) const override; + bool GetProxyMode(std::string* proxy_mode) const override; + bool GetProxyPacUrl(std::string* proxy_pac_url) const override; + bool GetProxyServer(std::string* proxy_server) const override; + + const std::vector<std::unique_ptr<PolicyManagerInterface>>& + policy_managers() { + return policy_managers_; + } + + void SetPolicyManagersForTesting( + std::vector<std::unique_ptr<PolicyManagerInterface>> managers); + const PolicyManagerInterface& GetActivePolicyManager(); + + private: + bool ShouldFallbackToDefaultManager() const; + + // Sets the policy manager that is managed and has the highest priority as the + // active policy manager. If no manager is managed, use the default policy + // manager as the active one. + void UpdateActivePolicyManager(); + // List of policy managers in descending order of priority. The first policy + // manager's policies takes precedence over the following. + std::vector<std::unique_ptr<PolicyManagerInterface>> policy_managers_; + std::unique_ptr<PolicyManagerInterface> default_policy_manager_; + const PolicyManagerInterface* active_policy_manager_; +}; + +std::unique_ptr<PolicyService> GetUpdaterPolicyService(); + +} // namespace updater + +#endif // CHROME_UPDATER_POLICY_SERVICE_H_
diff --git a/chrome/updater/policy_service_unittest.cc b/chrome/updater/policy_service_unittest.cc new file mode 100644 index 0000000..50a8d547 --- /dev/null +++ b/chrome/updater/policy_service_unittest.cc
@@ -0,0 +1,138 @@ +// 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 <memory> +#include <string> +#include <vector> + +#include "chrome/updater/policy_manager.h" +#include "chrome/updater/policy_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace updater { + +// The Policy Manager Interface is implemented by policy managers such as Group +// Policy and Device Management. +class FakePolicyManager : public PolicyManagerInterface { + public: + ~FakePolicyManager() override = default; + + std::string source() const override { return source_; } + bool IsManaged() const override { return managed_; } + bool GetLastCheckPeriodMinutes(int* minutes) const override { return false; } + bool GetUpdatesSuppressedTimes(int* start_hour, + int* start_min, + int* duration_min) const override { + return false; + } + bool GetDownloadPreferenceGroupPolicy( + std::string* download_preference) const override { + return false; + } + bool GetPackageCacheSizeLimitMBytes(int* cache_size_limit) const override { + return false; + } + bool GetPackageCacheExpirationTimeDays(int* cache_life_limit) const override { + return false; + } + bool GetEffectivePolicyForAppInstalls(const std::string& app_id, + int* install_policy) const override { + return false; + } + bool GetEffectivePolicyForAppUpdates(const std::string& app_id, + int* update_policy) const override { + return false; + } + bool GetTargetVersionPrefix( + const std::string& app_id, + std::string* target_version_prefix) const override { + return false; + } + bool IsRollbackToTargetVersionAllowed(const std::string& app_id, + bool* rollback_allowed) const override { + return false; + } + bool GetProxyMode(std::string* proxy_mode) const override { return false; } + bool GetProxyPacUrl(std::string* proxy_pac_url) const override { + return false; + } + bool GetProxyServer(std::string* proxy_server) const override { + return false; + } + bool GetTargetChannel(const std::string& app_id, + std::string* channel) const override { + auto value = channels_.find(app_id); + if (value == channels_.end()) + return false; + *channel = value->second; + return true; + } + void SetChannel(const std::string& app_id, std::string channel) { + channels_[app_id] = std::move(channel); + } + + static std::unique_ptr<FakePolicyManager> GetTestingPolicyManager( + std::string source, + bool managed) { + auto manager = std::make_unique<FakePolicyManager>(); + manager->source_ = std::move(source); + manager->managed_ = managed; + return manager; + } + + private: + std::string source_; + std::map<std::string, std::string> channels_; + bool managed_; +}; + +TEST(PolicyService, ReturnsHighestPriorityManagedPolicyManager) { + std::unique_ptr<PolicyService> policy_service(GetUpdaterPolicyService()); + std::vector<std::unique_ptr<PolicyManagerInterface>> managers; + managers.emplace_back( + FakePolicyManager::GetTestingPolicyManager("highest_unmanaged", false)); + managers.emplace_back( + FakePolicyManager::GetTestingPolicyManager("highest_managed", true)); + managers.emplace_back( + FakePolicyManager::GetTestingPolicyManager("managed", true)); + managers.emplace_back( + FakePolicyManager::GetTestingPolicyManager("lowest_managed", true)); + managers.emplace_back( + FakePolicyManager::GetTestingPolicyManager("lowest_unmanaged", false)); + policy_service->SetPolicyManagersForTesting(std::move(managers)); + ASSERT_EQ("highest_managed", + policy_service->GetActivePolicyManager().source()); +} + +TEST(PolicyService, ReturnsDefaultPolicyManager) { + std::unique_ptr<PolicyService> policy_service(GetUpdaterPolicyService()); + policy_service->SetPolicyManagersForTesting({}); + ASSERT_EQ("default", policy_service->GetActivePolicyManager().source()); +} + +TEST(PolicyService, TargetChannelUnmanagedSource) { + std::unique_ptr<PolicyService> policy_service(GetUpdaterPolicyService()); + auto manager = FakePolicyManager::GetTestingPolicyManager("unmanaged", false); + manager->SetChannel("", "channel"); + std::vector<std::unique_ptr<PolicyManagerInterface>> managers; + managers.emplace_back(std::move(manager)); + policy_service->SetPolicyManagersForTesting(std::move(managers)); + std::string channel; + policy_service->GetTargetChannel("", &channel); + ASSERT_TRUE(channel.empty()); +} + +TEST(PolicyService, TargetChannelManagedSource) { + std::unique_ptr<PolicyService> policy_service(GetUpdaterPolicyService()); + auto manager = FakePolicyManager::GetTestingPolicyManager("managed", true); + manager->SetChannel("", "channel"); + std::vector<std::unique_ptr<PolicyManagerInterface>> managers; + managers.emplace_back(std::move(manager)); + policy_service->SetPolicyManagersForTesting(std::move(managers)); + std::string channel; + policy_service->GetTargetChannel("", &channel); + ASSERT_EQ(channel, "channel"); +} + +} // namespace updater
diff --git a/chrome/updater/protos/omaha_settings.proto b/chrome/updater/protos/omaha_settings.proto index 5a1c49e..178383e 100644 --- a/chrome/updater/protos/omaha_settings.proto +++ b/chrome/updater/protos/omaha_settings.proto
@@ -129,6 +129,24 @@ // specified by "Target version prefix override" will be downgraded to the // highest available version that matches the target version. optional RollbackToTargetVersionValue rollback_to_target_version = 6; + + // Gcpw specific application setting which contains a list of domains from + // which the user is allowed to login. + optional GcpwSpecificApplicationSettings gcpw_application_settings = 7; + + // Target Channel + // + // Specifies the channel to which <app> should be updated. + // + // When this policy is set, the binaries returned by Google Update will be the + // binaries for the specified channel. If this policy is not set, the default + // channel will be used. + optional string target_channel = 8; +} + +message GcpwSpecificApplicationSettings { + // List of domains from which the user is allowed to login. + repeated string domains_allowed_to_login = 1; } message OmahaSettingsClientProto {
diff --git a/chrome/updater/win/group_policy_manager.cc b/chrome/updater/win/group_policy_manager.cc index b761eac..ab9e934e 100644 --- a/chrome/updater/win/group_policy_manager.cc +++ b/chrome/updater/win/group_policy_manager.cc
@@ -48,6 +48,7 @@ const base::char16 kRegValueUpdateAppsDefault[] = L"UpdateDefault"; const base::char16 kRegValueUpdateAppPrefix[] = L"Update"; const base::char16 kRegValueTargetVersionPrefix[] = L"TargetVersionPrefix"; +const base::char16 kRegValueTargetChannel[] = L"TargetChannel"; const base::char16 kRegValueRollbackToTargetVersion[] = L"RollbackToTargetVersion"; @@ -112,6 +113,13 @@ : ReadValueDW(kRegValueUpdateAppsDefault, update_policy); } +bool GroupPolicyManager::GetTargetChannel(const std::string& app_id, + std::string* channel) const { + base::string16 app_value_name(kRegValueTargetChannel); + app_value_name.append(base::SysUTF8ToWide(app_id)); + return ReadValue(app_value_name.c_str(), channel); +} + bool GroupPolicyManager::GetTargetVersionPrefix( const std::string& app_id, std::string* target_version_prefix) const {
diff --git a/chrome/updater/win/group_policy_manager.h b/chrome/updater/win/group_policy_manager.h index 18a5192..5249199 100644 --- a/chrome/updater/win/group_policy_manager.h +++ b/chrome/updater/win/group_policy_manager.h
@@ -39,6 +39,8 @@ int* install_policy) const override; bool GetEffectivePolicyForAppUpdates(const std::string& app_id, int* update_policy) const override; + bool GetTargetChannel(const std::string& app_id, + std::string* channel) const override; bool GetTargetVersionPrefix( const std::string& app_id, std::string* target_version_prefix) const override;
diff --git a/chromeos/components/sync_wifi/synced_network_metrics_logger.cc b/chromeos/components/sync_wifi/synced_network_metrics_logger.cc index 3f4423c..9fffb3b 100644 --- a/chromeos/components/sync_wifi/synced_network_metrics_logger.cc +++ b/chromeos/components/sync_wifi/synced_network_metrics_logger.cc
@@ -166,9 +166,19 @@ } bool SyncedNetworkMetricsLogger::IsEligible(const NetworkState* network) { - return network && - NetworkHandler::Get()->network_metadata_store()->GetIsConfiguredBySync( - network->guid()); + // Only non-tether Wi-Fi networks are eligible for logging. + if (!network || network->type() != shill::kTypeWifi || + !network->tether_guid().empty()) { + return false; + } + + NetworkMetadataStore* metadata_store = + NetworkHandler::Get()->network_metadata_store(); + if (!metadata_store) { + return false; + } + + return metadata_store->GetIsConfiguredBySync(network->guid()); } void SyncedNetworkMetricsLogger::OnConnectErrorGetProperties(
diff --git a/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc b/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc index 6cfbe88..033992fcf 100644 --- a/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc +++ b/chromeos/components/sync_wifi/synced_network_metrics_logger_unittest.cc
@@ -235,6 +235,18 @@ testing::ElementsAre(base::Bucket(/*min=*/10, /*count=*/1))); } +TEST_F(SyncedNetworkMetricsLoggerTest, NetworkStatusChange_DuringLogout) { + base::HistogramTester histogram_tester; + const NetworkState* network = CreateNetwork(/*from_sync=*/true); + NetworkHandler::Get()->ShutdownPrefServices(); + synced_network_metrics_logger()->NetworkConnectionStateChanged(network); + base::RunLoop().RunUntilIdle(); + + // Expect that there is no crash, and no Wi-Fi sync histograms recorded. + EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("Network.Wifi.Synced"), + testing::ContainerEq(base::HistogramTester::CountsMap())); +} + } // namespace sync_wifi } // namespace chromeos
diff --git a/chromeos/cryptohome/system_salt_getter.h b/chromeos/cryptohome/system_salt_getter.h index 4e22729..f5013980 100644 --- a/chromeos/cryptohome/system_salt_getter.h +++ b/chromeos/cryptohome/system_salt_getter.h
@@ -44,6 +44,8 @@ // Returns pointer to binary system salt if it is already known. // Returns nullptr if system salt is not known. + // WARNING: This pointer is null early in startup. Do not assume it is valid. + // Prefer GetSystemSalt() above. https://crbug.com/1122674 const RawSalt* GetRawSalt() const; // This is for browser tests API.
diff --git a/chromeos/network/onc/variable_expander.cc b/chromeos/network/onc/variable_expander.cc index 92ff57a..1df4464 100644 --- a/chromeos/network/onc/variable_expander.cc +++ b/chromeos/network/onc/variable_expander.cc
@@ -4,6 +4,8 @@ #include "chromeos/network/onc/variable_expander.h" +#include <algorithm> + #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -86,8 +88,8 @@ } } - const base::StringPiece replacement_part = - replacement.substr(replacement_start, replacement_count); + const base::StringPiece replacement_part = replacement.substr( + std::min(replacement_start, replacement.size()), replacement_count); // Don't use ReplaceSubstringsAfterOffset here, it can lead to a doubling // of tokens, see VariableExpanderTest.DoesNotRecurse test. base::ReplaceFirstSubstringAfterOffset(str, token_start, full_token,
diff --git a/components/exo/README b/components/exo/README deleted file mode 100644 index 81ae61f..0000000 --- a/components/exo/README +++ /dev/null
@@ -1,2 +0,0 @@ -This directory contains an implementation of a display server on top of -the Aura Shell.
diff --git a/components/exo/README.md b/components/exo/README.md new file mode 100644 index 0000000..def122078 --- /dev/null +++ b/components/exo/README.md
@@ -0,0 +1,31 @@ +Exo implements a display server on top of the Aura Shell. It uses the +[Wayland protocol](https://wayland.freedesktop.org/docs/html/) +to communicate with clients. For a general introduction to Wayland see +https://wayland-book.com/. + +Current clients of Exo include: + +* ARC++ (Android apps on Chrome OS) +* [Chromecast](https://chromium.googlesource.com/chromium/src/+/master/chromecast/README.md) +* Crostini (Linux apps on Chrome OS) +* [Lacros](https://chromium.googlesource.com/chromium/src/+/master/docs/lacros.md) +* PluginVM + +In addition to the core Wayland protocol, Exo supports a number of protocol +extensions. Some are third-party; see +[//third_party/wayland-protocols/README.chromium](https://chromium.googlesource.com/chromium/src/+/master/third_party/wayland-protocols/README.chromium). +Others are Chromium-specific. + +A few noteworthy extensions (this list is not at all exhaustive): + +* zaura_shell + * A Chromium-specific protocol used by all Exo clients. See + [//components/exo/wayland/protocol/aura-shell.xml](wayland/protocol/aura-shell.xml) + and [//components/exo/wayland/zaura_shell.h](wayland/zaura_shell.h) +* zcr_remote_shell + * A Chromium-specific protocol used exclusively by ARC++. See + [//components/exo/wayland/zcr_remote_shell.h](wayland/zcr_remote_shell.h) and + [//components/exo/client_controlled_shell_surface.h](client_controlled_shell_surface.h) +* zwp_fullscreen_shell + * A third-party protocol, used in Chromium only by Chromecast. See + [//components/exo/wayland/zwp_fullscreen_shell.h](wayland/zwp_fullscreen_shell.h)
diff --git a/components/language/core/common/language_experiments.cc b/components/language/core/common/language_experiments.cc index 7ea587f..ad4827b 100644 --- a/components/language/core/common/language_experiments.cc +++ b/components/language/core/common/language_experiments.cc
@@ -30,6 +30,8 @@ }; const base::Feature kNotifySyncOnLanguageDetermined{ "NotifySyncOnLanguageDetermined", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kDetailedLanguageSettings{ + "DetailedLanguageSettings", base::FEATURE_DISABLED_BY_DEFAULT}; // Params: const char kBackoffThresholdKey[] = "backoff_threshold";
diff --git a/components/language/core/common/language_experiments.h b/components/language/core/common/language_experiments.h index 6332de1..283be88 100644 --- a/components/language/core/common/language_experiments.h +++ b/components/language/core/common/language_experiments.h
@@ -36,6 +36,9 @@ // This feature uses the existing UI for translate bubble. extern const base::Feature kUseButtonTranslateBubbleUi; +// This feature enables setting the application language on Android. +extern const base::Feature kDetailedLanguageSettings; + enum class OverrideLanguageModel { DEFAULT, FLUENT,
diff --git a/components/payments/content/BUILD.gn b/components/payments/content/BUILD.gn index 77b0cd9..3581775 100644 --- a/components/payments/content/BUILD.gn +++ b/components/payments/content/BUILD.gn
@@ -64,6 +64,7 @@ "//components/webdata/common", "//content/public/browser", "//device/fido", + "//services/data_decoder/public/cpp", "//third_party/blink/public:blink_headers", "//url", ]
diff --git a/components/payments/content/secure_payment_confirmation_app_factory.cc b/components/payments/content/secure_payment_confirmation_app_factory.cc index bf182e55bc..8dcd0a6 100644 --- a/components/payments/content/secure_payment_confirmation_app_factory.cc +++ b/components/payments/content/secure_payment_confirmation_app_factory.cc
@@ -23,6 +23,7 @@ #include "components/payments/core/secure_payment_confirmation_instrument.h" #include "components/webdata/common/web_data_results.h" #include "components/webdata/common/web_data_service_base.h" +#include "services/data_decoder/public/cpp/decode_image.h" #include "third_party/blink/public/mojom/payments/payment_request.mojom.h" #include "url/origin.h" @@ -187,10 +188,23 @@ std::unique_ptr<SecurePaymentConfirmationInstrument> instrument = std::move(instruments.front()); - // TODO(https://crbug.com/1110324): Decode `instrument->icon` from - // std::unique_ptr<std::vector<uint8_t>> into std::unique_ptr<SkBitmap> and - // check the icon validity. - auto icon = std::make_unique<SkBitmap>(); + auto* instrument_ptr = instrument.get(); + // Decode the icon in a sandboxed process off the main thread. + data_decoder::DecodeImageIsolated( + instrument_ptr->icon, data_decoder::mojom::ImageCodec::DEFAULT, + /*shrink_to_fit=*/false, data_decoder::kDefaultMaxSizeInBytes, + /*desired_image_frame_size=*/gfx::Size(), + base::BindOnce(&SecurePaymentConfirmationAppFactory::OnAppIconDecoded, + weak_ptr_factory_.GetWeakPtr(), std::move(instrument), + std::move(request))); +} + +void SecurePaymentConfirmationAppFactory::OnAppIconDecoded( + std::unique_ptr<SecurePaymentConfirmationInstrument> instrument, + std::unique_ptr<Request> request, + const SkBitmap& decoded_icon) { + DCHECK(!decoded_icon.drawsNothing()); + auto icon = std::make_unique<SkBitmap>(decoded_icon); request->delegate->OnPaymentAppCreated( std::make_unique<SecurePaymentConfirmationApp>(
diff --git a/components/payments/content/secure_payment_confirmation_app_factory.h b/components/payments/content/secure_payment_confirmation_app_factory.h index fd058bc..3eab505 100644 --- a/components/payments/content/secure_payment_confirmation_app_factory.h +++ b/components/payments/content/secure_payment_confirmation_app_factory.h
@@ -14,6 +14,8 @@ namespace payments { +struct SecurePaymentConfirmationInstrument; + class SecurePaymentConfirmationAppFactory : public PaymentAppFactory, public WebDataServiceConsumer { public: @@ -42,6 +44,11 @@ std::unique_ptr<autofill::InternalAuthenticator> authenticator, bool is_available); + void OnAppIconDecoded( + std::unique_ptr<SecurePaymentConfirmationInstrument> instrument, + std::unique_ptr<Request> request, + const SkBitmap& decoded_image); + std::map<WebDataServiceBase::Handle, std::unique_ptr<Request>> requests_; base::WeakPtrFactory<SecurePaymentConfirmationAppFactory> weak_ptr_factory_{ this};
diff --git a/components/services/heap_profiling/public/cpp/profiling_client.cc b/components/services/heap_profiling/public/cpp/profiling_client.cc index cfdfe5d8..ff58a17 100644 --- a/components/services/heap_profiling/public/cpp/profiling_client.cc +++ b/components/services/heap_profiling/public/cpp/profiling_client.cc
@@ -8,7 +8,6 @@ #include <unordered_set> #include <vector> -#include "base/allocator/allocator_interception_mac.h" #include "base/bind.h" #include "base/debug/stack_trace.h" #include "base/lazy_instance.h" @@ -25,6 +24,10 @@ #include "base/trace_event/cfi_backtrace_android.h" #endif +#if defined(OS_APPLE) +#include "base/allocator/allocator_interception_mac.h" +#endif + namespace heap_profiling { ProfilingClient::ProfilingClient() = default;
diff --git a/components/update_client/protocol_definition.h b/components/update_client/protocol_definition.h index aaacc76..f82015d 100644 --- a/components/update_client/protocol_definition.h +++ b/components/update_client/protocol_definition.h
@@ -103,6 +103,8 @@ std::string cohort_hint; // Server may use to move the app to a new cohort. std::string cohort_name; // Human-readable interpretation of the cohort. + std::string release_channel; + base::Optional<bool> enabled; base::Optional<std::vector<int>> disabled_reasons;
diff --git a/components/update_client/protocol_serializer.cc b/components/update_client/protocol_serializer.cc index 1074c93..1bec4106 100644 --- a/components/update_client/protocol_serializer.cc +++ b/components/update_client/protocol_serializer.cc
@@ -193,6 +193,7 @@ const std::string& cohort, const std::string& cohort_hint, const std::string& cohort_name, + const std::string& release_channel, const std::vector<int>& disabled_reasons, base::Optional<protocol_request::UpdateCheck> update_check, base::Optional<protocol_request::Ping> ping) { @@ -205,6 +206,7 @@ app.cohort = cohort; app.cohort_hint = cohort_hint; app.cohort_name = cohort_name; + app.release_channel = release_channel; app.enabled = disabled_reasons.empty(); app.disabled_reasons = disabled_reasons; app.update_check = std::move(update_check);
diff --git a/components/update_client/protocol_serializer.h b/components/update_client/protocol_serializer.h index 47c212a4..5ebe196 100644 --- a/components/update_client/protocol_serializer.h +++ b/components/update_client/protocol_serializer.h
@@ -60,6 +60,7 @@ const std::string& cohort, const std::string& cohort_hint, const std::string& cohort_name, + const std::string& release_channel, const std::vector<int>& disabled_reasons, base::Optional<protocol_request::UpdateCheck> update_check, base::Optional<protocol_request::Ping> ping);
diff --git a/components/update_client/protocol_serializer_json.cc b/components/update_client/protocol_serializer_json.cc index 8e7aee8..ea7f220 100644 --- a/components/update_client/protocol_serializer_json.cc +++ b/components/update_client/protocol_serializer_json.cc
@@ -97,6 +97,10 @@ app_node.SetKey("installsource", Value(app.install_source)); if (!app.install_location.empty()) app_node.SetKey("installedby", Value(app.install_location)); + // TODO(crbug/1120685): Test that this is never sent to the server if the + // machine is not enterprise managed. + if (!app.release_channel.empty()) + app_node.SetKey("release_channel", Value(app.release_channel)); if (!app.cohort.empty()) app_node.SetKey("cohort", Value(app.cohort)); if (!app.cohort_name.empty())
diff --git a/components/update_client/protocol_serializer_json_unittest.cc b/components/update_client/protocol_serializer_json_unittest.cc index eb9fca0..48d7879 100644 --- a/components/update_client/protocol_serializer_json_unittest.cc +++ b/components/update_client/protocol_serializer_json_unittest.cc
@@ -47,7 +47,7 @@ std::vector<protocol_request::App> apps; apps.push_back(MakeProtocolApp( "id1", base::Version("1.0"), "brand1", "source1", "location1", "fp1", - {{"attr1", "1"}, {"attr2", "2"}}, "c1", "ch1", "cn1", {0, 1}, + {{"attr1", "1"}, {"attr2", "2"}}, "c1", "ch1", "cn1", "test", {0, 1}, MakeProtocolUpdateCheck(true), MakeProtocolPing("id1", metadata.get()))); apps.push_back( MakeProtocolApp("id2", base::Version("2.0"), std::move(events))); @@ -65,6 +65,7 @@ R"("installedby":"location1","installsource":"source1",)" R"("packages":{"package":\[{"fp":"fp1"}]},)" R"("ping":{"ping_freshness":"{[-\w]{36}}","rd":1234},)" + R"("release_channel":"test",)" R"("updatecheck":{"updatedisabled":true},"version":"1.0"},)" R"({"appid":"id2","event":\[{"a":1,"b":"2"},{"error":0}],)" R"("version":"2.0"}],"arch":"\w+","dedup":"cr","dlpref":"cacheable",)" @@ -74,7 +75,7 @@ R"("prodversion":"1.0","protocol":"3.1","requestid":"{[-\w]{36}}",)" R"("sessionid":"{[-\w]{36}}","updaterchannel":"channel",)" R"("updaterversion":"1.0"(,"wow64":true)?}})"; - EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; + EXPECT_TRUE(RE2::FullMatch(request, regex)) << request << "\n VS \n" << regex; } TEST(SerializeRequestJSON, DownloadPreference) {
diff --git a/components/update_client/update_checker.cc b/components/update_client/update_checker.cc index 9eea680..facdea48 100644 --- a/components/update_client/update_checker.cc +++ b/components/update_client/update_checker.cc
@@ -200,7 +200,8 @@ crx_component->fingerprint, SanitizeInstallerAttributes(crx_component->installer_attributes), metadata_->GetCohort(app_id), metadata_->GetCohortName(app_id), - metadata_->GetCohortHint(app_id), crx_component->disabled_reasons, + metadata_->GetCohortHint(app_id), crx_component->channel, + crx_component->disabled_reasons, MakeProtocolUpdateCheck(is_update_disabled), MakeProtocolPing(app_id, metadata_))); }
diff --git a/components/update_client/update_client.h b/components/update_client/update_client.h index 45bc2150..be4f702 100644 --- a/components/update_client/update_client.h +++ b/components/update_client/update_client.h
@@ -315,6 +315,11 @@ // For extensions, this information is inferred from the extension // registry. std::string install_location; + + // Information about the channel to send to the update server when updating + // the component. This optional field is typically populated by policy and is + // only populated on managed devices. + std::string channel; }; // Called when a non-blocking call of UpdateClient completes.
diff --git a/components/viz/common/gl_i420_converter.cc b/components/viz/common/gl_i420_converter.cc index 3bfc042..c00e202 100644 --- a/components/viz/common/gl_i420_converter.cc +++ b/components/viz/common/gl_i420_converter.cc
@@ -10,16 +10,17 @@ namespace viz { -GLI420Converter::GLI420Converter( - scoped_refptr<ContextProvider> context_provider) - : GLI420Converter(std::move(context_provider), true) {} +GLI420Converter::GLI420Converter(ContextProvider* context_provider) + : GLI420Converter(context_provider, true) { + DCHECK(context_provider_); +} -GLI420Converter::GLI420Converter( - scoped_refptr<ContextProvider> context_provider, - bool allow_mrt_path) - : context_provider_(std::move(context_provider)), +GLI420Converter::GLI420Converter(ContextProvider* context_provider, + bool allow_mrt_path) + : context_provider_(context_provider), step1_(context_provider_), step2_(context_provider_) { + DCHECK(context_provider_); context_provider_->AddObserver(this); if (!allow_mrt_path || step1_.GetMaxDrawBuffersSupported() < 2) { step3_ = std::make_unique<GLScaler>(context_provider_);
diff --git a/components/viz/common/gl_i420_converter.h b/components/viz/common/gl_i420_converter.h index 779445a..b5be44c 100644 --- a/components/viz/common/gl_i420_converter.h +++ b/components/viz/common/gl_i420_converter.h
@@ -76,7 +76,7 @@ // GLI420Converter uses the exact same parameters as GLScaler. using Parameters = GLScaler::Parameters; - explicit GLI420Converter(scoped_refptr<ContextProvider> context_provider); + explicit GLI420Converter(ContextProvider* context_provider); ~GLI420Converter() final; // Returns true if the GL context provides the necessary support for enabling @@ -145,8 +145,7 @@ private: friend class GLI420ConverterPixelTest; - GLI420Converter(scoped_refptr<ContextProvider> context_provider, - bool allow_mrt_path); + GLI420Converter(ContextProvider* context_provider, bool allow_mrt_path); bool is_using_mrt_path() const { return !step3_; } @@ -159,7 +158,7 @@ // The provider of the GL context. This is non-null while the GL context is // valid and GLI420Converter is observing for context loss. - scoped_refptr<ContextProvider> context_provider_; + ContextProvider* context_provider_; // Scales the source content and produces either: // * MRT path: NV61-format output in two textures.
diff --git a/components/viz/common/gl_scaler.cc b/components/viz/common/gl_scaler.cc index c75e71f3..129fc12 100644 --- a/components/viz/common/gl_scaler.cc +++ b/components/viz/common/gl_scaler.cc
@@ -42,8 +42,8 @@ } // namespace -GLScaler::GLScaler(scoped_refptr<ContextProvider> context_provider) - : context_provider_(std::move(context_provider)) { +GLScaler::GLScaler(ContextProvider* context_provider) + : context_provider_(context_provider) { if (context_provider_) { DCHECK(context_provider_->ContextGL()); context_provider_->AddObserver(this);
diff --git a/components/viz/common/gl_scaler.h b/components/viz/common/gl_scaler.h index dd1dd7b3..9304ba2 100644 --- a/components/viz/common/gl_scaler.h +++ b/components/viz/common/gl_scaler.h
@@ -191,7 +191,7 @@ ~Parameters(); }; - explicit GLScaler(scoped_refptr<ContextProvider> context_provider); + explicit GLScaler(ContextProvider* context_provider); ~GLScaler() final; @@ -474,7 +474,7 @@ // The provider of the GL context. This is non-null while the GL context is // valid and GLScaler is observing for context loss. - scoped_refptr<ContextProvider> context_provider_; + ContextProvider* context_provider_; // Set by Configure() to the resolved set of Parameters. Parameters params_;
diff --git a/components/viz/common/gl_scaler_unittest.cc b/components/viz/common/gl_scaler_unittest.cc index 69e9c6d..3f6c393b7 100644 --- a/components/viz/common/gl_scaler_unittest.cc +++ b/components/viz/common/gl_scaler_unittest.cc
@@ -99,7 +99,7 @@ .WillOnce(SaveArg<0>(®istered_observer)); EXPECT_CALL(provider, RemoveObserver(Eq(ByRef(registered_observer)))) .InSequence(s); - GLScaler scaler(base::WrapRefCounted(&provider)); + GLScaler scaler(&provider); } TEST_F(GLScalerTest, RemovesObserverWhenContextIsLost) { @@ -111,7 +111,7 @@ .WillOnce(SaveArg<0>(®istered_observer)); EXPECT_CALL(provider, RemoveObserver(Eq(ByRef(registered_observer)))) .InSequence(s); - GLScaler scaler(base::WrapRefCounted(&provider)); + GLScaler scaler(&provider); static_cast<ContextLostObserver&>(scaler).OnContextLost(); // Verify RemoveObserver() was called before |scaler| goes out-of-scope. Mock::VerifyAndClearExpectations(&provider);
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc index 8d50154..c725e7c2 100644 --- a/components/viz/service/display/gl_renderer.cc +++ b/components/viz/service/display/gl_renderer.cc
@@ -2092,11 +2092,35 @@ SetupQuadForClippingAndAntialiasing(device_transform, quad, aa_quad, clip_region, &local_quad, edge); - gfx::ColorSpace quad_color_space = gfx::ColorSpace::CreateSRGB(); SetUseProgram(ProgramKey::SolidColor(use_aa ? USE_AA : NO_AA, tint_gl_composited_content_, ShouldApplyRoundedCorner(quad)), - quad_color_space, CurrentRenderPassColorSpace()); + CurrentRenderPassColorSpace(), CurrentRenderPassColorSpace()); + + gfx::ColorSpace quad_color_space = gfx::ColorSpace::CreateSRGB(); + SkColor4f color_f = SkColor4f::FromColor(color); + + // Apply color transform if the color space or source and target do not match. + if (quad_color_space != CurrentRenderPassColorSpace()) { + const gfx::ColorTransform* color_transform = + GetColorTransform(quad_color_space, CurrentRenderPassColorSpace()); + gfx::ColorTransform::TriStim col(color_f.fR, color_f.fG, color_f.fB); + color_transform->Transform(&col, 1); + color_f.fR = col.x(); + color_f.fG = col.y(); + color_f.fB = col.z(); + color = color_f.toSkColor(); + } + + // Apply any color matrix that may be present. + if (HasOutputColorMatrix()) { + const SkMatrix44& output_color_matrix = output_surface_->color_matrix(); + const SkVector4 color_v(color_f.fR, color_f.fG, color_f.fB, color_f.fA); + const SkVector4 result = output_color_matrix * color_v; + std::copy(result.fData, result.fData + 4, color_f.vec()); + color = color_f.toSkColor(); + } + SetShaderColor(color, opacity); if (current_program_->rounded_corner_rect_location() != -1) { SetShaderRoundedCorner( @@ -3537,12 +3561,9 @@ GetColorTransform(adjusted_src_color_space, dst_color_space); program_key.SetColorTransform(color_transform); - const bool is_root_render_pass = - current_frame()->current_render_pass == current_frame()->root_render_pass; - const SkMatrix44& output_color_matrix = output_surface_->color_matrix(); - const bool has_output_color_matrix = - is_root_render_pass && !output_color_matrix.isIdentity(); - + bool has_output_color_matrix = false; + if (program_key.type() != ProgramType::PROGRAM_TYPE_SOLID_COLOR) + has_output_color_matrix = HasOutputColorMatrix(); program_key.set_has_output_color_matrix(has_output_color_matrix); // Create and set the program if needed. @@ -3577,7 +3598,7 @@ if (has_output_color_matrix) { DCHECK_NE(current_program_->output_color_matrix_location(), -1); float matrix[16]; - output_color_matrix.asColMajorf(matrix); + output_surface_->color_matrix().asColMajorf(matrix); gl_->UniformMatrix4fv(current_program_->output_color_matrix_location(), 1, false, matrix); } @@ -4217,6 +4238,13 @@ return PlatformColor::BestSupportedTextureFormat(caps); } +bool GLRenderer::HasOutputColorMatrix() const { + const bool is_root_render_pass = + current_frame()->current_render_pass == current_frame()->root_render_pass; + const SkMatrix44& output_color_matrix = output_surface_->color_matrix(); + return is_root_render_pass && !output_color_matrix.isIdentity(); +} + void GLRenderer::AllocateRenderPassResourceIfNeeded( const AggregatedRenderPassId& render_pass_id, const RenderPassRequirements& requirements) {
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h index 81901243..e668d91 100644 --- a/components/viz/service/display/gl_renderer.h +++ b/components/viz/service/display/gl_renderer.h
@@ -370,6 +370,8 @@ ResourceFormat CurrentRenderPassResourceFormat() const; + bool HasOutputColorMatrix() const; + // A map from RenderPass id to the texture used to draw the RenderPass from. base::flat_map<AggregatedRenderPassId, ScopedRenderPassTexture> render_pass_textures_;
diff --git a/components/viz/service/display/gl_renderer_copier.cc b/components/viz/service/display/gl_renderer_copier.cc index cb8fc93..115f0535 100644 --- a/components/viz/service/display/gl_renderer_copier.cc +++ b/components/viz/service/display/gl_renderer_copier.cc
@@ -28,8 +28,6 @@ #include "third_party/libyuv/include/libyuv/planar_functions.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkImageInfo.h" -#include "ui/gfx/color_space.h" -#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" // Syntactic sugar to DCHECK that two sizes are equal. @@ -108,11 +106,9 @@ } // namespace -GLRendererCopier::GLRendererCopier( - scoped_refptr<ContextProvider> context_provider, - TextureDeleter* texture_deleter) - : context_provider_(std::move(context_provider)), - texture_deleter_(texture_deleter) {} +GLRendererCopier::GLRendererCopier(ContextProvider* context_provider, + TextureDeleter* texture_deleter) + : context_provider_(context_provider), texture_deleter_(texture_deleter) {} GLRendererCopier::~GLRendererCopier() { for (auto& entry : cache_) @@ -373,27 +369,43 @@ namespace { +// This is the type of CopyOutputResult we send for RGBA readback. The +// constructor is called during on GLRendererCopier::FinishReadPixelsWorkflow(), +// thus it always have access to the GLContext. The ReadRGBAPlane and destructor +// are called asynchronously, and thus might not have access to the GLContext if +// it has been destroyed in the meantime. We use the WeakPtr to the +// GLRendererCopier as an indicator that the GLContext is still alive. If the +// access to the GLContext is lost, we treat the copy output as failed. class GLPixelBufferRGBAResult : public CopyOutputResult { public: GLPixelBufferRGBAResult(const gfx::Rect& result_rect, const gfx::ColorSpace& color_space, - scoped_refptr<ContextProvider> context_provider, + base::WeakPtr<GLRendererCopier> copier_weak_ptr, + ContextProvider* context_provider, GLuint transfer_buffer, bool is_upside_down, bool swap_red_and_blue) : CopyOutputResult(CopyOutputResult::Format::RGBA_BITMAP, result_rect), color_space_(color_space), + copier_weak_ptr_(std::move(copier_weak_ptr)), context_provider_(std::move(context_provider)), transfer_buffer_(transfer_buffer), is_upside_down_(is_upside_down), swap_red_and_blue_(swap_red_and_blue) {} ~GLPixelBufferRGBAResult() final { - if (transfer_buffer_) + if (transfer_buffer_ && copier_weak_ptr_) { context_provider_->ContextGL()->DeleteBuffers(1, &transfer_buffer_); + } } bool ReadRGBAPlane(uint8_t* dest, int stride) const final { + // If the GLRendererCopier is gone, this implies the display compositor + // which contains the GLContext is gone. Regard this copy output readback as + // failed. + if (!copier_weak_ptr_) + return false; + const int src_bytes_per_row = size().width() * kRGBABytesPerPixel; DCHECK_GE(stride, src_bytes_per_row); @@ -434,6 +446,10 @@ gfx::ColorSpace GetRGBAColorSpace() const final { return color_space_; } + // This method is always called on the same sequence as the GLRendererCopier. + // This method will be inside Viz and has access to the WeakPtr of the + // GLRendererCopier to check whether we still have the access to an alive + // GLContext. const SkBitmap& AsSkBitmap() const final { if (rect().IsEmpty()) return *cached_bitmap(); // Return "null" bitmap for empty result. @@ -441,7 +457,9 @@ if (cached_bitmap()->readyToDraw()) return *cached_bitmap(); - DCHECK(context_provider_); + if (!copier_weak_ptr_) + return *cached_bitmap(); + SkBitmap result_bitmap; // size() was clamped to render pass or framebuffer size. If we can't // allocate it then OOM. @@ -458,114 +476,86 @@ context_provider_->ContextGL()->DeleteBuffers(1, &transfer_buffer_); transfer_buffer_ = 0; - // We don't need context provider anymore. If these CopyOutputResults will - // be sent to different thread we might end holding last reference to - // context provider, so drop it now. - context_provider_.reset(); - return *cached_bitmap(); } private: const gfx::ColorSpace color_space_; - mutable scoped_refptr<ContextProvider> context_provider_; + base::WeakPtr<GLRendererCopier> copier_weak_ptr_; + ContextProvider* context_provider_; mutable GLuint transfer_buffer_; const bool is_upside_down_; const bool swap_red_and_blue_; }; - -// Manages the execution of one asynchronous framebuffer readback and contains -// all the relevant state needed to complete a copy request. The constructor -// initiates the operation, and then at some later point either: 1) the Finish() -// method is invoked; or 2) the instance will be destroyed (cancelled) because -// the GL context is going away. Either way, the GL objects created for this -// workflow are properly cleaned-up. -// -// Motivation: In case #2, it's possible GLRendererCopier will have been -// destroyed before Finish(). However, since there are no dependencies on -// GLRendererCopier to finish the copy request, there's no reason to mess around -// with a complex WeakPtr-to-GLRendererCopier scheme. -class ReadPixelsWorkflow { - public: - // Saves all revelant state and initiates the GL asynchronous read-pixels - // workflow. - ReadPixelsWorkflow(std::unique_ptr<CopyOutputRequest> copy_request, - const gfx::Vector2d& readback_offset, - bool flipped_source, - bool swap_red_and_blue, - const gfx::Rect& result_rect, - const gfx::ColorSpace& color_space, - scoped_refptr<ContextProvider> context_provider, - GLenum readback_format) - : copy_request_(std::move(copy_request)), - flipped_source_(flipped_source), - swap_red_and_blue_(swap_red_and_blue), - result_rect_(result_rect), - color_space_(color_space), - context_provider_(std::move(context_provider)) { - DCHECK(readback_format == GL_RGBA || readback_format == GL_BGRA_EXT); - - auto* const gl = context_provider_->ContextGL(); - - // Create a buffer for the pixel transfer. - gl->GenBuffers(1, &transfer_buffer_); - gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_); - gl->BufferData( - GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, - (result_rect.size().GetCheckedArea() * kRGBABytesPerPixel).ValueOrDie(), - nullptr, GL_STREAM_READ); - - // Execute an asynchronous read-pixels operation, with a query that triggers - // when Finish() should be run. - gl->GenQueriesEXT(1, &query_); - gl->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, query_); - gl->ReadPixels(readback_offset.x(), readback_offset.y(), - result_rect.width(), result_rect.height(), readback_format, - GL_UNSIGNED_BYTE, nullptr); - gl->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); - gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); - } - - // The destructor is called when the callback that owns this instance is - // destroyed. That will happen either with or without a call to Finish(), - // but either way everything will be clean-up appropriately. - ~ReadPixelsWorkflow() { - auto* const gl = context_provider_->ContextGL(); - gl->DeleteQueriesEXT(1, &query_); - if (transfer_buffer_) - gl->DeleteBuffers(1, &transfer_buffer_); - } - - GLuint query() const { return query_; } - - // Callback for the asynchronous glReadPixels(). The pixels are read from the - // transfer buffer, and a CopyOutputResult is sent to the requestor. - void Finish() { - auto result = std::make_unique<GLPixelBufferRGBAResult>( - result_rect_, color_space_, context_provider_, transfer_buffer_, - flipped_source_, swap_red_and_blue_); - transfer_buffer_ = 0; // Ownerhip was transferred to the result. - if (!copy_request_->SendsResultsInCurrentSequence()) { - // Force readback into a SkBitmap now, because after PostTask we don't - // have access to |context_provider_|. - result->AsSkBitmap(); - } - copy_request_->SendResult(std::move(result)); - } - - private: - const std::unique_ptr<CopyOutputRequest> copy_request_; - const bool flipped_source_; - const bool swap_red_and_blue_; - const gfx::Rect result_rect_; - const gfx::ColorSpace color_space_; - const scoped_refptr<ContextProvider> context_provider_; - GLuint transfer_buffer_ = 0; - GLuint query_ = 0; -}; - } // namespace +GLRendererCopier::ReadPixelsWorkflow::ReadPixelsWorkflow( + std::unique_ptr<CopyOutputRequest> copy_request, + const gfx::Vector2d& readback_offset, + bool flipped_source, + bool swap_red_and_blue, + const gfx::Rect& result_rect, + const gfx::ColorSpace& color_space, + ContextProvider* context_provider, + GLenum readback_format) + : copy_request(std::move(copy_request)), + flipped_source(flipped_source), + swap_red_and_blue(swap_red_and_blue), + result_rect(result_rect), + color_space(color_space), + context_provider_(context_provider) { + DCHECK(readback_format == GL_RGBA || readback_format == GL_BGRA_EXT); + DCHECK(context_provider_); + auto* const gl = context_provider_->ContextGL(); + + // Create a buffer for the pixel transfer. + gl->GenBuffers(1, &transfer_buffer); + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer); + gl->BufferData( + GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, + (result_rect.size().GetCheckedArea() * kRGBABytesPerPixel).ValueOrDie(), + nullptr, GL_STREAM_READ); + + // Execute an asynchronous read-pixels operation, with a query that triggers + // when Finish() should be run. + gl->GenQueriesEXT(1, &query_); + gl->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, query_); + gl->ReadPixels(readback_offset.x(), readback_offset.y(), result_rect.width(), + result_rect.height(), readback_format, GL_UNSIGNED_BYTE, + nullptr); + gl->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); +} + +GLRendererCopier::ReadPixelsWorkflow::~ReadPixelsWorkflow() { + auto* const gl = context_provider_->ContextGL(); + gl->DeleteQueriesEXT(1, &query_); + if (transfer_buffer) + gl->DeleteBuffers(1, &transfer_buffer); +} + +// Callback for the asynchronous glReadPixels(). The pixels are read from the +// transfer buffer, and a CopyOutputResult is sent to the requestor. This would +// mark this workflow as finished, and the workflow will be cleared later. +void GLRendererCopier::FinishReadPixelsWorkflow(ReadPixelsWorkflow* workflow) { + auto result = std::make_unique<GLPixelBufferRGBAResult>( + workflow->result_rect, workflow->color_space, weak_factory_.GetWeakPtr(), + context_provider_, workflow->transfer_buffer, workflow->flipped_source, + workflow->swap_red_and_blue); + workflow->transfer_buffer = 0; // Ownerhip was transferred to the result. + if (!workflow->copy_request->SendsResultsInCurrentSequence()) { + // Force readback into a SkBitmap now, because after PostTask we don't + // have access to |context_provider_|. + result->AsSkBitmap(); + } + workflow->copy_request->SendResult(std::move(result)); + const auto it = + std::find_if(read_pixels_workflows_.begin(), read_pixels_workflows_.end(), + [workflow](auto& ptr) { return ptr.get() == workflow; }); + DCHECK(it != read_pixels_workflows_.end()); + read_pixels_workflows_.erase(it); +} + void GLRendererCopier::StartReadbackFromFramebuffer( std::unique_ptr<CopyOutputRequest> request, const gfx::Vector2d& readback_offset, @@ -575,13 +565,15 @@ const gfx::ColorSpace& color_space) { DCHECK_EQ(request->result_format(), ResultFormat::RGBA_BITMAP); - auto workflow = std::make_unique<ReadPixelsWorkflow>( + read_pixels_workflows_.emplace_back(std::make_unique<ReadPixelsWorkflow>( std::move(request), readback_offset, flipped_source, ShouldSwapRedAndBlueForBitmapReadback() != swapped_red_and_blue, - result_rect, color_space, context_provider_, GetOptimalReadbackFormat()); - const GLuint query = workflow->query(); + result_rect, color_space, context_provider_, GetOptimalReadbackFormat())); context_provider_->ContextSupport()->SignalQuery( - query, base::BindOnce(&ReadPixelsWorkflow::Finish, std::move(workflow))); + read_pixels_workflows_.back()->query(), + base::BindOnce(&GLRendererCopier::FinishReadPixelsWorkflow, + weak_factory_.GetWeakPtr(), + read_pixels_workflows_.back().get())); } void GLRendererCopier::RenderAndSendTextureResult( @@ -636,14 +628,15 @@ public: // |aligned_rect| identifies the region of result pixels in the pixel buffer, // while the |result_rect| is the subregion that is exposed to the client. - GLPixelBufferI420Result( - const gfx::Rect& aligned_rect, - const gfx::Rect& result_rect, - scoped_refptr<ContextProvider> context_provider, - GLuint transfer_buffer) + GLPixelBufferI420Result(const gfx::Rect& aligned_rect, + const gfx::Rect& result_rect, + base::WeakPtr<GLRendererCopier> copier_weak_ptr, + ContextProvider* context_provider, + GLuint transfer_buffer) : CopyOutputResult(CopyOutputResult::Format::I420_PLANES, result_rect), aligned_rect_(aligned_rect), - context_provider_(std::move(context_provider)), + copier_weak_ptr_(copier_weak_ptr), + context_provider_(context_provider), transfer_buffer_(transfer_buffer) { auto* const gl = context_provider_->ContextGL(); gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_); @@ -653,11 +646,13 @@ } ~GLPixelBufferI420Result() final { - auto* const gl = context_provider_->ContextGL(); - gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_); - gl->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); - gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); - gl->DeleteBuffers(1, &transfer_buffer_); + if (copier_weak_ptr_) { + auto* const gl = context_provider_->ContextGL(); + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_); + gl->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); + gl->DeleteBuffers(1, &transfer_buffer_); + } } bool ReadI420Planes(uint8_t* y_out, @@ -670,6 +665,8 @@ const int chroma_row_bytes = (size().width() + 1) / 2; DCHECK_GE(u_out_stride, chroma_row_bytes); DCHECK_GE(v_out_stride, chroma_row_bytes); + if (!copier_weak_ptr_) + return false; uint8_t* pixels = pixels_; if (pixels) { @@ -696,131 +693,98 @@ private: const gfx::Rect aligned_rect_; - const scoped_refptr<ContextProvider> context_provider_; + base::WeakPtr<GLRendererCopier> copier_weak_ptr_; + ContextProvider* const context_provider_; const GLuint transfer_buffer_; uint8_t* pixels_; }; - -// Like the ReadPixelsWorkflow, except for I420 planes readback. Because there -// are three separate glReadPixels operations that may complete in any order, a -// ReadI420PlanesWorkflow will receive notifications from three separate "GL -// query" callbacks. It is only after all three operations have completed that a -// fully-assembled CopyOutputResult can be sent. -// -// Please see class comments for ReadPixelsWorkflow for discussion about how GL -// context loss is handled during the workflow. -// -// Also, see class comments for GLI420Converter for an explanation of how planar -// data is packed into RGBA textures. -class ReadI420PlanesWorkflow - : public base::RefCountedThreadSafe<ReadI420PlanesWorkflow> { - public: - ReadI420PlanesWorkflow( - std::unique_ptr<CopyOutputRequest> copy_request, - const gfx::Rect& aligned_rect, - const gfx::Rect& result_rect, - scoped_refptr<ContextProvider> context_provider) - : copy_request_(std::move(copy_request)), - aligned_rect_(aligned_rect), - result_rect_(result_rect), - context_provider_(std::move(context_provider)) { - // Create a buffer for the pixel transfer: A single buffer is used and will - // contain the Y plane, then the U plane, then the V plane. - auto* const gl = context_provider_->ContextGL(); - gl->GenBuffers(1, &transfer_buffer_); - gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_); - base::CheckedNumeric<int> y_plane_bytes = - y_texture_size().GetCheckedArea() * kRGBABytesPerPixel; - base::CheckedNumeric<int> chroma_plane_bytes = - chroma_texture_size().GetCheckedArea() * kRGBABytesPerPixel; - gl->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, - (y_plane_bytes + chroma_plane_bytes * 2).ValueOrDie(), - nullptr, GL_STREAM_READ); - data_offsets_ = {0, y_plane_bytes.ValueOrDie(), - (y_plane_bytes + chroma_plane_bytes).ValueOrDie()}; - gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); - - // Generate the three queries used for determining when each of the plane - // readbacks has completed. - gl->GenQueriesEXT(3, queries_.data()); - } - - void BindTransferBuffer() { - DCHECK_NE(transfer_buffer_, 0u); - context_provider_->ContextGL()->BindBuffer( - GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_); - } - - void StartPlaneReadback(int plane, GLenum readback_format) { - DCHECK_NE(queries_[plane], 0u); - auto* const gl = context_provider_->ContextGL(); - gl->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, queries_[plane]); - const gfx::Size& size = - plane == 0 ? y_texture_size() : chroma_texture_size(); - // Note: While a PIXEL_PACK_BUFFER is bound, OpenGL interprets the last - // argument to ReadPixels() as a byte offset within the buffer instead of - // an actual pointer in system memory. - uint8_t* offset_in_buffer = 0; - offset_in_buffer += data_offsets_[plane]; - gl->ReadPixels(0, 0, size.width(), size.height(), readback_format, - GL_UNSIGNED_BYTE, offset_in_buffer); - gl->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); - context_provider_->ContextSupport()->SignalQuery( - queries_[plane], - base::BindOnce(&ReadI420PlanesWorkflow::OnFinishedPlane, this, plane)); - } - - void UnbindTransferBuffer() { - context_provider_->ContextGL()->BindBuffer( - GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); - } - - private: - friend class base::RefCountedThreadSafe<ReadI420PlanesWorkflow>; - - ~ReadI420PlanesWorkflow() { - auto* const gl = context_provider_->ContextGL(); - if (transfer_buffer_ != 0) - gl->DeleteBuffers(1, &transfer_buffer_); - for (GLuint& query : queries_) { - if (query != 0) - gl->DeleteQueriesEXT(1, &query); - } - } - - gfx::Size y_texture_size() const { - return gfx::Size(aligned_rect_.width() / kRGBABytesPerPixel, - aligned_rect_.height()); - } - - gfx::Size chroma_texture_size() const { - return gfx::Size(aligned_rect_.width() / kRGBABytesPerPixel / 2, - aligned_rect_.height() / 2); - } - - void OnFinishedPlane(int plane) { - context_provider_->ContextGL()->DeleteQueriesEXT(1, &queries_[plane]); - queries_[plane] = 0; - - // If all three readbacks have completed, send the result. - if (queries_ == std::array<GLuint, 3>{{0, 0, 0}}) { - copy_request_->SendResult(std::make_unique<GLPixelBufferI420Result>( - aligned_rect_, result_rect_, context_provider_, transfer_buffer_)); - transfer_buffer_ = 0; // Ownership was transferred to the result. - } - } - - const std::unique_ptr<CopyOutputRequest> copy_request_; - const gfx::Rect aligned_rect_; - const gfx::Rect result_rect_; - const scoped_refptr<ContextProvider> context_provider_; - GLuint transfer_buffer_; - std::array<int, 3> data_offsets_; - std::array<GLuint, 3> queries_; -}; - } // namespace +GLRendererCopier::ReadI420PlanesWorkflow::ReadI420PlanesWorkflow( + std::unique_ptr<CopyOutputRequest> copy_request, + const gfx::Rect& aligned_rect, + const gfx::Rect& result_rect, + base::WeakPtr<GLRendererCopier> copier_weak_ptr, + ContextProvider* context_provider) + : copy_request(std::move(copy_request)), + aligned_rect(aligned_rect), + result_rect(result_rect), + copier_weak_ptr_(copier_weak_ptr), + context_provider_(context_provider) { + // Create a buffer for the pixel transfer: A single buffer is used and will + // contain the Y plane, then the U plane, then the V plane. + auto* const gl = context_provider_->ContextGL(); + gl->GenBuffers(1, &transfer_buffer); + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer); + base::CheckedNumeric<int> y_plane_bytes = + y_texture_size().GetCheckedArea() * kRGBABytesPerPixel; + base::CheckedNumeric<int> chroma_plane_bytes = + chroma_texture_size().GetCheckedArea() * kRGBABytesPerPixel; + gl->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, + (y_plane_bytes + chroma_plane_bytes * 2).ValueOrDie(), nullptr, + GL_STREAM_READ); + data_offsets_ = {0, y_plane_bytes.ValueOrDie(), + (y_plane_bytes + chroma_plane_bytes).ValueOrDie()}; + gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); + + // Generate the three queries used for determining when each of the plane + // readbacks has completed. + gl->GenQueriesEXT(3, queries.data()); +} + +void GLRendererCopier::ReadI420PlanesWorkflow::BindTransferBuffer() { + DCHECK_NE(transfer_buffer, 0u); + context_provider_->ContextGL()->BindBuffer( + GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer); +} + +void GLRendererCopier::ReadI420PlanesWorkflow::StartPlaneReadback( + int plane, + GLenum readback_format) { + DCHECK_NE(queries[plane], 0u); + auto* const gl = context_provider_->ContextGL(); + gl->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, queries[plane]); + const gfx::Size& size = plane == 0 ? y_texture_size() : chroma_texture_size(); + // Note: While a PIXEL_PACK_BUFFER is bound, OpenGL interprets the last + // argument to ReadPixels() as a byte offset within the buffer instead of + // an actual pointer in system memory. + uint8_t* offset_in_buffer = reinterpret_cast<uint8_t*>(/* byte_offset = */ 0); + offset_in_buffer += data_offsets_[plane]; + gl->ReadPixels(0, 0, size.width(), size.height(), readback_format, + GL_UNSIGNED_BYTE, offset_in_buffer); + gl->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); + context_provider_->ContextSupport()->SignalQuery( + queries[plane], + base::BindOnce(&GLRendererCopier::FinishReadI420PlanesWorkflow, + copier_weak_ptr_, this, plane)); +} + +void GLRendererCopier::ReadI420PlanesWorkflow::UnbindTransferBuffer() { + context_provider_->ContextGL()->BindBuffer( + GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); +} + +GLRendererCopier::ReadI420PlanesWorkflow::~ReadI420PlanesWorkflow() { + auto* const gl = context_provider_->ContextGL(); + if (transfer_buffer != 0) + gl->DeleteBuffers(1, &transfer_buffer); + for (GLuint& query : queries) { + if (query != 0) + gl->DeleteQueriesEXT(1, &query); + } +} + +gfx::Size GLRendererCopier::ReadI420PlanesWorkflow::y_texture_size() const { + return gfx::Size(aligned_rect.width() / kRGBABytesPerPixel, + aligned_rect.height()); +} + +gfx::Size GLRendererCopier::ReadI420PlanesWorkflow::chroma_texture_size() + const { + return gfx::Size(aligned_rect.width() / kRGBABytesPerPixel / 2, + aligned_rect.height() / 2); +} + void GLRendererCopier::StartI420ReadbackFromTextures( std::unique_ptr<CopyOutputRequest> request, const gfx::Rect& aligned_rect, @@ -835,8 +799,10 @@ // Execute three asynchronous read-pixels operations, one for each plane. The // CopyOutputRequest is passed to the ReadI420PlanesWorkflow, which will send // the CopyOutputResult once all readback operations are complete. - const auto workflow = base::MakeRefCounted<ReadI420PlanesWorkflow>( - std::move(request), aligned_rect, result_rect, context_provider_); + read_i420_workflows_.emplace_back(std::make_unique<ReadI420PlanesWorkflow>( + std::move(request), aligned_rect, result_rect, weak_factory_.GetWeakPtr(), + context_provider_)); + ReadI420PlanesWorkflow* workflow = read_i420_workflows_.back().get(); workflow->BindTransferBuffer(); for (int plane = 0; plane < 3; ++plane) { gl->BindFramebuffer(GL_FRAMEBUFFER, @@ -848,6 +814,29 @@ workflow->UnbindTransferBuffer(); } +void GLRendererCopier::FinishReadI420PlanesWorkflow( + ReadI420PlanesWorkflow* workflow, + int plane) { + context_provider_->ContextGL()->DeleteQueriesEXT(1, + &workflow->queries[plane]); + workflow->queries[plane] = 0; + + // If all three readbacks have completed, send the result. + if (workflow->queries == std::array<GLuint, 3>{{0, 0, 0}}) { + workflow->copy_request->SendResult( + std::make_unique<GLPixelBufferI420Result>( + workflow->aligned_rect, workflow->result_rect, + weak_factory_.GetWeakPtr(), context_provider_, + workflow->transfer_buffer)); + workflow->transfer_buffer = 0; // Ownership was transferred to the result. + const auto it = + std::find_if(read_i420_workflows_.begin(), read_i420_workflows_.end(), + [workflow](auto& ptr) { return ptr.get() == workflow; }); + DCHECK(it != read_i420_workflows_.end()); + read_i420_workflows_.erase(it); + } +} + std::unique_ptr<GLRendererCopier::ReusableThings> GLRendererCopier::TakeReusableThingsOrCreate( const base::UnguessableToken& requester) {
diff --git a/components/viz/service/display/gl_renderer_copier.h b/components/viz/service/display/gl_renderer_copier.h index 57eba45..0f9a904 100644 --- a/components/viz/service/display/gl_renderer_copier.h +++ b/components/viz/service/display/gl_renderer_copier.h
@@ -9,6 +9,7 @@ #include <array> #include <memory> +#include <vector> #include "base/callback.h" #include "base/containers/flat_map.h" @@ -17,6 +18,8 @@ #include "base/task_runner.h" #include "base/unguessable_token.h" #include "components/viz/service/viz_service_export.h" +#include "ui/gfx/color_space.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" namespace gfx { @@ -66,8 +69,8 @@ using GLuint = unsigned int; using GLenum = unsigned int; - // |texture_deleter| must outlive this instance. - GLRendererCopier(scoped_refptr<ContextProvider> context_provider, + // |context_provider| and |texture_deleter| must outlive this instance. + GLRendererCopier(ContextProvider* context_provider, TextureDeleter* texture_deleter); ~GLRendererCopier(); @@ -141,6 +144,44 @@ DISALLOW_COPY_AND_ASSIGN(ReusableThings); }; + // Manages the execution of one asynchronous framebuffer readback and contains + // all the relevant state needed to complete a copy request. The constructor + // initiates the operation, and the destructor cleans up all the GL objects + // created for this workflow. This class is owned by the GLRendererCopier, and + // GLRendererCopier is responsible for deleting this either after the workflow + // is finished, or when the GLRendererCopier is being destroyed. + struct ReadPixelsWorkflow { + public: + // Saves all revelant state and initiates the GL asynchronous read-pixels + // workflow. + ReadPixelsWorkflow(std::unique_ptr<CopyOutputRequest> copy_request, + const gfx::Vector2d& readback_offset, + bool flipped_source, + bool swap_red_and_blue, + const gfx::Rect& result_rect, + const gfx::ColorSpace& color_space, + ContextProvider* context_provider, + GLenum readback_format); + ReadPixelsWorkflow(const ReadPixelsWorkflow&) = delete; + + // The destructor is by the GLRendererCopier, either called after the + // workflow is finished or when GLRendererCopier is being destoryed. + ~ReadPixelsWorkflow(); + + GLuint query() const { return query_; } + + const std::unique_ptr<CopyOutputRequest> copy_request; + const bool flipped_source; + const bool swap_red_and_blue; + const gfx::Rect result_rect; + const gfx::ColorSpace color_space; + GLuint transfer_buffer = 0; + + private: + ContextProvider* const context_provider_; + GLuint query_ = 0; + }; + // Renders a scaled/transformed copy of a source texture according to the // |request| parameters and other source characteristics. |result_texture| // must be allocated/sized by the caller. For RGBA_BITMAP requests, the image @@ -157,6 +198,43 @@ GLuint result_texture, ReusableThings* things); + // Like the ReadPixelsWorkflow, except for I420 planes readback. Because there + // are three separate glReadPixels operations that may complete in any order, + // a ReadI420PlanesWorkflow will receive notifications from three separate "GL + // query" callbacks. It is only after all three operations have completed that + // a fully-assembled CopyOutputResult can be sent. + // + // See class comments for GLI420Converter for an explanation of how + // planar data is packed into RGBA textures. + struct ReadI420PlanesWorkflow { + public: + ReadI420PlanesWorkflow(std::unique_ptr<CopyOutputRequest> copy_request, + const gfx::Rect& aligned_rect, + const gfx::Rect& result_rect, + base::WeakPtr<GLRendererCopier> copier_weak_ptr, + ContextProvider* context_provider); + + void BindTransferBuffer(); + void StartPlaneReadback(int plane, GLenum readback_format); + void UnbindTransferBuffer(); + + ~ReadI420PlanesWorkflow(); + + const std::unique_ptr<CopyOutputRequest> copy_request; + const gfx::Rect aligned_rect; + const gfx::Rect result_rect; + GLuint transfer_buffer; + std::array<GLuint, 3> queries; + + private: + gfx::Size y_texture_size() const; + gfx::Size chroma_texture_size() const; + + base::WeakPtr<GLRendererCopier> copier_weak_ptr_; + ContextProvider* const context_provider_; + std::array<int, 3> data_offsets_; + }; + // Similar to RenderResultTexture(), except also transform the image into I420 // format (a popular video format). Three textures, representing each of the // Y/U/V planes (as described in GLI420Converter), are populated and their GL @@ -251,8 +329,11 @@ // swap does not need to happen on the CPU (non-negligible cost). bool ShouldSwapRedAndBlueForBitmapReadback(); + void FinishReadPixelsWorkflow(ReadPixelsWorkflow*); + void FinishReadI420PlanesWorkflow(ReadI420PlanesWorkflow*, int plane); + // Injected dependencies. - const scoped_refptr<ContextProvider> context_provider_; + ContextProvider* const context_provider_; TextureDeleter* const texture_deleter_; // This increments by one for every call to FreeUnusedCachedResources(). It @@ -279,6 +360,12 @@ // things to be auto-purged after approx. 1-2 seconds of not being used. static constexpr int kKeepalivePeriod = 60; + std::vector<std::unique_ptr<ReadPixelsWorkflow>> read_pixels_workflows_; + std::vector<std::unique_ptr<ReadI420PlanesWorkflow>> read_i420_workflows_; + + // Weak ptr to this class. + base::WeakPtrFactory<GLRendererCopier> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(GLRendererCopier); };
diff --git a/components/viz/service/display/gl_renderer_copier_perftest.cc b/components/viz/service/display/gl_renderer_copier_perftest.cc index 37069121..6e2edbb 100644 --- a/components/viz/service/display/gl_renderer_copier_perftest.cc +++ b/components/viz/service/display/gl_renderer_copier_perftest.cc
@@ -61,15 +61,15 @@ class GLRendererCopierPerfTest : public testing::Test { public: GLRendererCopierPerfTest() { - auto context_provider = base::MakeRefCounted<TestInProcessContextProvider>( + context_provider_ = base::MakeRefCounted<TestInProcessContextProvider>( /*enable_gpu_rasterization=*/false, /*enable_oop_rasterization=*/false, /*support_locking=*/false); - gpu::ContextResult result = context_provider->BindToCurrentThread(); + gpu::ContextResult result = context_provider_->BindToCurrentThread(); DCHECK_EQ(result, gpu::ContextResult::kSuccess); - gl_ = context_provider->ContextGL(); + gl_ = context_provider_->ContextGL(); texture_deleter_ = std::make_unique<TextureDeleter>(base::ThreadTaskRunnerHandle::Get()); - copier_ = std::make_unique<GLRendererCopier>(std::move(context_provider), + copier_ = std::make_unique<GLRendererCopier>(context_provider_.get(), texture_deleter_.get()); } @@ -259,6 +259,7 @@ private: gpu::gles2::GLES2Interface* gl_ = nullptr; + scoped_refptr<TestInProcessContextProvider> context_provider_; std::unique_ptr<TextureDeleter> texture_deleter_; std::unique_ptr<GLRendererCopier> copier_; GLuint source_texture_ = 0;
diff --git a/components/viz/service/display/gl_renderer_copier_unittest.cc b/components/viz/service/display/gl_renderer_copier_unittest.cc index fb3452b..13fdca6 100644 --- a/components/viz/service/display/gl_renderer_copier_unittest.cc +++ b/components/viz/service/display/gl_renderer_copier_unittest.cc
@@ -62,11 +62,11 @@ using ReusableThings = GLRendererCopier::ReusableThings; void SetUp() override { - auto context_provider = TestContextProvider::Create( + context_provider_ = TestContextProvider::Create( std::make_unique<CopierTestGLES2Interface>()); - context_provider->BindToCurrentThread(); - copier_ = std::make_unique<GLRendererCopier>(std::move(context_provider), - nullptr); + context_provider_->BindToCurrentThread(); + copier_ = + std::make_unique<GLRendererCopier>(context_provider_.get(), nullptr); } void TearDown() override { copier_.reset(); } @@ -102,6 +102,7 @@ static constexpr int kKeepalivePeriod = GLRendererCopier::kKeepalivePeriod; private: + scoped_refptr<ContextProvider> context_provider_; std::unique_ptr<GLRendererCopier> copier_; };
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc index c2d68df..ad04f2a 100644 --- a/components/viz/service/display/gl_renderer_unittest.cc +++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -230,6 +230,7 @@ auto color_transform = gfx::ColorTransform::NewColorTransform( adjusted_color_space, dst_color_space, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); + ASSERT_EQ(color_transform->GetShaderSource(), renderer() ->current_program_->color_transform_for_testing() @@ -237,8 +238,15 @@ } if (validate_output_color_matrix) { - ASSERT_NE( - -1, renderer()->current_program_->output_color_matrix_location()); + if (program_key.type() == ProgramType::PROGRAM_TYPE_SOLID_COLOR) { + ASSERT_EQ( + -1, + renderer()->current_program_->output_color_matrix_location()); + } else { + ASSERT_NE( + -1, + renderer()->current_program_->output_color_matrix_location()); + } } } }
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h index 2772299..35b009a 100644 --- a/components/viz/service/display/output_surface.h +++ b/components/viz/service/display/output_surface.h
@@ -117,13 +117,9 @@ // enforced if zero. int max_render_target_size = 0; - // The SkColorType and GrBackendFormat for non-HDR and HDR. - // TODO(penghuang): remove SkColorType and GrBackendFormat when - // OutputSurface uses the |format| passed to Reshape(). - SkColorType sk_color_type = kUnknown_SkColorType; - GrBackendFormat gr_backend_format; - SkColorType sk_color_type_for_hdr = kUnknown_SkColorType; - GrBackendFormat gr_backend_format_for_hdr; + // SkColorType for all supported buffer formats. + SkColorType sk_color_types[static_cast<int>(gfx::BufferFormat::LAST) + 1] = + {}; }; // Constructor for skia-based compositing.
diff --git a/components/viz/service/display/program_binding.h b/components/viz/service/display/program_binding.h index bba6169e..04b05dd3 100644 --- a/components/viz/service/display/program_binding.h +++ b/components/viz/service/display/program_binding.h
@@ -126,6 +126,8 @@ } TexCoordPrecision tex_coord_precision() const { return precision_; } + ProgramType type() const { return type_; } + private: friend struct ProgramKeyHash; friend class Program;
diff --git a/components/viz/service/display_embedder/output_presenter_fuchsia.cc b/components/viz/service/display_embedder/output_presenter_fuchsia.cc index e1e15de..9d37ed16 100644 --- a/components/viz/service/display_embedder/output_presenter_fuchsia.cc +++ b/components/viz/service/display_embedder/output_presenter_fuchsia.cc
@@ -188,10 +188,10 @@ capabilities->supports_post_sub_buffer = false; capabilities->supports_commit_overlay_planes = false; - capabilities->sk_color_type = kRGBA_8888_SkColorType; - capabilities->gr_backend_format = - dependency_->GetSharedContextState()->gr_context()->defaultBackendFormat( - capabilities->sk_color_type, GrRenderable::kYes); + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + kRGBA_8888_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + kRGBA_8888_SkColorType; } bool OutputPresenterFuchsia::Reshape(const gfx::Size& size,
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc index d0e262d..b74a3f2 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.cc +++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -214,23 +214,6 @@ // GL is origin is at bottom left normally, all Surfaceless implementations // are flipped. DCHECK_EQ(gl_surface_->GetOrigin(), gfx::SurfaceOrigin::kTopLeft); - - // TODO(https://crbug.com/958166): The initial |image_format_| should not be - // used, and the gfx::BufferFormat specified in Reshape should be used - // instead, because it may be updated to reflect changes in the content being - // displayed (e.g, HDR content appearing on-screen). -#if defined(OS_APPLE) - image_format_ = BGRA_8888; -#else -#if defined(USE_OZONE) - if (features::IsUsingOzonePlatform()) { - image_format_ = - GetResourceFormat(display::DisplaySnapshot::PrimaryFormat()); - return; - } -#endif - image_format_ = RGBA_8888; -#endif } OutputPresenterGL::~OutputPresenterGL() = default; @@ -247,13 +230,28 @@ // We expect origin of buffers is at top left. capabilities->output_surface_origin = gfx::SurfaceOrigin::kTopLeft; - // TODO(penghuang): Use defaultBackendFormat() in shared image implementation - // to make sure backend format is consistent. - capabilities->sk_color_type = ResourceFormatToClosestSkColorType( - true /* gpu_compositing */, image_format_); - capabilities->gr_backend_format = - dependency_->GetSharedContextState()->gr_context()->defaultBackendFormat( - capabilities->sk_color_type, GrRenderable::kYes); + // TODO(https://crbug.com/1108406): only add supported formats base on + // platform, driver, etc. + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::BGR_565)] = + kRGB_565_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_4444)] = + kARGB_4444_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = + kRGB_888x_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + kRGBA_8888_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = + kBGRA_8888_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + kBGRA_8888_SkColorType; + capabilities + ->sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_1010102)] = + kBGRA_1010102_SkColorType; + capabilities + ->sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_1010102)] = + kRGBA_1010102_SkColorType; + capabilities->sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_F16)] = + kRGBA_F16_SkColorType; } bool OutputPresenterGL::Reshape(const gfx::Size& size, @@ -261,6 +259,7 @@ const gfx::ColorSpace& color_space, gfx::BufferFormat format, gfx::OverlayTransform transform) { + image_format_ = GetResourceFormat(format); return gl_surface_->Resize(size, device_scale_factor, color_space, gfx::AlphaBitsForBufferFormat(format)); }
diff --git a/components/viz/service/display_embedder/output_presenter_gl.h b/components/viz/service/display_embedder/output_presenter_gl.h index bfbf5199..66cc8ce9 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.h +++ b/components/viz/service/display_embedder/output_presenter_gl.h
@@ -65,7 +65,7 @@ SkiaOutputSurfaceDependency* dependency_; const bool supports_async_swap_; - ResourceFormat image_format_; + ResourceFormat image_format_ = RGBA_8888; // Shared Image factories gpu::SharedImageFactory shared_image_factory_;
diff --git a/components/viz/service/display_embedder/skia_output_device.cc b/components/viz/service/display_embedder/skia_output_device.cc index ecb8359..fa40e44 100644 --- a/components/viz/service/display_embedder/skia_output_device.cc +++ b/components/viz/service/display_embedder/skia_output_device.cc
@@ -120,6 +120,12 @@ void SkiaOutputDevice::EnsureBackbuffer() {} void SkiaOutputDevice::DiscardBackbuffer() {} +void SkiaOutputDevice::SetDrawTimings(base::TimeTicks submitted, + base::TimeTicks started) { + viz_scheduled_draw_ = submitted; + gpu_started_draw_ = started; +} + void SkiaOutputDevice::StartSwapBuffers(BufferPresentedCallback feedback) { DCHECK_LT(static_cast<int>(pending_swaps_.size()), capabilities_.max_frames_pending); @@ -158,12 +164,6 @@ pending_swaps_.pop(); } -void SkiaOutputDevice::SetDrawTimings(base::TimeTicks submitted, - base::TimeTicks started) { - viz_scheduled_draw_ = submitted; - gpu_started_draw_ = started; -} - SkiaOutputDevice::SwapInfo::SwapInfo( uint64_t swap_id, SkiaOutputDevice::BufferPresentedCallback feedback,
diff --git a/components/viz/service/display_embedder/skia_output_device_dawn.cc b/components/viz/service/display_embedder/skia_output_device_dawn.cc index 2d7317f..084d0f5 100644 --- a/components/viz/service/display_embedder/skia_output_device_dawn.cc +++ b/components/viz/service/display_embedder/skia_output_device_dawn.cc
@@ -44,11 +44,10 @@ capabilities_.uses_default_gl_framebuffer = false; capabilities_.supports_post_sub_buffer = false; - capabilities_.sk_color_type = kSurfaceColorType; - capabilities_.gr_backend_format = - context_provider_->GetGrContext()->defaultBackendFormat( - kSurfaceColorType, GrRenderable::kYes); - + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + kSurfaceColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + kSurfaceColorType; vsync_provider_ = std::make_unique<gl::VSyncProviderWin>(widget); child_window_.Initialize(); }
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc index 1de042f..436d206 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.cc +++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -105,15 +105,20 @@ glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); } CHECK_GL_ERROR(); - supports_alpha_ = alpha_bits > 0; - capabilities_.sk_color_type = - supports_alpha_ ? kRGBA_8888_SkColorType : kRGB_888x_SkColorType; - capabilities_.gr_backend_format = gr_context->defaultBackendFormat( - capabilities_.sk_color_type, GrRenderable::kYes); - capabilities_.sk_color_type_for_hdr = kRGBA_F16_SkColorType; - capabilities_.gr_backend_format_for_hdr = gr_context->defaultBackendFormat( - capabilities_.sk_color_type_for_hdr, GrRenderable::kYes); + auto color_type = + (alpha_bits > 0) ? kRGBA_8888_SkColorType : kRGB_888x_SkColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + color_type; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = + color_type; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + color_type; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = + color_type; + + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_F16)] = + kRGBA_F16_SkColorType; } SkiaOutputDeviceGL::~SkiaOutputDeviceGL() { @@ -140,22 +145,21 @@ framebuffer_info.fFBOID = 0; DCHECK_EQ(gl_surface_->GetBackingFramebufferObject(), 0u); - SkColorType color_type; - // TODO(https://crbug.com/1049334): The pixel format should be determined by - // |buffer_format|, not |color_space|, and not |supports_alpha_|. - if (color_space.IsHDR()) { - color_type = capabilities_.sk_color_type_for_hdr; - framebuffer_info.fFormat = GL_RGBA16F; - DCHECK_EQ(capabilities_.gr_backend_format_for_hdr.asGLFormat(), - GrGLFormat::kRGBA16F); - } else if (supports_alpha_) { - color_type = capabilities_.sk_color_type; - framebuffer_info.fFormat = GL_RGBA8; - DCHECK_EQ(capabilities_.gr_backend_format.asGLFormat(), GrGLFormat::kRGBA8); - } else { - color_type = capabilities_.sk_color_type; - framebuffer_info.fFormat = GL_RGB8; - DCHECK_EQ(capabilities_.gr_backend_format.asGLFormat(), GrGLFormat::kRGB8); + const auto format_index = static_cast<int>(buffer_format); + SkColorType color_type = capabilities_.sk_color_types[format_index]; + switch (color_type) { + case kRGBA_8888_SkColorType: + framebuffer_info.fFormat = GL_RGBA8; + break; + case kRGB_888x_SkColorType: + framebuffer_info.fFormat = GL_RGB8; + break; + case kRGBA_F16_SkColorType: + framebuffer_info.fFormat = GL_RGBA16F; + break; + default: + NOTREACHED() << "color_type: " << color_type + << " buffer_format: " << format_index; } // TODO(kylechar): We might need to support RGB10A2 for HDR10. HDR10 was only // used with Windows updated RS3 (2017) as a workaround for a DWM bug so it
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.h b/components/viz/service/display_embedder/skia_output_device_gl.h index c237b00..db933d9e 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.h +++ b/components/viz/service/display_embedder/skia_output_device_gl.h
@@ -81,7 +81,6 @@ sk_sp<SkSurface> sk_surface_; - bool supports_alpha_ = false; uint64_t backbuffer_estimated_size_ = 0; base::WeakPtrFactory<SkiaOutputDeviceGL> weak_ptr_factory_{this};
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc index 37066fc..a6948f6 100644 --- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -34,10 +34,16 @@ capabilities_.output_surface_origin = origin; capabilities_.supports_post_sub_buffer = true; - capabilities_.sk_color_type = kSurfaceColorType; - capabilities_.gr_backend_format = - context_state_->gr_context()->defaultBackendFormat(kSurfaceColorType, - GrRenderable::kYes); + // TODO(https://crbug.com/1108406): use the right color types base on GPU + // capabilities. + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + kSurfaceColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = + kSurfaceColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + kSurfaceColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] = + kSurfaceColorType; } SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() { @@ -53,6 +59,7 @@ DiscardBackbuffer(); size_ = size; + format_ = format; sk_color_space_ = color_space.ToSkColorSpace(); EnsureBackbuffer(); return true; @@ -82,15 +89,20 @@ if (size_.IsEmpty()) return; + auto format_index = static_cast<int>(format_); + const auto& sk_color_type = capabilities_.sk_color_types[format_index]; + DCHECK(sk_color_type != kUnknown_SkColorType) + << "SkColorType is invalid for format: " << format_index; + if (has_alpha_) { backend_texture_ = context_state_->gr_context()->createBackendTexture( - size_.width(), size_.height(), kSurfaceColorType, GrMipMapped::kNo, + size_.width(), size_.height(), sk_color_type, GrMipMapped::kNo, GrRenderable::kYes); } else { is_emulated_rgbx_ = true; // Initialize alpha channel to opaque. backend_texture_ = context_state_->gr_context()->createBackendTexture( - size_.width(), size_.height(), kSurfaceColorType, SkColors::kBlack, + size_.width(), size_.height(), sk_color_type, SkColors::kBlack, GrMipMapped::kNo, GrRenderable::kYes); } DCHECK(backend_texture_.isValid());
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.h b/components/viz/service/display_embedder/skia_output_device_offscreen.h index 1acc7044..9457d65 100644 --- a/components/viz/service/display_embedder/skia_output_device_offscreen.h +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -51,6 +51,7 @@ private: gfx::Size size_; + gfx::BufferFormat format_ = gfx::BufferFormat::RGBA_8888; uint64_t backbuffer_estimated_size_ = 0; sk_sp<SkColorSpace> sk_color_space_;
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc index 5febb78..d68844e 100644 --- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -318,10 +318,14 @@ const auto surface_format = vulkan_surface_->surface_format().format; DCHECK(surface_format == VK_FORMAT_B8G8R8A8_UNORM || surface_format == VK_FORMAT_R8G8B8A8_UNORM); - capabilities_.sk_color_type = surface_format == VK_FORMAT_R8G8B8A8_UNORM - ? kRGBA_8888_SkColorType - : kBGRA_8888_SkColorType; - capabilities_.gr_backend_format = GrBackendFormat::MakeVk(surface_format); + + auto sk_color_type = surface_format == VK_FORMAT_R8G8B8A8_UNORM + ? kRGBA_8888_SkColorType + : kBGRA_8888_SkColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + sk_color_type; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + sk_color_type; return true; }
diff --git a/components/viz/service/display_embedder/skia_output_device_webview.cc b/components/viz/service/display_embedder/skia_output_device_webview.cc index e2c50ed..74f8c33 100644 --- a/components/viz/service/display_embedder/skia_output_device_webview.cc +++ b/components/viz/service/display_embedder/skia_output_device_webview.cc
@@ -16,6 +16,10 @@ namespace viz { +namespace { +constexpr auto kSurfaceColorType = kRGBA_8888_SkColorType; +} + SkiaOutputDeviceWebView::SkiaOutputDeviceWebView( gpu::SharedContextState* context_state, scoped_refptr<gl::GLSurface> gl_surface, @@ -36,10 +40,10 @@ DCHECK(context_state_->gr_context()); DCHECK(context_state_->context()); - capabilities_.sk_color_type = kRGBA_8888_SkColorType; - capabilities_.gr_backend_format = - context_state_->gr_context()->defaultBackendFormat( - capabilities_.sk_color_type, GrRenderable::kYes); + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = + kSurfaceColorType; + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] = + kSurfaceColorType; } SkiaOutputDeviceWebView::~SkiaOutputDeviceWebView() = default; @@ -100,8 +104,7 @@ GrGLFramebufferInfo framebuffer_info; framebuffer_info.fFBOID = fbo; framebuffer_info.fFormat = GL_RGBA8; - DCHECK_EQ(capabilities_.gr_backend_format.asGLFormat(), GrGLFormat::kRGBA8); - SkColorType color_type = capabilities_.sk_color_type; + SkColorType color_type = kSurfaceColorType; GrBackendRenderTarget render_target(size_.width(), size_.height(), /*sampleCnt=*/0,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index bb4eb79..594dc14 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -236,9 +236,10 @@ color_space_ = color_space; is_hdr_ = color_space_.IsHDR(); size_ = size; + format_ = format; characterization_ = CreateSkSurfaceCharacterization( - size, GetResourceFormat(format), false /* mipmap */, - color_space_.ToSkColorSpace(), true /* is_root_render_pass */); + size, format, false /* mipmap */, color_space_.ToSkColorSpace(), + true /* is_root_render_pass */); RecreateRootRecorder(); } @@ -289,8 +290,8 @@ nway_canvas_->addCanvas(current_paint_->recorder()->getCanvas()); SkSurfaceCharacterization characterization = CreateSkSurfaceCharacterization( - gfx::Size(characterization_.width(), characterization_.height()), - BGRA_8888, false /* mipmap */, characterization_.refColorSpace(), + gfx::Size(characterization_.width(), characterization_.height()), format_, + false /* mipmap */, characterization_.refColorSpace(), false /* is_root_render_pass */); if (characterization.isValid()) { overdraw_surface_recorder_.emplace(characterization); @@ -493,7 +494,7 @@ DCHECK(resource_sync_tokens_.empty()); SkSurfaceCharacterization characterization = CreateSkSurfaceCharacterization( - surface_size, format, mipmap, std::move(color_space), + surface_size, BufferFormat(format), mipmap, std::move(color_space), false /* is_root_render_pass */); if (!characterization.isValid()) return nullptr; @@ -779,7 +780,7 @@ SkSurfaceCharacterization SkiaOutputSurfaceImpl::CreateSkSurfaceCharacterization( const gfx::Size& surface_size, - ResourceFormat format, + gfx::BufferFormat format, bool mipmap, sk_sp<SkColorSpace> color_space, bool is_root_render_pass) { @@ -791,15 +792,15 @@ SkSurfaceProps surface_props(0 /*flags */, SkSurfaceProps::kLegacyFontHost_InitType); if (is_root_render_pass) { - auto color_type = - is_hdr_ && capabilities_.sk_color_type_for_hdr != kUnknown_SkColorType - ? capabilities_.sk_color_type_for_hdr - : capabilities_.sk_color_type; - - const auto& backend_format = - is_hdr_ && capabilities_.gr_backend_format_for_hdr.isValid() - ? capabilities_.gr_backend_format_for_hdr - : capabilities_.gr_backend_format; + const auto format_index = static_cast<int>(format); + const auto& color_type = capabilities_.sk_color_types[format_index]; + const auto backend_format = gr_context_thread_safe_->defaultBackendFormat( + color_type, GrRenderable::kYes); + DCHECK(color_type != kUnknown_SkColorType) + << "SkColorType is invalid for buffer format_index: " << format_index; + DCHECK(backend_format.isValid()) + << "GrBackendFormat is invalid for buffer format_index: " + << format_index; auto surface_origin = capabilities_.output_surface_origin == gfx::SurfaceOrigin::kBottomLeft ? kBottomLeft_GrSurfaceOrigin @@ -838,8 +839,9 @@ return characterization; } - auto color_type = - ResourceFormatToClosestSkColorType(true /* gpu_compositing */, format); + auto resource_format = GetResourceFormat(format); + auto color_type = ResourceFormatToClosestSkColorType( + true /* gpu_compositing */, resource_format); auto backend_format = gr_context_thread_safe_->defaultBackendFormat( color_type, GrRenderable::kYes); DCHECK(backend_format.isValid());
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index f2abcd6..cff99942 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -159,7 +159,7 @@ bool* result); SkSurfaceCharacterization CreateSkSurfaceCharacterization( const gfx::Size& surface_size, - ResourceFormat format, + gfx::BufferFormat format, bool mipmap, sk_sp<SkColorSpace> color_space, bool is_root_render_pass); @@ -202,6 +202,7 @@ gfx::Size size_; gfx::ColorSpace color_space_; + gfx::BufferFormat format_; bool is_hdr_ = false; SkSurfaceCharacterization characterization_; base::Optional<SkDeferredDisplayListRecorder> root_recorder_;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 1635479f..40e29b8 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -365,7 +365,8 @@ #if defined(OS_CHROMEOS) if (chromeos::switches::MemoryPressureHandlingEnabled()) monitor = std::make_unique<util::MultiSourceMemoryPressureMonitor>(); -#elif defined(OS_MAC) || defined(OS_WIN) || defined(OS_FUCHSIA) +#elif defined(OS_MAC) || defined(OS_WIN) || defined(OS_FUCHSIA) || \ + (defined(OS_LINUX) && !defined(OS_CHROMEOS)) monitor = std::make_unique<util::MultiSourceMemoryPressureMonitor>(); #endif // No memory monitor on other platforms...
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h index c934841..32682547 100644 --- a/content/browser/frame_host/render_frame_host_delegate.h +++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -359,7 +359,8 @@ // coordinate space. virtual void OnFocusedElementChangedInFrame( RenderFrameHostImpl* frame, - const gfx::Rect& bounds_in_root_view) {} + const gfx::Rect& bounds_in_root_view, + blink::mojom::FocusType focus_type) {} // The page is trying to open a new page (e.g. a popup window). The window // should be created associated the process of |opener|, but it should not
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 7836afd..3936083 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4510,16 +4510,19 @@ void RenderFrameHostImpl::FocusedElementChanged( bool is_editable_element, - const gfx::Rect& bounds_in_frame_widget) { + const gfx::Rect& bounds_in_frame_widget, + blink::mojom::FocusType focus_type) { if (!GetView()) return; has_focused_editable_element_ = is_editable_element; // First convert the bounds to root view. delegate_->OnFocusedElementChangedInFrame( - this, gfx::Rect(GetView()->TransformPointToRootCoordSpace( - bounds_in_frame_widget.origin()), - bounds_in_frame_widget.size())); + this, + gfx::Rect(GetView()->TransformPointToRootCoordSpace( + bounds_in_frame_widget.origin()), + bounds_in_frame_widget.size()), + focus_type); } void RenderFrameHostImpl::DidReceiveFirstUserActivation() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 88ef3e7..4b90c78 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1619,7 +1619,8 @@ std::vector<blink::mojom::FaviconURLPtr> favicon_urls) override; void DownloadURL(blink::mojom::DownloadURLParamsPtr params) override; void FocusedElementChanged(bool is_editable_element, - const gfx::Rect& bounds_in_frame_widget) override; + const gfx::Rect& bounds_in_frame_widget, + blink::mojom::FocusType focus_type) override; void ShowPopupMenu( mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client, const gfx::Rect& bounds,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index f9cb56fd..ecc7332 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -6957,7 +6957,8 @@ void WebContentsImpl::OnFocusedElementChangedInFrame( RenderFrameHostImpl* frame, - const gfx::Rect& bounds_in_root_view) { + const gfx::Rect& bounds_in_root_view, + blink::mojom::FocusType focus_type) { RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView()); if (!root_view || !frame->GetView()) @@ -6972,7 +6973,7 @@ bounds_in_screen); FocusedNodeDetails details = {frame->has_focused_editable_element(), - bounds_in_screen}; + bounds_in_screen, focus_type}; // TODO(ekaramad): We should replace this with an observer notification // (https://crbug.com/675975).
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 85985f23..e2a8d8c8 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -644,7 +644,8 @@ RenderFrameHost* GetFocusedFrameIncludingInnerWebContents() override; void OnFocusedElementChangedInFrame( RenderFrameHostImpl* frame, - const gfx::Rect& bounds_in_root_view) override; + const gfx::Rect& bounds_in_root_view, + blink::mojom::FocusType focus_type) override; void OnAdvanceFocus(RenderFrameHostImpl* source_rfh) override; RenderFrameHostDelegate* CreateNewWindow( RenderFrameHost* opener,
diff --git a/content/browser/web_contents/web_contents_observer_browsertest.cc b/content/browser/web_contents/web_contents_observer_browsertest.cc index cf382d66..643c68e 100644 --- a/content/browser/web_contents/web_contents_observer_browsertest.cc +++ b/content/browser/web_contents/web_contents_observer_browsertest.cc
@@ -8,6 +8,7 @@ #include "content/browser/service_worker/embedded_worker_status.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/allow_service_worker_result.h" +#include "content/public/browser/focused_node_details.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/content_client.h" @@ -610,4 +611,41 @@ cookie_tracker.cookie_accesses().clear(); } +namespace { + +class FocusedNodeObserver : public WebContentsObserver { + public: + explicit FocusedNodeObserver(WebContentsImpl* web_contents) + : WebContentsObserver(web_contents) {} + + blink::mojom::FocusType last_focus_type() const { return last_focus_type_; } + + void WaitForFocusChangedInPage() { run_loop_.Run(); } + + // WebContentsObserver: + void OnFocusChangedInPage(FocusedNodeDetails* details) override { + last_focus_type_ = details->focus_type; + run_loop_.Quit(); + } + + private: + base::RunLoop run_loop_; + blink::mojom::FocusType last_focus_type_; +}; + +// Tests that the focus type is reported correctly in FocusedNodeDetails when +// WebContentsObserver::OnFocusChangedInPage() is called. +IN_PROC_BROWSER_TEST_F(WebContentsObserverBrowserTest, + OnFocusChangedInPageFocusType) { + FocusedNodeObserver observer(web_contents()); + GURL url(embedded_test_server()->GetURL("/form_that_posts_cross_site.html")); + + EXPECT_TRUE(NavigateToURL(web_contents(), url)); + SimulateMouseClickOrTapElementWithId(web_contents(), "text"); + observer.WaitForFocusChangedInPage(); + EXPECT_EQ(blink::mojom::FocusType::kMouse, observer.last_focus_type()); +} + +} // namespace + } // namespace content
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index f5e7b729..f47393b 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -217,6 +217,7 @@ {wf::EnableWebXRHitTest, features::kWebXrHitTest, kUseFeatureState}, {wf::EnableWebXRAnchors, features::kWebXrIncubations, kEnableOnly}, {wf::EnableWebXRCameraAccess, features::kWebXrIncubations, kEnableOnly}, + {wf::EnableWebXRDepth, features::kWebXrIncubations, kEnableOnly}, {wf::EnableWebXRLightEstimation, features::kWebXrIncubations, kEnableOnly}, {wf::EnableWebXRPlaneDetection, features::kWebXrIncubations, kEnableOnly}, {wf::EnableWebXRReflectionEstimation, features::kWebXrIncubations, @@ -604,6 +605,8 @@ // these features. if (enable_experimental_web_platform_features) { WebRuntimeFeatures::EnableNetInfoDownlinkMax(true); + WebRuntimeFeatures::EnableSignedExchangePrefetchCacheForNavigations(true); + WebRuntimeFeatures::EnableSignedExchangeSubresourcePrefetch(true); } if (enable_blink_test_features) {
diff --git a/content/public/browser/focused_node_details.h b/content/public/browser/focused_node_details.h index 6870bc4..0d5a5a2 100644 --- a/content/public/browser/focused_node_details.h +++ b/content/public/browser/focused_node_details.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_PUBLIC_BROWSER_FOCUSED_NODE_DETAILS_H_ #define CONTENT_PUBLIC_BROWSER_FOCUSED_NODE_DETAILS_H_ +#include "third_party/blink/public/mojom/input/focus_type.mojom.h" #include "ui/gfx/geometry/rect.h" namespace content { @@ -12,6 +13,7 @@ struct FocusedNodeDetails { bool is_editable_node; gfx::Rect node_bounds_in_screen; + blink::mojom::FocusType focus_type; }; } // namespace content
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 6fdee39..e7efa714 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -841,6 +841,36 @@ ui::LatencyInfo()); } +void SimulateMouseClickOrTapElementWithId(content::WebContents* web_contents, + const std::string& id) { + // Get the center coordinates of the DOM element. + const int x = + content::EvalJs( + web_contents, + content::JsReplace("const bounds = " + "document.getElementById($1)." + "getBoundingClientRect();" + "Math.floor(bounds.left + bounds.width / 2)", + id)) + .ExtractInt(); + const int y = + content::EvalJs( + web_contents, + content::JsReplace("const bounds = " + "document.getElementById($1)." + "getBoundingClientRect();" + "Math.floor(bounds.top + bounds.height / 2)", + id)) + .ExtractInt(); +#if defined(OS_ANDROID) + content::SimulateTapDownAt(web_contents, gfx::Point(x, y)); + content::SimulateTapAt(web_contents, gfx::Point(x, y)); +#else + content::SimulateMouseClickAt( + web_contents, 0, blink::WebMouseEvent::Button::kLeft, gfx::Point(x, y)); +#endif // defined(OS_ANDROID) +} + void SendMouseDownToWidget(RenderWidgetHost* target, int modifiers, blink::WebMouseEvent::Button button) {
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 486af7f..eeaf18a 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -216,6 +216,11 @@ blink::WebMouseEvent::Button button, const gfx::Point& point); +// Retrieves the center coordinates of the element with id |id| and simulates a +// mouse click there using SimulateMouseClickAt(). +void SimulateMouseClickOrTapElementWithId(content::WebContents* web_contents, + const std::string& id); + // Simulates MouseDown at the center of the given RenderWidgetHost's area. // This does not send a corresponding MouseUp. void SendMouseDownToWidget(RenderWidgetHost* target,
diff --git a/content/test/data/form_that_posts_cross_site.html b/content/test/data/form_that_posts_cross_site.html index 44c3bd18..36663ed 100644 --- a/content/test/data/form_that_posts_cross_site.html +++ b/content/test/data/form_that_posts_cross_site.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <head></head> + <meta name="viewport" content="width=device-width"> <body> <form id="text-form" method="POST" action="/cross-site-307/i.com/cross-site-307/x.com/echoall"> <input type="text" id="text" name="text" value="value">
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 53e2fab..3bdd18e7 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -133,6 +133,7 @@ crbug.com/angleproject/4417 [ win d3d11 ] conformance2/rendering/framebuffer-render-to-layer-angle-issue.html [ Failure ] # Intel flaky issues +crbug.com/1122744 [ win d3d11 intel ] conformance/textures/misc/texparameter-test.html [ RetryOnFailure ] crbug.com/912579 [ opengl win passthrough intel ] conformance2/rendering/out-of-bounds-index-buffers-after-copying.html [ RetryOnFailure ] crbug.com/1114780 [ win intel ] deqp/functional/gles3/multisample.html [ RetryOnFailure ] # Flakily times out on driver 26.20.100.8141.
diff --git a/content/test/gpu/run_gpu_integration_test_fuchsia.py b/content/test/gpu/run_gpu_integration_test_fuchsia.py index 972ef55..a7efe4d 100755 --- a/content/test/gpu/run_gpu_integration_test_fuchsia.py +++ b/content/test/gpu/run_gpu_integration_test_fuchsia.py
@@ -27,10 +27,12 @@ args, gpu_test_args = parser.parse_known_args() ConfigureLogging(args) - # If output directory is not set, assume the script is being launched + additional_target_args = {} + + # If output_dir is not set, assume the script is being launched # from the output directory. - if not args.output_directory: - args.output_directory = os.getcwd() + if not args.output_dir: + args.output_dir = os.getcwd() # Create a temporary log file that Telemetry will look to use to build # an artifact when tests fail. @@ -38,10 +40,10 @@ if not args.system_log_file: args.system_log_file = os.path.join(tempfile.mkdtemp(), 'system-log') temp_log_file = True + additional_target_args['system_log_file'] = args.system_log_file package_names = ['web_engine', 'web_engine_shell'] - web_engine_dir = os.path.join(args.output_directory, 'gen', 'fuchsia', - 'engine') + web_engine_dir = os.path.join(args.output_dir, 'gen', 'fuchsia', 'engine') gpu_script = [ os.path.join(path_util.GetChromiumSrcDir(), 'content', 'test', 'gpu', 'run_gpu_integration_test.py') @@ -50,10 +52,10 @@ # Pass all other arguments to the gpu integration tests. gpu_script.extend(gpu_test_args) try: - with GetDeploymentTargetForArgs(args) as target: + with GetDeploymentTargetForArgs(additional_target_args) as target: target.Start() _, fuchsia_ssh_port = target._GetEndpoint() - gpu_script.extend(['--fuchsia-ssh-config-dir', args.output_directory]) + gpu_script.extend(['--fuchsia-ssh-config-dir', args.output_dir]) gpu_script.extend(['--fuchsia-ssh-port', str(fuchsia_ssh_port)]) gpu_script.extend(['--fuchsia-system-log-file', args.system_log_file]) if args.verbose:
diff --git a/extensions/common/api/printer_provider.idl b/extensions/common/api/printer_provider.idl index 3de58fa0..aec9d79 100644 --- a/extensions/common/api/printer_provider.idl +++ b/extensions/common/api/printer_provider.idl
@@ -37,7 +37,7 @@ }; // Printing request parameters. Passed to $(ref:onPrintRequested) event. - dictionary PrintJob { + [noinline_doc] dictionary PrintJob { // ID of the printer which should handle the job. DOMString printerId;
diff --git a/fuchsia/engine/test/web_engine_test_launcher.cc b/fuchsia/engine/test/web_engine_test_launcher.cc index 6cc9cea..18a8543 100644 --- a/fuchsia/engine/test/web_engine_test_launcher.cc +++ b/fuchsia/engine/test/web_engine_test_launcher.cc
@@ -50,7 +50,7 @@ int main(int argc, char** argv) { base::CommandLine::Init(argc, argv); auto* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendSwitchASCII(switches::kOzonePlatform, "headless"); + command_line->AppendSwitchASCII(switches::kOzonePlatform, "scenic"); command_line->AppendSwitchASCII(switches::kEnableLogging, "stderr"); command_line->AppendSwitch(switches::kDisableGpu);
diff --git a/google_apis/gaia/oauth_multilogin_result.cc b/google_apis/gaia/oauth_multilogin_result.cc index 84b0511..ea734b5 100644 --- a/google_apis/gaia/oauth_multilogin_result.cc +++ b/google_apis/gaia/oauth_multilogin_result.cc
@@ -4,6 +4,8 @@ #include "google_apis/gaia/oauth_multilogin_result.h" +#include <algorithm> + #include "base/compiler_specific.h" #include "base/json/json_reader.h" #include "base/logging.h" @@ -59,7 +61,7 @@ base::StringPiece OAuthMultiloginResult::StripXSSICharacters( const std::string& raw_data) { base::StringPiece body(raw_data); - return body.substr(body.find('\n')); + return body.substr(std::min(body.find('\n'), body.size())); } void OAuthMultiloginResult::TryParseFailedAccountsFromValue(
diff --git a/gpu/command_buffer/service/shared_image_backing_gl_image.cc b/gpu/command_buffer/service/shared_image_backing_gl_image.cc index c34decc5..6f8ff6e 100644 --- a/gpu/command_buffer/service/shared_image_backing_gl_image.cc +++ b/gpu/command_buffer/service/shared_image_backing_gl_image.cc
@@ -17,6 +17,8 @@ #include "ui/gl/gl_context.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_gl_api_implementation.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/scoped_binders.h" #include "ui/gl/trace_util.h" #if defined(OS_MAC) @@ -569,6 +571,22 @@ gl::GLApi* api = gl::g_current_gl_context; api->glFlushFn(); } + + // When SwANGLE is used as the GL implementation, we have to call + // ReleaseTexImage to signal an UnlockIOSurface call to sync the surface + // between the CPU and GPU. The next time this texture is accessed we will + // call BindTexImage to signal a LockIOSurface call before rendering to it via + // the CPU. + if (IsPassthrough() && + gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader && + image_->ShouldBindOrCopy() == gl::GLImage::BIND) { + const GLenum target = GetGLTarget(); + gl::ScopedTextureBinder binder(target, passthrough_texture_->service_id()); + if (!passthrough_texture_->is_bind_pending()) { + image_->ReleaseTexImage(target); + image_bind_or_copy_needed_ = true; + } + } #endif }
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index d40b431..178ad42 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -1257,10 +1257,7 @@ } builders { name: "chromium/try/mac-coverage-rel" - experiment_percentage: 5 - location_regexp: ".*" - location_regexp_exclude: ".+/[+]/docs/.+" - location_regexp_exclude: ".+/[+]/infra/config/.+" + includable_only: true } builders { name: "chromium/try/mac-dawn-rel"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index ad30554..172aedf 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -366,6 +366,3 @@ * [`//content/browser/tracing/.+`](https://cs.chromium.org/chromium/src/content/browser/tracing/) * [`//services/tracing/.+`](https://cs.chromium.org/chromium/src/services/tracing/) -* [mac-coverage-rel](https://ci.chromium.org/p/chromium/builders/try/mac-coverage-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+mac-coverage-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+mac-coverage-rel)) - * Experiment percentage: 5 -
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index ee19eda5..9492ace 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -5388,7 +5388,7 @@ swarming_tags: "vpython:native-python-wrapper" dimensions: "builder:Mac deterministic (dbg)" dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.13" + dimensions: "os:Mac-10.15" dimensions: "pool:luci.chromium.ci" exe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star index 561ec521..a18563e3 100644 --- a/infra/config/subprojects/chromium/ci.star +++ b/infra/config/subprojects/chromium/ci.star
@@ -2899,6 +2899,7 @@ cores = None, executable = "recipe:swarming/deterministic_build", execution_timeout = 6 * time.hour, + os = os.MAC_10_15, ) ci.fyi_mac_builder(
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star index 2ceb669f..297d169 100644 --- a/infra/config/subprojects/chromium/try.star +++ b/infra/config/subprojects/chromium/try.star
@@ -1098,7 +1098,6 @@ name = "mac-coverage-rel", use_clang_coverage = True, goma_jobs = goma.jobs.J150, - tryjob = try_.job(experiment_percentage = 5), ) try_.chromium_mac_builder(
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 5fda2cc..eb7a9672 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -101,7 +101,6 @@ "//ios/chrome/browser/complex_tasks", "//ios/chrome/browser/download", "//ios/chrome/browser/itunes_urls", - "//ios/chrome/browser/ssl:feature_flags", "//ios/chrome/browser/sync/glue", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
diff --git a/ios/chrome/browser/ssl/BUILD.gn b/ios/chrome/browser/ssl/BUILD.gn index 2c95a685..81f0a1aa 100644 --- a/ios/chrome/browser/ssl/BUILD.gn +++ b/ios/chrome/browser/ssl/BUILD.gn
@@ -9,8 +9,6 @@ "captive_portal_detector_tab_helper.mm", "captive_portal_detector_tab_helper_delegate.h", "captive_portal_metrics.h", - "captive_portal_metrics_tab_helper.h", - "captive_portal_metrics_tab_helper.mm", "ios_captive_portal_blocking_page.h", "ios_captive_portal_blocking_page.mm", "ios_ssl_blocking_page.h", @@ -19,7 +17,6 @@ "ios_ssl_error_handler.mm", ] deps = [ - ":feature_flags", "//base", "//base:i18n", "//components/autofill/ios/form_util", @@ -46,15 +43,6 @@ ] } -source_set("feature_flags") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "captive_portal_features.cc", - "captive_portal_features.h", - ] - deps = [ "//base" ] -} - source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true @@ -63,7 +51,6 @@ "ios_ssl_error_handler_unittest.mm", ] deps = [ - ":feature_flags", ":ssl", "//base/test:test_support", "//components/security_interstitials/core",
diff --git a/ios/chrome/browser/ssl/README.md b/ios/chrome/browser/ssl/README.md new file mode 100644 index 0000000..d745dd9 --- /dev/null +++ b/ios/chrome/browser/ssl/README.md
@@ -0,0 +1,6 @@ +## Captive Portal Metrics Tab Helper + +A tab helper was in place previously to collect metrics regarding current +captive portal issues. It was removed in [crrev.com/c/2372901][cl]. + +[cl]: https://chromium-review.googlesource.com/2372901
diff --git a/ios/chrome/browser/ssl/captive_portal_features.cc b/ios/chrome/browser/ssl/captive_portal_features.cc deleted file mode 100644 index e9209ef6..0000000 --- a/ios/chrome/browser/ssl/captive_portal_features.cc +++ /dev/null
@@ -1,8 +0,0 @@ -// Copyright 2017 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 "ios/chrome/browser/ssl/captive_portal_features.h" - -const base::Feature kCaptivePortalMetrics{"CaptivePortalMetrics", - base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ssl/captive_portal_features.h b/ios/chrome/browser/ssl/captive_portal_features.h deleted file mode 100644 index ca06f80a..0000000 --- a/ios/chrome/browser/ssl/captive_portal_features.h +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2017 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 IOS_CHROME_BROWSER_SSL_CAPTIVE_PORTAL_FEATURES_H_ -#define IOS_CHROME_BROWSER_SSL_CAPTIVE_PORTAL_FEATURES_H_ - -#include "base/feature_list.h" - -// Used to control the state of logging Captive Portal Metrics. -extern const base::Feature kCaptivePortalMetrics; - -#endif // IOS_CHROME_BROWSER_SSL_CAPTIVE_PORTAL_FEATURES_H_
diff --git a/ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.h b/ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.h deleted file mode 100644 index 625dd94c..0000000 --- a/ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2017 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 IOS_CHROME_BROWSER_SSL_CAPTIVE_PORTAL_METRICS_TAB_HELPER_H_ -#define IOS_CHROME_BROWSER_SSL_CAPTIVE_PORTAL_METRICS_TAB_HELPER_H_ - -#include "base/macros.h" -#include "base/timer/timer.h" -#include "components/captive_portal/core/captive_portal_detector.h" -#include "ios/chrome/browser/ssl/captive_portal_metrics.h" -#include "ios/web/public/web_state_observer.h" -#import "ios/web/public/web_state_user_data.h" - -namespace web { -class WebState; -} - -// Logs the result of a captive portal detector when users enter error states -// which could be caused by being on a Captive Portal network. These metrics -// will be used to identify how many users incorrectly see these error cases -// because they are on captive portal networks without a network connection. In -// the future, these users should be shown the captive portal login interstitial -// if these metrics show that enough users are affected. -// 1. When a -1200 error occurs. -// 2. If a request is taking a long time to complete. -class CaptivePortalMetricsTabHelper - : public web::WebStateObserver, - public web::WebStateUserData<CaptivePortalMetricsTabHelper> { - public: - ~CaptivePortalMetricsTabHelper() override; - - private: - explicit CaptivePortalMetricsTabHelper(web::WebState* web_state); - friend class web::WebStateUserData<CaptivePortalMetricsTabHelper>; - - // Tests if network access is currently blocked by a captive portal. - void TestForCaptivePortal( - captive_portal::CaptivePortalDetector::DetectionCallback callback); - - // Tests for a captive portal and logs the resulting metric. - void TimerTriggered(); - - // Returns the associated CaptivePortalStatus value for logging to UMA metrics - // based on detection |results|. - static CaptivePortalStatus CaptivePortalStatusFromDetectionResult( - const captive_portal::CaptivePortalDetector::Results& results); - - // Logs the |results| of the captive portal detector to the UMA metric for a - // failed secure connection. - static void HandleSecureConnectionFailedCaptivePortalDetectionResult( - const captive_portal::CaptivePortalDetector::Results& results); - - // Logs the |results| of the captive portal detector to the UMA metric for a - // potential request timeout. - static void HandleTimeoutCaptivePortalDetectionResult( - const captive_portal::CaptivePortalDetector::Results& results); - - // web::WebStateObserver implementation. - void DidStartNavigation(web::WebState* web_state, - web::NavigationContext* navigation_context) override; - void DidFinishNavigation(web::WebState* web_state, - web::NavigationContext* navigation_context) override; - void WebStateDestroyed(web::WebState* web_state) override; - - // A timer to test for a captive portal blocking an ongoing request. - base::OneShotTimer timer_; - // The web state associated with this tab helper. - web::WebState* web_state_; - - WEB_STATE_USER_DATA_KEY_DECL(); - - DISALLOW_COPY_AND_ASSIGN(CaptivePortalMetricsTabHelper); -}; - -#endif // IOS_CHROME_BROWSER_SSL_CAPTIVE_PORTAL_METRICS_TAB_HELPER_H_
diff --git a/ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.mm b/ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.mm deleted file mode 100644 index 917c053..0000000 --- a/ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.mm +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright 2017 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 "ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.h" - -#include "base/bind.h" -#include "base/metrics/histogram_macros.h" -#include "components/captive_portal/core/captive_portal_detector.h" -#import "ios/chrome/browser/ssl/captive_portal_detector_tab_helper.h" -#import "ios/web/public/navigation/navigation_context.h" -#import "ios/web/public/web_state.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// Result of captive portal network check after a request takes longer than -// |kCaptivePortalTestDelayInMilliseconds|. -const char kCaptivePortalCausingTimeoutHistogram[] = - "CaptivePortal.Session.TimeoutDetectionResult"; - -// Result of captive portal network check after a request fails with -// NSURLErrorSecureConnectionFailed. -const char kCaptivePortalSecureConnectionFailedHistogram[] = - "CaptivePortal.Session.SecureConnectionFailed"; - -// Time in milliseconds of still ongoing request before testing if the user is -// behind a captive portal. -const int64_t kCaptivePortalTestDelayInMilliseconds = 8000; - -CaptivePortalMetricsTabHelper::CaptivePortalMetricsTabHelper( - web::WebState* web_state) - : web_state_(web_state) { - web_state_->AddObserver(this); -} - -CaptivePortalMetricsTabHelper::~CaptivePortalMetricsTabHelper() = default; - -void CaptivePortalMetricsTabHelper::TimerTriggered() { - TestForCaptivePortal( - base::BindOnce(&HandleTimeoutCaptivePortalDetectionResult)); -} - -void CaptivePortalMetricsTabHelper::TestForCaptivePortal( - captive_portal::CaptivePortalDetector::DetectionCallback callback) { - CaptivePortalDetectorTabHelper* tab_helper = - CaptivePortalDetectorTabHelper::FromWebState(web_state_); - // TODO(crbug.com/760873): replace test with DCHECK when this method is only - // called on WebStates attached to tabs. - if (tab_helper) { - tab_helper->detector()->DetectCaptivePortal( - GURL(captive_portal::CaptivePortalDetector::kDefaultURL), - std::move(callback), NO_TRAFFIC_ANNOTATION_YET); - } -} - -// static -CaptivePortalStatus -CaptivePortalMetricsTabHelper::CaptivePortalStatusFromDetectionResult( - const captive_portal::CaptivePortalDetector::Results& results) { - CaptivePortalStatus status; - switch (results.result) { - case captive_portal::RESULT_INTERNET_CONNECTED: - status = CaptivePortalStatus::ONLINE; - break; - case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: - status = CaptivePortalStatus::PORTAL; - break; - default: - status = CaptivePortalStatus::UNKNOWN; - break; - } - return status; -} - -// static -void CaptivePortalMetricsTabHelper:: - HandleSecureConnectionFailedCaptivePortalDetectionResult( - const captive_portal::CaptivePortalDetector::Results& results) { - CaptivePortalStatus status = - CaptivePortalMetricsTabHelper::CaptivePortalStatusFromDetectionResult( - results); - UMA_HISTOGRAM_ENUMERATION(kCaptivePortalSecureConnectionFailedHistogram, - static_cast<int>(status), - static_cast<int>(CaptivePortalStatus::COUNT)); -} - -// static -void CaptivePortalMetricsTabHelper::HandleTimeoutCaptivePortalDetectionResult( - const captive_portal::CaptivePortalDetector::Results& results) { - CaptivePortalStatus status = - CaptivePortalMetricsTabHelper::CaptivePortalStatusFromDetectionResult( - results); - UMA_HISTOGRAM_ENUMERATION(kCaptivePortalCausingTimeoutHistogram, - static_cast<int>(status), - static_cast<int>(CaptivePortalStatus::COUNT)); -} - -// WebStateObserver -void CaptivePortalMetricsTabHelper::DidStartNavigation( - web::WebState* web_state, - web::NavigationContext* navigation_context) { - timer_.Stop(); - - timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kCaptivePortalTestDelayInMilliseconds), - this, &CaptivePortalMetricsTabHelper::TimerTriggered); -} - -void CaptivePortalMetricsTabHelper::DidFinishNavigation( - web::WebState* web_state, - web::NavigationContext* navigation_context) { - timer_.Stop(); - - NSError* error = navigation_context->GetError(); - if ([error.domain isEqualToString:NSURLErrorDomain] && - error.code == NSURLErrorSecureConnectionFailed) { - TestForCaptivePortal( - base::Bind(&HandleSecureConnectionFailedCaptivePortalDetectionResult)); - } else if ([error.domain isEqualToString:NSURLErrorDomain] && - error.code == NSURLErrorTimedOut) { - TestForCaptivePortal( - base::Bind(&HandleTimeoutCaptivePortalDetectionResult)); - } -} - -void CaptivePortalMetricsTabHelper::WebStateDestroyed( - web::WebState* web_state) { - DCHECK_EQ(web_state_, web_state); - - timer_.Stop(); - - // Ensure the captive portal detection is canceled if it never completed. - CaptivePortalDetectorTabHelper* tab_helper = - CaptivePortalDetectorTabHelper::FromWebState(web_state_); - // TODO(crbug.com/760873): replace test with DCHECK when this method is only - // called on WebStates attached to tabs. - if (tab_helper) { - tab_helper->detector()->Cancel(); - } - - web_state_->RemoveObserver(this); - web_state_ = nullptr; -} - -WEB_STATE_USER_DATA_KEY_IMPL(CaptivePortalMetricsTabHelper)
diff --git a/ios/chrome/browser/ssl/ios_ssl_error_handler.mm b/ios/chrome/browser/ssl/ios_ssl_error_handler.mm index 095683d..99df7a81 100644 --- a/ios/chrome/browser/ssl/ios_ssl_error_handler.mm +++ b/ios/chrome/browser/ssl/ios_ssl_error_handler.mm
@@ -16,7 +16,6 @@ #include "components/security_interstitials/core/ssl_error_ui.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/ssl/captive_portal_detector_tab_helper.h" -#include "ios/chrome/browser/ssl/captive_portal_features.h" #include "ios/chrome/browser/ssl/captive_portal_metrics.h" #include "ios/chrome/browser/ssl/ios_captive_portal_blocking_page.h" #include "ios/chrome/browser/ssl/ios_ssl_blocking_page.h"
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index c235acf2..f12e080 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -96,7 +96,6 @@ "//ios/chrome/browser/sessions:session_service", "//ios/chrome/browser/snapshots", "//ios/chrome/browser/ssl", - "//ios/chrome/browser/ssl:feature_flags", "//ios/chrome/browser/store_kit", "//ios/chrome/browser/sync", "//ios/chrome/browser/translate",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index adec82a..12dce93d 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -57,8 +57,6 @@ #import "ios/chrome/browser/search_engines/search_engine_tab_helper.h" #import "ios/chrome/browser/sessions/ios_chrome_session_tab_helper.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" -#include "ios/chrome/browser/ssl/captive_portal_features.h" -#import "ios/chrome/browser/ssl/captive_portal_metrics_tab_helper.h" #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" #import "ios/chrome/browser/sync/ios_chrome_synced_tab_delegate.h" #import "ios/chrome/browser/translate/chrome_ios_translate_client.h" @@ -131,10 +129,6 @@ TranslateOverlayTabHelper::CreateForWebState(web_state); } - if (base::FeatureList::IsEnabled(kCaptivePortalMetrics)) { - CaptivePortalMetricsTabHelper::CreateForWebState(web_state); - } - if (base::FeatureList::IsEnabled(web::kWebPageTextAccessibility)) { FontSizeTabHelper::CreateForWebState(web_state); }
diff --git a/ios/chrome/test/app/signin_test_util.mm b/ios/chrome/test/app/signin_test_util.mm index 3d3569a..d85392a 100644 --- a/ios/chrome/test/app/signin_test_util.mm +++ b/ios/chrome/test/app/signin_test_util.mm
@@ -125,6 +125,7 @@ prefs->SetBoolean(prefs::kIosBookmarkPromoAlreadySeen, false); prefs->SetInteger(prefs::kIosSettingsSigninPromoDisplayedCount, 0); prefs->SetBoolean(prefs::kIosSettingsPromoAlreadySeen, false); + prefs->SetBoolean(prefs::kSigninShouldPromptForSigninAgain, false); } } // namespace chrome_test_util
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index d6edd7a..eef3f5e8 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -453,3 +453,9 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_start_peer_migration_earlier, false) + +// If true, neuter initial packet in the coalescer when discarding initial keys. +QUIC_FLAG( + bool, + FLAGS_quic_reloadable_flag_quic_neuter_initial_packet_in_coalescer_with_initial_key_discarded, + true)
diff --git a/sandbox/linux/syscall_broker/broker_client.cc b/sandbox/linux/syscall_broker/broker_client.cc index fb897eb..71114e7 100644 --- a/sandbox/linux/syscall_broker/broker_client.cc +++ b/sandbox/linux/syscall_broker/broker_client.cc
@@ -112,11 +112,14 @@ return -ENOMEM; if (return_length < 0) return -ENOMEM; + // Sanity check that our broker is behaving correctly. + RAW_CHECK(return_length == static_cast<size_t>(return_value)); - if (static_cast<size_t>(return_length) > bufsize) - return -ENAMETOOLONG; + if (return_length > bufsize) { + return_length = bufsize; + } memcpy(buf, return_data, return_length); - return return_value; + return return_length; } int BrokerClient::Rename(const char* oldpath, const char* newpath) const {
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc index e4a8b04..6cd2fde8 100644 --- a/sandbox/linux/syscall_broker/broker_process_unittest.cc +++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -1094,7 +1094,7 @@ BrokerProcess open_broker(kFakeErrnoSentinel, command_set, permissions, fast_check_in_client); ASSERT_TRUE(open_broker.Init(base::BindOnce(&NoOpCallback))); - EXPECT_EQ(-ENAMETOOLONG, open_broker.Readlink(newpath_name, buf, 4)); + EXPECT_EQ(4, open_broker.Readlink(newpath_name, buf, 4)); } // Cleanup both paths.
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 3609335..8408a2c 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -4548,7 +4548,7 @@ }, { "args": [ - "--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont" + "--test-launcher-filter-file=../../testing/buildbot/filters/lacros.content_browsertests.filter" ], "merge": { "args": [],
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json index 8d14896..30183c00 100644 --- a/testing/buildbot/chromium.ci.json +++ b/testing/buildbot/chromium.ci.json
@@ -243684,7 +243684,7 @@ }, { "args": [ - "--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont" + "--test-launcher-filter-file=../../testing/buildbot/filters/lacros.content_browsertests.filter" ], "merge": { "args": [],
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index 578f0fc..2e700ea5 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -89,6 +89,7 @@ "//testing/buildbot/filters/android.emulator_p.content_browsertests.filter", "//testing/buildbot/filters/cast-linux.content_browsertests.filter", "//testing/buildbot/filters/gpu.skiarenderer_vulkan_content_browsertests.filter", + "//testing/buildbot/filters/lacros.content_browsertests.filter", "//testing/buildbot/filters/site_isolation_android.content_browsertests.filter", "//testing/buildbot/filters/skia_renderer.content_browsertests.filter", "//testing/buildbot/filters/vulkan.content_browsertests.filter",
diff --git a/testing/buildbot/filters/lacros.content_browsertests.filter b/testing/buildbot/filters/lacros.content_browsertests.filter new file mode 100644 index 0000000..bf84e3e4 --- /dev/null +++ b/testing/buildbot/filters/lacros.content_browsertests.filter
@@ -0,0 +1,6 @@ + +# TODO(crbug.com/1111979) Enable all tests on lacros. +-OutOfProcessPPAPITest.TrueTypeFont + +# Following tests are flaky. +-All/WebContentsVideoCaptureDeviceBrowserTestP.CapturesContentChanges*
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 80179d18..f30ab3a 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -46,8 +46,11 @@ # : the test is a python script; the path to the script is specified in # the "script" field. # "generated_script" -# : the test is a script generated at build time; the path to the script -# *relative to the output directory* is specified in the "script" field. +# : the test is a script generated at build time; the script *should* be +# in output_dir/bin/run_$target (or output_dir\bin\run_$target.bat on +# Windows), but an alternative path *may* be specified, +# in the "script" field, as *relative to the output directory*. +# TODO(crbug.com/816629): remove support for "script". # "unknown" # : (the default), which indicates that we don't know what the command line # needs to be (this is a fatal error). @@ -58,9 +61,10 @@ # On Windows, ".exe" will be automatically appended if need be, so # the executable name (and target name) should not contain an ".exe". # -# The optional "args" field can be used to append extra command line -# args onto the command line determined by the "type". If not specified, -# it defaults to an empty list (no extra args). +# The optional "args" field may be specified for "windowed_test_launcher", +# "console_test_launcher", and "script"-type tests, and can be used to +# append extra command line args onto the command line determined by the +# "type". If not specified, it defaults to an empty list (no extra args). # # The optional "label_type" field can be used in conjunction with # "type" == "console_test_launcher" or "type" == "windowed_test_launcher" @@ -487,7 +491,6 @@ "chrome_sizes": { "label": "//chrome/test:chrome_sizes", "type": "generated_script", - "script": "bin/run_chrome_sizes", }, "chromedriver": { "label": "//chrome/test/chromedriver:chromedriver", @@ -647,7 +650,6 @@ "cronet_sizes": { "label": "//components/cronet/android:cronet_sizes", "type": "generated_script", - "script": "bin/run_cronet_sizes", }, "cronet_smoketests_missing_native_library_instrumentation_apk": { "label": "//components/cronet/android:cronet_smoketests_missing_native_library_instrumentation_apk", @@ -660,7 +662,6 @@ "cronet_test": { "label": "//components/cronet/ios/test:cronet_test", "type": "generated_script", - "script": "bin/run_cronet_test" }, "cronet_test_instrumentation_apk": { "label": "//components/cronet/android:cronet_test_instrumentation_apk", @@ -896,21 +897,15 @@ "type": "windowed_test_launcher", }, "ios_chrome_bookmarks_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_bookmarks_egtests", - "script": "bin/run_ios_chrome_bookmarks_egtests", "type": "generated_script", }, "ios_chrome_integration_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_integration_egtests", - "script": "bin/run_ios_chrome_integration_egtests", "type": "generated_script", }, "ios_chrome_reading_list_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_reading_list_egtests", - "script": "bin/run_ios_chrome_reading_list_egtests", "type": "generated_script", }, "ios_chrome_settings_egtests": { @@ -918,162 +913,110 @@ "--enable-features=ClearSyncedData", ], "label": "//ios/chrome/test/earl_grey:ios_chrome_settings_egtests", - "script": "bin/run_ios_chrome_settings_egtests", "type": "generated_script", }, "ios_chrome_signin_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_signin_egtests", - "script": "bin/run_ios_chrome_signin_egtests", "type": "generated_script", }, "ios_chrome_translate_egtests": { "label": "//ios/chrome/test/earl_grey:ios_chrome_translate_egtests", - "script": "bin/run_ios_chrome_translate_egtests", "type": "generated_script", }, "ios_chrome_smoke_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_smoke_egtests", - "script": "bin/run_ios_chrome_smoke_egtests", "type": "generated_script", }, "ios_chrome_ui_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_ui_egtests", - "script": "bin/run_ios_chrome_ui_egtests", "type": "generated_script", }, "ios_chrome_unittests": { - "args": [], "label": "//ios/chrome/test:ios_chrome_unittests", - "script": "bin/run_ios_chrome_unittests", "type": "generated_script", }, "ios_chrome_web_egtests": { - "args": [], "label": "//ios/chrome/test/earl_grey:ios_chrome_web_egtests", - "script": "bin/run_ios_chrome_web_egtests", "type": "generated_script", }, "ios_chrome_bookmarks_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module", - "script": "bin/run_ios_chrome_bookmarks_eg2tests_module", "type": "generated_script", }, "ios_chrome_integration_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module", - "script": "bin/run_ios_chrome_integration_eg2tests_module", "type": "generated_script", }, "ios_chrome_settings_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module", - "script": "bin/run_ios_chrome_settings_eg2tests_module", "type": "generated_script", }, "ios_chrome_signin_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module", - "script": "bin/run_ios_chrome_signin_eg2tests_module", "type": "generated_script", }, "ios_chrome_smoke_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module", - "script": "bin/run_ios_chrome_smoke_eg2tests_module", "type": "generated_script", }, "ios_chrome_ui_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module", - "script": "bin/run_ios_chrome_ui_eg2tests_module", "type": "generated_script", }, "ios_chrome_web_eg2tests_module": { - "args": [], "label": "//ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module", - "script": "bin/run_ios_chrome_web_eg2tests_module", "type": "generated_script", }, "ios_crash_xcuitests_module": { - "args": [], "label": "//third_party/crashpad/crashpad/test/ios:ios_crash_xcuitests_module", - "script": "bin/run_ios_crash_xcuitests_module", "type": "generated_script", }, "ios_components_unittests": { - "args": [], "label": "//ios/components:ios_components_unittests", - "script": "bin/run_ios_components_unittests", "type": "generated_script", }, "ios_net_unittests": { - "args": [], "label": "//ios/net:ios_net_unittests", - "script": "bin/run_ios_net_unittests", "type": "generated_script", }, "ios_remoting_unittests": { - "args": [], "label": "//remoting/ios:ios_remoting_unittests", - "script": "bin/run_ios_remoting_unittests", "type": "generated_script", }, "ios_showcase_egtests": { - "args": [], "label": "//ios/showcase:ios_showcase_egtests", - "script": "bin/run_ios_showcase_egtests", "type": "generated_script", }, "ios_showcase_eg2tests_module": { - "args":[], "label": "//ios/showcase:ios_showcase_eg2tests_module", - "script": "bin/run_ios_showcase_eg2tests_module", "type": "generated_script", }, "ios_testing_unittests": { - "args": [], "label": "//ios/testing:ios_testing_unittests", - "script": "bin/run_ios_testing_unittests", "type": "generated_script", }, "ios_web_inttests": { - "args": [], "label": "//ios/web:ios_web_inttests", - "script": "bin/run_ios_web_inttests", "type": "generated_script", }, "ios_web_shell_eg2tests_module": { - "args": [], "label": "//ios/web/shell/test:ios_web_shell_eg2tests_module", - "script": "bin/run_ios_web_shell_eg2tests_module", "type": "generated_script", }, "ios_web_shell_egtests": { - "args": [], "label": "//ios/web/shell/test:ios_web_shell_egtests", - "script": "bin/run_ios_web_shell_egtests", "type": "generated_script", }, "ios_web_unittests": { - "args": [], "label": "//ios/web:ios_web_unittests", - "script": "bin/run_ios_web_unittests", "type": "generated_script", }, "ios_web_view_inttests": { - "args": [], "label": "//ios/web_view:ios_web_view_inttests", - "script": "bin/run_ios_web_view_inttests", "type": "generated_script", }, "ios_web_view_unittests": { - "args": [], "label": "//ios/web_view:ios_web_view_unittests", - "script": "bin/run_ios_web_view_unittests", "type": "generated_script", }, "ipc_tests": {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index b6b2c16a..0ae31cee 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -993,7 +993,7 @@ # https://crbug.com/1111979, 'linux-lacros-tester-rel': { 'args': [ - '--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont', + '--test-launcher-filter-file=../../testing/buildbot/filters/lacros.content_browsertests.filter', ], }, },
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index 73763f5..23a586c 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn
@@ -527,15 +527,6 @@ ":androidx_fragment_fragment_java", ":androidx_recyclerview_recyclerview_java", ] - deps += [ "//third_party/android_deps/local_modifications/androidx_preference_preference:androidx_preference_preference_prebuilt_java" ] - - # Omit these files since we use our own copy from AndroidX master, included above. - # We can remove this once we migrate to AndroidX master for all libraries. - jar_excluded_patterns = [ - "androidx/preference/PreferenceDialogFragmentCompat*", - "androidx/preference/PreferenceFragmentCompat*", - ] - ignore_proguard_configs = true }
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index 18e62be..286f875e 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -433,17 +433,6 @@ sb.append(' jar_excluded_patterns = [ "*xmlpull*" ]\n') break case 'androidx_preference_preference': - sb.append("""\ - | deps += [ "//third_party/android_deps/local_modifications/androidx_preference_preference:androidx_preference_preference_prebuilt_java" ] - | # Omit these files since we use our own copy from AndroidX master, included above. - | # We can remove this once we migrate to AndroidX master for all libraries. - | jar_excluded_patterns = [ - | "androidx/preference/PreferenceDialogFragmentCompat*", - | "androidx/preference/PreferenceFragmentCompat*", - | ] - | - |""".stripMargin()) - // fallthrough case 'com_android_support_preference_v7': // Replace broad library -keep rules with a more limited set in // chrome/android/java/proguard.flags instead.
diff --git a/third_party/android_deps/local_modifications/androidx_preference_preference/BUILD.gn b/third_party/android_deps/local_modifications/androidx_preference_preference/BUILD.gn deleted file mode 100644 index 15afb59..0000000 --- a/third_party/android_deps/local_modifications/androidx_preference_preference/BUILD.gn +++ /dev/null
@@ -1,33 +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. - -import("//build/config/android/rules.gni") - -# This rule contains the jar file produced by building -# :androidx_preference_preference_partial_java. After building the -# aforementioned target, the jar file can be found in: -# out/<dir>/lib.java/third_party/android_deps/local_modifications/androidx_preference_preference/androidx_preference_preference_partial_java.jar -android_java_prebuilt("androidx_preference_preference_prebuilt_java") { - jar_path = "androidx_preference_preference_java.jar" - - # Normally this would depend on //third_party/android_deps:androidx_preference_preference_java, - # but the dependency is reversed to keep the .class file customization - # transparent to dependents. Disable bytecode checks, which would otherwise - # complain about this. - enable_bytecode_checks = false -} - -android_library("androidx_preference_preference_partial_java") { - sources = [ - "java/androidx/preference/PreferenceDialogFragmentCompat.java", - "java/androidx/preference/PreferenceFragmentCompat.java", - ] - deps = [ - "//third_party/android_deps:androidx_annotation_annotation_java", - "//third_party/android_deps:androidx_appcompat_appcompat_java", - "//third_party/android_deps:androidx_fragment_fragment_java", - "//third_party/android_deps:androidx_preference_preference_java", - "//third_party/android_deps:androidx_recyclerview_recyclerview_java", - ] -}
diff --git a/third_party/android_deps/local_modifications/androidx_preference_preference/README b/third_party/android_deps/local_modifications/androidx_preference_preference/README deleted file mode 100644 index f4fb51c..0000000 --- a/third_party/android_deps/local_modifications/androidx_preference_preference/README +++ /dev/null
@@ -1,10 +0,0 @@ -This directory contains PreferenceFragmentCompat.java and -PreferenceDialogFragmentCompat.java, copied without changes from the AndroidX -preference library at commit beeb6fb. These files contain two changes (commits -72c0381 and beeb6fb) that we want in Chromium, but are not yet in an official -preference library release. - -To pull in these changes, we exclude PreferenceFragmentCompat and -PreferenceDialogFragmentCompat from the androidx_preference_preference library -in CIPD (which is from an official release), and add a dependency from that -library to a prebuilt jar file containing the two classes we want to update.
diff --git a/third_party/android_deps/local_modifications/androidx_preference_preference/androidx_preference_preference_java.jar b/third_party/android_deps/local_modifications/androidx_preference_preference/androidx_preference_preference_java.jar deleted file mode 100644 index 201cd50..0000000 --- a/third_party/android_deps/local_modifications/androidx_preference_preference/androidx_preference_preference_java.jar +++ /dev/null Binary files differ
diff --git a/third_party/android_deps/local_modifications/androidx_preference_preference/java/androidx/preference/PreferenceDialogFragmentCompat.java b/third_party/android_deps/local_modifications/androidx_preference_preference/java/androidx/preference/PreferenceDialogFragmentCompat.java deleted file mode 100644 index fbf4b72..0000000 --- a/third_party/android_deps/local_modifications/androidx_preference_preference/java/androidx/preference/PreferenceDialogFragmentCompat.java +++ /dev/null
@@ -1,268 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package androidx.preference; - -import static androidx.annotation.RestrictTo.Scope.LIBRARY; - -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.text.TextUtils; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.TextView; - -import androidx.annotation.LayoutRes; -import androidx.annotation.NonNull; -import androidx.annotation.RestrictTo; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; - -/** - * Abstract base class which presents a dialog associated with a {@link DialogPreference}. Since - * the preference object may not be available during fragment re-creation, the necessary - * information for displaying the dialog is read once during the initial call to - * {@link #onCreate(Bundle)} and saved/restored in the saved instance state. Custom subclasses - * should also follow this pattern. - */ -public abstract class PreferenceDialogFragmentCompat extends DialogFragment implements - DialogInterface.OnClickListener { - - protected static final String ARG_KEY = "key"; - - private static final String SAVE_STATE_TITLE = "PreferenceDialogFragment.title"; - private static final String SAVE_STATE_POSITIVE_TEXT = "PreferenceDialogFragment.positiveText"; - private static final String SAVE_STATE_NEGATIVE_TEXT = "PreferenceDialogFragment.negativeText"; - private static final String SAVE_STATE_MESSAGE = "PreferenceDialogFragment.message"; - private static final String SAVE_STATE_LAYOUT = "PreferenceDialogFragment.layout"; - private static final String SAVE_STATE_ICON = "PreferenceDialogFragment.icon"; - - private DialogPreference mPreference; - - private CharSequence mDialogTitle; - private CharSequence mPositiveButtonText; - private CharSequence mNegativeButtonText; - private CharSequence mDialogMessage; - private @LayoutRes int mDialogLayoutRes; - - private BitmapDrawable mDialogIcon; - - /** Which button was clicked. */ - private int mWhichButtonClicked; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - final Fragment rawFragment = getTargetFragment(); - if (!(rawFragment instanceof DialogPreference.TargetFragment)) { - throw new IllegalStateException("Target fragment must implement TargetFragment" + - " interface"); - } - - final DialogPreference.TargetFragment fragment = - (DialogPreference.TargetFragment) rawFragment; - - final String key = getArguments().getString(ARG_KEY); - if (savedInstanceState == null) { - mPreference = fragment.findPreference(key); - mDialogTitle = mPreference.getDialogTitle(); - mPositiveButtonText = mPreference.getPositiveButtonText(); - mNegativeButtonText = mPreference.getNegativeButtonText(); - mDialogMessage = mPreference.getDialogMessage(); - mDialogLayoutRes = mPreference.getDialogLayoutResource(); - - final Drawable icon = mPreference.getDialogIcon(); - if (icon == null || icon instanceof BitmapDrawable) { - mDialogIcon = (BitmapDrawable) icon; - } else { - final Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(), - icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - final Canvas canvas = new Canvas(bitmap); - icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - icon.draw(canvas); - mDialogIcon = new BitmapDrawable(getResources(), bitmap); - } - } else { - mDialogTitle = savedInstanceState.getCharSequence(SAVE_STATE_TITLE); - mPositiveButtonText = savedInstanceState.getCharSequence(SAVE_STATE_POSITIVE_TEXT); - mNegativeButtonText = savedInstanceState.getCharSequence(SAVE_STATE_NEGATIVE_TEXT); - mDialogMessage = savedInstanceState.getCharSequence(SAVE_STATE_MESSAGE); - mDialogLayoutRes = savedInstanceState.getInt(SAVE_STATE_LAYOUT, 0); - final Bitmap bitmap = savedInstanceState.getParcelable(SAVE_STATE_ICON); - if (bitmap != null) { - mDialogIcon = new BitmapDrawable(getResources(), bitmap); - } - } - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - - outState.putCharSequence(SAVE_STATE_TITLE, mDialogTitle); - outState.putCharSequence(SAVE_STATE_POSITIVE_TEXT, mPositiveButtonText); - outState.putCharSequence(SAVE_STATE_NEGATIVE_TEXT, mNegativeButtonText); - outState.putCharSequence(SAVE_STATE_MESSAGE, mDialogMessage); - outState.putInt(SAVE_STATE_LAYOUT, mDialogLayoutRes); - if (mDialogIcon != null) { - outState.putParcelable(SAVE_STATE_ICON, mDialogIcon.getBitmap()); - } - } - - @Override - public @NonNull - Dialog onCreateDialog(Bundle savedInstanceState) { - mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE; - - final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()) - .setTitle(mDialogTitle) - .setIcon(mDialogIcon) - .setPositiveButton(mPositiveButtonText, this) - .setNegativeButton(mNegativeButtonText, this); - - View contentView = onCreateDialogView(getContext()); - if (contentView != null) { - onBindDialogView(contentView); - builder.setView(contentView); - } else { - builder.setMessage(mDialogMessage); - } - - onPrepareDialogBuilder(builder); - - // Create the dialog - final Dialog dialog = builder.create(); - if (needInputMethod()) { - requestInputMethod(dialog); - } - - return dialog; - } - - /** - * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has - * been called on the {@link PreferenceFragmentCompat} which launched this dialog. - * - * @return The {@link DialogPreference} associated with this dialog - */ - public DialogPreference getPreference() { - if (mPreference == null) { - final String key = getArguments().getString(ARG_KEY); - final DialogPreference.TargetFragment fragment = - (DialogPreference.TargetFragment) getTargetFragment(); - mPreference = fragment.findPreference(key); - } - return mPreference; - } - - /** - * Prepares the dialog builder to be shown when the preference is clicked. - * Use this to set custom properties on the dialog. - * - * <p>Do not {@link AlertDialog.Builder#create()} or {@link AlertDialog.Builder#show()}. - */ - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {} - - /** - * Returns whether the preference needs to display a soft input method when the dialog is - * displayed. Default is false. Subclasses should override this method if they need the soft - * input method brought up automatically. - * - * <p>Note: If your application targets P or above, ensure your subclass manually requests - * focus (ideally in {@link #onBindDialogView(View)}) for the input field in order to - * correctly attach the input method to the field. - * - * @hide - */ - @RestrictTo(LIBRARY) - protected boolean needInputMethod() { - return false; - } - - /** - * Sets the required flags on the dialog window to enable input method window to show up. - */ - private void requestInputMethod(Dialog dialog) { - Window window = dialog.getWindow(); - window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); - } - - /** - * Creates the content view for the dialog (if a custom content view is required). - * By default, it inflates the dialog layout resource if it is set. - * - * @return The content view for the dialog - * @see DialogPreference#setLayoutResource(int) - */ - protected View onCreateDialogView(Context context) { - final int resId = mDialogLayoutRes; - if (resId == 0) { - return null; - } - - return getLayoutInflater().inflate(resId, null); - } - - /** - * Binds views in the content view of the dialog to data. - * - * <p>Make sure to call through to the superclass implementation. - * - * @param view The content view of the dialog, if it is custom - */ - protected void onBindDialogView(View view) { - View dialogMessageView = view.findViewById(android.R.id.message); - - if (dialogMessageView != null) { - final CharSequence message = mDialogMessage; - int newVisibility = View.GONE; - - if (!TextUtils.isEmpty(message)) { - if (dialogMessageView instanceof TextView) { - ((TextView) dialogMessageView).setText(message); - } - - newVisibility = View.VISIBLE; - } - - if (dialogMessageView.getVisibility() != newVisibility) { - dialogMessageView.setVisibility(newVisibility); - } - } - } - - @Override - public void onClick(DialogInterface dialog, int which) { - mWhichButtonClicked = which; - } - - @Override - public void onDismiss(@NonNull DialogInterface dialog) { - super.onDismiss(dialog); - onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE); - } - - public abstract void onDialogClosed(boolean positiveResult); -}
diff --git a/third_party/android_deps/local_modifications/androidx_preference_preference/java/androidx/preference/PreferenceFragmentCompat.java b/third_party/android_deps/local_modifications/androidx_preference_preference/java/androidx/preference/PreferenceFragmentCompat.java deleted file mode 100644 index 1fa26698..0000000 --- a/third_party/android_deps/local_modifications/androidx_preference_preference/java/androidx/preference/PreferenceFragmentCompat.java +++ /dev/null
@@ -1,872 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package androidx.preference; - -import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.util.Log; -import android.util.TypedValue; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RestrictTo; -import androidx.annotation.XmlRes; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -/** - * A PreferenceFragmentCompat is the entry point to using the Preference library. This - * {@link Fragment} displays a hierarchy of {@link Preference} objects to the user. It also - * handles persisting values to the device. To retrieve an instance of - * {@link android.content.SharedPreferences} that the preference hierarchy in this fragment will - * use by default, call - * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)} with a context - * in the same package as this fragment. - * - * <p>You can define a preference hierarchy as an XML resource, or you can build a hierarchy in - * code. In both cases you need to use a {@link PreferenceScreen} as the root component in your - * hierarchy. - * - * <p>To inflate from XML, use the {@link #setPreferencesFromResource(int, String)}. An example - * example XML resource is shown further down. - * - * <p>To build a hierarchy from code, use - * {@link PreferenceManager#createPreferenceScreen(Context)} to create the root - * {@link PreferenceScreen}. Once you have added other {@link Preference}s to this root scree - * with {@link PreferenceScreen#addPreference(Preference)}, you then need to set the screen as - * the root screen in your hierarchy with {@link #setPreferenceScreen(PreferenceScreen)}. - * - * <p>As a convenience, this fragment implements a click listener for any preference in the - * current hierarchy, see {@link #onPreferenceTreeClick(Preference)}. - * - * <div class="special reference"> <h3>Developer Guides</h3> <p>For more information about - * building a settings screen using the AndroidX Preference library, see - * <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>.</p> </div> - * - * <a name="SampleCode"></a> - * <h3>Sample Code</h3> - * - * <p>The following sample code shows a simple settings screen using an XML resource. The XML - * resource is as follows:</p> - * - * {@sample frameworks/support/samples/SupportPreferenceDemos/src/main/res/xml/preferences.xml preferences} - * - * <p>The fragment that loads the XML resource is as follows:</p> - * - * {@sample frameworks/support/samples/SupportPreferenceDemos/src/main/java/com/example/androidx/preference/Preferences.java preferences} - * - * @see Preference - * @see PreferenceScreen - */ -public abstract class PreferenceFragmentCompat extends Fragment implements - PreferenceManager.OnPreferenceTreeClickListener, - PreferenceManager.OnDisplayPreferenceDialogListener, - PreferenceManager.OnNavigateToScreenListener, - DialogPreference.TargetFragment { - - private static final String TAG = "PreferenceFragment"; - - /** - * Fragment argument used to specify the tag of the desired root {@link PreferenceScreen} - * object. - */ - public static final String ARG_PREFERENCE_ROOT = - "androidx.preference.PreferenceFragmentCompat.PREFERENCE_ROOT"; - - private static final String PREFERENCES_TAG = "android:preferences"; - - private static final String DIALOG_FRAGMENT_TAG = - "androidx.preference.PreferenceFragment.DIALOG"; - - private static final int MSG_BIND_PREFERENCES = 1; - - private final DividerDecoration mDividerDecoration = new DividerDecoration(); - private PreferenceManager mPreferenceManager; - @SuppressWarnings("WeakerAccess") /* synthetic access */ - RecyclerView mList; - private boolean mHavePrefs; - private boolean mInitDone; - private int mLayoutResId = R.layout.preference_list_fragment; - private Runnable mSelectPreferenceRunnable; - - @SuppressWarnings("deprecation") - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_BIND_PREFERENCES: - bindPreferences(); - break; - } - } - }; - - final private Runnable mRequestFocus = new Runnable() { - @Override - public void run() { - mList.focusableViewAvailable(mList); - } - }; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - final TypedValue tv = new TypedValue(); - getContext().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true); - int theme = tv.resourceId; - if (theme == 0) { - // Fallback to default theme. - theme = R.style.PreferenceThemeOverlay; - } - getContext().getTheme().applyStyle(theme, false); - - mPreferenceManager = new PreferenceManager(getContext()); - mPreferenceManager.setOnNavigateToScreenListener(this); - final Bundle args = getArguments(); - final String rootKey; - if (args != null) { - rootKey = getArguments().getString(ARG_PREFERENCE_ROOT); - } else { - rootKey = null; - } - onCreatePreferences(savedInstanceState, rootKey); - } - - /** - * Called during {@link #onCreate(Bundle)} to supply the preferences for this fragment. - * Subclasses are expected to call {@link #setPreferenceScreen(PreferenceScreen)} either - * directly or via helper methods such as {@link #addPreferencesFromResource(int)}. - * - * @param savedInstanceState If the fragment is being re-created from a previous saved state, - * this is the state. - * @param rootKey If non-null, this preference fragment should be rooted at the - * {@link PreferenceScreen} with this key. - */ - public abstract void onCreatePreferences(Bundle savedInstanceState, String rootKey); - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - - TypedArray a = getContext().obtainStyledAttributes(null, - R.styleable.PreferenceFragmentCompat, - R.attr.preferenceFragmentCompatStyle, - 0); - - mLayoutResId = a.getResourceId(R.styleable.PreferenceFragmentCompat_android_layout, - mLayoutResId); - - final Drawable divider = a.getDrawable( - R.styleable.PreferenceFragmentCompat_android_divider); - final int dividerHeight = a.getDimensionPixelSize( - R.styleable.PreferenceFragmentCompat_android_dividerHeight, -1); - final boolean allowDividerAfterLastItem = a.getBoolean( - R.styleable.PreferenceFragmentCompat_allowDividerAfterLastItem, true); - - a.recycle(); - - final LayoutInflater themedInflater = inflater.cloneInContext(getContext()); - - final View view = themedInflater.inflate(mLayoutResId, container, false); - - final View rawListContainer = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER); - if (!(rawListContainer instanceof ViewGroup)) { - throw new IllegalStateException("Content has view with id attribute " - + "'android.R.id.list_container' that is not a ViewGroup class"); - } - - final ViewGroup listContainer = (ViewGroup) rawListContainer; - - final RecyclerView listView = onCreateRecyclerView(themedInflater, listContainer, - savedInstanceState); - if (listView == null) { - throw new RuntimeException("Could not create RecyclerView"); - } - - mList = listView; - - listView.addItemDecoration(mDividerDecoration); - setDivider(divider); - if (dividerHeight != -1) { - setDividerHeight(dividerHeight); - } - mDividerDecoration.setAllowDividerAfterLastItem(allowDividerAfterLastItem); - - // If mList isn't present in the view hierarchy, add it. mList is automatically inflated - // on an Auto device so don't need to add it. - if (mList.getParent() == null) { - listContainer.addView(mList); - } - mHandler.post(mRequestFocus); - - return view; - } - - /** - * Sets the {@link Drawable} that will be drawn between each item in the list. - * - * <p><strong>Note:</strong> If the drawable does not have an intrinsic height, you should also - * call {@link #setDividerHeight(int)}. - * - * @param divider The drawable to use - * {@link android.R.attr#divider} - */ - public void setDivider(Drawable divider) { - mDividerDecoration.setDivider(divider); - } - - /** - * Sets the height of the divider that will be drawn between each item in the list. Calling - * this will override the intrinsic height as set by {@link #setDivider(Drawable)}. - * - * @param height The new height of the divider in pixels - * {@link android.R.attr#dividerHeight} - */ - public void setDividerHeight(int height) { - mDividerDecoration.setDividerHeight(height); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - if (savedInstanceState != null) { - Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG); - if (container != null) { - final PreferenceScreen preferenceScreen = getPreferenceScreen(); - if (preferenceScreen != null) { - preferenceScreen.restoreHierarchyState(container); - } - } - } - - if (mHavePrefs) { - bindPreferences(); - if (mSelectPreferenceRunnable != null) { - mSelectPreferenceRunnable.run(); - mSelectPreferenceRunnable = null; - } - } - - mInitDone = true; - } - - @Override - public void onStart() { - super.onStart(); - mPreferenceManager.setOnPreferenceTreeClickListener(this); - mPreferenceManager.setOnDisplayPreferenceDialogListener(this); - } - - @Override - public void onStop() { - super.onStop(); - mPreferenceManager.setOnPreferenceTreeClickListener(null); - mPreferenceManager.setOnDisplayPreferenceDialogListener(null); - } - - @Override - public void onDestroyView() { - mHandler.removeCallbacks(mRequestFocus); - mHandler.removeMessages(MSG_BIND_PREFERENCES); - if (mHavePrefs) { - unbindPreferences(); - } - mList = null; - super.onDestroyView(); - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - - final PreferenceScreen preferenceScreen = getPreferenceScreen(); - if (preferenceScreen != null) { - Bundle container = new Bundle(); - preferenceScreen.saveHierarchyState(container); - outState.putBundle(PREFERENCES_TAG, container); - } - } - - /** - * Returns the {@link PreferenceManager} used by this fragment. - * - * @return The {@link PreferenceManager} used by this fragment - */ - public PreferenceManager getPreferenceManager() { - return mPreferenceManager; - } - - /** - * Gets the root of the preference hierarchy that this fragment is showing. - * - * @return The {@link PreferenceScreen} that is the root of the preference hierarchy - */ - public PreferenceScreen getPreferenceScreen() { - return mPreferenceManager.getPreferenceScreen(); - } - - /** - * Sets the root of the preference hierarchy that this fragment is showing. - * - * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy - */ - public void setPreferenceScreen(PreferenceScreen preferenceScreen) { - if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) { - onUnbindPreferences(); - mHavePrefs = true; - if (mInitDone) { - postBindPreferences(); - } - } - } - - /** - * Inflates the given XML resource and adds the preference hierarchy to the current - * preference hierarchy. - * - * @param preferencesResId The XML resource ID to inflate - */ - public void addPreferencesFromResource(@XmlRes int preferencesResId) { - requirePreferenceManager(); - - setPreferenceScreen(mPreferenceManager.inflateFromResource(getContext(), - preferencesResId, getPreferenceScreen())); - } - - /** - * Inflates the given XML resource and replaces the current preference hierarchy (if any) with - * the preference hierarchy rooted at {@code key}. - * - * @param preferencesResId The XML resource ID to inflate - * @param key The preference key of the {@link PreferenceScreen} to use as the - * root of the preference hierarchy, or {@code null} to use the root - * {@link PreferenceScreen}. - */ - public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) { - requirePreferenceManager(); - - final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(getContext(), - preferencesResId, null); - - final Preference root; - if (key != null) { - root = xmlRoot.findPreference(key); - if (!(root instanceof PreferenceScreen)) { - throw new IllegalArgumentException("Preference object with key " + key - + " is not a PreferenceScreen"); - } - } else { - root = xmlRoot; - } - - setPreferenceScreen((PreferenceScreen) root); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean onPreferenceTreeClick(Preference preference) { - if (preference.getFragment() != null) { - boolean handled = false; - if (getCallbackFragment() instanceof OnPreferenceStartFragmentCallback) { - handled = ((OnPreferenceStartFragmentCallback) getCallbackFragment()) - .onPreferenceStartFragment(this, preference); - } - if (!handled && getContext() instanceof OnPreferenceStartFragmentCallback) { - handled = ((OnPreferenceStartFragmentCallback) getContext()) - .onPreferenceStartFragment(this, preference); - } - // Check the Activity as well in case getContext was overridden to return something - // other than the Activity. - if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback) { - handled = ((OnPreferenceStartFragmentCallback) getActivity()) - .onPreferenceStartFragment(this, preference); - } - if (!handled) { - Log.w(TAG, - "onPreferenceStartFragment is not implemented in the parent activity - " - + "attempting to use a fallback implementation. You should " - + "implement this method so that you can configure the new " - + "fragment that will be displayed, and set a transition between " - + "the fragments."); - final FragmentManager fragmentManager = requireActivity() - .getSupportFragmentManager(); - final Bundle args = preference.getExtras(); - final Fragment fragment = fragmentManager.getFragmentFactory().instantiate( - requireActivity().getClassLoader(), preference.getFragment()); - fragment.setArguments(args); - fragment.setTargetFragment(this, 0); - fragmentManager.beginTransaction() - // Attempt to replace this fragment in its root view - developers should - // implement onPreferenceStartFragment in their activity so that they can - // customize this behaviour and handle any transitions between fragments - .replace(((View) getView().getParent()).getId(), fragment) - .addToBackStack(null) - .commit(); - } - return true; - } - return false; - } - - /** - * Called by {@link PreferenceScreen#onClick()} in order to navigate to a new screen of - * preferences. Calls - * {@link PreferenceFragmentCompat.OnPreferenceStartScreenCallback#onPreferenceStartScreen} - * if the target fragment or containing activity implements - * {@link PreferenceFragmentCompat.OnPreferenceStartScreenCallback}. - * - * @param preferenceScreen The {@link PreferenceScreen} to navigate to - */ - @Override - public void onNavigateToScreen(PreferenceScreen preferenceScreen) { - boolean handled = false; - if (getCallbackFragment() instanceof OnPreferenceStartScreenCallback) { - handled = ((OnPreferenceStartScreenCallback) getCallbackFragment()) - .onPreferenceStartScreen(this, preferenceScreen); - } - if (!handled && getContext() instanceof OnPreferenceStartScreenCallback) { - ((OnPreferenceStartScreenCallback) getContext()) - .onPreferenceStartScreen(this, preferenceScreen); - } - // Check the Activity as well in case getContext was overridden to return something other - // than the Activity. - if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) { - ((OnPreferenceStartScreenCallback) getActivity()) - .onPreferenceStartScreen(this, preferenceScreen); - } - } - - @Override - @SuppressWarnings("TypeParameterUnusedInFormals") - @Nullable - public <T extends Preference> T findPreference(@NonNull CharSequence key) { - if (mPreferenceManager == null) { - return null; - } - return mPreferenceManager.findPreference(key); - } - - private void requirePreferenceManager() { - if (mPreferenceManager == null) { - throw new RuntimeException("This should be called after super.onCreate."); - } - } - - private void postBindPreferences() { - if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return; - mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget(); - } - - @SuppressWarnings("WeakerAccess") /* synthetic access */ - void bindPreferences() { - final PreferenceScreen preferenceScreen = getPreferenceScreen(); - if (preferenceScreen != null) { - getListView().setAdapter(onCreateAdapter(preferenceScreen)); - preferenceScreen.onAttached(); - } - onBindPreferences(); - } - - private void unbindPreferences() { - getListView().setAdapter(null); - final PreferenceScreen preferenceScreen = getPreferenceScreen(); - if (preferenceScreen != null) { - preferenceScreen.onDetached(); - } - onUnbindPreferences(); - } - - /** - * Used by Settings. - * @hide - */ - @RestrictTo(LIBRARY_GROUP_PREFIX) - protected void onBindPreferences() {} - - /** - * Used by Settings. - * @hide - */ - @RestrictTo(LIBRARY_GROUP_PREFIX) - protected void onUnbindPreferences() {} - - public final RecyclerView getListView() { - return mList; - } - - /** - * Creates the {@link RecyclerView} used to display the preferences. - * Subclasses may override this to return a customized {@link RecyclerView}. - * - * @param inflater The LayoutInflater object that can be used to inflate the - * {@link RecyclerView}. - * @param parent The parent {@link ViewGroup} that the RecyclerView will be attached - * to. This method should not add the view itself, but this can be - * used to generate the layout params of the view. - * @param savedInstanceState If non-null, this view is being re-constructed from a previous - * saved state as given here. - * @return A new {@link RecyclerView} object to be placed into the view hierarchy - */ - @SuppressWarnings("deprecation") - public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, - Bundle savedInstanceState) { - // If device detected is Auto, use Auto's custom layout that contains a custom ViewGroup - // wrapping a RecyclerView - if (getContext().getPackageManager().hasSystemFeature(PackageManager - .FEATURE_AUTOMOTIVE)) { - RecyclerView recyclerView = parent.findViewById(R.id.recycler_view); - if (recyclerView != null) { - return recyclerView; - } - } - RecyclerView recyclerView = (RecyclerView) inflater - .inflate(R.layout.preference_recyclerview, parent, false); - - recyclerView.setLayoutManager(onCreateLayoutManager()); - recyclerView.setAccessibilityDelegateCompat( - new PreferenceRecyclerViewAccessibilityDelegate(recyclerView)); - - return recyclerView; - } - - /** - * Called from {@link #onCreateRecyclerView} to create the {@link RecyclerView.LayoutManager} - * for the created {@link RecyclerView}. - * - * @return A new {@link RecyclerView.LayoutManager} instance - */ - public RecyclerView.LayoutManager onCreateLayoutManager() { - return new LinearLayoutManager(getContext()); - } - - /** - * Creates the root adapter. - * - * @param preferenceScreen The {@link PreferenceScreen} object to create the adapter for - * @return An adapter that contains the preferences contained in this {@link PreferenceScreen} - */ - protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { - return new PreferenceGroupAdapter(preferenceScreen); - } - - /** - * Called when a preference in the tree requests to display a dialog. Subclasses should - * override this method to display custom dialogs or to handle dialogs for custom preference - * classes. - * - * @param preference The {@link Preference} object requesting the dialog - */ - @Override - public void onDisplayPreferenceDialog(Preference preference) { - - boolean handled = false; - if (getCallbackFragment() instanceof OnPreferenceDisplayDialogCallback) { - handled = ((OnPreferenceDisplayDialogCallback) getCallbackFragment()) - .onPreferenceDisplayDialog(this, preference); - } - if (!handled && getContext() instanceof OnPreferenceDisplayDialogCallback) { - handled = ((OnPreferenceDisplayDialogCallback) getContext()) - .onPreferenceDisplayDialog(this, preference); - } - // Check the Activity as well in case getContext was overridden to return something other - // than the Activity. - if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) { - handled = ((OnPreferenceDisplayDialogCallback) getActivity()) - .onPreferenceDisplayDialog(this, preference); - } - - if (handled) { - return; - } - - // check if dialog is already showing - if (getParentFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) { - return; - } - - final DialogFragment f; - if (preference instanceof EditTextPreference) { - f = EditTextPreferenceDialogFragmentCompat.newInstance(preference.getKey()); - } else if (preference instanceof ListPreference) { - f = ListPreferenceDialogFragmentCompat.newInstance(preference.getKey()); - } else if (preference instanceof MultiSelectListPreference) { - f = MultiSelectListPreferenceDialogFragmentCompat.newInstance(preference.getKey()); - } else { - throw new IllegalArgumentException( - "Cannot display dialog for an unknown Preference type: " - + preference.getClass().getSimpleName() - + ". Make sure to implement onPreferenceDisplayDialog() to handle " - + "displaying a custom dialog for this Preference."); - } - f.setTargetFragment(this, 0); - f.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG); - } - - /** - * A wrapper for getParentFragment which is v17+. Used by the leanback preference lib. - * - * @return The {@link Fragment} to possibly use as a callback - * @hide - */ - @RestrictTo(LIBRARY_GROUP_PREFIX) - public Fragment getCallbackFragment() { - return null; - } - - public void scrollToPreference(final String key) { - scrollToPreferenceInternal(null, key); - } - - public void scrollToPreference(final Preference preference) { - scrollToPreferenceInternal(preference, null); - } - - private void scrollToPreferenceInternal(final Preference preference, final String key) { - final Runnable r = new Runnable() { - @Override - public void run() { - final RecyclerView.Adapter adapter = mList.getAdapter(); - if (!(adapter instanceof - PreferenceGroup.PreferencePositionCallback)) { - if (adapter != null) { - throw new IllegalStateException("Adapter must implement " - + "PreferencePositionCallback"); - } else { - // Adapter was set to null, so don't scroll - return; - } - } - final int position; - if (preference != null) { - position = ((PreferenceGroup.PreferencePositionCallback) adapter) - .getPreferenceAdapterPosition(preference); - } else { - position = ((PreferenceGroup.PreferencePositionCallback) adapter) - .getPreferenceAdapterPosition(key); - } - if (position != RecyclerView.NO_POSITION) { - mList.scrollToPosition(position); - } else { - // Item not found, wait for an update and try again - adapter.registerAdapterDataObserver( - new ScrollToPreferenceObserver(adapter, mList, preference, key)); - } - } - }; - if (mList == null) { - mSelectPreferenceRunnable = r; - } else { - r.run(); - } - } - - /** - * Interface that the fragment's containing activity should implement to be able to process - * preference items that wish to switch to a specified fragment. - */ - public interface OnPreferenceStartFragmentCallback { - /** - * Called when the user has clicked on a preference that has a fragment class name - * associated with it. The implementation should instantiate and switch to an instance - * of the given fragment. - * - * @param caller The fragment requesting navigation - * @param pref The preference requesting the fragment - * @return {@code true} if the fragment creation has been handled - */ - boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref); - } - - /** - * Interface that the fragment's containing activity should implement to be able to process - * preference items that wish to switch to a new screen of preferences. - */ - public interface OnPreferenceStartScreenCallback { - /** - * Called when the user has clicked on a {@link PreferenceScreen} in order to navigate to - * a new screen of preferences. - * - * @param caller The fragment requesting navigation - * @param pref The preference screen to navigate to - * @return {@code true} if the screen navigation has been handled - */ - boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref); - } - - /** - * Interface that the fragment's containing activity should implement to be able to process - * preference items that wish to display a dialog. - */ - public interface OnPreferenceDisplayDialogCallback { - /** - * @param caller The fragment containing the preference requesting the dialog - * @param pref The preference requesting the dialog - * @return {@code true} if the dialog creation has been handled - */ - boolean onPreferenceDisplayDialog(@NonNull PreferenceFragmentCompat caller, - Preference pref); - } - - private static class ScrollToPreferenceObserver extends RecyclerView.AdapterDataObserver { - private final RecyclerView.Adapter mAdapter; - private final RecyclerView mList; - private final Preference mPreference; - private final String mKey; - - public ScrollToPreferenceObserver(RecyclerView.Adapter adapter, RecyclerView list, - Preference preference, String key) { - mAdapter = adapter; - mList = list; - mPreference = preference; - mKey = key; - } - - private void scrollToPreference() { - mAdapter.unregisterAdapterDataObserver(this); - final int position; - if (mPreference != null) { - position = ((PreferenceGroup.PreferencePositionCallback) mAdapter) - .getPreferenceAdapterPosition(mPreference); - } else { - position = ((PreferenceGroup.PreferencePositionCallback) mAdapter) - .getPreferenceAdapterPosition(mKey); - } - if (position != RecyclerView.NO_POSITION) { - mList.scrollToPosition(position); - } - } - - @Override - public void onChanged() { - scrollToPreference(); - } - - @Override - public void onItemRangeChanged(int positionStart, int itemCount) { - scrollToPreference(); - } - - @Override - public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { - scrollToPreference(); - } - - @Override - public void onItemRangeInserted(int positionStart, int itemCount) { - scrollToPreference(); - } - - @Override - public void onItemRangeRemoved(int positionStart, int itemCount) { - scrollToPreference(); - } - - @Override - public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { - scrollToPreference(); - } - } - - private class DividerDecoration extends RecyclerView.ItemDecoration { - - private Drawable mDivider; - private int mDividerHeight; - private boolean mAllowDividerAfterLastItem = true; - - DividerDecoration() {} - - @Override - public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { - if (mDivider == null) { - return; - } - final int childCount = parent.getChildCount(); - final int width = parent.getWidth(); - for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) { - final View view = parent.getChildAt(childViewIndex); - if (shouldDrawDividerBelow(view, parent)) { - int top = (int) view.getY() + view.getHeight(); - mDivider.setBounds(0, top, width, top + mDividerHeight); - mDivider.draw(c); - } - } - } - - @Override - public void getItemOffsets(Rect outRect, View view, RecyclerView parent, - RecyclerView.State state) { - if (shouldDrawDividerBelow(view, parent)) { - outRect.bottom = mDividerHeight; - } - } - - private boolean shouldDrawDividerBelow(View view, RecyclerView parent) { - final RecyclerView.ViewHolder holder = parent.getChildViewHolder(view); - final boolean dividerAllowedBelow = holder instanceof PreferenceViewHolder - && ((PreferenceViewHolder) holder).isDividerAllowedBelow(); - if (!dividerAllowedBelow) { - return false; - } - boolean nextAllowed = mAllowDividerAfterLastItem; - int index = parent.indexOfChild(view); - if (index < parent.getChildCount() - 1) { - final View nextView = parent.getChildAt(index + 1); - final RecyclerView.ViewHolder nextHolder = parent.getChildViewHolder(nextView); - nextAllowed = nextHolder instanceof PreferenceViewHolder - && ((PreferenceViewHolder) nextHolder).isDividerAllowedAbove(); - } - return nextAllowed; - } - - public void setDivider(Drawable divider) { - if (divider != null) { - mDividerHeight = divider.getIntrinsicHeight(); - } else { - mDividerHeight = 0; - } - mDivider = divider; - mList.invalidateItemDecorations(); - } - - public void setDividerHeight(int dividerHeight) { - mDividerHeight = dividerHeight; - mList.invalidateItemDecorations(); - } - - public void setAllowDividerAfterLastItem(boolean allowDividerAfterLastItem) { - mAllowDividerAfterLastItem = allowDividerAfterLastItem; - } - } -}
diff --git a/third_party/apple_apsl/README.chromium b/third_party/apple_apsl/README.chromium index e4b86f3..361d5fa 100644 --- a/third_party/apple_apsl/README.chromium +++ b/third_party/apple_apsl/README.chromium
@@ -7,11 +7,12 @@ Four files are excerpted here: malloc.h from: -http://www.opensource.apple.com/source/Libc/Libc-763.11/include/malloc/malloc.h +https://opensource.apple.com/source/libmalloc/libmalloc-283/include/malloc/malloc.h Modifications: - Modified #ifdef guards. - Removed everything but the definition of malloc_zone_t. +- Added a header for the definition of boolean_t. - Renamed _malloc_zone_t to ChromeMallocZone to avoid possible name conflicts. CFRuntime.h from:
diff --git a/third_party/apple_apsl/malloc.h b/third_party/apple_apsl/malloc.h index 9fd1d5d..1af648d 100644 --- a/third_party/apple_apsl/malloc.h +++ b/third_party/apple_apsl/malloc.h
@@ -24,6 +24,8 @@ #ifndef THIRD_PARTY_APPLE_APSL_MALLOC_H_ #define THIRD_PARTY_APPLE_APSL_MALLOC_H_ +#include <mach/boolean.h> + typedef struct _ChromeMallocZone { /* Only zone implementors should depend on the layout of this structure; Regular callers should use the access functions below */ @@ -53,6 +55,13 @@ /* Empty out caches in the face of memory pressure. The callback may be NULL. Present in version >= 8. */ size_t (*pressure_relief)(struct _malloc_zone_t *zone, size_t goal); + + /* + * Checks whether an address might belong to the zone. May be NULL. Present in version >= 10. + * False positives are allowed (e.g. the pointer was freed, or it's in zone space that has + * not yet been allocated. False negatives are not allowed. + */ + boolean_t (*claimed_address)(struct _malloc_zone_t *zone, void *ptr); } ChromeMallocZone; #endif // THIRD_PARTY_APPLE_APSL_MALLOC_H_
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index e48968a..a5bdf4e 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -370,7 +370,7 @@ // local root's view, and it will be an empty bounds if there is no focused // element. FocusedElementChanged(bool is_editable_element, - gfx.mojom.Rect bounds_in_frame_widget); + gfx.mojom.Rect bounds_in_frame_widget, blink.mojom.FocusType focus_type); // Show a popup menu using native controls on Mac or Android. // The popup menu is hidden when the mojo channel is closed.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index aad09090..f435cf7 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -189,6 +189,7 @@ BLINK_PLATFORM_EXPORT static void EnableWebXRAnchors(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRARModule(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRCameraAccess(bool); + BLINK_PLATFORM_EXPORT static void EnableWebXRDepth(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRHitTest(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRLightEstimation(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRPlaneDetection(bool);
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 8fd82a0..51f4c2c 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -165,8 +165,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_dynamics_compressor_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_config.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_config.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_event_source_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_event_source_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_extendable_cookie_change_event_init.cc", @@ -689,6 +687,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_usb_device_request_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_configuration.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_configuration.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_config.cc", @@ -1062,6 +1062,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_user_verification_requirement.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_acceleration_preference.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_acceleration_preference.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_webgl_power_preference.cc", @@ -2065,6 +2067,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_anchor_set.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_bounded_reference_space.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_bounded_reference_space.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_depth_information.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_depth_information.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_dom_overlay_state.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_dom_overlay_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_xr_frame.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 0672667..b31585e6 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -747,7 +747,6 @@ "//third_party/blink/renderer/modules/webcodecs/encoded_audio_config.idl", "//third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.idl", "//third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_init.idl", - "//third_party/blink/renderer/modules/webcodecs/encoded_video_config.idl", "//third_party/blink/renderer/modules/webcodecs/image_decoder.idl", "//third_party/blink/renderer/modules/webcodecs/image_decoder_init.idl", "//third_party/blink/renderer/modules/webcodecs/image_frame.idl", @@ -755,6 +754,7 @@ "//third_party/blink/renderer/modules/webcodecs/plane.idl", "//third_party/blink/renderer/modules/webcodecs/plane_init.idl", "//third_party/blink/renderer/modules/webcodecs/video_decoder.idl", + "//third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl", "//third_party/blink/renderer/modules/webcodecs/video_decoder_init.idl", "//third_party/blink/renderer/modules/webcodecs/video_encoder.idl", "//third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl", @@ -764,6 +764,7 @@ "//third_party/blink/renderer/modules/webcodecs/video_frame.idl", "//third_party/blink/renderer/modules/webcodecs/video_frame_init.idl", "//third_party/blink/renderer/modules/webcodecs/video_frame_output_callback.idl", + "//third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl", "//third_party/blink/renderer/modules/webcodecs/video_track_reader.idl", "//third_party/blink/renderer/modules/webcodecs/video_track_writer_parameters.idl", "//third_party/blink/renderer/modules/webcodecs/web_codecs_error_callback.idl", @@ -975,6 +976,7 @@ "//third_party/blink/renderer/modules/xr/xr_anchor.idl", "//third_party/blink/renderer/modules/xr/xr_anchor_set.idl", "//third_party/blink/renderer/modules/xr/xr_bounded_reference_space.idl", + "//third_party/blink/renderer/modules/xr/xr_depth_information.idl", "//third_party/blink/renderer/modules/xr/xr_dom_overlay_init.idl", "//third_party/blink/renderer/modules/xr/xr_dom_overlay_state.idl", "//third_party/blink/renderer/modules/xr/xr_frame.idl",
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index 0f00c3c..74a9dac4 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -3050,7 +3050,7 @@ default_value: "nullptr", type_name: "QuotesData", converter: "ConvertQuotes", - keywords: ["none"], + keywords: ["auto", "none"], typedom_types: ["Keyword"] }, {
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index aaeadfa9..9903598 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -4917,8 +4917,11 @@ const CSSValue* Quotes::ParseSingleValue(CSSParserTokenRange& range, const CSSParserContext& context, const CSSParserLocalContext&) const { - if (range.Peek().Id() == CSSValueID::kNone) - return css_parsing_utils::ConsumeIdent(range); + if (auto* value = + css_parsing_utils::ConsumeIdent<CSSValueID::kAuto, CSSValueID::kNone>( + range)) { + return value; + } CSSValueList* values = CSSValueList::CreateSpaceSeparated(); while (!range.AtEnd()) { CSSStringValue* parsed_value = css_parsing_utils::ConsumeString(range); @@ -4936,11 +4939,8 @@ const SVGComputedStyle&, const LayoutObject*, bool allow_visited_style) const { - if (!style.Quotes()) { - // TODO(ramya.v): We should return the quote values that we're actually - // using. - return nullptr; - } + if (!style.Quotes()) + return CSSIdentifierValue::Create(CSSValueID::kAuto); if (style.Quotes()->size()) { CSSValueList* list = CSSValueList::CreateSpaceSeparated(); for (int i = 0; i < style.Quotes()->size(); i++) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index 47be63f..68eaa37 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1384,8 +1384,10 @@ } return quotes; } - DCHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueID::kNone); - return QuotesData::Create(); + if (To<CSSIdentifierValue>(value).GetValueID() == CSSValueID::kNone) + return QuotesData::Create(); + DCHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueID::kAuto); + return nullptr; } LengthSize StyleBuilderConverter::ConvertRadius(StyleResolverState& state,
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 2654a31b..d6056a1 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3157,7 +3157,8 @@ if (focused_element_.Get()) { Element* old_focused_element = focused_element_; focused_element_ = nullptr; - NotifyFocusedElementChanged(old_focused_element, nullptr); + NotifyFocusedElementChanged(old_focused_element, nullptr, + mojom::blink::FocusType::kNone); } sequential_focus_navigation_starting_point_ = nullptr; @@ -5199,8 +5200,10 @@ } } - if (!focus_change_blocked) - NotifyFocusedElementChanged(old_focused_element, focused_element_.Get()); + if (!focus_change_blocked) { + NotifyFocusedElementChanged(old_focused_element, focused_element_.Get(), + params.type); + } UpdateStyleAndLayoutTree(); if (LocalFrame* frame = GetFrame()) @@ -5214,7 +5217,8 @@ mojom::blink::FocusType::kNone, nullptr)); } -void Document::SendFocusNotification(Element* new_focused_element) { +void Document::SendFocusNotification(Element* new_focused_element, + mojom::blink::FocusType focus_type) { if (!GetPage()) return; @@ -5244,12 +5248,13 @@ element_bounds = gfx::Rect(rect); } - GetFrame()->GetLocalFrameHostRemote().FocusedElementChanged(is_editable, - element_bounds); + GetFrame()->GetLocalFrameHostRemote().FocusedElementChanged( + is_editable, element_bounds, focus_type); } void Document::NotifyFocusedElementChanged(Element* old_focused_element, - Element* new_focused_element) { + Element* new_focused_element, + mojom::blink::FocusType focus_type) { // |old_focused_element| may not belong to this document by invoking // adoptNode in event handlers during moving the focus to the new element. DCHECK(!new_focused_element || new_focused_element->GetDocument() == this); @@ -5263,7 +5268,7 @@ GetPage()->GetValidationMessageClient().DidChangeFocusTo( new_focused_element); - SendFocusNotification(new_focused_element); + SendFocusNotification(new_focused_element, focus_type); Document* old_document = old_focused_element ? &old_focused_element->GetDocument() : nullptr;
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 9f98651..fe69959 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -1167,7 +1167,7 @@ // updating focus appearance. bool WillUpdateFocusAppearance() const; - void SendFocusNotification(Element*); + void SendFocusNotification(Element*, mojom::blink::FocusType); bool IsDNSPrefetchEnabled() const { return is_dns_prefetch_enabled_; } void ParseDNSPrefetchControlHeader(const String&); @@ -1782,7 +1782,8 @@ } void NotifyFocusedElementChanged(Element* old_focused_element, - Element* new_focused_element); + Element* new_focused_element, + mojom::blink::FocusType focus_type); void DisplayNoneChangedForFrame(); // Handles a connection error to |has_trust_tokens_answerer_| by rejecting all
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index 2352e586..b064a97 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -13584,7 +13584,8 @@ // FakeLocalFrameHost: void FocusedElementChanged(bool is_editable_element, - const gfx::Rect& bounds_in_frame_widget) override { + const gfx::Rect& bounds_in_frame_widget, + blink::mojom::FocusType focus_type) override { did_notify_ = true; }
diff --git a/third_party/blink/renderer/core/frame/root_frame_viewport.h b/third_party/blink/renderer/core/frame/root_frame_viewport.h index b2c9e412..89baa70 100644 --- a/third_party/blink/renderer/core/frame/root_frame_viewport.h +++ b/third_party/blink/renderer/core/frame/root_frame_viewport.h
@@ -9,7 +9,7 @@ #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/scroll/scrollable_area.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -95,12 +95,10 @@ cc::Layer* LayerForHorizontalScrollbar() const override; cc::Layer* LayerForVerticalScrollbar() const override; cc::Layer* LayerForScrollCorner() const override; - int HorizontalScrollbarHeight( - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; - int VerticalScrollbarWidth( - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; + int HorizontalScrollbarHeight(OverlayScrollbarClipBehavior = + kIgnoreOverlayScrollbarSize) const override; + int VerticalScrollbarWidth(OverlayScrollbarClipBehavior = + kIgnoreOverlayScrollbarSize) const override; ScrollResult UserScroll(ScrollGranularity, const FloatSize&, ScrollableArea::ScrollCallback on_finish) override;
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc index 15d463d6..f424381 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -632,7 +632,9 @@ int thumb_thickness = theme.ThumbThickness(scale); int scrollbar_margin = theme.ScrollbarMargin(scale); cc::ScrollbarOrientation cc_orientation = - orientation == kHorizontalScrollbar ? cc::HORIZONTAL : cc::VERTICAL; + orientation == kHorizontalScrollbar + ? cc::ScrollbarOrientation::HORIZONTAL + : cc::ScrollbarOrientation::VERTICAL; scrollbar_layer = cc::SolidColorScrollbarLayer::Create( cc_orientation, thumb_thickness, scrollbar_margin, /*is_left_side_vertical_scrollbar*/ false);
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index e8f8b43..ff13dfd 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -2603,7 +2603,7 @@ EXPECT_FALSE(scrollbar->HitTestable()); EXPECT_TRUE(scrollbar->IsScrollbarLayerForTesting()); EXPECT_EQ( - cc::VERTICAL, + cc::ScrollbarOrientation::VERTICAL, static_cast<const cc::ScrollbarLayerBase*>(scrollbar)->orientation()); EXPECT_EQ(gfx::Size(7, 393), scrollbar->bounds()); EXPECT_EQ(gfx::Vector2dF(393, 0), scrollbar->offset_to_transform_parent());
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc index f93494ee..1bbde6b3 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -491,7 +491,8 @@ void HTMLVideoElement::DidEnterFullscreen() { UpdateControlsVisibility(); - if (DisplayType() == WebMediaPlayer::DisplayType::kPictureInPicture) { + if (DisplayType() == WebMediaPlayer::DisplayType::kPictureInPicture && + !IsInAutoPIP()) { PictureInPictureController::From(GetDocument()) .ExitPictureInPicture(this, nullptr); }
diff --git a/third_party/blink/renderer/core/html/media/html_video_element_test.cc b/third_party/blink/renderer/core/html/media/html_video_element_test.cc index d18d9a18..37ec61c 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element_test.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element_test.cc
@@ -191,4 +191,17 @@ EXPECT_TRUE(video()->HasAvailableVideoFrame()); } +TEST_F(HTMLVideoElementTest, AutoPIPExitPIPTest) { + video()->SetSrc("http://example.com/foo.mp4"); + test::RunPendingTasks(); + + // Set in auto PIP. + video()->OnBecamePersistentVideo(true); + + // Shouldn't get to PictureInPictureController::ExitPictureInPicture + // and fail the DCHECK. + EXPECT_NO_FATAL_FAILURE(video()->DidEnterFullscreen()); + test::RunPendingTasks(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 070bb2e5..1b6d318 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -30,7 +30,7 @@ #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/min_max_sizes.h" #include "third_party/blink/renderer/core/layout/overflow_model.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" namespace blink { @@ -1325,14 +1325,14 @@ // Returns the intersection of all overflow clips which apply. virtual PhysicalRect OverflowClipRect( const PhysicalOffset& location, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const; + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize) const; PhysicalRect ClipRect(const PhysicalOffset& location) const; // This version is for legacy code that has not switched to the new physical // geometry yet. LayoutRect OverflowClipRect(const LayoutPoint& location, OverlayScrollbarClipBehavior behavior = - kIgnorePlatformOverlayScrollbarSize) const { + kIgnoreOverlayScrollbarSize) const { return OverflowClipRect(PhysicalOffset(location), behavior).ToLayoutRect(); } @@ -1801,7 +1801,7 @@ void ExcludeScrollbars( PhysicalRect&, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const; + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize) const; LayoutUnit ContainingBlockLogicalWidthForPositioned( const LayoutBoxModelObject* containing_block,
diff --git a/third_party/blink/renderer/core/layout/layout_file_upload_control.h b/third_party/blink/renderer/core/layout/layout_file_upload_control.h index 372714a..a9869961 100644 --- a/third_party/blink/renderer/core/layout/layout_file_upload_control.h +++ b/third_party/blink/renderer/core/layout/layout_file_upload_control.h
@@ -23,7 +23,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/layout/layout_block_flow.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" namespace blink {
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 6c34d774..08f804d 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1752,7 +1752,7 @@ FloatClipRect clip_rect((FloatRect(rect))); intersects = GeometryMapper::LocalToAncestorVisualRect( container_properties, ancestor->FirstFragment().ContentsProperties(), - clip_rect, kIgnorePlatformOverlayScrollbarSize, + clip_rect, kIgnoreOverlayScrollbarSize, (visual_rect_flags & kEdgeInclusive) ? kInclusiveIntersect : kNonInclusiveIntersect); rect = PhysicalRect::EnclosingRect(clip_rect.Rect());
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h index 6c57542..1f99679 100644 --- a/third_party/blink/renderer/core/layout/layout_table.h +++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -31,7 +31,7 @@ #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/layout/layout_block.h" #include "third_party/blink/renderer/core/layout/ng/table/layout_ng_table_interface.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -472,10 +472,9 @@ LayoutUnit ConvertStyleLogicalHeightToComputedHeight( const Length& style_logical_height) const; - PhysicalRect OverflowClipRect( - const PhysicalOffset& location, - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; + PhysicalRect OverflowClipRect(const PhysicalOffset& location, + OverlayScrollbarClipBehavior = + kIgnoreOverlayScrollbarSize) const override; void ComputeVisualOverflow(bool recompute_floats) final;
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h index 0fb838d..d44e74b 100644 --- a/third_party/blink/renderer/core/layout/layout_view.h +++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -30,7 +30,7 @@ #include "third_party/blink/renderer/core/layout/layout_block_flow.h" #include "third_party/blink/renderer/core/layout/layout_state.h" #include "third_party/blink/renderer/core/scroll/scrollable_area.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/casting.h" @@ -161,10 +161,9 @@ MapCoordinatesFlags mode = 0) const override; PhysicalRect ViewRect() const override; - PhysicalRect OverflowClipRect( - const PhysicalOffset& location, - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; + PhysicalRect OverflowClipRect(const PhysicalOffset& location, + OverlayScrollbarClipBehavior = + kIgnoreOverlayScrollbarSize) const override; // If either direction has a non-auto mode, the other must as well. void SetAutosizeScrollbarModes(mojom::blink::ScrollbarMode h_mode,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h index e55f7e8..d1ad96b0 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -13,7 +13,7 @@ #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h" #include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h" #include "third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -167,7 +167,7 @@ // and change them to use NG geometry types once LayoutNG supports overflow. PhysicalRect OverflowClipRect( const PhysicalOffset& location, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const; + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize) const; LayoutSize PixelSnappedScrolledContentOffset() const; PhysicalSize ScrollSize() const;
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc index 1572481..279a5d9 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -998,8 +998,10 @@ EXPECT_TRUE(scroll_node->user_scrollable_horizontal); EXPECT_TRUE(scroll_node->user_scrollable_vertical); - EXPECT_TRUE(ScrollbarLayerForScrollNode(scroll_node, cc::HORIZONTAL)); - EXPECT_TRUE(ScrollbarLayerForScrollNode(scroll_node, cc::VERTICAL)); + EXPECT_TRUE(ScrollbarLayerForScrollNode( + scroll_node, cc::ScrollbarOrientation::HORIZONTAL)); + EXPECT_TRUE(ScrollbarLayerForScrollNode(scroll_node, + cc::ScrollbarOrientation::VERTICAL)); } TEST_P(ScrollingTest, overflowHidden) { @@ -1045,8 +1047,10 @@ const auto* scroll_node = ScrollNodeForScrollableArea(inner_frame_view->LayoutViewport()); ASSERT_TRUE(scroll_node); - EXPECT_TRUE(ScrollbarLayerForScrollNode(scroll_node, cc::HORIZONTAL)); - EXPECT_TRUE(ScrollbarLayerForScrollNode(scroll_node, cc::VERTICAL)); + EXPECT_TRUE(ScrollbarLayerForScrollNode( + scroll_node, cc::ScrollbarOrientation::HORIZONTAL)); + EXPECT_TRUE(ScrollbarLayerForScrollNode(scroll_node, + cc::ScrollbarOrientation::VERTICAL)); } TEST_P(ScrollingTest, rtlIframe) { @@ -1111,8 +1115,8 @@ ScrollNodeForScrollableArea(frame_view->LayoutViewport()); ASSERT_TRUE(scroll_node); - const auto* horizontal_scrollbar_layer = - ScrollbarLayerForScrollNode(scroll_node, cc::HORIZONTAL); + const auto* horizontal_scrollbar_layer = ScrollbarLayerForScrollNode( + scroll_node, cc::ScrollbarOrientation::HORIZONTAL); ASSERT_TRUE(horizontal_scrollbar_layer); // TODO(crbug.com/1029620): CAP needs more accurate contents_opaque. if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { @@ -1122,7 +1126,8 @@ horizontal_scrollbar_layer->contents_opaque()); } - EXPECT_FALSE(ScrollbarLayerForScrollNode(scroll_node, cc::VERTICAL)); + EXPECT_FALSE(ScrollbarLayerForScrollNode(scroll_node, + cc::ScrollbarOrientation::VERTICAL)); } TEST_P(ScrollingTest, NestedIFramesMainThreadScrollingRegion) {
diff --git a/third_party/blink/renderer/core/paint/clip_rects_cache.h b/third_party/blink/renderer/core/paint/clip_rects_cache.h index 6730fa1c..2b82d78 100644 --- a/third_party/blink/renderer/core/paint/clip_rects_cache.h +++ b/third_party/blink/renderer/core/paint/clip_rects_cache.h
@@ -8,7 +8,7 @@ #include "third_party/blink/renderer/core/paint/clip_rects.h" #if DCHECK_IS_ON() -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" // For OverlayScrollbarClipBehavior. +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #endif namespace blink { @@ -37,7 +37,7 @@ : root(nullptr) #if DCHECK_IS_ON() , - overlay_scrollbar_clip_behavior(kIgnorePlatformOverlayScrollbarSize) + overlay_scrollbar_clip_behavior(kIgnoreOverlayScrollbarSize) #endif { }
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc index 7a778f85e..feb341a 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -481,7 +481,7 @@ .CalculateBackgroundClipRect( ClipRectsContext(root_layer_, &root_layer_->GetLayoutObject().FirstFragment(), - cache_slot, kIgnorePlatformOverlayScrollbarSize, + cache_slot, kIgnoreOverlayScrollbarSize, kIgnoreOverflowClipAndScroll), clip_rect); IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index b909fe7..ad423db 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -58,8 +58,8 @@ #include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h" #include "third_party/blink/renderer/core/paint/paint_result.h" #include "third_party/blink/renderer/platform/graphics/compositing_reasons.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -986,7 +986,7 @@ PaintLayerFragments&, const PaintLayer* root_layer, const CullRect* cull_rect, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize, + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize, ShouldRespectOverflowClipType = kRespectOverflowClip, const PhysicalOffset* offset_from_root = nullptr, const PhysicalOffset& sub_pixel_accumulation = PhysicalOffset()) const; @@ -995,7 +995,7 @@ PaintLayerFragments&, const PaintLayer* root_layer, const CullRect* cull_rect, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize, + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize, ShouldRespectOverflowClipType = kRespectOverflowClip, const PhysicalOffset* offset_from_root = nullptr, const PhysicalOffset& sub_pixel_accumulation = PhysicalOffset()) const;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.cc b/third_party/blink/renderer/core/paint/paint_layer_clipper.cc index dd2996d1..28b216d 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
@@ -475,7 +475,7 @@ context.overlay_scrollbar_clip_behavior; if (is_clipping_root) - clip_behavior = kIgnorePlatformOverlayScrollbarSize; + clip_behavior = kIgnoreOverlayScrollbarSize; FloatClipRect clip_rect(FloatRect(LocalVisualRect(context))); clip_rect.MoveBy(FloatPoint(fragment_data.PaintOffset()));
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper.h b/third_party/blink/renderer/core/paint/paint_layer_clipper.h index a298bcd..a627998c 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper.h +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper.h
@@ -47,8 +47,8 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/paint/clip_rects_cache.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" namespace blink { @@ -71,7 +71,7 @@ const FragmentData* fragment, ClipRectsCacheSlot slot, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior = - kIgnorePlatformOverlayScrollbarSize, + kIgnoreOverlayScrollbarSize, ShouldRespectOverflowClipType root_layer_clip_behavior = kRespectOverflowClip, const PhysicalOffset& sub_pixel_accumulation = PhysicalOffset())
diff --git a/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc b/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc index ae447df..b5c72c8 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
@@ -31,11 +31,11 @@ Element* target = GetDocument().getElementById("target"); PaintLayer* target_paint_layer = ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip, - PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip, + PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); ClipRect background_rect_gm; target_paint_layer @@ -65,11 +65,11 @@ Element* target = GetDocument().getElementById("target"); PaintLayer* target_paint_layer = ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip, - PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip, + PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); ClipRect background_rect_gm; target_paint_layer @@ -99,11 +99,11 @@ Element* target = GetDocument().getElementById("target"); PaintLayer* target_paint_layer = ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip, - PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip, + PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); ClipRect background_rect_gm; target_paint_layer @@ -135,11 +135,11 @@ ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); // When RLS is enabled, the LayoutView will have a composited scrolling layer, // so don't apply an overflow clip. - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip, - PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip, + PhysicalOffset(LayoutUnit(0.25), LayoutUnit(0.35))); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -171,10 +171,10 @@ ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); // When RLS is enabled, the LayoutView will have a composited scrolling layer, // so don't apply an overflow clip. - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -202,10 +202,10 @@ Element* target = GetDocument().getElementById("target"); PaintLayer* target_paint_layer = ToLayoutBoxModelObject(target->GetLayoutObject())->Layer(); - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -276,10 +276,10 @@ )HTML"); LayoutBox* target = ToLayoutBox(GetLayoutObjectByElementId("target")); PaintLayer* target_paint_layer = target->Layer(); - ClipRectsContext context( - GetDocument().GetLayoutView()->Layer(), - &GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(GetDocument().GetLayoutView()->Layer(), + &GetDocument().GetLayoutView()->FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -335,9 +335,9 @@ PaintLayer* layer = ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); - ClipRectsContext context( - layer, &layer->GetLayoutObject().FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(layer, &layer->GetLayoutObject().FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -373,8 +373,7 @@ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); ClipRectsContext context( layer->Parent(), &layer->Parent()->GetLayoutObject().FirstFragment(), - kUncachedClipRects, kIgnorePlatformOverlayScrollbarSize, - kIgnoreOverflowClip); + kUncachedClipRects, kIgnoreOverlayScrollbarSize, kIgnoreOverflowClip); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -622,9 +621,9 @@ ToLayoutBoxModelObject(GetLayoutObjectByElementId("root"))->Layer(); PaintLayer* target = ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); - ClipRectsContext context( - root, &root->GetLayoutObject().FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(root, &root->GetLayoutObject().FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect infinite_rect(LayoutRect::InfiniteIntRect()); PhysicalRect layer_bounds(infinite_rect); ClipRect background_rect(infinite_rect); @@ -657,9 +656,9 @@ ToLayoutBoxModelObject(GetLayoutObjectByElementId("root"))->Layer(); PaintLayer* target = ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); - ClipRectsContext context( - root, &root->GetLayoutObject().FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(root, &root->GetLayoutObject().FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect infinite_rect(LayoutRect::InfiniteIntRect()); PhysicalRect layer_bounds(infinite_rect); ClipRect background_rect(infinite_rect); @@ -693,9 +692,9 @@ ToLayoutBoxModelObject(GetLayoutObjectByElementId("root"))->Layer(); PaintLayer* target = ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer(); - ClipRectsContext context( - root, &root->GetLayoutObject().FirstFragment(), kUncachedClipRects, - kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip); + ClipRectsContext context(root, &root->GetLayoutObject().FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize, + kIgnoreOverflowClip); PhysicalRect infinite_rect(LayoutRect::InfiniteIntRect()); PhysicalRect layer_bounds(infinite_rect); ClipRect background_rect(infinite_rect); @@ -722,9 +721,9 @@ Element* root = GetDocument().getElementById("root"); PaintLayer* root_paint_layer = ToLayoutBoxModelObject(root->GetLayoutObject())->Layer(); - ClipRectsContext context( - root_paint_layer, &root_paint_layer->GetLayoutObject().FirstFragment(), - kUncachedClipRects, kIgnorePlatformOverlayScrollbarSize); + ClipRectsContext context(root_paint_layer, + &root_paint_layer->GetLayoutObject().FirstFragment(), + kUncachedClipRects, kIgnoreOverlayScrollbarSize); PhysicalRect layer_bounds; ClipRect background_rect, foreground_rect; @@ -912,7 +911,7 @@ ClipRectsContext( target_layer.GetLayoutObject().View()->Layer(), &target_layer.GetLayoutObject().View()->FirstFragment(), - kUncachedClipRects, kIgnorePlatformOverlayScrollbarSize, + kUncachedClipRects, kIgnoreOverlayScrollbarSize, kIgnoreOverflowClipAndScroll), clip_rect); EXPECT_EQ(expected_rect, clip_rect.Rect()); @@ -925,7 +924,7 @@ ClipRectsContext( target_layer.GetLayoutObject().View()->Layer(), &target_layer.GetLayoutObject().View()->FirstFragment(), - kUncachedClipRects, kIgnorePlatformOverlayScrollbarSize, + kUncachedClipRects, kIgnoreOverlayScrollbarSize, kIgnoreOverflowClipAndScroll), clip_rect); EXPECT_EQ(expected_rect, clip_rect.Rect());
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc index 0a54dce..502721d9 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -442,7 +442,7 @@ // offsets for each layer fragment. paint_layer_.CollectFragments( layer_fragments, local_painting_info.root_layer, - &local_painting_info.cull_rect, kIgnorePlatformOverlayScrollbarSize, + &local_painting_info.cull_rect, kIgnoreOverlayScrollbarSize, respect_overflow_clip, &offset_from_root, local_painting_info.sub_pixel_accumulation);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 7cc46df..5c425ca1 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -703,11 +703,10 @@ if (this == controller.RootScrollerArea()) { visible_size = controller.RootScrollerVisibleArea(); } else { - visible_size = - PixelSnappedIntRect(GetLayoutBox()->OverflowClipRect( - GetLayoutBox()->Location(), - kIgnorePlatformAndCSSOverlayScrollbarSize)) - .Size(); + visible_size = PixelSnappedIntRect(GetLayoutBox()->OverflowClipRect( + GetLayoutBox()->Location(), + kIgnoreOverlayScrollbarSize)) + .Size(); } // TODO(skobes): We should really ASSERT that contentSize >= visibleSize @@ -839,9 +838,9 @@ } void PaintLayerScrollableArea::ScrollbarFrameRectChanged() { - // Size of non-overlay scrollbar affects overflow clip rect. - if (!HasOverlayScrollbars()) - GetLayoutBox()->SetNeedsPaintPropertyUpdate(); + // Size of non-overlay scrollbar affects overflow clip rect. Size of overlay + // scrollbar effects hit testing rect excluding overlay scrollbars. + GetLayoutBox()->SetNeedsPaintPropertyUpdate(); } bool PaintLayerScrollableArea::ScrollbarsCanBeActive() const { @@ -1255,9 +1254,8 @@ // converse problem seems to happen much less frequently in practice, so we // bias the logic towards preventing unwanted horizontal scrollbars, which // are more common and annoying. - LayoutUnit client_width = - LayoutContentRect(kIncludeScrollbars).Width() - - VerticalScrollbarWidth(kIgnorePlatformAndCSSOverlayScrollbarSize); + LayoutUnit client_width = LayoutContentRect(kIncludeScrollbars).Width() - + VerticalScrollbarWidth(kIgnoreOverlayScrollbarSize); if (NeedsRelayout() && !HadVerticalScrollbarBeforeRelayout()) client_width += VerticalScrollbarWidth(); LayoutUnit scroll_width(ScrollWidth()); @@ -1269,7 +1267,7 @@ bool PaintLayerScrollableArea::HasVerticalOverflow() const { LayoutUnit client_height = LayoutContentRect(kIncludeScrollbars).Height() - - HorizontalScrollbarHeight(kIgnorePlatformAndCSSOverlayScrollbarSize); + HorizontalScrollbarHeight(kIgnoreOverlayScrollbarSize); LayoutUnit scroll_height(ScrollHeight()); LayoutUnit box_y = GetLayoutBox()->Location().Y(); return SnapSizeToPixel(scroll_height, box_y) > @@ -1747,14 +1745,11 @@ OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { if (!HasVerticalScrollbar()) return 0; - if (overlay_scrollbar_clip_behavior == - kIgnorePlatformAndCSSOverlayScrollbarSize && + if (overlay_scrollbar_clip_behavior == kIgnoreOverlayScrollbarSize && GetLayoutBox()->StyleRef().OverflowY() == EOverflow::kOverlay) { return 0; } - if ((overlay_scrollbar_clip_behavior == kIgnorePlatformOverlayScrollbarSize || - overlay_scrollbar_clip_behavior == - kIgnorePlatformAndCSSOverlayScrollbarSize || + if ((overlay_scrollbar_clip_behavior == kIgnoreOverlayScrollbarSize || !VerticalScrollbar()->ShouldParticipateInHitTesting()) && VerticalScrollbar()->IsOverlayScrollbar()) { return 0; @@ -1766,14 +1761,11 @@ OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { if (!HasHorizontalScrollbar()) return 0; - if (overlay_scrollbar_clip_behavior == - kIgnorePlatformAndCSSOverlayScrollbarSize && + if (overlay_scrollbar_clip_behavior == kIgnoreOverlayScrollbarSize && GetLayoutBox()->StyleRef().OverflowX() == EOverflow::kOverlay) { return 0; } - if ((overlay_scrollbar_clip_behavior == kIgnorePlatformOverlayScrollbarSize || - overlay_scrollbar_clip_behavior == - kIgnorePlatformAndCSSOverlayScrollbarSize || + if ((overlay_scrollbar_clip_behavior == kIgnoreOverlayScrollbarSize || !HorizontalScrollbar()->ShouldParticipateInHitTesting()) && HorizontalScrollbar()->IsOverlayScrollbar()) { return 0; @@ -1857,11 +1849,20 @@ } bool PaintLayerScrollableArea::HasOverlayOverflowControls() const { - return HasOverlayScrollbars() || - (!HasScrollbar() && GetLayoutBox()->CanResize()); + if (HasOverlayScrollbars()) + return true; + if (!HasScrollbar() && GetLayoutBox()->CanResize()) + return true; + if (GetLayoutBox()->StyleRef().OverflowX() == EOverflow::kOverlay || + GetLayoutBox()->StyleRef().OverflowY() == EOverflow::kOverlay) + return true; + return false; } -bool PaintLayerScrollableArea::HasNonOverlayOverflowControls() const { +bool PaintLayerScrollableArea::NeedsScrollCorner() const { + // This is one of the differences between platform overlay scrollbars and + // overflow:overlay scrollbars: the former don't need scroll corner, while + // the latter do. HasOverlayScrollbars doesn't include overflow:overlay. return HasScrollbar() && !HasOverlayScrollbars(); } @@ -1910,7 +1911,7 @@ } void PaintLayerScrollableArea::UpdateScrollCornerStyle() { - if (!HasNonOverlayOverflowControls()) { + if (!NeedsScrollCorner()) { if (scroll_corner_) { scroll_corner_->Destroy(); scroll_corner_ = nullptr; @@ -2891,8 +2892,9 @@ void PaintLayerScrollableArea::DidAddScrollbar( Scrollbar& scrollbar, ScrollbarOrientation orientation) { - // Z-order of reparented scrollbar is updated along with the z-order lists. - if (scrollbar.IsOverlayScrollbar()) + // Z-order of recordered overflow controls is updated along with the z-order + // lists. + if (HasOverlayOverflowControls()) layer_->DirtyStackingContextZOrderLists(); ScrollableArea::DidAddScrollbar(scrollbar, orientation); @@ -2902,8 +2904,8 @@ Scrollbar& scrollbar, ScrollbarOrientation orientation) { if (layer_->NeedsReorderOverlayOverflowControls()) { - // Z-order of reparented scrollbar is updated along with the z-order lists. - DCHECK(scrollbar.IsOverlayScrollbar()); + // Z-order of recordered overflow controls is updated along with the z-order + // lists. layer_->DirtyStackingContextZOrderLists(); }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index 1537ad5..fc41101b 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -51,7 +51,7 @@ #include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h" #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h" #include "third_party/blink/renderer/core/scroll/scrollable_area.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/persistent.h" @@ -399,7 +399,7 @@ bool HasOverflowControls() const; bool HasOverlayOverflowControls() const; - bool HasNonOverlayOverflowControls() const; + bool NeedsScrollCorner() const; bool HasOverflow() const { return HasHorizontalOverflow() || HasVerticalOverflow(); @@ -418,12 +418,10 @@ LayoutUnit ScrollWidth() const; LayoutUnit ScrollHeight() const; - int VerticalScrollbarWidth( - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; - int HorizontalScrollbarHeight( - OverlayScrollbarClipBehavior = - kIgnorePlatformOverlayScrollbarSize) const override; + int VerticalScrollbarWidth(OverlayScrollbarClipBehavior = + kIgnoreOverlayScrollbarSize) const override; + int HorizontalScrollbarHeight(OverlayScrollbarClipBehavior = + kIgnoreOverlayScrollbarSize) const override; DoubleSize AdjustedScrollOffset() const { return ToDoubleSize(DoublePoint(ScrollOrigin()) + scroll_offset_);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 9f1ce1b..036d07f 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1637,19 +1637,6 @@ context_.current.clip = border_radius_clip; } -static PhysicalRect OverflowClipRect(const LayoutBox& box, - const PhysicalOffset& offset) { - // TODO(pdr): We should ignore CSS overlay scrollbars for non-root scrollers - // but cannot due to compositing bugs (crbug.com/984167). This special-case is - // here instead of LayoutBox::OverflowClipRect because the layout size of the - // scrolling content is still affected by overlay scrollbar behavior, just not - // the clip. - auto behavior = IsA<LayoutView>(box) - ? kIgnorePlatformAndCSSOverlayScrollbarSize - : kIgnorePlatformOverlayScrollbarSize; - return box.OverflowClipRect(offset, behavior); -} - static bool CanOmitOverflowClip(const LayoutObject& object) { DCHECK(NeedsOverflowClip(object)); @@ -1672,7 +1659,7 @@ // We need OverflowClip for hit-testing if the clip rect excluding overlay // scrollbars is different from the normal clip rect. - auto clip_rect = OverflowClipRect(*block, PhysicalOffset()); + auto clip_rect = block->OverflowClipRect(PhysicalOffset()); auto clip_rect_excluding_overlay_scrollbars = block->OverflowClipRect( PhysicalOffset(), kExcludeOverlayScrollbarSizeForHitTesting); if (clip_rect != clip_rect_excluding_overlay_scrollbars) @@ -1735,8 +1722,8 @@ state.SetClipRect(adjusted_clip_rect, adjusted_clip_rect); } } else if (object_.IsBox()) { - const auto& clip_rect = OverflowClipRect(ToLayoutBox(object_), - context_.current.paint_offset); + const auto& clip_rect = ToLayoutBox(object_).OverflowClipRect( + context_.current.paint_offset); state.SetClipRect(FloatRoundedRect(FloatRect(clip_rect)), ToSnappedClipRect(clip_rect));
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc index ebc20b3f..87b27b8 100644 --- a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc +++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -54,7 +54,7 @@ // Draw a frame around the resizer (1px grey line) if there are any scrollbars // present. Clipping will exclude the right and bottom edges of this frame. - if (GetScrollableArea().HasNonOverlayOverflowControls()) { + if (GetScrollableArea().NeedsScrollCorner()) { GraphicsContextStateSaver state_saver(context); context.Clip(visual_rect); IntRect larger_corner = visual_rect;
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.cc b/third_party/blink/renderer/core/scroll/scrollable_area.cc index 8b1def6..b5c9797 100644 --- a/third_party/blink/renderer/core/scroll/scrollable_area.cc +++ b/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -827,7 +827,7 @@ int ScrollableArea::VerticalScrollbarWidth( OverlayScrollbarClipBehavior behavior) const { - DCHECK_EQ(behavior, kIgnorePlatformOverlayScrollbarSize); + DCHECK_EQ(behavior, kIgnoreOverlayScrollbarSize); if (Scrollbar* vertical_bar = VerticalScrollbar()) return !vertical_bar->IsOverlayScrollbar() ? vertical_bar->Width() : 0; return 0; @@ -835,7 +835,7 @@ int ScrollableArea::HorizontalScrollbarHeight( OverlayScrollbarClipBehavior behavior) const { - DCHECK_EQ(behavior, kIgnorePlatformOverlayScrollbarSize); + DCHECK_EQ(behavior, kIgnoreOverlayScrollbarSize); if (Scrollbar* horizontal_bar = HorizontalScrollbar()) return !horizontal_bar->IsOverlayScrollbar() ? horizontal_bar->Height() : 0; return 0;
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.h b/third_party/blink/renderer/core/scroll/scrollable_area.h index 578ad26c9..8598821 100644 --- a/third_party/blink/renderer/core/scroll/scrollable_area.h +++ b/third_party/blink/renderer/core/scroll/scrollable_area.h
@@ -37,7 +37,7 @@ #include "third_party/blink/renderer/platform/geometry/float_quad.h" #include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/graphics/compositor_element_id.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" @@ -215,6 +215,10 @@ virtual void ContentsResized(); + // This is for platform overlay scrollbars only, doesn't include + // overflow:overlay scrollbars. Probably this should be renamed to + // HasPlatformOverlayScrollbars() but we don't bother it because + // overflow:overlay might be deprecated soon. bool HasOverlayScrollbars() const; void SetScrollbarOverlayColorTheme(ScrollbarOverlayColorTheme); void RecalculateScrollbarOverlayColorTheme(Color); @@ -465,9 +469,9 @@ IntSize ExcludeScrollbars(const IntSize&) const; virtual int VerticalScrollbarWidth( - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const; + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize) const; virtual int HorizontalScrollbarHeight( - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const; + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize) const; virtual LayoutBox* GetLayoutBox() const { return nullptr; }
diff --git a/third_party/blink/renderer/core/scroll/scrollbar.h b/third_party/blink/renderer/core/scroll/scrollbar.h index d116250..66fd17d 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar.h +++ b/third_party/blink/renderer/core/scroll/scrollbar.h
@@ -118,7 +118,13 @@ void Paint(GraphicsContext&, const IntPoint& paint_offset) const; virtual bool IsSolidColor() const; + + // Returns true if the scrollbar is a overlay scrollbar. This doesn't include + // overflow:overlay scrollbars. Probably this should be renamed to + // IsPlatformOverlayScrollbar() but we don't bother it because + // overflow:overlay might be deprecated soon. virtual bool IsOverlayScrollbar() const; + bool ShouldParticipateInHitTesting(); bool IsWindowActive() const;
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc index e9332965..25d451ef 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc +++ b/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
@@ -52,8 +52,8 @@ cc::ScrollbarOrientation ScrollbarLayerDelegate::Orientation() const { if (scrollbar_->Orientation() == kHorizontalScrollbar) - return cc::HORIZONTAL; - return cc::VERTICAL; + return cc::ScrollbarOrientation::HORIZONTAL; + return cc::ScrollbarOrientation::VERTICAL; } bool ScrollbarLayerDelegate::IsLeftSideVerticalScrollbar() const { @@ -112,7 +112,7 @@ } bool ScrollbarLayerDelegate::NeedsRepaintPart(cc::ScrollbarPart part) const { - if (part == cc::THUMB) + if (part == cc::ScrollbarPart::THUMB) return scrollbar_->ThumbNeedsRepaint(); return scrollbar_->TrackNeedsRepaint(); } @@ -161,11 +161,11 @@ ScopedScrollbarPainter painter(*canvas, device_scale_factor_); // The canvas coordinate space is relative to the part's origin. switch (part) { - case cc::THUMB: + case cc::ScrollbarPart::THUMB: theme.PaintThumb(painter.Context(), *scrollbar_, IntRect(rect)); scrollbar_->ClearThumbNeedsRepaint(); break; - case cc::TRACK_BUTTONS_TICKMARKS: { + case cc::ScrollbarPart::TRACK_BUTTONS_TICKMARKS: { DCHECK_EQ(IntSize(rect.size()), scrollbar_->FrameRect().Size()); IntPoint offset(IntPoint(rect.origin()) - scrollbar_->FrameRect().Location());
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc index d1b341a..5168f1f1 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -164,7 +164,8 @@ void FakeLocalFrameHost::FocusedElementChanged( bool is_editable_element, - const gfx::Rect& bounds_in_frame_widget) {} + const gfx::Rect& bounds_in_frame_widget, + blink::mojom::FocusType focus_type) {} void FakeLocalFrameHost::ShowPopupMenu( mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client,
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/third_party/blink/renderer/core/testing/fake_local_frame_host.h index b10f036b..8eaaaaa3 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.h +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -98,7 +98,8 @@ WTF::Vector<blink::mojom::blink::FaviconURLPtr> favicon_urls) override; void DownloadURL(mojom::blink::DownloadURLParamsPtr params) override; void FocusedElementChanged(bool is_editable_element, - const gfx::Rect& bounds_in_frame_widget) override; + const gfx::Rect& bounds_in_frame_widget, + blink::mojom::FocusType focus_type) override; void ShowPopupMenu( mojo::PendingRemote<mojom::blink::PopupMenuClient> popup_client, const gfx::Rect& bounds,
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc index ac228be3..9b40356 100644 --- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc +++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -242,6 +242,7 @@ if (!EnsureService()) return; + DCHECK(picture_in_picture_session_.is_bound()); picture_in_picture_session_->Stop( WTF::Bind(&PictureInPictureControllerImpl::OnExitedPictureInPicture, WrapPersistent(this), WrapPersistent(resolver)));
diff --git a/third_party/blink/renderer/modules/webcodecs/decoder_template.cc b/third_party/blink/renderer/modules/webcodecs/decoder_template.cc index 9762fa5..47772f51 100644 --- a/third_party/blink/renderer/modules/webcodecs/decoder_template.cc +++ b/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
@@ -18,7 +18,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_chunk.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
diff --git a/third_party/blink/renderer/modules/webcodecs/encoded_video_config.idl b/third_party/blink/renderer/modules/webcodecs/encoded_video_config.idl deleted file mode 100644 index 7af04a6..0000000 --- a/third_party/blink/renderer/modules/webcodecs/encoded_video_config.idl +++ /dev/null
@@ -1,21 +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. - -// https://github.com/WICG/web-codecs - -dictionary EncodedVideoConfig { - // Codec string, eg. "avc1.42001e" or "vp09.00.10.08". - // TODO(sandersd): Accept "avc1" if |description| is provided? - required DOMString codec; - - // avcC, vpcC, or etc. - BufferSource description; - - // If provided, these override in-band configuration. - double sampleAspect; - // TODO(sandersd): color space. - - // TODO(sandersd): Constraints (sequential access) and requirements - // (imagebitmap, colorspace conversion). -};
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc index b958cbd..c9c72b2 100644 --- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc +++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.cc
@@ -10,7 +10,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_image_bitmap_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_config.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h" @@ -45,9 +45,9 @@ return ScriptValue(); } -EncodedVideoConfig* MakeVideoDecoderConfig( +VideoDecoderConfig* MakeVideoDecoderConfig( const wc_fuzzer::ConfigureVideoDecoder& proto) { - auto* config = EncodedVideoConfig::Create(); + auto* config = VideoDecoderConfig::Create(); config->setCodec(proto.codec().c_str()); DOMArrayBuffer* data_copy = DOMArrayBuffer::Create( proto.description().data(), proto.description().size());
diff --git a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h index ef538132b..60780639 100644 --- a/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h +++ b/third_party/blink/renderer/modules/webcodecs/fuzzer_utils.h
@@ -8,7 +8,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_audio_config.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_encode_options.h" @@ -37,7 +37,7 @@ const std::string name_; }; -EncodedVideoConfig* MakeVideoDecoderConfig( +VideoDecoderConfig* MakeVideoDecoderConfig( const wc_fuzzer::ConfigureVideoDecoder& proto); EncodedAudioConfig* MakeAudioDecoderConfig(
diff --git a/third_party/blink/renderer/modules/webcodecs/idls.gni b/third_party/blink/renderer/modules/webcodecs/idls.gni index b97d8fa..0dbbb21 100644 --- a/third_party/blink/renderer/modules/webcodecs/idls.gni +++ b/third_party/blink/renderer/modules/webcodecs/idls.gni
@@ -24,7 +24,6 @@ modules_dictionary_idl_files = [ "audio_decoder_init.idl", - "encoded_video_config.idl", "encoded_video_chunk_init.idl", "encoded_audio_config.idl", "encoded_audio_chunk_init.idl", @@ -32,6 +31,7 @@ "image_frame.idl", "image_track.idl", "plane_init.idl", + "video_decoder_config.idl", "video_decoder_init.idl", "video_encoder_config.idl", "video_encoder_init.idl", @@ -41,7 +41,10 @@ "video_track_writer_parameters.idl", ] -modules_typedefs_enums_only_idl_files = [ "codec_state.idl" ] +modules_typedefs_enums_only_idl_files = [ + "codec_state.idl", + "video_pixel_format.idl", +] # IDL files that either define partial interfaces or target (right side of) # `includes`.
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc index 96ba5052..aa951212 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
@@ -16,7 +16,7 @@ #include "media/media_buildflags.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/modules/webcodecs/codec_config_eval.h" #include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h" @@ -150,9 +150,9 @@ } #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) - // TODO(sandersd): Either remove sizes from VideoDecoderConfig (replace with - // sample aspect) or parse the AvcC here to get the actual size. - // For the moment, hard-code 720p to prefer hardware decoders. + // TODO(sandersd): Use size information from the VideoDecoderConfig when it is + // provided, and figure out how to combine it with the avcC. Update fuzzer to + // match. gfx::Size size = gfx::Size(1280, 720); out_media_config->Initialize(codec, profile,
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.h b/third_party/blink/renderer/modules/webcodecs/video_decoder.h index 3213109..11b19b99 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.h +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.h
@@ -44,8 +44,8 @@ namespace blink { class EncodedVideoChunk; -class EncodedVideoConfig; class ExceptionState; +class VideoDecoderConfig; class VideoDecoderInit; class VideoFrame; class V8VideoFrameOutputCallback; @@ -57,7 +57,7 @@ using MediaOutputType = media::VideoFrame; using MediaDecoderType = media::VideoDecoder; using OutputCallbackType = V8VideoFrameOutputCallback; - using ConfigType = EncodedVideoConfig; + using ConfigType = VideoDecoderConfig; using MediaConfigType = media::VideoDecoderConfig; using InputType = EncodedVideoChunk;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.idl b/third_party/blink/renderer/modules/webcodecs/video_decoder.idl index cb50995fb..b385993 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.idl +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.idl
@@ -39,7 +39,7 @@ // The next decode request must be for a keyframe. // // TODO(sandersd): Move the keyframe rule into the bytestream registry. - [RaisesException] void configure(EncodedVideoConfig config); + [RaisesException] void configure(VideoDecoderConfig config); // Request decoding of an input chunk. //
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl b/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl new file mode 100644 index 0000000..f770f2d --- /dev/null +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_config.idl
@@ -0,0 +1,35 @@ +// 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. + +// https://github.com/WICG/web-codecs + +dictionary VideoDecoderConfig { + // Codec string, eg. "avc1.42001e" or "vp09.00.10.08". + // TODO(sandersd): Should we accept "avc1" when |description| is provided? + required DOMString codec; + + // avcC, vpcC, or etc. + // TODO(sandersd): Define what happens if the parsed description differs from + // the metadata below. + BufferSource description; + + // Hint about the encoded size of the content. + // TODO(sandersd): Draft spec marks these as required. + unsigned long codedWidth; + unsigned long codedHeight; + + // Hint about the visible region of the content. + unsigned long cropLeft; + unsigned long cropTop; + unsigned long cropWidth; + unsigned long cropHeight; + + // Hint about the pixel aspect ratio of the content. + unsigned long displayWidth; + unsigned long displayHeight; + + // TODO(sandersd): color space. + // TODO(sandersd): Constraints (sequential access) and requirements + // (imagebitmap, colorspace conversion). +};
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc index d27c510..73f1b31 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc
@@ -5,7 +5,7 @@ #include "base/run_loop.h" #include "testing/libfuzzer/proto/lpm_interface.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_output_callback.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_web_codecs_error_callback.h"
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc index be28c3d..5b74d84a 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc
@@ -6,7 +6,7 @@ #include "base/run_loop.h" #include "testing/libfuzzer/proto/lpm_interface.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_config.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_output_callback.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_web_codecs_error_callback.h"
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc index 3c613b1..fd90c0f 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -16,6 +16,7 @@ #include "media/renderers/video_frame_yuv_converter.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h" #include "third_party/blink/renderer/core/html/canvas/image_data.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h" @@ -184,7 +185,7 @@ switch (local_frame->format()) { case media::PIXEL_FORMAT_I420: - return "I420"; + return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kI420); default: NOTREACHED();
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.idl b/third_party/blink/renderer/modules/webcodecs/video_frame.idl index 66dc371..028602b 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.idl +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.idl
@@ -4,11 +4,6 @@ // https://github.com/WICG/web-codecs -enum VideoPixelFormat { - // 4:2:0 subsampled planar YUV - "I420" -}; - [ Exposed=(Window,Worker), Serializable,
diff --git a/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl b/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl new file mode 100644 index 0000000..490e6fa --- /dev/null +++ b/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl
@@ -0,0 +1,10 @@ +// 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. + +// https://github.com/WICG/web-codecs + +enum VideoPixelFormat { + // 4:2:0 subsampled planar YUV + "I420" +};
diff --git a/third_party/blink/renderer/modules/xr/BUILD.gn b/third_party/blink/renderer/modules/xr/BUILD.gn index e6144d5..7ce764a1 100644 --- a/third_party/blink/renderer/modules/xr/BUILD.gn +++ b/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -21,6 +21,8 @@ "xr_canvas_input_provider.h", "xr_cube_map.cc", "xr_cube_map.h", + "xr_depth_information.cc", + "xr_depth_information.h", "xr_dom_overlay_state.cc", "xr_dom_overlay_state.h", "xr_frame.cc",
diff --git a/third_party/blink/renderer/modules/xr/idls.gni b/third_party/blink/renderer/modules/xr/idls.gni index 50897f7d..0346ec6 100644 --- a/third_party/blink/renderer/modules/xr/idls.gni +++ b/third_party/blink/renderer/modules/xr/idls.gni
@@ -8,6 +8,7 @@ "xr_anchor.idl", "xr_anchor_set.idl", "xr_bounded_reference_space.idl", + "xr_depth_information.idl", "xr_dom_overlay_state.idl", "xr_frame.idl", "xr_input_source.idl",
diff --git a/third_party/blink/renderer/modules/xr/xr_depth_information.cc b/third_party/blink/renderer/modules/xr/xr_depth_information.cc new file mode 100644 index 0000000..7a0a14cb --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_depth_information.cc
@@ -0,0 +1,25 @@ +// 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 "third_party/blink/renderer/modules/xr/xr_depth_information.h" + +namespace blink { + +DOMUint16Array* XRDepthInformation::data() const { + return nullptr; +} + +uint32_t XRDepthInformation::width() const { + return 0; +} + +uint32_t XRDepthInformation::height() const { + return 0; +} + +float XRDepthInformation::getDepth(uint32_t col, uint32_t row) const { + return 0.0; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_depth_information.h b/third_party/blink/renderer/modules/xr/xr_depth_information.h new file mode 100644 index 0000000..954c21c --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_depth_information.h
@@ -0,0 +1,31 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DEPTH_INFORMATION_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DEPTH_INFORMATION_H_ + +#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/wtf/forward.h" + +namespace blink { + +class XRDepthInformation final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + DOMUint16Array* data() const; + + uint32_t width() const; + + uint32_t height() const; + + float getDepth(uint32_t col, uint32_t row) const; + + private: +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DEPTH_INFORMATION_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_depth_information.idl b/third_party/blink/renderer/modules/xr/xr_depth_information.idl new file mode 100644 index 0000000..433254d --- /dev/null +++ b/third_party/blink/renderer/modules/xr/xr_depth_information.idl
@@ -0,0 +1,16 @@ +// 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. + +[ + SecureContext, + Exposed=Window, + RuntimeEnabled=WebXRDepth +] interface XRDepthInformation { + readonly attribute Uint16Array data; + + readonly attribute unsigned long width; + readonly attribute unsigned long height; + + float getDepth(unsigned long column, unsigned long row); +};
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.cc b/third_party/blink/renderer/modules/xr/xr_frame.cc index 5b1de602..8e6da76 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.cc +++ b/third_party/blink/renderer/modules/xr/xr_frame.cc
@@ -128,6 +128,10 @@ return light_probe->getLightEstimate(); } +XRDepthInformation* XRFrame::getDepthInformation(XRView* view) const { + return nullptr; +} + // Return an XRPose that has a transform of basespace_from_space, while // accounting for the base pose matrix of this frame. If computing a transform // isn't possible, return nullptr.
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.h b/third_party/blink/renderer/modules/xr/xr_frame.h index b19ca82..1e63c4a 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.h +++ b/third_party/blink/renderer/modules/xr/xr_frame.h
@@ -19,6 +19,7 @@ class ExceptionState; class XRAnchorSet; +class XRDepthInformation; class XRHitTestResult; class XRHitTestSource; class XRInputSource; @@ -31,6 +32,7 @@ class XRSpace; class XRTransientInputHitTestResult; class XRTransientInputHitTestSource; +class XRView; class XRViewerPose; class XRWorldInformation; @@ -47,6 +49,7 @@ XRWorldInformation* worldInformation() const { return world_information_; } XRAnchorSet* trackedAnchors() const; XRLightEstimate* getLightEstimate(XRLightProbe*, ExceptionState&) const; + XRDepthInformation* getDepthInformation(XRView* view) const; void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.idl b/third_party/blink/renderer/modules/xr/xr_frame.idl index 17bc688c4..5a0b55ec5 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.idl +++ b/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -29,4 +29,7 @@ [RuntimeEnabled=WebXRLightEstimation, RaisesException] XRLightEstimate? getLightEstimate(XRLightProbe lightProbe); + + [RuntimeEnabled=WebXRDepth] + XRDepthInformation getDepthInformation(XRView view); };
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 08e980ba..7bf42f2bd 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1020,6 +1020,7 @@ "graphics/mutator_client.h", "graphics/offscreen_canvas_placeholder.cc", "graphics/offscreen_canvas_placeholder.h", + "graphics/overlay_scrollbar_clip_behavior.h", "graphics/paint/clip_paint_property_node.cc", "graphics/paint/clip_paint_property_node.h", "graphics/paint/cull_rect.cc", @@ -1117,7 +1118,6 @@ "graphics/replaying_canvas.cc", "graphics/replaying_canvas.h", "graphics/scoped_interpolation_quality.h", - "graphics/scroll_types.h", "graphics/scrollbar_theme_settings.cc", "graphics/scrollbar_theme_settings.h", "graphics/skia/image_pixel_locker.cc",
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index becdaed..e688360 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -471,6 +471,10 @@ RuntimeEnabledFeatures::SetWebXRCameraAccessEnabled(enable); } +void WebRuntimeFeatures::EnableWebXRDepth(bool enable) { + RuntimeEnabledFeatures::SetWebXRDepthEnabled(enable); +} + void WebRuntimeFeatures::EnableWebXRHitTest(bool enable) { RuntimeEnabledFeatures::SetWebXRHitTestEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index bf3c19f..ce59ac7 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -518,7 +518,7 @@ FloatClipRect visual_rect(bounds); GeometryMapper::LocalToAncestorVisualRect( property_tree_state, PropertyTreeState::Root(), visual_rect, - kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect, + kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect, kExpandVisualRectForAnimation); return visual_rect.Rect(); }
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc b/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc index 910fc54..51ceeb1 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc +++ b/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc
@@ -60,18 +60,16 @@ } SkColor InvertColor(SkColor color) const override { - blink::FloatPoint3D rgb = {SkColorGetR(color) / 255.0f, - SkColorGetG(color) / 255.0f, - SkColorGetB(color) / 255.0f}; - blink::FloatPoint3D lab = transformer_.sRGBToLab(rgb); - float invertedL = std::min(110.0f - lab.X(), 100.0f); - lab.SetX(invertedL); + SkV3 rgb = {SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, + SkColorGetB(color) / 255.0f}; + SkV3 lab = transformer_.sRGBToLab(rgb); + lab.x = std::min(110.0f - lab.x, 100.0f); rgb = transformer_.LabToSRGB(lab); SkColor inverted_color = SkColorSetARGB( - SkColorGetA(color), static_cast<unsigned int>(rgb.X() * 255 + 0.5), - static_cast<unsigned int>(rgb.Y() * 255 + 0.5), - static_cast<unsigned int>(rgb.Z() * 255 + 0.5)); + SkColorGetA(color), static_cast<unsigned int>(rgb.x * 255 + 0.5), + static_cast<unsigned int>(rgb.y * 255 + 0.5), + static_cast<unsigned int>(rgb.z * 255 + 0.5)); return AdjustGray(inverted_color); }
diff --git a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc index 9abb2b2..7cffc61 100644 --- a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
@@ -51,30 +51,36 @@ ImageDataBuffer::ImageDataBuffer(scoped_refptr<StaticBitmapImage> image) { if (!image) return; - retained_image_ = image->PaintImageForCurrentFrame().GetSkImage(); - if (!retained_image_) + PaintImage paint_image = image->PaintImageForCurrentFrame(); + if (!paint_image || paint_image.IsPaintWorklet()) return; + + SkImageInfo paint_image_info = paint_image.GetSkImageInfo(); + if (paint_image_info.isEmpty()) + return; + #if defined(MEMORY_SANITIZER) - // Test if retained_image has an initialized pixmap. + // Test if software SKImage has an initialized pixmap. SkPixmap pixmap; - if (retained_image_->peekPixels(&pixmap)) + if (!paint_image.IsTextureBacked() && + paint_image.GetSwSkImage()->peekPixels(&pixmap)) { MSAN_CHECK_MEM_IS_INITIALIZED(pixmap.addr(), pixmap.computeByteSize()); + } #endif - if (retained_image_->isTextureBacked() || - retained_image_->isLazyGenerated() || - retained_image_->alphaType() != kUnpremul_SkAlphaType) { + if (paint_image.IsTextureBacked() || paint_image.IsLazyGenerated() || + paint_image_info.alphaType() != kUnpremul_SkAlphaType) { // Unpremul is handled upfront, using readPixels, which will correctly clamp // premul color values that would otherwise cause overflows in the skia // encoder unpremul logic. - SkColorType colorType = retained_image_->colorType(); + SkColorType colorType = paint_image.GetColorType(); if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) colorType = kN32_SkColorType; // Work around for bug with JPEG encoder const SkImageInfo info = - SkImageInfo::Make(retained_image_->width(), retained_image_->height(), - retained_image_->colorType(), kUnpremul_SkAlphaType, - retained_image_->refColorSpace()); + SkImageInfo::Make(paint_image_info.width(), paint_image_info.height(), + paint_image_info.colorType(), kUnpremul_SkAlphaType, + paint_image_info.refColorSpace()); const size_t rowBytes = info.minRowBytes(); size_t size = info.computeByteSize(rowBytes); if (SkImageInfo::ByteSizeOverflowed(size)) @@ -82,13 +88,15 @@ sk_sp<SkData> data = SkData::MakeUninitialized(size); pixmap_ = {info, data->writable_data(), info.minRowBytes()}; - if (!retained_image_->readPixels(pixmap_, 0, 0)) { + if (!paint_image.readPixels(info, pixmap_.writable_addr(), rowBytes, 0, + 0)) { pixmap_.reset(); return; } MSAN_CHECK_MEM_IS_INITIALIZED(pixmap_.addr(), pixmap_.computeByteSize()); retained_image_ = SkImage::MakeRasterData(info, std::move(data), rowBytes); } else { + retained_image_ = paint_image.GetSwSkImage(); if (!retained_image_->peekPixels(&pixmap_)) return; MSAN_CHECK_MEM_IS_INITIALIZED(pixmap_.addr(), pixmap_.computeByteSize());
diff --git a/third_party/blink/renderer/platform/graphics/lab_color_space.h b/third_party/blink/renderer/platform/graphics/lab_color_space.h index e002057..931c0633 100644 --- a/third_party/blink/renderer/platform/graphics/lab_color_space.h +++ b/third_party/blink/renderer/platform/graphics/lab_color_space.h
@@ -3,167 +3,176 @@ #include <algorithm> #include <cmath> -#include <initializer_list> -#include <iterator> -#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" +#include "base/check.h" +#include "third_party/skia/include/core/SkM44.h" // Class to handle color transformation between RGB and CIE L*a*b* color spaces. namespace LabColorSpace { -using blink::FloatPoint3D; -using blink::TransformationMatrix; - -static constexpr FloatPoint3D kIlluminantD50 = - FloatPoint3D(0.964212f, 1.0f, 0.825188f); -static constexpr FloatPoint3D kIlluminantD65 = - FloatPoint3D(0.95042855f, 1.0f, 1.0889004f); +static constexpr SkV3 kIlluminantD50 = {0.964212f, 1.0f, 0.825188f}; +static constexpr SkV3 kIlluminantD65 = {0.95042855f, 1.0f, 1.0889004f}; // All matrices here are 3x3 matrices. -// They are stored in blink::TransformationMatrix which is 4x4 matrix in the -// following form. +// They are stored in SkM44 which is 4x4 matrix in the following form. // |a b c 0| // |d e f 0| // |g h i 0| // |0 0 0 1| -inline TransformationMatrix mul3x3Diag(const FloatPoint3D& lhs, - const TransformationMatrix& rhs) { - return TransformationMatrix( - lhs.X() * rhs.M11(), lhs.Y() * rhs.M12(), lhs.Z() * rhs.M13(), 0.0f, - lhs.X() * rhs.M21(), lhs.Y() * rhs.M22(), lhs.Z() * rhs.M23(), 0.0f, - lhs.X() * rhs.M31(), lhs.Y() * rhs.M32(), lhs.Z() * rhs.M33(), 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); -} - template <typename T> -inline constexpr T clamp(T x, T min, T max) { +inline constexpr T Clamp(T x, T min, T max) { return x < min ? min : x > max ? max : x; } // See https://en.wikipedia.org/wiki/Chromatic_adaptation#Von_Kries_transform. -inline TransformationMatrix chromaticAdaptation( - const TransformationMatrix& matrix, - const FloatPoint3D& srcWhitePoint, - const FloatPoint3D& dstWhitePoint) { - FloatPoint3D srcLMS = matrix.MapPoint(srcWhitePoint); - FloatPoint3D dstLMS = matrix.MapPoint(dstWhitePoint); - // LMS is a diagonal matrix stored as a float[3] - FloatPoint3D LMS = {dstLMS.X() / srcLMS.X(), dstLMS.Y() / srcLMS.Y(), - dstLMS.Z() / srcLMS.Z()}; - return matrix.Inverse() * mul3x3Diag(LMS, matrix); +inline SkM44 ChromaticAdaptation(const SkM44& matrix, + const SkV3& src_white_point, + const SkV3& dst_white_point) { + SkV3 src_lms = matrix * src_white_point; + SkV3 dst_lms = matrix * dst_white_point; + // |lms| is a diagonal matrix stored as a float[3]. + SkV3 lms = {dst_lms.x / src_lms.x, dst_lms.y / src_lms.y, + dst_lms.z / src_lms.z}; + SkM44 inverse; + bool success = matrix.invert(&inverse); + DCHECK(success); + return inverse * (SkM44::Scale(lms.x, lms.y, lms.z) * matrix); } class sRGBColorSpace { public: - FloatPoint3D toLinear(const FloatPoint3D& v) const { - auto EOTF = [](float u) { - return u < 0.04045f - ? clamp(u / 12.92f, .0f, 1.0f) - : clamp(std::pow((u + 0.055f) / 1.055f, 2.4f), .0f, 1.0f); - }; - return {EOTF(v.X()), EOTF(v.Y()), EOTF(v.Z())}; + sRGBColorSpace() { + bool success = transform_.invert(&inverseTransform_); + DCHECK(success); } - FloatPoint3D fromLinear(const FloatPoint3D& v) const { + SkV3 ToLinear(const SkV3& v) const { + auto EOTF = [](float u) { + return u < 0.04045f + ? Clamp(u / 12.92f, .0f, 1.0f) + : Clamp(std::pow((u + 0.055f) / 1.055f, 2.4f), .0f, 1.0f); + }; + return {EOTF(v.x), EOTF(v.y), EOTF(v.z)}; + } + + SkV3 FromLinear(const SkV3& v) const { auto OETF = [](float u) { return (u < 0.0031308f - ? clamp(12.92 * u, .0, 1.0) - : clamp(1.055 * std::pow(u, 1.0 / 2.4) - 0.055, .0, 1.0)); + ? Clamp(12.92 * u, .0, 1.0) + : Clamp(1.055 * std::pow(u, 1.0 / 2.4) - 0.055, .0, 1.0)); }; - return {OETF(v.X()), OETF(v.Y()), OETF(v.Z())}; + return {OETF(v.x), OETF(v.y), OETF(v.z)}; } // See https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation. - FloatPoint3D toXYZ(const FloatPoint3D& rgb) const { - return transform_.MapPoint(toLinear(rgb)); - } + SkV3 ToXYZ(const SkV3& rgb) const { return transform_ * ToLinear(rgb); } // See // https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_(CIE_XYZ_to_sRGB). - FloatPoint3D fromXYZ(const FloatPoint3D& xyz) const { - return fromLinear(inverseTransform_.MapPoint(xyz)); + SkV3 FromXYZ(const SkV3& xyz) const { + return FromLinear(inverseTransform_ * xyz); } private: - TransformationMatrix kBradford = TransformationMatrix( - 0.8951f, -0.7502f, 0.0389f, 0.0f, - 0.2664f, 1.7135f, -0.0685f, 0.0f, - -0.1614f, 0.0367f, 1.0296f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + SkM44 kBradford = SkM44(0.8951f, + 0.2664f, + -0.1614f, + 0.0f, + -0.7502f, + 1.7135f, + 0.0367f, + 0.0f, + 0.0389f, + 0.0685f, + 1.0296f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f); - TransformationMatrix xyzTransform = TransformationMatrix( - 0.41238642f, 0.21263677f, 0.019330615f, 0.0f, - 0.3575915f, 0.715183f, 0.11919712f, 0.0f, - 0.18045056f, 0.07218022f, 0.95037293f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); + SkM44 xyzTransform = SkM44(0.41238642f, + 0.3575915f, + 0.18045056f, + 0.0f, + 0.21263677f, + 0.715183f, + 0.07218022f, + 0.0f, + 0.019330615f, + 0.11919712f, + 0.95037293f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f); - TransformationMatrix transform_ = - chromaticAdaptation(kBradford, kIlluminantD65, kIlluminantD50) * + SkM44 transform_ = + ChromaticAdaptation(kBradford, kIlluminantD65, kIlluminantD50) * xyzTransform; - TransformationMatrix inverseTransform_ = transform_.Inverse(); + SkM44 inverseTransform_; }; class LABColorSpace { public: // See // https://en.wikipedia.org/wiki/CIELAB_color_space#Reverse_transformation. - FloatPoint3D fromXYZ(const FloatPoint3D& v) const { + SkV3 FromXYZ(const SkV3& v) const { auto f = [](float x) { return x > kSigma3 ? pow(x, 1.0f / 3.0f) : x / (3 * kSigma2) + 4.0f / 29.0f; }; - float fx = f(v.X() / kIlluminantD50.X()); - float fy = f(v.Y() / kIlluminantD50.Y()); - float fz = f(v.Z() / kIlluminantD50.Z()); + float fx = f(v.x / kIlluminantD50.x); + float fy = f(v.y / kIlluminantD50.y); + float fz = f(v.z / kIlluminantD50.z); float L = 116.0f * fy - 16.0f; float a = 500.0f * (fx - fy); float b = 200.0f * (fy - fz); - return {clamp(L, 0.0f, 100.0f), clamp(a, -128.0f, 128.0f), - clamp(b, -128.0f, 128.0f)}; + return {Clamp(L, 0.0f, 100.0f), Clamp(a, -128.0f, 128.0f), + Clamp(b, -128.0f, 128.0f)}; } // See // https://en.wikipedia.org/wiki/CIELAB_color_space#Forward_transformation. - FloatPoint3D toXYZ(const FloatPoint3D& lab) const { + SkV3 ToXYZ(const SkV3& lab) const { auto invf = [](float x) { return x > kSigma ? pow(x, 3) : 3 * kSigma2 * (x - 4.0f / 29.0f); }; - FloatPoint3D v = {clamp(lab.X(), 0.0f, 100.0f), - clamp(lab.Y(), -128.0f, 128.0f), - clamp(lab.Z(), -128.0f, 128.0f)}; + SkV3 v = {Clamp(lab.x, 0.0f, 100.0f), Clamp(lab.y, -128.0f, 128.0f), + Clamp(lab.z, -128.0f, 128.0f)}; - return { - invf((v.X() + 16.0f) / 116.0f + (v.Y() * 0.002f)) * kIlluminantD50.X(), - invf((v.X() + 16.0f) / 116.0f) * kIlluminantD50.Y(), - invf((v.X() + 16.0f) / 116.0f - (v.Z() * 0.005f)) * kIlluminantD50.Z()}; + return {invf((v.x + 16.0f) / 116.0f + (v.y * 0.002f)) * kIlluminantD50.x, + invf((v.x + 16.0f) / 116.0f) * kIlluminantD50.y, + invf((v.x + 16.0f) / 116.0f - (v.z * 0.005f)) * kIlluminantD50.z}; } private: - static constexpr float kSigma = 6.0f / 29.0f; - static constexpr float kSigma2 = 36.0f / 841.0f; - static constexpr float kSigma3 = 216.0f / 24389.0f; + static const constexpr float kSigma = 6.0f / 29.0f; + static const constexpr float kSigma2 = 36.0f / 841.0f; + static const constexpr float kSigma3 = 216.0f / 24389.0f; }; class RGBLABTransformer { public: - FloatPoint3D sRGBToLab(const FloatPoint3D& rgb) const { - FloatPoint3D xyz = rcs.toXYZ(rgb); - return lcs.fromXYZ(xyz); + SkV3 sRGBToLab(const SkV3& rgb) const { + SkV3 xyz = rgb_space_.ToXYZ(rgb); + return lab_space_.FromXYZ(xyz); } - FloatPoint3D LabToSRGB(const FloatPoint3D& lab) const { - FloatPoint3D xyz = lcs.toXYZ(lab); - return rcs.fromXYZ(xyz); + SkV3 LabToSRGB(const SkV3& lab) const { + SkV3 xyz = lab_space_.ToXYZ(lab); + return rgb_space_.FromXYZ(xyz); } private: - sRGBColorSpace rcs = sRGBColorSpace(); - LABColorSpace lcs = LABColorSpace(); + sRGBColorSpace rgb_space_ = sRGBColorSpace(); + LABColorSpace lab_space_ = LABColorSpace(); }; } // namespace LabColorSpace
diff --git a/third_party/blink/renderer/platform/graphics/lab_color_space_test.cc b/third_party/blink/renderer/platform/graphics/lab_color_space_test.cc index cacdb7ee..3c1af5c 100644 --- a/third_party/blink/renderer/platform/graphics/lab_color_space_test.cc +++ b/third_party/blink/renderer/platform/graphics/lab_color_space_test.cc
@@ -3,21 +3,16 @@ namespace LabColorSpace { -using blink::FloatPoint3D; - -static constexpr FloatPoint3D rgbReferenceWhite = - FloatPoint3D(1.0f, 1.0f, 1.0f); -static constexpr FloatPoint3D labReferenceWhite = - FloatPoint3D(100.0f, 0.0f, 0.0f); +static constexpr SkV3 rgbReferenceWhite = {1.0f, 1.0f, 1.0f}; +static constexpr SkV3 labReferenceWhite = {100.0f, 0.0f, 0.0f}; static constexpr float epsilon = 0.0001; class LabColorSpaceTest : public testing::Test { public: - void AssertColorsEqual(const FloatPoint3D& color1, - const FloatPoint3D& color2) { - EXPECT_NEAR(color1.X(), color2.X(), epsilon); - EXPECT_NEAR(color1.Y(), color2.Y(), epsilon); - EXPECT_NEAR(color1.Z(), color2.Z(), epsilon); + void AssertColorsEqual(const SkV3& color1, const SkV3& color2) { + EXPECT_NEAR(color1.x, color2.x, epsilon); + EXPECT_NEAR(color1.y, color2.y, epsilon); + EXPECT_NEAR(color1.z, color2.z, epsilon); } }; @@ -25,10 +20,10 @@ sRGBColorSpace colorSpace = sRGBColorSpace(); // Check whether white transformation is correct - FloatPoint3D xyzWhite = colorSpace.toXYZ(rgbReferenceWhite); + SkV3 xyzWhite = colorSpace.ToXYZ(rgbReferenceWhite); AssertColorsEqual(xyzWhite, kIlluminantD50); - FloatPoint3D rgbWhite = colorSpace.fromXYZ(kIlluminantD50); + SkV3 rgbWhite = colorSpace.FromXYZ(kIlluminantD50); AssertColorsEqual(rgbWhite, rgbReferenceWhite); // Check whether transforming sRGB to XYZ and back gives the same RGB values @@ -36,9 +31,9 @@ for (unsigned r = 0; r <= 255; r += 40) { for (unsigned g = 0; r <= 255; r += 50) { for (unsigned b = 0; r <= 255; r += 60) { - FloatPoint3D rgb = FloatPoint3D(r / 255.0f, g / 255.0f, b / 255.0f); - FloatPoint3D xyz = colorSpace.toXYZ(rgb); - AssertColorsEqual(rgb, colorSpace.fromXYZ(xyz)); + SkV3 rgb = {r / 255.0f, g / 255.0f, b / 255.0f}; + SkV3 xyz = colorSpace.ToXYZ(rgb); + AssertColorsEqual(rgb, colorSpace.FromXYZ(xyz)); } } } @@ -48,10 +43,10 @@ RGBLABTransformer transformer = RGBLABTransformer(); // Check whether white transformation is correct - FloatPoint3D labWhite = transformer.sRGBToLab(rgbReferenceWhite); + SkV3 labWhite = transformer.sRGBToLab(rgbReferenceWhite); AssertColorsEqual(labWhite, labReferenceWhite); - FloatPoint3D rgbWhite = transformer.LabToSRGB(labReferenceWhite); + SkV3 rgbWhite = transformer.LabToSRGB(labReferenceWhite); AssertColorsEqual(rgbWhite, rgbReferenceWhite); // Check whether transforming sRGB to Lab and back gives the same RGB values @@ -59,8 +54,8 @@ for (unsigned r = 0; r <= 255; r += 40) { for (unsigned g = 0; r <= 255; r += 50) { for (unsigned b = 0; r <= 255; r += 60) { - FloatPoint3D rgb = FloatPoint3D(r / 255.0f, g / 255.0f, b / 255.0f); - FloatPoint3D lab = transformer.sRGBToLab(rgb); + SkV3 rgb = {r / 255.0f, g / 255.0f, b / 255.0f}; + SkV3 lab = transformer.sRGBToLab(rgb); AssertColorsEqual(rgb, transformer.LabToSRGB(lab)); } }
diff --git a/third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h b/third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h new file mode 100644 index 0000000..ecbfe890 --- /dev/null +++ b/third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h
@@ -0,0 +1,17 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OVERLAY_SCROLLBAR_CLIP_BEHAVIOR_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OVERLAY_SCROLLBAR_CLIP_BEHAVIOR_H_ + +namespace blink { + +enum OverlayScrollbarClipBehavior { + kIgnoreOverlayScrollbarSize, + kExcludeOverlayScrollbarSizeForHitTesting +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OVERLAY_SCROLLBAR_CLIP_BEHAVIOR_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h index 6a831abb..17b90c3 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -6,9 +6,9 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GEOMETRY_MAPPER_H_ #include "base/optional.h" +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h" #include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/transforms/transformation_matrix.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -211,15 +211,14 @@ static FloatClipRect LocalToAncestorClipRect( const PropertyTreeStateOrAlias& local_state, const PropertyTreeStateOrAlias& ancestor_state, - OverlayScrollbarClipBehavior behavior = - kIgnorePlatformOverlayScrollbarSize) { + OverlayScrollbarClipBehavior behavior = kIgnoreOverlayScrollbarSize) { return LocalToAncestorClipRect(local_state.Unalias(), ancestor_state.Unalias(), behavior); } static FloatClipRect LocalToAncestorClipRect( const PropertyTreeState& local_state, const PropertyTreeState& ancestor_state, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize); + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize); // Maps from a rect in |local_state| to its visual rect in |ancestor_state|. // If there is no effect node between |local_state| (included) and @@ -260,7 +259,7 @@ const PropertyTreeStateOrAlias& local_state, const PropertyTreeStateOrAlias& ancestor_state, FloatClipRect& mapping_rect, - OverlayScrollbarClipBehavior clip = kIgnorePlatformOverlayScrollbarSize, + OverlayScrollbarClipBehavior clip = kIgnoreOverlayScrollbarSize, InclusiveIntersectOrNot intersect = kNonInclusiveIntersect, ExpandVisualRectForAnimationOrNot animation = kDontExpandVisualRectForAnimation) { @@ -272,7 +271,7 @@ const PropertyTreeState& local_state, const PropertyTreeState& ancestor_state, FloatClipRect& mapping_rect, - OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize, + OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize, InclusiveIntersectOrNot = kNonInclusiveIntersect, ExpandVisualRectForAnimationOrNot = kDontExpandVisualRectForAnimation);
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h index 820475a..daebdde0 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h
@@ -5,8 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GEOMETRY_MAPPER_CLIP_CACHE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_GEOMETRY_MAPPER_CLIP_CACHE_H_ +#include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h" -#include "third_party/blink/renderer/platform/graphics/scroll_types.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc index da4cb060..00df6010 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -25,8 +25,7 @@ const PropertyTreeState& ancestor_property_tree_state) { GeometryMapperClipCache::ClipAndTransform clip_and_transform( &ancestor_property_tree_state.Clip(), - &ancestor_property_tree_state.Transform(), - kIgnorePlatformOverlayScrollbarSize); + &ancestor_property_tree_state.Transform(), kIgnoreOverlayScrollbarSize); return descendant_clip.GetClipCache().GetCachedClip(clip_and_transform); } @@ -36,9 +35,8 @@ FloatClipRect& mapping_rect, bool& success) { GeometryMapper::LocalToAncestorVisualRectInternal( - local_state, ancestor_state, mapping_rect, - kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect, - kDontExpandVisualRectForAnimation, success); + local_state, ancestor_state, mapping_rect, kIgnoreOverlayScrollbarSize, + kNonInclusiveIntersect, kDontExpandVisualRectForAnimation, success); } void CheckMappings(); @@ -95,7 +93,7 @@ actual_visual_rect = FloatClipRect(input_rect); GeometryMapper::LocalToAncestorVisualRect( local_state, ancestor_state, actual_visual_rect, - kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect, + kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect, kExpandVisualRectForAnimation); EXPECT_CLIP_RECT_EQ(expected_visual_rect_expanded_for_animation ? *expected_visual_rect_expanded_for_animation @@ -382,9 +380,9 @@ // Check that not passing kExcludeOverlayScrollbarSizeForHitTesting gives // a different result. actual_visual_rect = FloatClipRect(input_rect); - GeometryMapper::LocalToAncestorVisualRect( - local_state, ancestor_state, actual_visual_rect, - kIgnorePlatformOverlayScrollbarSize); + GeometryMapper::LocalToAncestorVisualRect(local_state, ancestor_state, + actual_visual_rect, + kIgnoreOverlayScrollbarSize); EXPECT_CLIP_RECT_EQ(FloatClipRect(FloatRect(10, 10, 50, 50)), actual_visual_rect); @@ -396,7 +394,7 @@ // Check that not passing kExcludeOverlayScrollbarSizeForHitTesting gives // a different result. actual_clip_rect = GeometryMapper::LocalToAncestorClipRect( - local_state, ancestor_state, kIgnorePlatformOverlayScrollbarSize); + local_state, ancestor_state, kIgnoreOverlayScrollbarSize); EXPECT_CLIP_RECT_EQ(FloatClipRect(FloatRect(10, 10, 50, 50)), actual_clip_rect); } @@ -408,7 +406,7 @@ FloatClipRect actual_clip_rect(FloatRect(60, 10, 10, 10)); GeometryMapper::LocalToAncestorVisualRect( local_state, ancestor_state, actual_clip_rect, - kIgnorePlatformOverlayScrollbarSize, kInclusiveIntersect); + kIgnoreOverlayScrollbarSize, kInclusiveIntersect); EXPECT_CLIP_RECT_EQ(FloatClipRect(FloatRect(60, 10, 0, 10)), actual_clip_rect); @@ -417,7 +415,7 @@ actual_clip_rect.SetRect(FloatRect(60, 10, 10, 10)); GeometryMapper::LocalToAncestorVisualRect( local_state, ancestor_state, actual_clip_rect, - kIgnorePlatformOverlayScrollbarSize, kNonInclusiveIntersect); + kIgnoreOverlayScrollbarSize, kNonInclusiveIntersect); EXPECT_CLIP_RECT_EQ(FloatClipRect(FloatRect()), actual_clip_rect); } @@ -446,7 +444,7 @@ FloatClipRect actual_clip_rect(FloatRect(10, 10, 10, 0)); auto intersects = GeometryMapper::LocalToAncestorVisualRect( local_state, ancestor_state, actual_clip_rect, - kIgnorePlatformOverlayScrollbarSize, kInclusiveIntersect); + kIgnoreOverlayScrollbarSize, kInclusiveIntersect); EXPECT_TRUE(actual_clip_rect.Rect().IsEmpty()); EXPECT_TRUE(intersects);
diff --git a/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc index 129b5446..2bc052e 100644 --- a/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc +++ b/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item.cc
@@ -38,8 +38,9 @@ sk_sp<const PaintRecord> ScrollbarDisplayItem::Paint() const { if (record_) { - DCHECK(!scrollbar_->NeedsRepaintPart(cc::TRACK_BUTTONS_TICKMARKS)); - DCHECK(!scrollbar_->NeedsRepaintPart(cc::THUMB)); + DCHECK(!scrollbar_->NeedsRepaintPart( + cc::ScrollbarPart::TRACK_BUTTONS_TICKMARKS)); + DCHECK(!scrollbar_->NeedsRepaintPart(cc::ScrollbarPart::THUMB)); return record_; } @@ -47,10 +48,11 @@ const IntRect& rect = VisualRect(); recorder.beginRecording(rect); auto* canvas = recorder.getRecordingCanvas(); - scrollbar_->PaintPart(canvas, cc::TRACK_BUTTONS_TICKMARKS, rect); + scrollbar_->PaintPart(canvas, cc::ScrollbarPart::TRACK_BUTTONS_TICKMARKS, + rect); gfx::Rect thumb_rect = scrollbar_->ThumbRect(); thumb_rect.Offset(rect.X(), rect.Y()); - scrollbar_->PaintPart(canvas, cc::THUMB, thumb_rect); + scrollbar_->PaintPart(canvas, cc::ScrollbarPart::THUMB, thumb_rect); record_ = recorder.finishRecordingAsPicture(); return record_; @@ -76,8 +78,8 @@ gfx::Vector2dF(FloatPoint(VisualRect().Location()))); layer->SetBounds(gfx::Size(VisualRect().Size())); - if (scrollbar_->NeedsRepaintPart(cc::THUMB) || - scrollbar_->NeedsRepaintPart(cc::TRACK_BUTTONS_TICKMARKS)) + if (scrollbar_->NeedsRepaintPart(cc::ScrollbarPart::THUMB) || + scrollbar_->NeedsRepaintPart(cc::ScrollbarPart::TRACK_BUTTONS_TICKMARKS)) layer->SetNeedsDisplay(); return layer; }
diff --git a/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc b/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc index c3b9e47..3a98a9b 100644 --- a/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc +++ b/third_party/blink/renderer/platform/graphics/paint/scrollbar_display_item_test.cc
@@ -17,7 +17,7 @@ CompositorElementId ScrollbarElementId(const cc::Scrollbar& scrollbar) { return CompositorElementIdFromUniqueObjectId( - 13579, scrollbar.Orientation() == cc::HORIZONTAL + 13579, scrollbar.Orientation() == cc::ScrollbarOrientation::HORIZONTAL ? CompositorElementIdNamespace::kHorizontalScrollbar : CompositorElementIdNamespace::kVerticalScrollbar); } @@ -38,7 +38,7 @@ TEST(ScrollbarDisplayItemTest, HorizontalSolidColorScrollbar) { auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>(); - scrollbar->set_orientation(cc::HORIZONTAL); + scrollbar->set_orientation(cc::ScrollbarOrientation::HORIZONTAL); scrollbar->set_is_solid_color(true); scrollbar->set_is_overlay(true); scrollbar->set_track_rect(gfx::Rect(2, 90, 96, 10)); @@ -58,7 +58,8 @@ auto* scrollbar_layer = static_cast<cc::SolidColorScrollbarLayer*>(layer.get()); - EXPECT_EQ(cc::HORIZONTAL, scrollbar_layer->orientation()); + EXPECT_EQ(cc::ScrollbarOrientation::HORIZONTAL, + scrollbar_layer->orientation()); EXPECT_EQ(7, scrollbar_layer->thumb_thickness()); EXPECT_EQ(2, scrollbar_layer->track_start()); EXPECT_EQ(element_id, scrollbar_layer->element_id()); @@ -69,7 +70,7 @@ TEST(ScrollbarDisplayItemTest, VerticalSolidColorScrollbar) { auto scrollbar = base::MakeRefCounted<cc::FakeScrollbar>(); - scrollbar->set_orientation(cc::VERTICAL); + scrollbar->set_orientation(cc::ScrollbarOrientation::VERTICAL); scrollbar->set_is_solid_color(true); scrollbar->set_is_overlay(true); scrollbar->set_track_rect(gfx::Rect(90, 2, 10, 96)); @@ -89,7 +90,7 @@ auto* scrollbar_layer = static_cast<cc::SolidColorScrollbarLayer*>(layer.get()); - EXPECT_EQ(cc::VERTICAL, scrollbar_layer->orientation()); + EXPECT_EQ(cc::ScrollbarOrientation::VERTICAL, scrollbar_layer->orientation()); EXPECT_EQ(7, scrollbar_layer->thumb_thickness()); EXPECT_EQ(2, scrollbar_layer->track_start()); EXPECT_EQ(element_id, scrollbar_layer->element_id());
diff --git a/third_party/blink/renderer/platform/graphics/scroll_types.h b/third_party/blink/renderer/platform/graphics/scroll_types.h deleted file mode 100644 index 1f00a31..0000000 --- a/third_party/blink/renderer/platform/graphics/scroll_types.h +++ /dev/null
@@ -1,21 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SCROLL_TYPES_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SCROLL_TYPES_H_ - -namespace blink { - -// Platform overlay scrollbars are controlled and painted by the operating -// system (e.g., OSX and Android). CSS overlay scrollbars are created by -// setting overflow:overlay, and they are painted by chromium. -enum OverlayScrollbarClipBehavior { - kIgnorePlatformOverlayScrollbarSize, - kIgnorePlatformAndCSSOverlayScrollbarSize, - kExcludeOverlayScrollbarSizeForHitTesting -}; - -} // namespace blink - -#endif
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 357a201..cd061b9 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2124,6 +2124,11 @@ status: "experimental", }, { + name: "WebXRDepth", + depends_on: ["WebXRARModule"], + status: "experimental", + }, + { name: "WebXRHitTest", depends_on: ["WebXRARModule"], status: "stable",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc b/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc index f755622..8c5b26f 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc
@@ -112,6 +112,7 @@ case Experiment::kVeryHighPriorityForCompositingAlways: return; case Experiment::kVeryHighPriorityForCompositingWhenFast: + scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority(); return; case Experiment::kVeryHighPriorityForCompositingAlternating: // Deprioritize the compositor if it has just run a task. Prioritize the
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index 7c9b16f5..ddec847 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -446,7 +446,11 @@ &main_thread_scheduler_impl->tracing_controller_, YesNoStateToString), compositor_priority_experiments(main_thread_scheduler_impl), - main_thread_compositing_is_fast(false) {} + main_thread_compositing_is_fast(false), + compositor_priority(TaskQueue::QueuePriority::kNormalPriority, + "Scheduler.CompositorPriority", + &main_thread_scheduler_impl->tracing_controller_, + TaskQueue::PriorityToString) {} MainThreadSchedulerImpl::MainThreadOnly::~MainThreadOnly() = default; @@ -1506,8 +1510,6 @@ new_policy.should_disable_throttling() = main_thread_only().use_virtual_time; - new_policy.compositor_priority() = ComputeCompositorPriority(); - new_policy.find_in_page_priority() = find_in_page_budget_pool_controller_->CurrentTaskPriority(); @@ -1547,6 +1549,8 @@ Policy old_policy = main_thread_only().current_policy; main_thread_only().current_policy = new_policy; + UpdateCompositorTaskQueuePriority(); + UpdateStateForAllTaskQueues(old_policy); } @@ -2083,8 +2087,6 @@ should_disable_throttling_(false), frozen_when_backgrounded_(false), should_prioritize_loading_with_compositing_(false), - compositor_priority_( - base::sequence_manager::TaskQueue::QueuePriority::kNormalPriority), find_in_page_priority_(FindInPageBudgetPoolController:: kFindInPageBudgetNotExhaustedPriority), use_case_(UseCase::kNone) {} @@ -2104,8 +2106,6 @@ state->EndDictionary(); state->SetString("rail_mode", RAILModeToString(rail_mode())); - state->SetString("compositor_priority", - TaskQueue::PriorityToString(compositor_priority())); state->SetString("use_case", UseCaseToString(use_case())); state->SetBoolean("should_disable_throttling", should_disable_throttling()); @@ -2551,8 +2551,7 @@ RecordTaskUkm(queue.get(), task, *task_timing); main_thread_only().compositor_priority_experiments.OnTaskCompleted( - queue.get(), main_thread_only().current_policy.compositor_priority(), - task_timing); + queue.get(), main_thread_only().compositor_priority, task_timing); find_in_page_budget_pool_controller_->OnTaskCompleted(queue.get(), task_timing); @@ -2671,7 +2670,7 @@ if (task_queue->GetPrioritisationType() == MainThreadTaskQueue::QueueTraits::PrioritisationType::kCompositor) { - return main_thread_only().current_policy.compositor_priority(); + return main_thread_only().compositor_priority; } // Default priority. @@ -2735,8 +2734,6 @@ Policy old_policy) const { return old_policy.use_case() != main_thread_only().current_policy.use_case() || - old_policy.compositor_priority() != - main_thread_only().current_policy.compositor_priority() || old_policy.find_in_page_priority() != main_thread_only().current_policy.find_in_page_priority(); } @@ -2758,12 +2755,12 @@ } main_thread_only().prioritize_compositing_after_input = prioritize_compositing_after_input; - UpdateCompositorPolicy(); + UpdateCompositorTaskQueuePriority(); } void MainThreadSchedulerImpl:: OnCompositorPriorityExperimentUpdateCompositorPriority() { - UpdateCompositorPolicy(); + UpdateCompositorTaskQueuePriority(); } TaskQueue::QueuePriority MainThreadSchedulerImpl::ComputeCompositorPriority() @@ -2788,9 +2785,8 @@ return TaskQueue::QueuePriority::kNormalPriority; } -void MainThreadSchedulerImpl::UpdateCompositorPolicy() { - main_thread_only().current_policy.compositor_priority() = - ComputeCompositorPriority(); +void MainThreadSchedulerImpl::UpdateCompositorTaskQueuePriority() { + main_thread_only().compositor_priority = ComputeCompositorPriority(); CompositorTaskQueue()->SetQueuePriority( ComputePriority(CompositorTaskQueue().get())); }
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h index e15972a5..757fa17c 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -405,7 +405,7 @@ base::WeakPtr<MainThreadSchedulerImpl> GetWeakPtr(); base::sequence_manager::TaskQueue::QueuePriority compositor_priority() const { - return main_thread_only().current_policy.compositor_priority(); + return main_thread_only().compositor_priority; } bool should_prioritize_loading_with_compositing() const { @@ -565,14 +565,6 @@ return should_freeze_compositor_task_queue_; } - base::sequence_manager::TaskQueue::QueuePriority& compositor_priority() { - return compositor_priority_; - } - base::sequence_manager::TaskQueue::QueuePriority compositor_priority() - const { - return compositor_priority_; - } - base::sequence_manager::TaskQueue::QueuePriority& find_in_page_priority() { return find_in_page_priority_; } @@ -592,7 +584,6 @@ other.should_prioritize_loading_with_compositing_ && should_freeze_compositor_task_queue_ == other.should_freeze_compositor_task_queue_ && - compositor_priority_ == other.compositor_priority_ && find_in_page_priority_ == other.find_in_page_priority_ && use_case_ == other.use_case_; } @@ -606,10 +597,6 @@ bool should_prioritize_loading_with_compositing_; bool should_freeze_compositor_task_queue_{false}; - // Priority of task queues belonging to the compositor class (Check - // MainThread::QueueClass). - base::sequence_manager::TaskQueue::QueuePriority compositor_priority_; - base::sequence_manager::TaskQueue::QueuePriority find_in_page_priority_; UseCase use_case_; @@ -770,9 +757,8 @@ // the use case. Defaults to kNormalPriority. TaskQueue::QueuePriority ComputeCompositorPriority() const; - // Used to update the compositor policy on the main thread when there is a - // change in the compositor priority. - void UpdateCompositorPolicy(); + // Used to update the compositor priority on the main thread. + void UpdateCompositorTaskQueuePriority(); // Computes the priority for compositing based on the current use case. // Returns nullopt if the use case does not need to set the priority. @@ -973,6 +959,11 @@ CompositorPriorityExperiments compositor_priority_experiments; bool main_thread_compositing_is_fast; + + // Priority given to the main thread's compositor task queue. Defaults to + // kNormalPriority and is updated via UpdateCompositorTaskQueuePriority(). + TraceableState<TaskQueue::QueuePriority, TracingCategoryName::kDefault> + compositor_priority; }; struct AnyThread {
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py index 547eaef7..2f24847 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
@@ -135,7 +135,6 @@ 'system_log_file': None, 'cpu_cores': CPU_CORES, 'require_kvm': True, - 'emu_type': target_device, 'ram_size_mb': 8192 } if target_device == 'qemu':
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=ForceSynchronousHTMLParsing b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=ForceSynchronousHTMLParsing index 8f2e187..5763dd9 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=ForceSynchronousHTMLParsing +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=ForceSynchronousHTMLParsing
@@ -38,8 +38,8 @@ ### virtual/composite-after-paint/scrollingcoordinator/ crbug.com/901056 virtual/composite-after-paint/scrollingcoordinator/donot-compute-non-fast-scrollable-region-for-hidden-frames.html [ Timeout ] -### virtual/sxg-subresource/external/wpt/signed-exchange/subresource/ -crbug.com/901056 virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource.tentative.html [ Timeout ] +### external/wpt/signed-exchange/subresource/ +crbug.com/901056 external/wpt/signed-exchange/subresource/sxg-subresource.tentative.html [ Timeout ] ### http/tests/devtools/sources/debugger/ crbug.com/1063051 http/tests/devtools/sources/debugger/debug-inlined-scripts-fragment-id.js [ Timeout ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 681552a7..ce8c8fc 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -2148,6 +2148,10 @@ crbug.com/1082020 http/tests/loading/wbn/origin-trial/* [ Skip ] virtual/subresource-web-bundles-disabled/http/tests/loading/wbn/origin-trial/* [ Pass ] +# This test requires sxg-subresource-disabled. +http/tests/loading/sxg/sxg-subresource-origin-trial.https.html [ Skip ] +virtual/sxg-subresource-disabled/http/tests/loading/sxg/sxg-subresource-origin-trial.https.html [ Pass ] + # No good way to automate this test yet external/wpt/native-file-system/showSaveFilePicker-manual.https.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index d687419..4b71364a 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -718,6 +718,7 @@ crbug.com/1081802 external/wpt/css/css-flexbox/overflow-area-002.html [ Failure ] crbug.com/807497 external/wpt/css/css-flexbox/anonymous-flex-item-005.html [ Failure ] crbug.com/1111708 external/wpt/css/css-flexbox/flexbox_justifycontent-center-overflow.html [ Failure ] +crbug.com/1111128 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002b.html [ Failure ] # These have some incorrect expectations. crbug.com/704294 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html [ Failure ] @@ -733,11 +734,7 @@ crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-005.xht [ Failure ] crbug.com/249112 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ] -# Not implemented yet -crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse-line-wrapping.html [ Failure ] -crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse.html [ Failure ] - -# These require justify-content:right and align-content:end +# These require css-align-3 positional keywords that Blink doesn't yet support for flexbox. crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001a.xhtml [ Failure ] crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-001b.xhtml [ Failure ] crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Failure ] @@ -749,6 +746,7 @@ crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-003.xhtml [ Failure ] crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-005.xhtml [ Failure ] crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-horiz-006.xhtml [ Failure ] +crbug.com/1011718 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-002.xhtml [ Failure ] # We don't support requesting flex line breaks and it is not clear that we should. # See https://lists.w3.org/Archives/Public/www-style/2015May/0065.html @@ -762,9 +760,8 @@ crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-001.html [ Failure ] crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-002.html [ Failure ] crbug.com/336604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-003.html [ Failure ] - -# We don't correctly implement aspect ratios for images in Flexbox -crbug.com/1111128 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002b.html [ Failure ] +crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse-line-wrapping.html [ Failure ] +crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse.html [ Failure ] # These tests are incorrect, as Firefox has a bug in this area. https://bugzilla.mozilla.org/show_bug.cgi?id=1136312 crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002a.html [ Failure ] @@ -775,21 +772,24 @@ # We paint in an incorrect order when layers are present. Blocked on composite-after-paint. crbug.com/370604 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-paint-ordering-002.xhtml [ Failure ] +# We haven't implemented last baseline alignment. +crbug.com/886585 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001a.xhtml [ Failure ] +crbug.com/886585 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001b.xhtml [ Failure ] +crbug.com/886585 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-006.xhtml [ Failure ] +crbug.com/886585 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-007.xhtml [ Failure ] +crbug.com/886585 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-008.xhtml [ Failure ] + +# We haven't implemented flex-basis: content yet. +crbug.com/470421 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html [ Failure ] +crbug.com/470421 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Failure ] +crbug.com/470421 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002a.html [ Failure ] +crbug.com/470421 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002b.html [ Failure ] +crbug.com/470421 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-003a.html [ Failure ] +crbug.com/470421 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-004a.html [ Failure ] + # Untriaged flex failures crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-wmvert-001.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001a.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-001b.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-006.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-007.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-baseline-horiz-008.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-002.xhtml [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-rtl-005.xhtml [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002a.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002b.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-003a.html [ Failure ] -crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-004a.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-vert-006.xhtml [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-justify-content-wmvert-001.xhtml [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-safe-overflow-position-001.html [ Failure ] @@ -1349,7 +1349,6 @@ crbug.com/753671 [ Mac10.15 ] external/wpt/css/css-content/quotes-020.html [ Failure ] crbug.com/753671 external/wpt/css/css-content/quotes-021.html [ Failure ] crbug.com/753671 external/wpt/css/css-content/quotes-022.html [ Failure ] -crbug.com/753671 external/wpt/css/css-content/quotes-033.html [ Failure ] crbug.com/989123 external/wpt/css/css-typed-om/the-stylepropertymap/computed/get-auto-min-size.html [ Failure ] crbug.com/995106 external/wpt/css/css-lists/inline-block-list.html [ Failure ] @@ -4182,7 +4181,7 @@ crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/flex-and-content-sized-resolution-columns.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/flex-and-intrinsic-sizes.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/flex-content-sized-column-use-available-width.html [ Failure ] -crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/flex-content-sized-columns-resize.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/flex-content-sized-columns-resize.html [ Failure Timeout ] crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/floating-empty-grids.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/grid-auto-columns-rows-auto-flow-resolution.html [ Failure Crash ] crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/grid-auto-columns-rows-get-set.html [ Failure ] @@ -6642,3 +6641,4 @@ # Sheriff 2020-08-26 crbug.com/1122106 external/wpt/webrtc/protocol/crypto-suite.https.html [ Pass Timeout ] +crbug.com/1122742 http/tests/devtools/sources/debugger/source-frame-inline-breakpoint-decorations.js [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 43972cd3..d9cf9b8 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -377,9 +377,9 @@ "args": ["--autoplay-policy=document-user-activation-required"] }, { - "prefix": "sxg-subresource", - "bases": ["external/wpt/signed-exchange"], - "args": ["--enable-features=SignedExchangeSubresourcePrefetch"] + "prefix": "sxg-subresource-disabled", + "bases": ["http/tests/loading/sxg/sxg-subresource-origin-trial.https.html"], + "args": ["--disable-blink-features=SignedExchangeSubresourcePrefetch"] }, { "prefix": "wbn-from-network",
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt index a75fca40..e271532d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -FAIL Property quotes has initial value auto assert_equals: expected "auto" but got "" +PASS Property quotes has initial value auto PASS Property quotes inherits FAIL Property bookmark-level has initial value none assert_true: bookmark-level doesn't seem to be supported in the computed style expected true got false FAIL Property bookmark-level does not inherit assert_true: expected true got false
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/quotes-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/quotes-expected.txt deleted file mode 100644 index 608583f..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/quotes-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -This is a testharness.js-based test. -FAIL Can set 'quotes' to CSS-wide keywords assert_not_equals: Computed value must not be null got disallowed value null -FAIL Can set 'quotes' to var() references assert_not_equals: Computed value must not be null got disallowed value null -PASS Can set 'quotes' to the 'none' keyword -PASS Setting 'quotes' to a length throws TypeError -PASS Setting 'quotes' to a percent throws TypeError -PASS Setting 'quotes' to a time throws TypeError -PASS Setting 'quotes' to an angle throws TypeError -PASS Setting 'quotes' to a flexible length throws TypeError -PASS Setting 'quotes' to a number throws TypeError -PASS Setting 'quotes' to a position throws TypeError -PASS Setting 'quotes' to a URL throws TypeError -PASS Setting 'quotes' to a transform throws TypeError -PASS 'quotes' does not supported '"<<" ">>" "<" ">"' -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative-expected.txt deleted file mode 100644 index 1cd5040..0000000 --- a/third_party/blink/web_tests/external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Subresource signed exchange prefetch. assert_equals: expected "from server" but got "sxg-subresource-script.js should not be prefetched" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/signed-exchange/subresource/sxg-subresource.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/signed-exchange/subresource/sxg-subresource.tentative-expected.txt deleted file mode 100644 index ee54a8c..0000000 --- a/third_party/blink/web_tests/external/wpt/signed-exchange/subresource/sxg-subresource.tentative-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Subresource signed exchange prefetch. assert_equals: expected "from signed exchange" but got "sxg-subresource-script.js should not be prefetched" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/position/layout-state-only-positioned-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/position/layout-state-only-positioned-expected.txt similarity index 93% rename from third_party/blink/web_tests/platform/mac/paint/invalidation/position/layout-state-only-positioned-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/position/layout-state-only-positioned-expected.txt index 1761aae..31c2dba7 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/position/layout-state-only-positioned-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/position/layout-state-only-positioned-expected.txt
@@ -10,7 +10,7 @@ ] }, { - "name": "LayoutNGBlockFlow (positioned) DIV", + "name": "LayoutBlockFlow (positioned) DIV", "bounds": [106, 106], "invalidations": [ [0, 0, 106, 106]
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt index 919414f..610f7cd 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -12,6 +12,12 @@ "transform": 1 }, { + "name": "Scrolling Contents Layer", + "bounds": [1000, 1000], + "backgroundColor": "#C0C0C0", + "transform": 1 + }, + { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -28,12 +34,6 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 - }, - { - "name": "Scrolling Contents Layer", - "bounds": [1000, 1000], - "backgroundColor": "#C0C0C0", - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/position/layout-state-only-positioned-expected.txt b/third_party/blink/web_tests/paint/invalidation/position/layout-state-only-positioned-expected.txt index 8f64356..1761aae 100644 --- a/third_party/blink/web_tests/paint/invalidation/position/layout-state-only-positioned-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/position/layout-state-only-positioned-expected.txt
@@ -8,6 +8,37 @@ "invalidations": [ [0, 50, 106, 106] ] + }, + { + "name": "LayoutNGBlockFlow (positioned) DIV", + "bounds": [106, 106], + "invalidations": [ + [0, 0, 106, 106] + ], + "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [3, 3], + "bounds": [100, 200], + "transform": 1 + }, + { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [88, 3], + "bounds": [15, 100], + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 50, 0, 1] + ] } ] }
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/position/layout-state-only-positioned-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/position/layout-state-only-positioned-expected.txt deleted file mode 100644 index 8f64356..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/position/layout-state-only-positioned-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "layers": [ - { - "name": "Scrolling Contents Layer", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "invalidations": [ - [0, 50, 106, 106] - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/scroll-partial-update-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/scroll-partial-update-expected.txt index 7b2227ab..9d75ad9 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/scroll-partial-update-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/scroll-partial-update-expected.txt
@@ -25,16 +25,16 @@ "transform": 2 }, { - "name": "Scrolling Contents Layer", - "bounds": [185, 400], - "backgroundColor": "#FFFF0080", - "transform": 3 - }, - { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [185, 0], "bounds": [15, 200], "transform": 2 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [185, 400], + "backgroundColor": "#FFFF0080", + "transform": 3 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt index 4c12a3a..ded1393 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -12,12 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [1000, 1000], - "backgroundColor": "#C0C0C0", - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -34,6 +28,12 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1000, 1000], + "backgroundColor": "#C0C0C0", + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt index 4c12a3a..ded1393 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -12,12 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [1000, 1000], - "backgroundColor": "#C0C0C0", - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -34,6 +28,12 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1000, 1000], + "backgroundColor": "#C0C0C0", + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt index 4374f06b..8fb4d11 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/squashing/invalidations-with-large-negative-margin-inline-content-expected.txt
@@ -12,14 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [585, 500], - "invalidations": [ - [400, 100, 20, 20] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 185], "bounds": [585, 15], @@ -36,6 +28,14 @@ "position": [585, 185], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [585, 500], + "invalidations": [ + [400, 100, 20, 20] + ], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt index b07ea9c..8b83b6df 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/invalidations-with-large-negative-margin-expected.txt
@@ -12,15 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [585, 400], - "invalidations": [ - [400, 0, 50, 50], - [0, 0, 50, 50] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 185], "bounds": [585, 15], @@ -37,6 +28,15 @@ "position": [585, 185], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [585, 400], + "invalidations": [ + [400, 0, 50, 50], + [0, 0, 50, 50] + ], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt index dc35a27..ca83f1b 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-color-change-expected.txt
@@ -12,14 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [185, 615], - "invalidations": [ - [0, 0, 47, 615] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 185], "bounds": [185, 15], @@ -36,6 +28,14 @@ "position": [185, 185], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [185, 615], + "invalidations": [ + [0, 0, 47, 615] + ], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt index 71ccc50..069d36da 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt
@@ -15,20 +15,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [785, 1340], - "invalidations": [ - [10, 72, 227, 18], - [20, 160, 200, 72], - [10, 126, 139, 12], - [268, 0, 46, 18], - [90, 0, 46, 18], - [224, 0, 45, 18], - [52, 18, 45, 18] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 485], "bounds": [785, 15], @@ -45,6 +31,20 @@ "position": [785, 485], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [785, 1340], + "invalidations": [ + [10, 72, 227, 18], + [20, 160, 200, 72], + [10, 126, 139, 12], + [268, 0, 46, 18], + [90, 0, 46, 18], + [224, 0, 45, 18], + [52, 18, 45, 18] + ], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt index d3f2950b..8766c26 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-and-content-expected.txt
@@ -12,6 +12,24 @@ "transform": 1 }, { + "name": "ContentsLayer for Horizontal Scrollbar Layer", + "position": [0, 185], + "bounds": [185, 15], + "transform": 1 + }, + { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [185, 0], + "bounds": [15, 185], + "transform": 1 + }, + { + "name": "Scroll Corner Layer", + "position": [185, 185], + "bounds": [15, 15], + "transform": 1 + }, + { "name": "Scrolling Contents Layer", "bounds": [185, 234], "invalidations": [ @@ -30,24 +48,6 @@ [0, 0, 75, 18] ], "transform": 2 - }, - { - "name": "ContentsLayer for Horizontal Scrollbar Layer", - "position": [0, 185], - "bounds": [185, 15], - "transform": 1 - }, - { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [185, 0], - "bounds": [15, 185], - "transform": 1 - }, - { - "name": "Scroll Corner Layer", - "position": [185, 185], - "bounds": [15, 15], - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt index 98ea9d6..67aadb1 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt
@@ -15,12 +15,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [5, 5], - "bounds": [400, 400], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [5, 190], "bounds": [185, 15], @@ -37,6 +31,12 @@ "position": [190, 190], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [5, 5], + "bounds": [400, 400], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/flexbox/scrollbars-changed-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/flexbox/scrollbars-changed-expected.txt index 54a7084c..c56fde6 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/flexbox/scrollbars-changed-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/flexbox/scrollbars-changed-expected.txt
@@ -11,17 +11,17 @@ "bounds": [200, 100] }, { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [185, 0], + "bounds": [15, 100] + }, + { "name": "Scrolling Contents Layer", "bounds": [185, 210], "backgroundColor": "#80808080", "invalidations": [ [0, 5, 15, 15] ] - }, - { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [185, 0], - "bounds": [15, 100] } ] }
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt index 5c83202..668454d 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/float-offscreen-expected.txt
@@ -12,11 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [784, 1027], - "transform": 1 - }, - { "name": "Horizontal Scrollbar Layer", "position": [0, 300], "bounds": [784, 0], @@ -27,6 +22,11 @@ "position": [784, 0], "bounds": [0, 300], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [784, 1027], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt index 3692673a..34f1fe8 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
@@ -20,16 +20,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [1, 1], - "bounds": [470, 19], - "backgroundColor": "#FFFFFF", - "invalidations": [ - [0, 0, 470, 19] - ], - "transform": 2 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [1, 20], "bounds": [164, 15], @@ -45,6 +35,16 @@ "transform": 1 }, { + "name": "Scrolling Contents Layer", + "position": [1, 1], + "bounds": [470, 19], + "backgroundColor": "#FFFFFF", + "invalidations": [ + [0, 0, 470, 19] + ], + "transform": 2 + }, + { "name": "Decoration Layer", "position": [-2, -2], "bounds": [185, 40],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt index bcdd642..7a56b4e 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt
@@ -12,15 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [1, 1], - "bounds": [2100, 185], - "invalidations": [ - [2000, 0, 100, 100] - ], - "transform": 2 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [1, 186], "bounds": [285, 15], @@ -37,6 +28,15 @@ "position": [286, 186], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [1, 1], + "bounds": [2100, 185], + "invalidations": [ + [2000, 0, 100, 100] + ], + "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt index 450ee51..89532e5 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt
@@ -12,15 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [1, 1], - "bounds": [2100, 185], - "invalidations": [ - [0, 0, 100, 100] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [1, 186], "bounds": [285, 15], @@ -37,6 +28,15 @@ "position": [286, 186], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [1, 1], + "bounds": [2100, 185], + "invalidations": [ + [0, 0, 100, 100] + ], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt index c59b6fb..db66808 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt
@@ -12,15 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [1, 1], - "bounds": [2100, 185], - "invalidations": [ - [0, 0, 100, 100] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [1, 186], "bounds": [285, 15], @@ -37,6 +28,15 @@ "position": [286, 186], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [1, 1], + "bounds": [2100, 185], + "invalidations": [ + [0, 0, 100, 100] + ], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-child-of-transformed-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-child-of-transformed-scrolled-expected.txt index ed0997d..da52e03 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-child-of-transformed-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-child-of-transformed-scrolled-expected.txt
@@ -12,14 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [1000, 1000], - "invalidations": [ - [100, 150, 100, 100] - ], - "transform": 2 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -36,6 +28,14 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1000, 1000], + "invalidations": [ + [100, 150, 100, 100] + ], + "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt index 38ca408..ecf0b357 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled-expected.txt
@@ -12,14 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [1050, 1050], - "invalidations": [ - [100, 150, 100, 100] - ], - "transform": 2 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -36,6 +28,14 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1050, 1050], + "invalidations": [ + [100, 150, 100, 100] + ], + "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/outline-change-in-scrollers-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/outline-change-in-scrollers-expected.txt index a4d3ea6..d434177 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/outline-change-in-scrollers-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/outline-change-in-scrollers-expected.txt
@@ -15,15 +15,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [10, 10], - "bounds": [150, 150], - "invalidations": [ - [0, 0, 75, 75] - ], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [10, 105], "bounds": [95, 15], @@ -42,11 +33,38 @@ "transform": 1 }, { + "name": "Scrolling Contents Layer", + "position": [10, 10], + "bounds": [150, 150], + "invalidations": [ + [0, 0, 75, 75] + ], + "transform": 1 + }, + { "name": "LayoutNGBlockFlow (relative positioned) DIV class='scroll'", "bounds": [130, 130], "transform": 2 }, { + "name": "ContentsLayer for Horizontal Scrollbar Layer", + "position": [10, 105], + "bounds": [95, 15], + "transform": 2 + }, + { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [105, 10], + "bounds": [15, 95], + "transform": 2 + }, + { + "name": "Scroll Corner Layer", + "position": [105, 105], + "bounds": [15, 15], + "transform": 2 + }, + { "name": "Scrolling Contents Layer", "position": [10, 10], "bounds": [95, 150], @@ -56,26 +74,26 @@ "transform": 2 }, { + "name": "LayoutNGBlockFlow (relative positioned) DIV class='scroll'", + "bounds": [130, 130], + "transform": 3 + }, + { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [10, 105], "bounds": [95, 15], - "transform": 2 + "transform": 3 }, { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [105, 10], "bounds": [15, 95], - "transform": 2 + "transform": 3 }, { "name": "Scroll Corner Layer", "position": [105, 105], "bounds": [15, 15], - "transform": 2 - }, - { - "name": "LayoutNGBlockFlow (relative positioned) DIV class='scroll'", - "bounds": [130, 130], "transform": 3 }, { @@ -88,38 +106,11 @@ "transform": 3 }, { - "name": "ContentsLayer for Horizontal Scrollbar Layer", - "position": [10, 105], - "bounds": [95, 15], - "transform": 3 - }, - { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [105, 10], - "bounds": [15, 95], - "transform": 3 - }, - { - "name": "Scroll Corner Layer", - "position": [105, 105], - "bounds": [15, 15], - "transform": 3 - }, - { "name": "LayoutNGBlockFlow (relative positioned) DIV class='scroll'", "bounds": [130, 130], "transform": 4 }, { - "name": "Scrolling Contents Layer", - "position": [25, 10], - "bounds": [95, 150], - "invalidations": [ - [20, 0, 75, 75] - ], - "transform": 4 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [25, 105], "bounds": [95, 15], @@ -138,17 +129,17 @@ "transform": 4 }, { - "name": "LayoutNGBlockFlow (relative positioned) DIV class='scroll'", - "bounds": [130, 130], - "transform": 5 + "name": "Scrolling Contents Layer", + "position": [25, 10], + "bounds": [95, 150], + "invalidations": [ + [20, 0, 75, 75] + ], + "transform": 4 }, { - "name": "Scrolling Contents Layer", - "position": [10, 10], - "bounds": [150, 95], - "invalidations": [ - [0, 20, 75, 75] - ], + "name": "LayoutNGBlockFlow (relative positioned) DIV class='scroll'", + "bounds": [130, 130], "transform": 5 }, { @@ -168,6 +159,15 @@ "position": [105, 105], "bounds": [15, 15], "transform": 5 + }, + { + "name": "Scrolling Contents Layer", + "position": [10, 10], + "bounds": [150, 95], + "invalidations": [ + [0, 20, 75, 75] + ], + "transform": 5 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt index a872fb78..43733428 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -12,6 +12,12 @@ "transform": 1 }, { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [769, 0], + "bounds": [15, 300], + "transform": 1 + }, + { "name": "Scrolling Contents Layer", "bounds": [769, 700], "transform": 2 @@ -22,21 +28,15 @@ "transform": 3 }, { - "name": "Scrolling Contents Layer", - "bounds": [754, 800], - "transform": 4 - }, - { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [754, 0], "bounds": [15, 400], "transform": 3 }, { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [769, 0], - "bounds": [15, 300], - "transform": 1 + "name": "Scrolling Contents Layer", + "bounds": [754, 800], + "transform": 4 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt index 03f2afb..57920cc5 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-delete-expected.txt
@@ -12,18 +12,18 @@ "transform": 1 }, { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [65, 0], + "bounds": [15, 69], + "transform": 1 + }, + { "name": "Scrolling Contents Layer", "bounds": [65, 198], "invalidations": [ [0, 162, 44, 36] ], "transform": 2 - }, - { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [65, 0], - "bounds": [15, 69], - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt index a872fb78..43733428 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -12,6 +12,12 @@ "transform": 1 }, { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [769, 0], + "bounds": [15, 300], + "transform": 1 + }, + { "name": "Scrolling Contents Layer", "bounds": [769, 700], "transform": 2 @@ -22,21 +28,15 @@ "transform": 3 }, { - "name": "Scrolling Contents Layer", - "bounds": [754, 800], - "transform": 4 - }, - { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [754, 0], "bounds": [15, 400], "transform": 3 }, { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [769, 0], - "bounds": [15, 300], - "transform": 1 + "name": "Scrolling Contents Layer", + "bounds": [754, 800], + "transform": 4 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt index 19abd96..654754a2 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt
@@ -12,12 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [650, 600], - "backgroundColor": "#0000FF80", - "transform": 2 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -36,6 +30,12 @@ "transform": 1 }, { + "name": "Scrolling Contents Layer", + "bounds": [650, 600], + "backgroundColor": "#0000FF80", + "transform": 2 + }, + { "name": "LayoutNGBlockFlow (positioned) DIV id='container'", "bounds": [600, 600], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt index 725212e6..e393107 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt
@@ -12,11 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [400, 400], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 185], "bounds": [85, 15], @@ -33,6 +28,11 @@ "position": [85, 185], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [400, 400], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt index 8260b99..39510ed 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt
@@ -16,12 +16,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [1, 1], - "bounds": [2000, 2000], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [1, 186], "bounds": [185, 15], @@ -38,6 +32,12 @@ "position": [186, 186], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [1, 1], + "bounds": [2000, 2000], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt index f880b7b..fbbb74c 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt
@@ -12,11 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "bounds": [150, 300], - "transform": 1 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 85], "bounds": [85, 15], @@ -33,6 +28,11 @@ "position": [85, 85], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [150, 300], + "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt index b5042ab..85952dfc 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
@@ -12,17 +12,17 @@ "transform": 2 }, { - "name": "Scrolling Contents Layer", - "bounds": [345, 2018], - "transform": 3 - }, - { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [345, 0], "bounds": [15, 640], "transform": 2 }, { + "name": "Scrolling Contents Layer", + "bounds": [345, 2018], + "transform": 3 + }, + { "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'", "bounds": [345, 18], "transform": 4
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt index 2d9e7eb..1393129 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-inside-table-cell-expected.txt
@@ -12,12 +12,6 @@ "transform": 1 }, { - "name": "Scrolling Contents Layer", - "position": [2, 2], - "bounds": [950, 450], - "transform": 2 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [2, 452], "bounds": [435, 15], @@ -34,6 +28,12 @@ "position": [437, 452], "bounds": [15, 15], "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "position": [2, 2], + "bounds": [950, 450], + "transform": 2 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt index b0b8a8c..9412cc0 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
@@ -13,12 +13,6 @@ "transform": 2 }, { - "name": "Scrolling Contents Layer", - "position": [2, 2], - "bounds": [950, 450], - "transform": 3 - }, - { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [2, 452], "bounds": [435, 15], @@ -37,6 +31,12 @@ "transform": 2 }, { + "name": "Scrolling Contents Layer", + "position": [2, 2], + "bounds": [950, 450], + "transform": 3 + }, + { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 585], "bounds": [785, 15],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt index 757afe5..0cdafde 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -12,6 +12,12 @@ "transform": 1 }, { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [769, 0], + "bounds": [15, 300], + "transform": 1 + }, + { "name": "Scrolling Contents Layer", "bounds": [769, 700], "transform": 2 @@ -22,21 +28,15 @@ "transform": 3 }, { - "name": "Scrolling Contents Layer", - "bounds": [754, 810], - "transform": 4 - }, - { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [754, 0], "bounds": [15, 400], "transform": 3 }, { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [769, 0], - "bounds": [15, 300], - "transform": 1 + "name": "Scrolling Contents Layer", + "bounds": [754, 810], + "transform": 4 } ], "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt index 757afe5..0cdafde 100644 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt +++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -12,6 +12,12 @@ "transform": 1 }, { + "name": "ContentsLayer for Vertical Scrollbar Layer", + "position": [769, 0], + "bounds": [15, 300], + "transform": 1 + }, + { "name": "Scrolling Contents Layer", "bounds": [769, 700], "transform": 2 @@ -22,21 +28,15 @@ "transform": 3 }, { - "name": "Scrolling Contents Layer", - "bounds": [754, 810], - "transform": 4 - }, - { "name": "ContentsLayer for Vertical Scrollbar Layer", "position": [754, 0], "bounds": [15, 400], "transform": 3 }, { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [769, 0], - "bounds": [15, 300], - "transform": 1 + "name": "Scrolling Contents Layer", + "bounds": [754, 810], + "transform": 4 } ], "transforms": [
diff --git a/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-stacked-children-expected.html b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-stacked-children-expected.html new file mode 100644 index 0000000..684de0c --- /dev/null +++ b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-stacked-children-expected.html
@@ -0,0 +1,2 @@ +<!doctype html> +<div style="width: 100px; height: 100px; background: green"></div>
diff --git a/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-stacked-children.html b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-stacked-children.html new file mode 100644 index 0000000..a55e6f0 --- /dev/null +++ b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-stacked-children.html
@@ -0,0 +1,34 @@ +<!doctype html> +<style> +#scroller::-webkit-scrollbar { + background: green; + width: 100px; +} +#scroller { + width: 100px; + height: 100px; + overflow-y: overlay; + overflow-x: hidden; + position: relative; +} +#notransform { + width: 100px; + height: 50px; + background: red; + position: relative; + z-index: 1; +} +#transform { + width: 100px; + height: 50px; + background: red; + position: absolute; + will-change: transform; + z-index: 2; +} +</style> +<div id="scroller"> + <div id="notransform"></div> + <div id="transform"></div> + <div id="forcescroll" style="height: 200px; width: 10px;"></div> +</div>
diff --git a/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-transparency-expected.html b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-transparency-expected.html new file mode 100644 index 0000000..684de0c --- /dev/null +++ b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-transparency-expected.html
@@ -0,0 +1,2 @@ +<!doctype html> +<div style="width: 100px; height: 100px; background: green"></div>
diff --git a/third_party/blink/web_tests/scrollbars/overlay-scrollbar-with-transparency.html b/third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-transparency.html similarity index 100% rename from third_party/blink/web_tests/scrollbars/overlay-scrollbar-with-transparency.html rename to third_party/blink/web_tests/scrollbars/overflow-overlay-scrollbar-with-transparency.html
diff --git a/third_party/blink/web_tests/scrollbars/overlay-scrollbar-with-transparency-expected.png b/third_party/blink/web_tests/scrollbars/overlay-scrollbar-with-transparency-expected.png deleted file mode 100644 index b5daa85..0000000 --- a/third_party/blink/web_tests/scrollbars/overlay-scrollbar-with-transparency-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt index ded1393..4c12a3a 100644 --- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt +++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -12,6 +12,12 @@ "transform": 1 }, { + "name": "Scrolling Contents Layer", + "bounds": [1000, 1000], + "backgroundColor": "#C0C0C0", + "transform": 1 + }, + { "name": "ContentsLayer for Horizontal Scrollbar Layer", "position": [0, 285], "bounds": [285, 15], @@ -28,12 +34,6 @@ "position": [285, 285], "bounds": [15, 15], "transform": 1 - }, - { - "name": "Scrolling Contents Layer", - "bounds": [1000, 1000], - "backgroundColor": "#C0C0C0", - "transform": 1 } ], "transforms": [
diff --git a/third_party/blink/web_tests/virtual/sxg-subresource-disabled/README.md b/third_party/blink/web_tests/virtual/sxg-subresource-disabled/README.md new file mode 100644 index 0000000..3c932a3 --- /dev/null +++ b/third_party/blink/web_tests/virtual/sxg-subresource-disabled/README.md
@@ -0,0 +1 @@ +With --disable-features=SignedExchangeSubresourcePrefetch
diff --git a/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/README.txt b/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/README.txt deleted file mode 100644 index d01256d..0000000 --- a/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/README.txt +++ /dev/null
@@ -1 +0,0 @@ -This directory is for testing the SignedExchangeSubresourcePrefetch feature.
diff --git a/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative-expected.txt b/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative-expected.txt deleted file mode 100644 index 943287c..0000000 --- a/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -PASS Subresource signed exchange prefetch. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource.tentative-expected.txt b/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource.tentative-expected.txt deleted file mode 100644 index 943287c..0000000 --- a/third_party/blink/web_tests/virtual/sxg-subresource/external/wpt/signed-exchange/subresource/sxg-subresource.tentative-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -PASS Subresource signed exchange prefetch. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index f87c815a..ec626bef 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -11371,6 +11371,13 @@ attribute @@toStringTag getter type method constructor +interface XRDepthInformation + attribute @@toStringTag + getter data + getter height + getter width + method constructor + method getDepth interface XRFrame attribute @@toStringTag getter session @@ -11378,6 +11385,7 @@ getter worldInformation method constructor method createAnchor + method getDepthInformation method getHitTestResults method getHitTestResultsForTransientInput method getLightEstimate
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index b433965..7a983bc5 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -1388,12 +1388,11 @@ cmdline = [] if test_type == 'generated_script' or is_ios or is_lacros: - script = isolate_map[target].get('script', 'bin/run_{}'.format(target)) - # TODO(crbug.com/816629): the 'script' in gn_isolate_map.pyl - # has a unix-style command line that won't work on win. We need to - # get rid of it. if is_win: - script = script.replace("bin/", "bin\\") + ".bat" + default_script = 'bin\\run_{}.bat'.format(target) + else: + default_script = 'bin/run_{}'.format(target) + script = isolate_map[target].get('script', default_script) cmdline += [script] return cmdline, []
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 2805531..de4861d 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -1188,7 +1188,8 @@ ], 'android_cronet_release_trybot_arm64': [ - 'android', 'cronet_android', 'release_trybot', 'arm64', 'strip_debug_info', + 'android', 'cronet_android', 'official_optimize', 'release_trybot', 'arm64', + 'strip_debug_info', ], 'android_debug_bot': [
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b8d0ae0..00e98fe 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -25470,6 +25470,9 @@ <histogram name="CaptivePortal.Session.SecureConnectionFailed" enum="CaptivePortalStatus" expires_after="M84"> + <obsolete> + Retired in M86. + </obsolete> <owner>michaeldo@chromium.org</owner> <owner>cros-networking@google.com</owner> <summary> @@ -25481,6 +25484,9 @@ <histogram name="CaptivePortal.Session.TimeoutDetectionResult" enum="CaptivePortalStatus" expires_after="M84"> + <obsolete> + Retired in M86. + </obsolete> <owner>michaeldo@chromium.org</owner> <owner>cros-networking@google.com</owner> <summary> @@ -51121,8 +51127,17 @@ <owner>donnd@chromium.org</owner> <owner>jinsukkim@chromium.org</owner> <summary> - Records whether the user opened the Ephemeral Tab panel when it was shown. - Recorded when the UX is hidden. Implemented for Android. + Records whether the user fully opened the Ephemeral Tab panel when it was + shown. Recorded when the UX is hidden. Implemented for Android. + </summary> +</histogram> + +<histogram name="EphemeralTab.CtrPeek" enum="BooleanOpened" expires_after="M88"> + <owner>donnd@chromium.org</owner> + <owner>jinsukkim@chromium.org</owner> + <summary> + Records whether the user opened the Ephemeral Tab panel beyond peeking + state. Recorded when the UX is hidden. Implemented for Android. </summary> </histogram>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index b304735..d24446c 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,12 +5,12 @@ "remote_path": "perfetto_binaries/trace_processor_shell/win/ef0fb4c2707e07b2cdff4186893bceea3ab1153c/trace_processor_shell.exe" }, "mac": { - "hash": "4a318e434590be8c4a5d7bb2fea5ce2411353104", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/11944f7122cf99f1aaa82eb2bed364d5edf0f85f/trace_processor_shell" + "hash": "f946b367c73e6bcbcd585ba616226febf2836477", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/ed2e4739280f8f0971c39966ac6319295b6598e4/trace_processor_shell" }, "linux": { - "hash": "a20c495e1e27fab6701fbb22250239da65afc8e5", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/8e6246dafe6190ad560958a549f11f973a573aa1/trace_processor_shell" + "hash": "a936e4844a2c42e3384d6e7fc96b00782ff6ef56", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/ed2e4739280f8f0971c39966ac6319295b6598e4/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/page_sets/data/rendering_desktop.json b/tools/perf/page_sets/data/rendering_desktop.json index 599106b..0cb4044 100644 --- a/tools/perf/page_sets/data/rendering_desktop.json +++ b/tools/perf/page_sets/data/rendering_desktop.json
@@ -21,6 +21,15 @@ "animometer_webgl_attrib_arrays": { "DEFAULT": "rendering_desktop_3a59b064d2.wprgo" }, + "animometer_webgl_indexed": { + "DEFAULT": "rendering_desktop_e66a172ea7.wprgo" + }, + "animometer_webgl_indexed_multi_draw": { + "DEFAULT": "rendering_desktop_e66a172ea7.wprgo" + }, + "animometer_webgl_indexed_multi_draw_base_vertex_base_instance": { + "DEFAULT": "rendering_desktop_e66a172ea7.wprgo" + }, "animometer_webgl_multi_draw": { "DEFAULT": "rendering_desktop_a8987d91b9.wprgo" },
diff --git a/tools/perf/page_sets/data/rendering_desktop_e66a172ea7.wprgo.sha1 b/tools/perf/page_sets/data/rendering_desktop_e66a172ea7.wprgo.sha1 new file mode 100644 index 0000000..6c48c78 --- /dev/null +++ b/tools/perf/page_sets/data/rendering_desktop_e66a172ea7.wprgo.sha1
@@ -0,0 +1 @@ +e66a172ea7810cf48688342f41f025d340bcdc2b \ No newline at end of file
diff --git a/tools/perf/page_sets/rendering/tough_webgl_cases.py b/tools/perf/page_sets/rendering/tough_webgl_cases.py index ad511ac..0676c5d6 100644 --- a/tools/perf/page_sets/rendering/tough_webgl_cases.py +++ b/tools/perf/page_sets/rendering/tough_webgl_cases.py
@@ -104,6 +104,25 @@ # pylint: disable=line-too-long URL = 'http://kenrussell.github.io/webgl-animometer/Animometer/tests/3d/webgl.html?webgl_version=2&use_ubos=1&use_multi_draw=1' + +class AnimometerWebGLIndexed(ToughWebglPage): + BASE_NAME = 'animometer_webgl_indexed' + # pylint: disable=line-too-long + URL = 'http://kenrussell.github.io/webgl-animometer/Animometer/tests/3d/webgl-indexed-instanced.html?webgl_version=2&use_attributes=1&num_geometries=120000' + + +class AnimometerWebGLIndexedMultiDraw(ToughWebglPage): + BASE_NAME = 'animometer_webgl_indexed_multi_draw' + # pylint: disable=line-too-long + URL = 'http://kenrussell.github.io/webgl-animometer/Animometer/tests/3d/webgl-indexed-instanced.html?webgl_version=2&use_attributes=1&use_multi_draw=1&num_geometries=120000' + + +class AnimometerWebGLIndexedBaseVertexBaseInstancePage(ToughWebglPage): + BASE_NAME = 'animometer_webgl_indexed_multi_draw_base_vertex_base_instance' + # pylint: disable=line-too-long + URL = 'http://kenrussell.github.io/webgl-animometer/Animometer/tests/3d/webgl-indexed-instanced.html?webgl_version=2&use_attributes=1&use_multi_draw=1&use_base_vertex_base_instance=1&num_geometries=120000' + + class AnimometerWebGLAttribArraysPage(ToughWebglPage): BASE_NAME = 'animometer_webgl_attrib_arrays' # pylint: disable=line-too-long
diff --git a/tools/polymer/polymer.py b/tools/polymer/polymer.py index a92fbb5..75d78fd 100644 --- a/tools/polymer/polymer.py +++ b/tools/polymer/polymer.py
@@ -179,24 +179,26 @@ def _generate_js_imports(html_file): output = [] + imports_start_offset = -1 imports_end_index = -1 imports_found = False with io.open(html_file, encoding='utf-8', mode='r') as f: lines = f.readlines() - deps = [] for i, line in enumerate(lines): match = re.search(r'\s*<link rel="import" href="(.*)"', line) if match: if not imports_found: imports_found = True + imports_start_offset = i # Include the previous line if it is an opening <if> tag. if (i > 0): previous_line = lines[i - 1] if re.search(r'^\s*<if', previous_line): + imports_start_offset -= 1 previous_line = '// ' + previous_line output.append(previous_line.rstrip('\n')) - imports_end_index = i + imports_end_index = i - imports_start_offset # Convert HTML import URL to equivalent JS import URL. dep = Dependency(html_file, match.group(1))
diff --git a/tools/polymer/polymer_test.py b/tools/polymer/polymer_test.py index f48d594..b5d96a5 100755 --- a/tools/polymer/polymer_test.py +++ b/tools/polymer/polymer_test.py
@@ -110,6 +110,13 @@ 'dom_module.js', 'dom_module.m.js', 'dom_module_with_if_expr_expected.js') + # Test case where HTML has some comment before the first <link rel="import"> \ + # and also uses <if expr> for imports. + def testDomModuleImportsWithCopyrightPrefix(self): + self._run_test('dom-module', 'dom_module_with_copyright.html', + 'dom_module.js', 'dom_module.m.js', + 'dom_module_with_if_expr_expected.js') + # Test case where HTML is extracted from a Polymer2 style module. def testStyleModule(self): self._run_test(
diff --git a/tools/polymer/tests/dom_module_with_copyright.html b/tools/polymer/tests/dom_module_with_copyright.html new file mode 100644 index 0000000..9aee84cc --- /dev/null +++ b/tools/polymer/tests/dom_module_with_copyright.html
@@ -0,0 +1,28 @@ +<!-- 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. +--> + +<if expr="chromeos"> +<link rel="import" href="../shared_vars_chromeos_css.html"> +</if> +<link rel="import" href="../../../ui/webui/resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html"> +<link rel="import" href="../shared_vars_css.html"> +<link rel="import" href="foo.html"> +<if expr="chromeos"> +<link rel="import" href="bar.html"> +</if> + +<dom-module id="cr-test-foo"> + <template> + <style> + div { + font-size: 2rem; + } + </style> + <div>Hello world</div> + </template> + <script src="dom_module.js"></script> +</dom-module>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 4e4326c..636e32714 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -186,7 +186,7 @@ <item id="network_location_provider" hash_code="23472048" type="1" second_id="96590038" content_hash_code="41087976" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="services/device/geolocation/network_location_provider.cc"/> <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="80741011" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="services/device/geolocation/network_location_request.cc"/> <item id="network_time_component" hash_code="46188932" type="0" content_hash_code="28051857" os_list="linux,windows" file_path="components/network_time/network_time_tracker.cc"/> - <item id="new_tab_page_handler" hash_code="48673144" type="0" content_hash_code="100789845" os_list="linux,windows" file_path="chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc"/> + <item id="new_tab_page_handler" hash_code="48673144" type="0" content_hash_code="49174657" os_list="linux,windows" file_path="chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc"/> <item id="notification_client" hash_code="78479125" type="0" content_hash_code="129874070" os_list="linux,windows" file_path="remoting/client/notification/notification_client.cc"/> <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" deprecated="2019-04-18" content_hash_code="107035434" file_path=""/> <item id="ntp_custom_background" hash_code="92125886" type="0" content_hash_code="61176452" os_list="linux,windows" file_path="chrome/browser/search/instant_service.cc"/>
diff --git a/tools/win/OWNERS b/tools/win/OWNERS index 0d31244e..327cc33 100644 --- a/tools/win/OWNERS +++ b/tools/win/OWNERS
@@ -1,3 +1,4 @@ ajgo@chromium.org brucedawson@chromium.org +jessemckenna@google.com scottmg@chromium.org
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc index a4a9ebd9..173c21a 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -52,6 +52,11 @@ MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_ABSOLUTE); ui::SendMouseEvent(screen_point, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE); desktop_host_->SetInTouchDrag(true); + // Gesture state gets left in a state where you can't start + // another drag, unless it's cleaned up. Cleaning it up before starting + // drag drop also fixes an issue with getting two kGestureScrollBegin events + // in a row. See crbug.com/1120809. + source_window->CleanupGestureState(); } base::WeakPtr<DesktopDragDropClientWin> alive(weak_factory_.GetWeakPtr()); @@ -69,9 +74,6 @@ ui::DragDropTypes::DragOperationToDropEffect(operation), &effect); if (alive && source == ui::mojom::DragEventSource::kTouch) { desktop_host_->SetInTouchDrag(false); - // Gesture state gets left in a state where you can't start - // another drag, unless it's cleaned up. - source_window->CleanupGestureState(); } drag_source_copy->set_data(nullptr);
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_icon.js b/ui/webui/resources/cr_components/chromeos/network/network_icon.js index e01e0d9..e2a74ac 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_icon.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_icon.js
@@ -216,7 +216,12 @@ * @private */ showTechnology_() { - return this.getTechnology_() !== '' && this.showTechnologyBadge; + if (!this.networkState) { + return false; + } + return OncMojo.connectionStateIsConnected( + this.networkState.connectionState) && + this.getTechnology_() !== '' && this.showTechnologyBadge; }, /**
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java index 5827515..deaf4e6 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
@@ -827,4 +827,32 @@ mActivityTestRule.navigateAndWait(URL2); assertFalse(mCallback.onStartedCallback.isPageInitiated()); } + + /** + * This test verifies calling destroyTab() from within onNavigationFailed doesn't crash. + */ + @Test + @SmallTest + @MinWebLayerVersion(87) + public void testDestroyTabInNavigationFailed() throws Throwable { + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null); + CallbackHelper callbackHelper = new CallbackHelper(); + runOnUiThreadBlocking(() -> { + NavigationController navigationController = activity.getTab().getNavigationController(); + navigationController.registerNavigationCallback(new NavigationCallback() { + @Override + public void onNavigationFailed(Navigation navigation) { + navigationController.unregisterNavigationCallback(this); + Tab tab = activity.getTab(); + tab.getBrowser().destroyTab(tab); + callbackHelper.notifyCalled(); + } + }); + }); + TestThreadUtils.runOnUiThreadBlocking(() -> { + activity.getTab().getNavigationController().navigate( + Uri.parse("http://localhost:7/non_existent")); + }); + callbackHelper.waitForFirst(); + } }
diff --git a/weblayer/browser/browser_impl.cc b/weblayer/browser/browser_impl.cc index 61b6bcfb..04c775fb 100644 --- a/weblayer/browser/browser_impl.cc +++ b/weblayer/browser/browser_impl.cc
@@ -271,6 +271,12 @@ #endif } +#if defined(OS_ANDROID) +void BrowserImpl::DestroyTabFromJava(Tab* tab) { + RemoveTab(tab); +} +#endif + void BrowserImpl::AddTab(Tab* tab) { DCHECK(tab); TabImpl* tab_impl = static_cast<TabImpl*>(tab); @@ -283,7 +289,12 @@ } void BrowserImpl::DestroyTab(Tab* tab) { +#if defined(OS_ANDROID) + Java_BrowserImpl_destroyTabImpl(AttachCurrentThread(), java_impl_, + static_cast<TabImpl*>(tab)->GetJavaTab()); +#else RemoveTab(tab); +#endif } void BrowserImpl::SetActiveTab(Tab* tab) {
diff --git a/weblayer/browser/browser_impl.h b/weblayer/browser/browser_impl.h index f5487af1..02363c1 100644 --- a/weblayer/browser/browser_impl.h +++ b/weblayer/browser/browser_impl.h
@@ -97,6 +97,14 @@ bool GetPasswordEchoEnabled(); void SetWebPreferences(content::WebPreferences* prefs); +#if defined(OS_ANDROID) + // On Android the Java Tab class owns the C++ Tab. DestroyTab() calls to the + // Java Tab class to initiate deletion. This function is called from the Java + // side, and must not call DestroyTab(), otherwise we get stuck in infinite + // recursion. + void DestroyTabFromJava(Tab* tab); +#endif + // Browser: void AddTab(Tab* tab) override; void DestroyTab(Tab* tab) override;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java index dfd34f0..1fc0c5bf 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -434,6 +434,7 @@ destroyTabImpl((TabImpl) iTab); } + @CalledByNative private void destroyTabImpl(TabImpl tab) { tab.destroy(); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/SiteSettingsFragmentImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/SiteSettingsFragmentImpl.java index 072df06..4621ed6 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/SiteSettingsFragmentImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/SiteSettingsFragmentImpl.java
@@ -24,6 +24,7 @@ import androidx.preference.PreferenceFragmentCompat; import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.components.browser_ui.site_settings.AllSiteSettings; import org.chromium.components.browser_ui.site_settings.SingleCategorySettings; import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings; import org.chromium.components.browser_ui.site_settings.SiteSettings; @@ -150,6 +151,11 @@ mFragmentImpl.getEmbedderContext(), mFragmentImpl.getProfile().getName(), newFragmentArgs.getString(SingleCategorySettings.EXTRA_CATEGORY), newFragmentArgs.getString(SingleCategorySettings.EXTRA_TITLE)); + } else if (newFragmentClassName.equals(AllSiteSettings.class.getName())) { + intent = SiteSettingsIntentHelper.createIntentForAllSites( + mFragmentImpl.getEmbedderContext(), mFragmentImpl.getProfile().getName(), + newFragmentArgs.getString(AllSiteSettings.EXTRA_CATEGORY), + newFragmentArgs.getString(AllSiteSettings.EXTRA_TITLE)); } else if (newFragmentClassName.equals(SingleWebsiteSettings.class.getName())) { WebsiteAddress address; if (newFragmentArgs.containsKey(SingleWebsiteSettings.EXTRA_SITE)) { @@ -217,6 +223,14 @@ // implementation fragments expect. Bundle fragmentArgs = intentExtras.getBundle(SiteSettingsFragmentArgs.FRAGMENT_ARGUMENTS); switch (intentExtras.getString(SiteSettingsFragmentArgs.FRAGMENT_NAME)) { + case SiteSettingsFragmentArgs.ALL_SITES: + mFragmentClass = AllSiteSettings.class; + mFragmentArguments = new Bundle(); + mFragmentArguments.putString(AllSiteSettings.EXTRA_TITLE, + fragmentArgs.getString(SiteSettingsFragmentArgs.ALL_SITES_TITLE)); + mFragmentArguments.putString(AllSiteSettings.EXTRA_CATEGORY, + fragmentArgs.getString(SiteSettingsFragmentArgs.ALL_SITES_TYPE)); + break; case SiteSettingsFragmentArgs.CATEGORY_LIST: mFragmentClass = SiteSettings.class; mFragmentArguments = null;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsFragmentArgs.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsFragmentArgs.java index a983e34..6278b6d 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsFragmentArgs.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsFragmentArgs.java
@@ -14,6 +14,7 @@ String FRAGMENT_ARGUMENTS = "fragment_arguments"; // FRAGMENT_NAME values + String ALL_SITES = "all_sites"; String CATEGORY_LIST = "category_list"; String SINGLE_CATEGORY = "single_category"; String SINGLE_WEBSITE = "single_website"; @@ -24,4 +25,8 @@ // SINGLE_CATEGORY argument names String SINGLE_CATEGORY_TITLE = "title"; String SINGLE_CATEGORY_TYPE = "type"; + + // ALL_SITES argument names + String ALL_SITES_TITLE = "title"; + String ALL_SITES_TYPE = "type"; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsIntentHelper.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsIntentHelper.java index 4b1b882..34a7b79c 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsIntentHelper.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SiteSettingsIntentHelper.java
@@ -50,6 +50,21 @@ return createIntentWithExtras(context, extras); } + /** Creates an Intent that launches the all sites settings UI. */ + public static Intent createIntentForAllSites( + Context context, String profileName, String type, String title) { + Bundle extras = new Bundle(); + extras.putString(SiteSettingsFragmentArgs.PROFILE_NAME, profileName); + extras.putString( + SiteSettingsFragmentArgs.FRAGMENT_NAME, SiteSettingsFragmentArgs.ALL_SITES); + + Bundle fragmentArgs = new Bundle(); + fragmentArgs.putString(SiteSettingsFragmentArgs.ALL_SITES_TITLE, title); + fragmentArgs.putString(SiteSettingsFragmentArgs.ALL_SITES_TYPE, type); + extras.putBundle(SiteSettingsFragmentArgs.FRAGMENT_ARGUMENTS, fragmentArgs); + return createIntentWithExtras(context, extras); + } + private static Intent createIntentWithExtras(Context context, Bundle extras) { Intent intent = new Intent(); intent.setClassName(context, SiteSettingsFragmentArgs.ACTIVITY_CLASS_NAME);
diff --git a/weblayer/browser/navigation_browsertest.cc b/weblayer/browser/navigation_browsertest.cc index c869c59..ba8caf7c 100644 --- a/weblayer/browser/navigation_browsertest.cc +++ b/weblayer/browser/navigation_browsertest.cc
@@ -14,6 +14,7 @@ #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_response.h" +#include "weblayer/public/browser.h" #include "weblayer/public/navigation.h" #include "weblayer/public/navigation_controller.h" #include "weblayer/public/navigation_observer.h" @@ -68,8 +69,11 @@ completed_callback_.Run(navigation); } void NavigationFailed(Navigation* navigation) override { - if (failed_callback_) - failed_callback_.Run(navigation); + // As |this| may be deleted when running the callback, the callback must be + // copied before running. To do otherwise results in use-after-free. + auto callback = failed_callback_; + if (callback) + callback.Run(navigation); } private: @@ -259,6 +263,25 @@ run_loop.Run(); } +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, DestroyTabInNavigation) { + ASSERT_TRUE(embedded_test_server()->Start()); + Tab* new_tab = shell()->browser()->CreateTab(); + base::RunLoop run_loop; + std::unique_ptr<NavigationObserverImpl> observer = + std::make_unique<NavigationObserverImpl>( + new_tab->GetNavigationController()); + observer->SetFailedCallback( + base::BindLambdaForTesting([&](Navigation* navigation) { + observer.reset(); + shell()->browser()->DestroyTab(new_tab); + run_loop.Quit(); + })); + new_tab->GetNavigationController()->Navigate( + embedded_test_server()->GetURL("/simple_pageX.html")); + + run_loop.Run(); +} + IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, StopInOnRedirect) { ASSERT_TRUE(embedded_test_server()->Start()); base::RunLoop run_loop;
diff --git a/weblayer/browser/navigation_controller_impl.cc b/weblayer/browser/navigation_controller_impl.cc index b7788f47..f931bf64 100644 --- a/weblayer/browser/navigation_controller_impl.cc +++ b/weblayer/browser/navigation_controller_impl.cc
@@ -31,6 +31,29 @@ namespace weblayer { +class NavigationControllerImpl::DelayDeletionHelper { + public: + explicit DelayDeletionHelper(NavigationControllerImpl* controller) + : controller_(controller->weak_ptr_factory_.GetWeakPtr()) { + // This should never be called reentrantly. + DCHECK(!controller->should_delay_web_contents_deletion_); + controller->should_delay_web_contents_deletion_ = true; + } + + DelayDeletionHelper(const DelayDeletionHelper&) = delete; + DelayDeletionHelper& operator=(const DelayDeletionHelper&) = delete; + + ~DelayDeletionHelper() { + if (controller_) + controller_->should_delay_web_contents_deletion_ = false; + } + + bool WasControllerDeleted() { return controller_.get() == nullptr; } + + private: + base::WeakPtr<NavigationControllerImpl> controller_; +}; + // NavigationThrottle implementation responsible for delaying certain // operations and performing them when safe. This is necessary as content // does allow certain operations to be called at certain times. For example, @@ -343,6 +366,7 @@ if (!navigation_handle->IsInMainFrame()) return; + DelayDeletionHelper deletion_helper(this); DCHECK(navigation_map_.find(navigation_handle) != navigation_map_.end()); auto* navigation = navigation_map_[navigation_handle].get(); if (navigation_handle->GetNetErrorCode() == net::OK && @@ -354,10 +378,15 @@ Java_NavigationControllerImpl_navigationCompleted( AttachCurrentThread(), java_controller_, navigation->java_navigation()); + if (deletion_helper.WasControllerDeleted()) + return; } #endif - for (auto& observer : observers_) + for (auto& observer : observers_) { observer.NavigationCompleted(navigation); + if (deletion_helper.WasControllerDeleted()) + return; + } } else { #if defined(OS_ANDROID) if (java_controller_) { @@ -366,10 +395,15 @@ Java_NavigationControllerImpl_navigationFailed( AttachCurrentThread(), java_controller_, navigation->java_navigation()); + if (deletion_helper.WasControllerDeleted()) + return; } #endif - for (auto& observer : observers_) + for (auto& observer : observers_) { observer.NavigationFailed(navigation); + if (deletion_helper.WasControllerDeleted()) + return; + } } // Note InsertVisualStateCallback currently does not take into account
diff --git a/weblayer/browser/navigation_controller_impl.h b/weblayer/browser/navigation_controller_impl.h index d7e24bd..240573b 100644 --- a/weblayer/browser/navigation_controller_impl.h +++ b/weblayer/browser/navigation_controller_impl.h
@@ -73,7 +73,13 @@ bool IsNavigationEntrySkippable(JNIEnv* env, int index); #endif + bool should_delay_web_contents_deletion() { + return should_delay_web_contents_deletion_; + } + private: + class DelayDeletionHelper; + class NavigationThrottleImpl; // Called from NavigationControllerImpl::WillRedirectRequest(). See @@ -134,6 +140,11 @@ base::android::ScopedJavaGlobalRef<jobject> java_controller_; #endif + // Set to true while processing an observer/callback and it's unsafe to + // delete the WebContents. This is not used for all callbacks, just the + // ones that we need to allow deletion from (such as completed/failed). + bool should_delay_web_contents_deletion_ = false; + base::WeakPtrFactory<NavigationControllerImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(NavigationControllerImpl);
diff --git a/weblayer/browser/persistence/browser_persister_browsertest.cc b/weblayer/browser/persistence/browser_persister_browsertest.cc index aa23fc94..a8eeec2 100644 --- a/weblayer/browser/persistence/browser_persister_browsertest.cc +++ b/weblayer/browser/persistence/browser_persister_browsertest.cc
@@ -47,50 +47,6 @@ namespace { using testing::UnorderedElementsAre; -class OneShotNavigationObserver : public NavigationObserver { - public: - explicit OneShotNavigationObserver(Shell* shell) : tab_(shell->tab()) { - tab_->GetNavigationController()->AddObserver(this); - } - - ~OneShotNavigationObserver() override { - tab_->GetNavigationController()->RemoveObserver(this); - } - - void WaitForNavigation() { run_loop_.Run(); } - - bool completed() { return completed_; } - bool is_error_page() { return is_error_page_; } - Navigation::LoadError load_error() { return load_error_; } - int http_status_code() { return http_status_code_; } - NavigationState navigation_state() { return navigation_state_; } - - private: - // NavigationObserver implementation: - void NavigationCompleted(Navigation* navigation) override { - completed_ = true; - Finish(navigation); - } - - void NavigationFailed(Navigation* navigation) override { Finish(navigation); } - - void Finish(Navigation* navigation) { - is_error_page_ = navigation->IsErrorPage(); - load_error_ = navigation->GetLoadError(); - http_status_code_ = navigation->GetHttpStatusCode(); - navigation_state_ = navigation->GetState(); - run_loop_.Quit(); - } - - base::RunLoop run_loop_; - Tab* tab_; - bool completed_ = false; - bool is_error_page_ = false; - Navigation::LoadError load_error_ = Navigation::kNoError; - int http_status_code_ = 0; - NavigationState navigation_state_ = NavigationState::kWaitingResponse; -}; - class BrowserObserverImpl : public BrowserObserver { public: static void WaitForNewTab(Browser* browser) {
diff --git a/weblayer/browser/profile_impl.cc b/weblayer/browser/profile_impl.cc index 2ccc51e6..4889094 100644 --- a/weblayer/browser/profile_impl.cc +++ b/weblayer/browser/profile_impl.cc
@@ -28,6 +28,7 @@ #include "content/public/browser/download_manager.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" #include "services/network/public/mojom/network_context.mojom.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" @@ -232,6 +233,10 @@ } ProfileImpl::~ProfileImpl() { + // Destroy any scheduled WebContents. These implicitly refer to the + // BrowserContext and must be destroyed before the BrowserContext. + web_contents_to_delete_.clear(); + if (browser_context_) { BrowserContextDependencyManager::GetInstance() ->DestroyBrowserContextServices(browser_context_.get()); @@ -260,6 +265,16 @@ GetObservers().RemoveObserver(observer); } +void ProfileImpl::DeleteWebContentsSoon( + std::unique_ptr<content::WebContents> web_contents) { + if (web_contents_to_delete_.empty()) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&ProfileImpl::DeleteScheduleWebContents, + weak_ptr_factory_.GetWeakPtr())); + } + web_contents_to_delete_.push_back(std::move(web_contents)); +} + BrowserContextImpl* ProfileImpl::GetBrowserContext() { if (browser_context_) return browser_context_.get(); @@ -667,4 +682,8 @@ [this](BrowserImpl* b) { return b->profile() == this; }); } +void ProfileImpl::DeleteScheduleWebContents() { + web_contents_to_delete_.clear(); +} + } // namespace weblayer
diff --git a/weblayer/browser/profile_impl.h b/weblayer/browser/profile_impl.h index 75c3162..5707d85 100644 --- a/weblayer/browser/profile_impl.h +++ b/weblayer/browser/profile_impl.h
@@ -6,6 +6,7 @@ #define WEBLAYER_BROWSER_PROFILE_IMPL_H_ #include <set> +#include <vector> #include "base/files/file_path.h" #include "base/macros.h" @@ -23,6 +24,7 @@ namespace content { class BrowserContext; +class WebContents; } namespace weblayer { @@ -64,6 +66,11 @@ static void AddProfileObserver(ProfileObserver* observer); static void RemoveProfileObserver(ProfileObserver* observer); + // Deletes |web_contents| after a delay. This is used if the owning Tab is + // deleted and it's not safe to delete the WebContents. + void DeleteWebContentsSoon( + std::unique_ptr<content::WebContents> web_contents); + BrowserContextImpl* GetBrowserContext(); // Called when the download subsystem has finished initializing. By this point @@ -156,6 +163,8 @@ // Returns the number of Browsers with this profile. int GetNumberOfBrowsers(); + void DeleteScheduleWebContents(); + ProfileInfo info_; std::unique_ptr<BrowserContextImpl> browser_context_; @@ -178,6 +187,10 @@ // CancelableTaskTracker is owned by Profile. base::CancelableTaskTracker cancelable_task_tracker_; + std::vector<std::unique_ptr<content::WebContents>> web_contents_to_delete_; + + base::WeakPtrFactory<ProfileImpl> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(ProfileImpl); };
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc index 29d8e3f..2a95b92 100644 --- a/weblayer/browser/tab_impl.cc +++ b/weblayer/browser/tab_impl.cc
@@ -301,8 +301,7 @@ sessions::SessionTabHelper::CreateForWebContents( web_contents_.get(), - base::BindRepeating(&TabImpl::GetSessionServiceTabHelperDelegate, - base::Unretained(this))); + base::BindRepeating(&TabImpl::GetSessionServiceTabHelperDelegate)); permissions::PermissionRequestManager::CreateForWebContents( web_contents_.get()); @@ -361,6 +360,14 @@ #endif Observe(nullptr); web_contents_->SetDelegate(nullptr); + if (navigation_controller_->should_delay_web_contents_deletion()) { + // Remove the linkage between this and the WebContents. + web_contents_->RemoveUserData(&kWebContentsUserDataKey); + // Have Profile handle the task posting to ensure the WebContents is + // deleted before Profile. To do otherwise means it would be possible for + // the Profile to outlive the WebContents, which is problematic (crash). + profile_->DeleteWebContentsSoon(std::move(web_contents_)); + } web_contents_.reset(); GetTabs().erase(this); } @@ -568,7 +575,8 @@ TabImpl* tab_impl = reinterpret_cast<TabImpl*>(tab); DCHECK(tab_impl); DCHECK(tab_impl->browser()); - tab_impl->browser()->DestroyTab(tab_impl); + // Don't call Browser::DestroyTab() as it calls back to the java side. + tab_impl->browser()->DestroyTabFromJava(tab_impl); } ScopedJavaLocalRef<jobject> TabImpl::GetWebContents(JNIEnv* env) { @@ -1246,10 +1254,11 @@ return find_in_page::FindTabHelper::FromWebContents(web_contents_.get()); } +// static sessions::SessionTabHelperDelegate* TabImpl::GetSessionServiceTabHelperDelegate( content::WebContents* web_contents) { - DCHECK_EQ(web_contents, web_contents_.get()); - return browser_ ? browser_->browser_persister() : nullptr; + TabImpl* tab = FromWebContents(web_contents); + return (tab && tab->browser_) ? tab->browser_->browser_persister() : nullptr; } bool TabImpl::SetDataInternal(const std::map<std::string, std::string>& data) {
diff --git a/weblayer/browser/tab_impl.h b/weblayer/browser/tab_impl.h index 4c56808..4476276 100644 --- a/weblayer/browser/tab_impl.h +++ b/weblayer/browser/tab_impl.h
@@ -345,7 +345,7 @@ // Returns the FindTabHelper for the page, or null if none exists. find_in_page::FindTabHelper* GetFindTabHelper(); - sessions::SessionTabHelperDelegate* GetSessionServiceTabHelperDelegate( + static sessions::SessionTabHelperDelegate* GetSessionServiceTabHelperDelegate( content::WebContents* web_contents); #if defined(OS_ANDROID)
diff --git a/weblayer/weblayer_resource_exclusions.gni b/weblayer/weblayer_resource_exclusions.gni index 169673e..f5498829 100644 --- a/weblayer/weblayer_resource_exclusions.gni +++ b/weblayer/weblayer_resource_exclusions.gni
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -_material_package = "*com_google_android_material_material*" +_material_package = "*com_google_android_material*" weblayer_resource_exclusion_exceptions = [ # TextInputLayout (used for HTTP Auth dialog) @@ -37,7 +37,7 @@ "${_material_package}:[Tt]oolbarLayout", ] -_material_package = "com_google_android_material_material.*" +_material_package = "com_google_android_material.*" # Used only by alert dialog on tiny screens. weblayer_resource_exclusion_regex = "${_material_package}values-small"