diff --git a/DEPS b/DEPS index faf734e..5fd6181 100644 --- a/DEPS +++ b/DEPS
@@ -145,11 +145,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': '8566dda51b421a9c2c6a7e8659fe3948a1fab3c9', + 'skia_revision': '52a6a40535b0839d3565e4be84e98f2ed25723d6', # 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': '05137a762c9ecaad8c9fa555284b4f907e273e2d', + 'v8_revision': '0803a22ad80fa936336cdd94985dd744b74b5b4e', # 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. @@ -161,11 +161,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'aad8cfca57fd78cfe8ad899d4718764f092f507a', + 'swiftshader_revision': 'fd72dd0a439f093bbac7f4693bfbad496c4fe922', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '4935770daa8e301c12f4e5d021b6124fc96dc28c', + 'pdfium_revision': '451ed2dbac83f787ca6438a4efe347e0ff986bf4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -180,7 +180,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': '27e17f7851e2cc51db2c47470d29513970327cc1', + 'googletest_revision': 'd5e9e0c38f85363e90b0a3e95a9484fe896d38e5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -208,7 +208,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': '1f288d915d107bef80b06ba6e3a1c26b40de554d', + 'catapult_revision': '939b6b1f1c56d6a863bdb4132637c010639f9006', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -280,7 +280,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'ee3de1e1f3da2386197a2c586304deb263890a35', + 'dawn_revision': 'd8cdcea0eeb1f0467bdd0c37c7be638b0427b169', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -377,7 +377,7 @@ 'packages': [ { 'package': 'chromium/android_webview/tools/cts_archive', - 'version': '5-mDBex75LGRj8ezea7057l5cu4pIXy6pjgdU1X3F78C', + 'version': 'V3W65R48ryiA3ecaekbuWV3duqeF8A5U_Q07E2bAyVYC', }, ], 'condition': 'checkout_android', @@ -825,7 +825,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '82c85d4f089f6c470fbc9a624d91f0302fceb6d0', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'caaa058f628b4875552b0dc198221cd6205b3056', 'condition': 'checkout_linux', }, @@ -850,7 +850,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '73b9263523ee68252313bd16a3a1396ada779f20', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'df7093214c55bf919d7da435d524d7f77d7c16c0', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -885,7 +885,7 @@ }, 'src/third_party/ffmpeg': - Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'e0e3133c40fbca0032a2d9400da736e4b933882f', + Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '0f36d36f49735b889d5cbcc1ed366a06b4651153', 'src/third_party/flac': Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596', @@ -1010,7 +1010,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'ecb3c4f4ce2c13278699489bd6356a31e1ee4d11', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '9a5af81f58a2bc2ea7a887505e38b50021496194', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '2b2ee7158675555acb4d0d0cbb5dff71c00e7c54', 'src/third_party/icu4j': { 'packages': [ @@ -1223,7 +1223,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '35b0708074d1a4c05113c1d94993c0fa452f0f1e', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '5817e8e9b2880d4fe03117def2f4ed5e2d95ab58', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1293,7 +1293,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': '6mmxCrRGY15GNu1r-XmGVxohZfruF6_XjiKSCZakkN4C', + 'version': 'PiWJNu1SdDl433fYwX_rFSX3zNZWizTfghShod_8QZ0C', }, ], 'condition': 'checkout_android', @@ -1432,7 +1432,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@4dfd57b8be2c85bbac503adb7dbc94b9d866f98f', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f2e04cc7654d0e2d34112dbee2a2c4bfebb1efea', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/tools/cts_archive/cipd.yaml b/android_webview/tools/cts_archive/cipd.yaml index b926981..00aa1b5b 100644 --- a/android_webview/tools/cts_archive/cipd.yaml +++ b/android_webview/tools/cts_archive/cipd.yaml
@@ -11,7 +11,9 @@ - file: arm64/M/android-cts-arm64-6.0_r32.zip - file: arm64/N/android-cts-arm64-7.0_r31.zip - file: arm64/O/android-cts-arm64-8.0_r19.zip + - file: arm64/P/android-cts-arm64-9.0_r8.zip - file: x86/L/android-cts-x86-5.1_r28.zip - file: x86/M/android-cts-x86-6.0_r32.zip - file: x86/N/android-cts-x86-7.0_r31.zip - file: x86/O/android-cts-x86-8.0_r19.zip + - file: x86/P/android-cts-x86-9.0_r8.zip
diff --git a/android_webview/tools/cts_archive/version.txt b/android_webview/tools/cts_archive/version.txt index 810ee4e..d3bdbdf 100644 --- a/android_webview/tools/cts_archive/version.txt +++ b/android_webview/tools/cts_archive/version.txt
@@ -1 +1 @@ -1.6 +1.7
diff --git a/android_webview/tools/cts_config/webview_cts_gcs_path.json b/android_webview/tools/cts_config/webview_cts_gcs_path.json index 4d3aeef..e46fd0d 100644 --- a/android_webview/tools/cts_config/webview_cts_gcs_path.json +++ b/android_webview/tools/cts_config/webview_cts_gcs_path.json
@@ -266,5 +266,34 @@ "apk": "android-cts/testcases/CtsWebViewStartupApp.apk" } ] + }, + "P": { + "arch": { + "arm64": { + "filename": "arm64/P/android-cts-arm64-9.0_r8.zip", + "_origin": "aosp-pie-cts-release@9.0_r8", + "unzip_dir": "arm64/P/9.0_r8/" + }, + "x86": { + "filename": "x86/P/android-cts-x86-9.0_r8.zip", + "_origin": "aosp-pie-cts-release@9.0_r8", + "unzip_dir": "x86/P/9.0_r8/" + } + }, + "test_runs": [ + { + "apk": "android-cts/testcases/CtsWebkitTestCases.apk", + "excludes": [ + { + "match": "android.webkit.cts.WebViewTest#testGetContentHeight", + "_bug_id": "crbug.com/967173" + } + ] + }, + { + "apk": "android-cts/testcases/CtsWebViewStartupApp.apk" + } + ] } + }
diff --git a/android_webview/tools/run_cts.py b/android_webview/tools/run_cts.py index 13774de..ef84ebb 100755 --- a/android_webview/tools/run_cts.py +++ b/android_webview/tools/run_cts.py
@@ -52,7 +52,8 @@ version_codes.NOUGAT: 'N', version_codes.NOUGAT_MR1: 'N', version_codes.OREO: 'O', - version_codes.OREO_MR1: 'O' + version_codes.OREO_MR1: 'O', + version_codes.PIE: 'P', } # The test apks are apparently compatible across all architectures, the
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index f9570242e..b4473dde 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -2729,6 +2729,8 @@ void AppsGridView::SetViewHidden(AppListItemView* view, bool hide, bool immediate) { + if (!view->layer()) + return; ui::ScopedLayerAnimationSettings animator(view->layer()->GetAnimator()); animator.SetPreemptionStrategy( immediate ? ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET
diff --git a/ash/display/display_error_observer_unittest.cc b/ash/display/display_error_observer_unittest.cc index bffa7ce..67e608e 100644 --- a/ash/display/display_error_observer_unittest.cc +++ b/ash/display/display_error_observer_unittest.cc
@@ -34,6 +34,7 @@ gfx::ColorSpace() /* color_space */, std::string() /* display_name */, base::FilePath() /* sys_path */, display::DisplaySnapshot::DisplayModeList() /* modes */, + display::PanelOrientation::kNormal /* panel_orientation */, std::vector<uint8_t>() /* edid */, nullptr /* current_mode */, nullptr /* native_mode */, 0 /* product_id */, display::kInvalidYearOfManufacture,
diff --git a/ash/login/ui/lock_screen_media_controls_view_unittest.cc b/ash/login/ui/lock_screen_media_controls_view_unittest.cc index 5078f15..68e6dd2b 100644 --- a/ash/login/ui/lock_screen_media_controls_view_unittest.cc +++ b/ash/login/ui/lock_screen_media_controls_view_unittest.cc
@@ -219,6 +219,12 @@ return header_row()->close_button_for_testing(); } + bool CloseButtonHasImage() const { + return !close_button() + ->GetImage(views::Button::ButtonState::STATE_NORMAL) + .isNull(); + } + const views::ImageView* icon_view() const { return header_row()->app_icon_for_testing(); } @@ -409,7 +415,8 @@ TEST_F(LockScreenMediaControlsViewTest, CloseButtonVisibility) { EXPECT_TRUE(media_controls_view_->IsDrawn()); - EXPECT_FALSE(close_button()->IsDrawn()); + EXPECT_TRUE(close_button()->IsDrawn()); + EXPECT_FALSE(CloseButtonHasImage()); // Move the mouse inside |media_controls_view_|. ui::test::EventGenerator* generator = GetEventGenerator(); @@ -417,14 +424,17 @@ media_controls_view_->GetBoundsInScreen().CenterPoint()); // Verify that the close button is shown. + EXPECT_TRUE(media_controls_view_->IsDrawn()); EXPECT_TRUE(close_button()->IsDrawn()); + EXPECT_TRUE(CloseButtonHasImage()); // Move the mouse outside |media_controls_view_|. generator->MoveMouseBy(500, 500); // Verify that the close button is hidden. EXPECT_TRUE(media_controls_view_->IsDrawn()); - EXPECT_FALSE(close_button()->IsDrawn()); + EXPECT_TRUE(close_button()->IsDrawn()); + EXPECT_FALSE(CloseButtonHasImage()); } TEST_F(LockScreenMediaControlsViewTest, CloseButtonClick) {
diff --git a/ash/login/ui/media_controls_header_view.cc b/ash/login/ui/media_controls_header_view.cc index 15cd7dd..c647e04 100644 --- a/ash/login/ui/media_controls_header_view.cc +++ b/ash/login/ui/media_controls_header_view.cc
@@ -9,6 +9,7 @@ #include "components/vector_icons/vector_icons.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/color_utils.h" #include "ui/gfx/font_list.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/background.h" @@ -90,14 +91,13 @@ AddChildView(std::move(spacer)); auto close_button = CreateVectorImageButton(this); - SetImageFromVectorIcon(close_button.get(), vector_icons::kCloseRoundedIcon, - kCloseButtonIconSize, gfx::kGoogleGrey700); close_button->SetPreferredSize(kCloseButtonSize); close_button->SetFocusBehavior(View::FocusBehavior::ALWAYS); base::string16 close_button_label( l10n_util::GetStringUTF16(IDS_ASH_LOCK_SCREEN_MEDIA_CONTROLS_CLOSE)); close_button->SetAccessibleName(close_button_label); - close_button->SetVisible(false); + close_button->set_ink_drop_base_color( + color_utils::DeriveDefaultIconColor(gfx::kGoogleGrey700)); close_button_ = AddChildView(std::move(close_button)); } @@ -112,9 +112,11 @@ } void MediaControlsHeaderView::SetCloseButtonVisibility(bool visible) { - if (visible != close_button_->GetVisible()) { - close_button_->SetVisible(visible); - Layout(); + if (visible) { + SetImageFromVectorIcon(close_button_, vector_icons::kCloseRoundedIcon, + kCloseButtonIconSize, gfx::kGoogleGrey700); + } else { + close_button_->SetImage(views::Button::ButtonState::STATE_NORMAL, nullptr); } }
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc index b69846ba..4ee88eb 100644 --- a/ash/shelf/scrollable_shelf_view.cc +++ b/ash/shelf/scrollable_shelf_view.cc
@@ -33,6 +33,10 @@ constexpr int kArrowButtonGroupWidth = kArrowButtonSize + kArrowButtonEndPadding + kDistanceToArrowButton; +// The gesture fling event with the velocity smaller than the threshold will be +// neglected. +constexpr int kFlingVelocityThreshold = 1000; + // Sum of the shelf button size and the gap between shelf buttons. int GetUnit() { return ShelfConstants::button_size() + ShelfConstants::button_spacing(); @@ -111,11 +115,8 @@ } float ScrollableShelfView::CalculateClampedScrollOffset(float scroll) const { - const float old_scroll = GetShelf()->IsHorizontalAlignment() - ? scroll_offset_.x() - : scroll_offset_.y(); const float scroll_upper_bound = CalculateScrollUpperBound(); - scroll = std::min(scroll_upper_bound, std::max(0.f, old_scroll + scroll)); + scroll = std::min(scroll_upper_bound, std::max(0.f, scroll)); return scroll; } @@ -312,19 +313,7 @@ views::View* sender_view = sender; DCHECK((sender_view == left_arrow_) || (sender_view == right_arrow_)); - // Implement the arrow button handler in the same way with the gesture - // scrolling. The key is to calculate the suitable scroll distance. - int offset = space_for_icons_ - kArrowButtonGroupWidth - - ShelfConstants::button_size() - kAppIconEndPadding; - if (layout_strategy_ == kShowRightArrowButton) - offset -= (kArrowButtonGroupWidth - kAppIconEndPadding); - DCHECK_GT(offset, 0); - - // If |forward| is true, scroll the scrollable shelf view rightward. - const bool forward = sender_view == right_arrow_; - if (!forward) - offset = -offset; - + float offset = CalculatePageScrollingOffset(sender_view == right_arrow_); if (GetShelf()->IsHorizontalAlignment()) ScrollByXOffset(offset, true); else @@ -377,9 +366,20 @@ // ShelfView. bool should_handle_gestures = !cross_main_axis_scrolling_; - if (event.type() == ui::ET_GESTURE_END) + if (should_handle_gestures && event.type() == ui::ET_GESTURE_SCROLL_BEGIN) { + scroll_offset_before_main_axis_scrolling_ = scroll_offset_; + layout_strategy_before_main_axis_scrolling_ = layout_strategy_; + } + + if (event.type() == ui::ET_GESTURE_END) { cross_main_axis_scrolling_ = false; + if (should_handle_gestures) { + scroll_offset_before_main_axis_scrolling_ = gfx::Vector2dF(); + layout_strategy_before_main_axis_scrolling_ = kNotShowArrowButtons; + } + } + return should_handle_gestures; } @@ -434,6 +434,32 @@ return true; } + if (event.type() == ui::ET_SCROLL_FLING_START) { + const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment(); + + int scroll_velocity = is_horizontal_alignment + ? event.details().velocity_x() + : event.details().velocity_y(); + if (abs(scroll_velocity) < kFlingVelocityThreshold) + return false; + + layout_strategy_ = layout_strategy_before_main_axis_scrolling_; + + float page_scrolling_offset = + CalculatePageScrollingOffset(scroll_velocity < 0); + if (is_horizontal_alignment) { + ScrollToXOffset( + scroll_offset_before_main_axis_scrolling_.x() + page_scrolling_offset, + true); + } else { + ScrollToYOffset( + scroll_offset_before_main_axis_scrolling_.y() + page_scrolling_offset, + true); + } + + return true; + } + if (event.type() != ui::ET_GESTURE_SCROLL_UPDATE) return false; @@ -445,23 +471,49 @@ } void ScrollableShelfView::ScrollByXOffset(float x_offset, bool animating) { + ScrollToXOffset(scroll_offset_.x() + x_offset, animating); +} + +void ScrollableShelfView::ScrollByYOffset(float y_offset, bool animating) { + ScrollToYOffset(scroll_offset_.y() + y_offset, animating); +} + +void ScrollableShelfView::ScrollToXOffset(float x_target_offset, + bool animating) { + x_target_offset = CalculateClampedScrollOffset(x_target_offset); const float old_x = scroll_offset_.x(); - const float x = CalculateClampedScrollOffset(x_offset); - scroll_offset_.set_x(x); + scroll_offset_.set_x(x_target_offset); Layout(); - const float diff = x - old_x; + const float diff = x_target_offset - old_x; + if (animating) StartShelfScrollAnimation(diff); } -void ScrollableShelfView::ScrollByYOffset(float y_offset, bool animating) { +void ScrollableShelfView::ScrollToYOffset(float y_target_offset, + bool animating) { + y_target_offset = CalculateClampedScrollOffset(y_target_offset); const int old_y = scroll_offset_.y(); - const int y = CalculateClampedScrollOffset(y_offset); - scroll_offset_.set_y(y); + scroll_offset_.set_y(y_target_offset); Layout(); - const float diff = y - old_y; + const float diff = y_target_offset - old_y; if (animating) StartShelfScrollAnimation(diff); } +float ScrollableShelfView::CalculatePageScrollingOffset(bool forward) const { + // Implement the arrow button handler in the same way with the gesture + // scrolling. The key is to calculate the suitable scroll distance. + float offset = space_for_icons_ - kArrowButtonGroupWidth - + ShelfConstants::button_size() - kAppIconEndPadding; + if (layout_strategy_ == kShowRightArrowButton) + offset -= (kArrowButtonGroupWidth - kAppIconEndPadding); + DCHECK_GT(offset, 0); + + if (!forward) + offset = -offset; + + return offset; +} + } // namespace ash
diff --git a/ash/shelf/scrollable_shelf_view.h b/ash/shelf/scrollable_shelf_view.h index d445ff2..0c954da 100644 --- a/ash/shelf/scrollable_shelf_view.h +++ b/ash/shelf/scrollable_shelf_view.h
@@ -57,8 +57,7 @@ // Returns the maximum scroll distance. int CalculateScrollUpperBound() const; - // Returns the clamped scroll offset after scrolling by the distance of - // |scroll|. + // Returns the clamped scroll offset. float CalculateClampedScrollOffset(float scroll) const; // Creates the animation for scrolling shelf by |scroll_distance|. @@ -103,12 +102,22 @@ // consumed. bool ProcessGestureEvent(const ui::GestureEvent& event); - // Scrolls the view. |animating| indicates whether animation is needed for - // scrolling. |x_offset| or |y_offset| has to be float. Otherwise the slow - // gesture drag is neglected + // Scrolls the view by distance of |x_offset| or |y_offset|. |animating| + // indicates whether the animation displays. |x_offset| or |y_offset| has to + // be float. Otherwise the slow gesture drag is neglected. void ScrollByXOffset(float x_offset, bool animating); void ScrollByYOffset(float y_offset, bool animating); + // Scrolls the view to the target offset. After scrolling, |scroll_offset_| is + // |x_dst_offset| or |y_dst_offset|. |animating| indicates whether the + // animation shows. + void ScrollToXOffset(float x_target_offset, bool animating); + void ScrollToYOffset(float y_target_offset, bool animating); + + // Calculates the distance of scrolling to show a new page of shelf icons. + // |forward| indicates whether the next page or previous page is shown. + float CalculatePageScrollingOffset(bool forward) const; + LayoutStrategy layout_strategy_ = kNotShowArrowButtons; // Child views Owned by views hierarchy. @@ -128,6 +137,14 @@ // whether it is scrolling horizontally for left/right shelf. bool cross_main_axis_scrolling_ = false; + // Gesture states are preserved when the gesture scrolling along the main axis + // (that is, whether it is scrolling horizontally for bottom shelf, or whether + // it is scrolling horizontally for left/right shelf) gets started. They help + // to handle the gesture fling event. + gfx::Vector2dF scroll_offset_before_main_axis_scrolling_; + LayoutStrategy layout_strategy_before_main_axis_scrolling_ = + kNotShowArrowButtons; + DISALLOW_COPY_AND_ASSIGN(ScrollableShelfView); };
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 449a240..dfe2083 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -1142,8 +1142,10 @@ gfx::Point nav_origin = gfx::Point(ShelfConstants::home_button_edge_spacing(), ShelfConstants::home_button_edge_spacing()); - target_bounds->nav_bounds_in_shelf = - gfx::Rect(nav_origin, shelf_widget_->navigation_widget()->GetIdealSize()); + const gfx::Size nav_size = shelf_widget_->navigation_widget()->GetIdealSize(); + if (shelf_->IsHorizontalAlignment() && base::i18n::IsRTL()) + nav_origin.set_x(shelf_width - nav_size.width() - nav_origin.x()); + target_bounds->nav_bounds_in_shelf = gfx::Rect(nav_origin, nav_size); gfx::Point hotseat_origin; int hotseat_width;
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 63532834..0e8b0ce 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -56,6 +56,7 @@ #include "ash/wm/workspace_controller.h" #include "base/bind.h" #include "base/command_line.h" +#include "base/i18n/rtl.h" #include "base/run_loop.h" #include "base/stl_util.h" #include "base/test/metrics/user_action_tester.h" @@ -3058,6 +3059,34 @@ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState()); } +// Verifies that shelf components are placed properly in right-to-left UI. +TEST_F(ShelfLayoutManagerTest, RtlPlacement) { + // Helper function to check that the given widget is placed symmetrically + // between LTR and RTL. + auto check_mirrored_placement = [](views::Widget* widget) { + base::i18n::SetICUDefaultLocale("en"); + EXPECT_FALSE(base::i18n::IsRTL()); + GetShelfLayoutManager()->LayoutShelf(); + const int ltr_left_position = + widget->GetNativeWindow()->GetBoundsInScreen().x(); + + base::i18n::SetICUDefaultLocale("ar"); + EXPECT_TRUE(base::i18n::IsRTL()); + GetShelfLayoutManager()->LayoutShelf(); + const int rtl_right_position = + widget->GetNativeWindow()->GetBoundsInScreen().right(); + + EXPECT_EQ( + GetShelfWidget()->GetWindowBoundsInScreen().width() - ltr_left_position, + rtl_right_position); + }; + + ShelfWidget* shelf_widget = GetPrimaryShelf()->shelf_widget(); + check_mirrored_placement(shelf_widget->navigation_widget()); + check_mirrored_placement(shelf_widget->status_area_widget()); + check_mirrored_placement(shelf_widget); +} + class ShelfLayoutManagerKeyboardTest : public AshTestBase { public: ShelfLayoutManagerKeyboardTest() = default;
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc index 8193e98..91d8646 100644 --- a/ash/wm/overview/overview_window_drag_controller.cc +++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -661,26 +661,6 @@ } } -gfx::Rect OverviewWindowDragController::GetGridBounds( - SplitViewController::SnapPosition snap_position) { - aura::Window* pending_snapped_window = item_->GetWindow(); - switch (snap_position) { - case SplitViewController::NONE: - return gfx::Rect( - screen_util::GetDisplayWorkAreaBoundsInParentForActiveDeskContainer( - pending_snapped_window)); - case SplitViewController::LEFT: - return split_view_controller_->GetSnappedWindowBoundsInScreen( - pending_snapped_window, SplitViewController::RIGHT); - case SplitViewController::RIGHT: - return split_view_controller_->GetSnappedWindowBoundsInScreen( - pending_snapped_window, SplitViewController::LEFT); - } - - NOTREACHED(); - return gfx::Rect(); -} - void OverviewWindowDragController::SnapWindow( SplitViewController::SnapPosition snap_position) { DCHECK_NE(snap_position, SplitViewController::NONE);
diff --git a/ash/wm/overview/overview_window_drag_controller.h b/ash/wm/overview/overview_window_drag_controller.h index 25f7720..d6f62ec 100644 --- a/ash/wm/overview/overview_window_drag_controller.h +++ b/ash/wm/overview/overview_window_drag_controller.h
@@ -111,9 +111,6 @@ SplitViewController::SnapPosition GetSnapPosition( const gfx::PointF& location_in_screen) const; - // Returns the expected window grid bounds based on |snap_position|. - gfx::Rect GetGridBounds(SplitViewController::SnapPosition snap_position); - void SnapWindow(SplitViewController::SnapPosition snap_position); OverviewSession* overview_session_;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 3ab36cb..1f72865 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -46,13 +46,6 @@ # file name) is saved. enable_location_source = true - # When enabled, iterators will validate that they are not used in ways that - # violate spatial safety (i.e. out-of-bounds memory accesses). - # TODO(https://crbug.com/817982): currently guarded by a buildflag since - # there are non-trivial binary size regressions which are especially - # noticeable on Android. - enable_checked_iterators = !is_android - # Unsafe developer build. Has developer-friendly features that may weaken or # disable security measures like sandboxing or ASLR. # IMPORTANT: Unsafe developer builds should never be distributed to end users. @@ -427,8 +420,6 @@ "memory/memory_pressure_monitor_chromeos.h", "memory/memory_pressure_monitor_mac.cc", "memory/memory_pressure_monitor_mac.h", - "memory/memory_pressure_monitor_win.cc", - "memory/memory_pressure_monitor_win.h", "memory/platform_shared_memory_region.cc", "memory/platform_shared_memory_region.h", "memory/protected_memory.cc", @@ -1272,7 +1263,6 @@ ":cfi_buildflags", ":clang_coverage_buildflags", ":debugging_buildflags", - ":iterator_buildflags", ":logging_buildflags", ":orderfile_buildflags", ":partition_alloc_buildflags", @@ -2094,12 +2084,6 @@ ] } -buildflag_header("iterator_buildflags") { - header = "iterator_buildflags.h" - header_dir = "base/containers" - flags = [ "ENABLE_CHECKED_ITERATORS=$enable_checked_iterators" ] -} - buildflag_header("logging_buildflags") { header = "logging_buildflags.h" @@ -2597,7 +2581,6 @@ "memory/memory_pressure_monitor_chromeos_unittest.cc", "memory/memory_pressure_monitor_mac_unittest.cc", "memory/memory_pressure_monitor_unittest.cc", - "memory/memory_pressure_monitor_win_unittest.cc", "memory/platform_shared_memory_region_unittest.cc", "memory/protected_memory_unittest.cc", "memory/ptr_util_unittest.cc",
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h index e9fdf916b..b7eb7b4 100644 --- a/base/containers/checked_iterators.h +++ b/base/containers/checked_iterators.h
@@ -8,20 +8,8 @@ #include <iterator> #include <memory> -#include "base/containers/iterator_buildflags.h" #include "base/containers/util.h" #include "base/logging.h" -#include "build/build_config.h" - -#if BUILDFLAG(ENABLE_CHECKED_ITERATORS) -#define ITERATOR_CHECK CHECK -#define ITERATOR_CHECK_EQ CHECK_EQ -#define ITERATOR_CHECK_LE CHECK_LE -#else -#define ITERATOR_CHECK DCHECK -#define ITERATOR_CHECK_EQ DCHECK_EQ -#define ITERATOR_CHECK_LE DCHECK_LE -#endif namespace base { @@ -44,8 +32,8 @@ : CheckedRandomAccessIterator(start, start, end) {} CheckedRandomAccessIterator(T* start, T* current, const T* end) : start_(start), current_(current), end_(end) { - ITERATOR_CHECK(start <= current); - ITERATOR_CHECK(current <= end); + CHECK(start <= current); + CHECK(current <= end); } CheckedRandomAccessIterator(const CheckedRandomAccessIterator& other) = default; @@ -75,7 +63,7 @@ } CheckedRandomAccessIterator& operator++() { - ITERATOR_CHECK(current_ != end_); + CHECK(current_ != end_); ++current_; return *this; } @@ -87,7 +75,7 @@ } CheckedRandomAccessIterator& operator--() { - ITERATOR_CHECK(current_ != start_); + CHECK(current_ != start_); --current_; return *this; } @@ -100,9 +88,9 @@ CheckedRandomAccessIterator& operator+=(difference_type rhs) { if (rhs > 0) { - ITERATOR_CHECK_LE(rhs, end_ - current_); + CHECK_LE(rhs, end_ - current_); } else { - ITERATOR_CHECK_LE(-rhs, current_ - start_); + CHECK_LE(-rhs, current_ - start_); } current_ += rhs; return *this; @@ -116,9 +104,9 @@ CheckedRandomAccessIterator& operator-=(difference_type rhs) { if (rhs < 0) { - ITERATOR_CHECK_LE(rhs, end_ - current_); + CHECK_LE(rhs, end_ - current_); } else { - ITERATOR_CHECK_LE(-rhs, current_ - start_); + CHECK_LE(-rhs, current_ - start_); } current_ -= rhs; return *this; @@ -132,18 +120,18 @@ friend difference_type operator-(const CheckedRandomAccessIterator& lhs, const CheckedRandomAccessIterator& rhs) { - ITERATOR_CHECK(lhs.start_ == rhs.start_); - ITERATOR_CHECK(lhs.end_ == rhs.end_); + CHECK(lhs.start_ == rhs.start_); + CHECK(lhs.end_ == rhs.end_); return lhs.current_ - rhs.current_; } reference operator*() const { - ITERATOR_CHECK(current_ != end_); + CHECK(current_ != end_); return *current_; } pointer operator->() const { - ITERATOR_CHECK(current_ != end_); + CHECK(current_ != end_); return current_; } @@ -165,8 +153,8 @@ private: void CheckComparable(const CheckedRandomAccessIterator& other) const { - ITERATOR_CHECK_EQ(start_, other.start_); - ITERATOR_CHECK_EQ(end_, other.end_); + CHECK_EQ(start_, other.start_); + CHECK_EQ(end_, other.end_); } const T* start_ = nullptr; @@ -188,16 +176,16 @@ : CheckedRandomAccessConstIterator(start, start, end) {} CheckedRandomAccessConstIterator(T* start, T* current, const T* end) : start_(start), current_(current), end_(end) { - ITERATOR_CHECK(start <= current); - ITERATOR_CHECK(current <= end); + CHECK(start <= current); + CHECK(current <= end); } CheckedRandomAccessConstIterator( const CheckedRandomAccessConstIterator& other) = default; CheckedRandomAccessConstIterator(const CheckedRandomAccessIterator<T>& other) : start_(other.start_), current_(other.current_), end_(other.end_) { // We explicitly don't delegate to the 3-argument constructor here. Its - // ITERATOR_CHECKs would be redundant, since we expect |other| to maintain - // its own invariant. However, DCHECKs never hurt anybody. Presumably. + // CHECKs would be redundant, since we expect |other| to maintain its own + // invariant. However, DCHECKs never hurt anybody. Presumably. DCHECK(other.start_ <= other.current_); DCHECK(other.current_ <= other.end_); } @@ -230,7 +218,7 @@ } CheckedRandomAccessConstIterator& operator++() { - ITERATOR_CHECK(current_ != end_); + CHECK(current_ != end_); ++current_; return *this; } @@ -242,7 +230,7 @@ } CheckedRandomAccessConstIterator& operator--() { - ITERATOR_CHECK(current_ != start_); + CHECK(current_ != start_); --current_; return *this; } @@ -255,9 +243,9 @@ CheckedRandomAccessConstIterator& operator+=(difference_type rhs) { if (rhs > 0) { - ITERATOR_CHECK_LE(rhs, end_ - current_); + CHECK_LE(rhs, end_ - current_); } else { - ITERATOR_CHECK_LE(-rhs, current_ - start_); + CHECK_LE(-rhs, current_ - start_); } current_ += rhs; return *this; @@ -271,9 +259,9 @@ CheckedRandomAccessConstIterator& operator-=(difference_type rhs) { if (rhs < 0) { - ITERATOR_CHECK_LE(rhs, end_ - current_); + CHECK_LE(rhs, end_ - current_); } else { - ITERATOR_CHECK_LE(-rhs, current_ - start_); + CHECK_LE(-rhs, current_ - start_); } current_ -= rhs; return *this; @@ -288,18 +276,18 @@ friend difference_type operator-( const CheckedRandomAccessConstIterator& lhs, const CheckedRandomAccessConstIterator& rhs) { - ITERATOR_CHECK(lhs.start_ == rhs.start_); - ITERATOR_CHECK(lhs.end_ == rhs.end_); + CHECK(lhs.start_ == rhs.start_); + CHECK(lhs.end_ == rhs.end_); return lhs.current_ - rhs.current_; } reference operator*() const { - ITERATOR_CHECK(current_ != end_); + CHECK(current_ != end_); return *current_; } pointer operator->() const { - ITERATOR_CHECK(current_ != end_); + CHECK(current_ != end_); return current_; } @@ -321,8 +309,8 @@ private: void CheckComparable(const CheckedRandomAccessConstIterator& other) const { - ITERATOR_CHECK_EQ(start_, other.start_); - ITERATOR_CHECK_EQ(end_, other.end_); + CHECK_EQ(start_, other.start_); + CHECK_EQ(end_, other.end_); } const T* start_ = nullptr; @@ -332,8 +320,4 @@ } // namespace base -#undef ITERATOR_CHECK -#undef ITERATOR_CHECK_EQ -#undef ITERATOR_CHECK_LE - #endif // BASE_CONTAINERS_CHECKED_ITERATORS_H_
diff --git a/base/containers/circular_deque.h b/base/containers/circular_deque.h index 93f1e79..bf42a95 100644 --- a/base/containers/circular_deque.h +++ b/base/containers/circular_deque.h
@@ -791,12 +791,12 @@ return iterator(this, first.index_); } else if (first.index_ < last.index_) { // Contiguous range. - buffer_.DestructRange(buffer_.begin() + first.index_, - buffer_.begin() + last.index_); + buffer_.DestructRange(&buffer_[first.index_], &buffer_[last.index_]); } else { // Deleted range wraps around. - buffer_.DestructRange(buffer_.begin() + first.index_, buffer_.end()); - buffer_.DestructRange(buffer_.begin(), buffer_.begin() + last.index_); + buffer_.DestructRange(&buffer_[first.index_], + &buffer_[buffer_.capacity()]); + buffer_.DestructRange(&buffer_[0], &buffer_[last.index_]); } if (first.index_ == begin_) { @@ -812,9 +812,9 @@ iterator move_src_end = end(); iterator move_dest(this, first.index_); for (; move_src < move_src_end; move_src++, move_dest++) { - buffer_.MoveRange(buffer_.begin() + move_src.index_, - buffer_.begin() + move_src.index_ + 1, - buffer_.begin() + move_dest.index_); + buffer_.MoveRange(&buffer_[move_src.index_], + &buffer_[move_src.index_ + 1], + &buffer_[move_dest.index_]); } end_ = move_dest.index_; @@ -860,8 +860,7 @@ void pop_front() { DCHECK(size()); - buffer_.DestructRange(buffer_.begin() + begin_, - buffer_.begin() + begin_ + 1); + buffer_.DestructRange(&buffer_[begin_], &buffer_[begin_ + 1]); begin_++; if (begin_ == buffer_.capacity()) begin_ = 0; @@ -880,7 +879,7 @@ end_ = buffer_.capacity() - 1; else end_--; - buffer_.DestructRange(buffer_.begin() + end_, buffer_.begin() + end_ + 1); + buffer_.DestructRange(&buffer_[end_], &buffer_[end_ + 1]); ShrinkCapacityIfNecessary(); @@ -918,17 +917,17 @@ *to_begin = 0; if (from_begin < from_end) { // Contiguous. - from_buf.MoveRange(from_buf.begin() + from_begin, - from_buf.begin() + from_end, to_buf->begin()); + from_buf.MoveRange(&from_buf[from_begin], &from_buf[from_end], + to_buf->begin()); *to_end = from_end - from_begin; } else if (from_begin > from_end) { // Discontiguous, copy the right side to the beginning of the new buffer. - from_buf.MoveRange(from_buf.begin() + from_begin, from_buf.end(), + from_buf.MoveRange(&from_buf[from_begin], &from_buf[from_capacity], to_buf->begin()); size_t right_size = from_capacity - from_begin; // Append the left side. - from_buf.MoveRange(from_buf.begin(), from_buf.begin() + from_end, - to_buf->begin() + right_size); + from_buf.MoveRange(&from_buf[0], &from_buf[from_end], + &(*to_buf)[right_size]); *to_end = right_size + from_end; } else { // No items. @@ -999,10 +998,10 @@ if (end == begin) { return; } else if (end > begin) { - buffer_.DestructRange(buffer_.begin() + begin, buffer_.begin() + end); + buffer_.DestructRange(&buffer_[begin], &buffer_[end]); } else { - buffer_.DestructRange(buffer_.begin() + begin, buffer_.end()); - buffer_.DestructRange(buffer_.begin(), buffer_.begin() + end); + buffer_.DestructRange(&buffer_[begin], &buffer_[buffer_.capacity()]); + buffer_.DestructRange(&buffer_[0], &buffer_[end]); } } @@ -1036,9 +1035,8 @@ break; --src; --dest; - buffer_.MoveRange(buffer_.begin() + src.index_, - buffer_.begin() + src.index_ + 1, - buffer_.begin() + dest.index_); + buffer_.MoveRange(&buffer_[src.index_], &buffer_[src.index_ + 1], + &buffer_[dest.index_]); } }
diff --git a/base/containers/vector_buffer.h b/base/containers/vector_buffer.h index 09c312ce..83cd2ac 100644 --- a/base/containers/vector_buffer.h +++ b/base/containers/vector_buffer.h
@@ -11,12 +11,10 @@ #include <type_traits> #include <utility> -#include "base/containers/checked_iterators.h" #include "base/containers/util.h" #include "base/logging.h" #include "base/macros.h" #include "base/numerics/checked_math.h" -#include "build/build_config.h" namespace base { namespace internal { @@ -42,8 +40,6 @@ class VectorBuffer { public: constexpr VectorBuffer() = default; - using iterator = CheckedRandomAccessIterator<T>; - using const_iterator = CheckedRandomAccessConstIterator<T>; #if defined(__clang__) && !defined(__native_client__) // This constructor converts an uninitialized void* to a T* which triggers @@ -90,12 +86,8 @@ return buffer_[i]; } - iterator begin() const noexcept { - return iterator(buffer_, buffer_ + capacity_); - } - iterator end() const noexcept { - return iterator(buffer_, buffer_ + capacity_, buffer_ + capacity_); - } + T* begin() { return buffer_; } + T* end() { return &buffer_[capacity_]; } // DestructRange ------------------------------------------------------------ @@ -103,15 +95,15 @@ template <typename T2 = T, typename std::enable_if<std::is_trivially_destructible<T2>::value, int>::type = 0> - void DestructRange(iterator begin, iterator end) {} + void DestructRange(T* begin, T* end) {} // Non-trivially destructible objects must have their destructors called // individually. template <typename T2 = T, typename std::enable_if<!std::is_trivially_destructible<T2>::value, int>::type = 0> - void DestructRange(iterator begin, iterator end) { - CHECK(begin <= end); + void DestructRange(T* begin, T* end) { + CHECK_LE(begin, end); while (begin != end) { begin->~T(); begin++; @@ -127,15 +119,16 @@ // and the address of the first element to copy to. There must be sufficient // room in the destination for all items in the range [begin, end). - // Trivially copyable types can use memcpy. Trivially copyable implies that - // there is a trivial destructor as we don't have to call it. + // Trivially copyable types can use memcpy. trivially copyable implies + // that there is a trivial destructor as we don't have to call it. template <typename T2 = T, typename std::enable_if<base::is_trivially_copyable<T2>::value, int>::type = 0> - static void MoveRange(iterator from_begin, iterator from_end, iterator to) { - CHECK(iterator::IsRangeMoveSafe(from_begin, from_end, to)); - memcpy(&(*to), &(*from_begin), - std::distance(from_begin, from_end) * sizeof(T)); + static void MoveRange(T* from_begin, T* from_end, T* to) { + CHECK(!RangesOverlap(from_begin, from_end, to)); + memcpy( + to, from_begin, + CheckSub(get_uintptr(from_end), get_uintptr(from_begin)).ValueOrDie()); } // Not trivially copyable, but movable: call the move constructor and @@ -144,10 +137,10 @@ typename std::enable_if<std::is_move_constructible<T2>::value && !base::is_trivially_copyable<T2>::value, int>::type = 0> - static void MoveRange(iterator from_begin, iterator from_end, iterator to) { - CHECK(iterator::IsRangeMoveSafe(from_begin, from_end, to)); + static void MoveRange(T* from_begin, T* from_end, T* to) { + CHECK(!RangesOverlap(from_begin, from_end, to)); while (from_begin != from_end) { - new (&(*to)) T(std::move(*from_begin)); + new (to) T(std::move(*from_begin)); from_begin->~T(); from_begin++; to++; @@ -160,10 +153,10 @@ typename std::enable_if<!std::is_move_constructible<T2>::value && !base::is_trivially_copyable<T2>::value, int>::type = 0> - static void MoveRange(iterator from_begin, iterator from_end, iterator to) { - CHECK(iterator::IsRangeMoveSafe(from_begin, from_end, to)); + static void MoveRange(T* from_begin, T* from_end, T* to) { + CHECK(!RangesOverlap(from_begin, from_end, to)); while (from_begin != from_end) { - new (&(*to)) T(*from_begin); + new (to) T(*from_begin); from_begin->~T(); from_begin++; to++; @@ -171,6 +164,18 @@ } private: + static bool RangesOverlap(const T* from_begin, + const T* from_end, + const T* to) { + const auto from_begin_uintptr = get_uintptr(from_begin); + const auto from_end_uintptr = get_uintptr(from_end); + const auto to_uintptr = get_uintptr(to); + return !( + to >= from_end || + CheckAdd(to_uintptr, CheckSub(from_end_uintptr, from_begin_uintptr)) + .ValueOrDie() <= from_begin_uintptr); + } + T* buffer_ = nullptr; size_t capacity_ = 0;
diff --git a/base/containers/vector_buffer_unittest.cc b/base/containers/vector_buffer_unittest.cc index bf838639..6d49505 100644 --- a/base/containers/vector_buffer_unittest.cc +++ b/base/containers/vector_buffer_unittest.cc
@@ -15,26 +15,26 @@ constexpr int size = 10; VectorBuffer<int> buffer(size); for (int i = 0; i < size; i++) - buffer[i] = i + 1; + buffer.begin()[i] = i + 1; buffer.DestructRange(buffer.begin(), buffer.end()); // Delete should do nothing. for (int i = 0; i < size; i++) - EXPECT_EQ(i + 1, buffer[i]); + EXPECT_EQ(i + 1, buffer.begin()[i]); } TEST(VectorBuffer, DeleteMoveOnly) { constexpr int size = 10; VectorBuffer<MoveOnlyInt> buffer(size); for (int i = 0; i < size; i++) - buffer[i] = MoveOnlyInt(i + 1); + new (buffer.begin() + i) MoveOnlyInt(i + 1); buffer.DestructRange(buffer.begin(), buffer.end()); // Delete should have reset all of the values to 0. for (int i = 0; i < size; i++) - EXPECT_EQ(0, buffer[i].data()); + EXPECT_EQ(0, buffer.begin()[i].data()); } TEST(VectorBuffer, PODMove) { @@ -43,11 +43,11 @@ VectorBuffer<int> original(size); for (int i = 0; i < size; i++) - original[i] = i + 1; + original.begin()[i] = i + 1; original.MoveRange(original.begin(), original.end(), dest.begin()); for (int i = 0; i < size; i++) - EXPECT_EQ(i + 1, dest[i]); + EXPECT_EQ(i + 1, dest.begin()[i]); } TEST(VectorBuffer, MovableMove) { @@ -56,13 +56,14 @@ VectorBuffer<MoveOnlyInt> original(size); for (int i = 0; i < size; i++) - original[i] = MoveOnlyInt(i + 1); + new (original.begin() + i) MoveOnlyInt(i + 1); original.MoveRange(original.begin(), original.end(), dest.begin()); + // Moving from a MoveOnlyInt resets to 0. for (int i = 0; i < size; i++) { - EXPECT_EQ(0, original[i].data()); - EXPECT_EQ(i + 1, dest[i].data()); + EXPECT_EQ(0, original.begin()[i].data()); + EXPECT_EQ(i + 1, dest.begin()[i].data()); } } @@ -72,15 +73,15 @@ VectorBuffer<CopyOnlyInt> original(size); for (int i = 0; i < size; i++) - new (&original[i]) CopyOnlyInt(i + 1); + new (original.begin() + i) CopyOnlyInt(i + 1); original.MoveRange(original.begin(), original.end(), dest.begin()); // The original should have been destructed, which should reset the value to // 0. Technically this dereferences the destructed object. for (int i = 0; i < size; i++) { - EXPECT_EQ(0, original[i].data()); - EXPECT_EQ(i + 1, dest[i].data()); + EXPECT_EQ(0, original.begin()[i].data()); + EXPECT_EQ(i + 1, dest.begin()[i].data()); } }
diff --git a/base/memory/memory_pressure_monitor_win.cc b/base/memory/memory_pressure_monitor_win.cc deleted file mode 100644 index f2ccb7d7..0000000 --- a/base/memory/memory_pressure_monitor_win.cc +++ /dev/null
@@ -1,235 +0,0 @@ -// Copyright 2015 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/memory/memory_pressure_monitor_win.h" - -#include <windows.h> - -#include "base/bind.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" - -namespace base { -namespace win { - -namespace { - -static const DWORDLONG kMBBytes = 1024 * 1024; - -} // namespace - -// The following constants have been lifted from similar values in the ChromeOS -// memory pressure monitor. The values were determined experimentally to ensure -// sufficient responsiveness of the memory pressure subsystem, and minimal -// overhead. -const int MemoryPressureMonitor::kModeratePressureCooldownMs = 10000; - -// TODO(chrisha): Explore the following constants further with an experiment. - -// A system is considered 'high memory' if it has more than 1.5GB of system -// memory available for use by the memory manager (not reserved for hardware -// and drivers). This is a fuzzy version of the ~2GB discussed below. -const int MemoryPressureMonitor::kLargeMemoryThresholdMb = 1536; - -// These are the default thresholds used for systems with < ~2GB of physical -// memory. Such systems have been observed to always maintain ~100MB of -// available memory, paging until that is the case. To try to avoid paging a -// threshold slightly above this is chosen. The moderate threshold is slightly -// less grounded in reality and chosen as 2.5x critical. -const int MemoryPressureMonitor::kSmallMemoryDefaultModerateThresholdMb = 500; -const int MemoryPressureMonitor::kSmallMemoryDefaultCriticalThresholdMb = 200; - -// These are the default thresholds used for systems with >= ~2GB of physical -// memory. Such systems have been observed to always maintain ~300MB of -// available memory, paging until that is the case. -const int MemoryPressureMonitor::kLargeMemoryDefaultModerateThresholdMb = 1000; -const int MemoryPressureMonitor::kLargeMemoryDefaultCriticalThresholdMb = 400; - -MemoryPressureMonitor::MemoryPressureMonitor() - : moderate_threshold_mb_(0), - critical_threshold_mb_(0), - current_memory_pressure_level_( - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), - moderate_pressure_repeat_count_(0), - dispatch_callback_( - base::BindRepeating(&MemoryPressureListener::NotifyMemoryPressure)), - weak_ptr_factory_(this) { - InferThresholds(); - StartObserving(); -} - -MemoryPressureMonitor::MemoryPressureMonitor(int moderate_threshold_mb, - int critical_threshold_mb) - : moderate_threshold_mb_(moderate_threshold_mb), - critical_threshold_mb_(critical_threshold_mb), - current_memory_pressure_level_( - MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), - moderate_pressure_repeat_count_(0), - dispatch_callback_( - base::BindRepeating(&MemoryPressureListener::NotifyMemoryPressure)), - weak_ptr_factory_(this) { - DCHECK_GE(moderate_threshold_mb_, critical_threshold_mb_); - DCHECK_LE(0, critical_threshold_mb_); - StartObserving(); -} - -MemoryPressureMonitor::~MemoryPressureMonitor() { - StopObserving(); -} - -void MemoryPressureMonitor::CheckMemoryPressureSoon() { - DCHECK(thread_checker_.CalledOnValidThread()); - - ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, BindOnce(&MemoryPressureMonitor::CheckMemoryPressure, - weak_ptr_factory_.GetWeakPtr())); -} - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::GetCurrentPressureLevel() const { - return current_memory_pressure_level_; -} - -void MemoryPressureMonitor::InferThresholds() { - // Default to a 'high' memory situation, which uses more conservative - // thresholds. - bool high_memory = true; - MEMORYSTATUSEX mem_status = {}; - if (GetSystemMemoryStatus(&mem_status)) { - static const DWORDLONG kLargeMemoryThresholdBytes = - static_cast<DWORDLONG>(kLargeMemoryThresholdMb) * kMBBytes; - high_memory = mem_status.ullTotalPhys >= kLargeMemoryThresholdBytes; - } - - if (high_memory) { - moderate_threshold_mb_ = kLargeMemoryDefaultModerateThresholdMb; - critical_threshold_mb_ = kLargeMemoryDefaultCriticalThresholdMb; - } else { - moderate_threshold_mb_ = kSmallMemoryDefaultModerateThresholdMb; - critical_threshold_mb_ = kSmallMemoryDefaultCriticalThresholdMb; - } -} - -void MemoryPressureMonitor::StartObserving() { - DCHECK(thread_checker_.CalledOnValidThread()); - - timer_.Start( - FROM_HERE, base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod, - BindRepeating( - &MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics, - weak_ptr_factory_.GetWeakPtr())); -} - -void MemoryPressureMonitor::StopObserving() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // If StartObserving failed, StopObserving will still get called. - timer_.Stop(); - weak_ptr_factory_.InvalidateWeakPtrs(); -} - -void MemoryPressureMonitor::CheckMemoryPressure() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Get the previous pressure level and update the current one. - MemoryPressureLevel old_pressure = current_memory_pressure_level_; - current_memory_pressure_level_ = 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_memory_pressure_level_) { - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - break; - - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - if (old_pressure != current_memory_pressure_level_) { - // 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 = - kModeratePressureCooldownMs / - base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod - .InMilliseconds(); - if (++moderate_pressure_repeat_count_ == - kModeratePressureCooldownCycles) { - moderate_pressure_repeat_count_ = 0; - notify = true; - } - } - break; - - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - // Always notify of critical pressure levels. - notify = true; - break; - } - - if (!notify) - return; - - // Emit a notification of the current memory pressure level. This can only - // happen for moderate and critical pressure levels. - DCHECK_NE(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, - current_memory_pressure_level_); - dispatch_callback_.Run(current_memory_pressure_level_); -} - -void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() { - DCHECK(thread_checker_.CalledOnValidThread()); - - CheckMemoryPressure(); - - RecordMemoryPressure(current_memory_pressure_level_, 1); -} - -MemoryPressureListener::MemoryPressureLevel -MemoryPressureMonitor::CalculateCurrentPressureLevel() { - MEMORYSTATUSEX mem_status = {}; - if (!GetSystemMemoryStatus(&mem_status)) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; - - // How much system memory is actively available for use right now, in MBs. - int phys_free = static_cast<int>(mem_status.ullAvailPhys / kMBBytes); - - // TODO(chrisha): This should eventually care about address space pressure, - // but the browser process (where this is running) effectively never runs out - // of address space. Renderers occasionally do, but it does them no good to - // have the browser process monitor address space pressure. Long term, - // renderers should run their own address space pressure monitors and act - // accordingly, with the browser making cross-process decisions based on - // system memory pressure. - - // Determine if the physical memory is under critical memory pressure. - if (phys_free <= critical_threshold_mb_) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; - - // Determine if the physical memory is under moderate memory pressure. - if (phys_free <= moderate_threshold_mb_) - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; - - // No memory pressure was detected. - return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; -} - -bool MemoryPressureMonitor::GetSystemMemoryStatus( - MEMORYSTATUSEX* mem_status) { - DCHECK(mem_status != nullptr); - mem_status->dwLength = sizeof(*mem_status); - if (!::GlobalMemoryStatusEx(mem_status)) - return false; - return true; -} - -void MemoryPressureMonitor::SetDispatchCallback( - const DispatchCallback& callback) { - dispatch_callback_ = callback; -} - -} // namespace win -} // namespace base
diff --git a/base/memory/memory_pressure_monitor_win_unittest.cc b/base/memory/memory_pressure_monitor_win_unittest.cc deleted file mode 100644 index 03832e2..0000000 --- a/base/memory/memory_pressure_monitor_win_unittest.cc +++ /dev/null
@@ -1,311 +0,0 @@ -// Copyright 2015 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/memory/memory_pressure_monitor_win.h" - -#include "base/bind.h" -#include "base/macros.h" -#include "base/memory/memory_pressure_listener.h" -#include "base/run_loop.h" -#include "base/test/scoped_task_environment.h" -#include "build/build_config.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(OS_WIN) -#include <windows.h> -#endif - -namespace base { -namespace win { - -namespace { - -struct PressureSettings { - int phys_left_mb; - MemoryPressureListener::MemoryPressureLevel level; -}; - -} // namespace - -// This is outside of the anonymous namespace so that it can be seen as a friend -// to the monitor class. -class TestMemoryPressureMonitor : public MemoryPressureMonitor { - public: - using MemoryPressureMonitor::CalculateCurrentPressureLevel; - using MemoryPressureMonitor::CheckMemoryPressure; - - static const DWORDLONG kMBBytes = 1024 * 1024; - - explicit TestMemoryPressureMonitor(bool large_memory) - : mem_status_() { - // Generate a plausible amount of memory. - mem_status_.ullTotalPhys = - static_cast<DWORDLONG>(GenerateTotalMemoryMb(large_memory)) * kMBBytes; - - // Rerun InferThresholds using the test fixture's GetSystemMemoryStatus. - InferThresholds(); - // Stop the timer. - StopObserving(); - } - - TestMemoryPressureMonitor(int system_memory_mb, - int moderate_threshold_mb, - int critical_threshold_mb) - : MemoryPressureMonitor(moderate_threshold_mb, critical_threshold_mb), - mem_status_() { - // Set the amount of system memory. - mem_status_.ullTotalPhys = static_cast<DWORDLONG>( - system_memory_mb * kMBBytes); - - // Stop the timer. - StopObserving(); - } - - virtual ~TestMemoryPressureMonitor() {} - - MOCK_METHOD1(OnMemoryPressure, - void(MemoryPressureListener::MemoryPressureLevel level)); - - // Generates an amount of total memory that is consistent with the requested - // memory model. - int GenerateTotalMemoryMb(bool large_memory) { - int total_mb = 64; - while (total_mb < MemoryPressureMonitor::kLargeMemoryThresholdMb) - total_mb *= 2; - if (large_memory) - return total_mb * 2; - return total_mb / 2; - } - - // 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_.ullAvailPhys = - static_cast<DWORDLONG>(phys_left_mb) * kMBBytes; - DCHECK_LT(mem_status_.ullAvailPhys, mem_status_.ullTotalPhys); - - // These fields are unused. - mem_status_.dwMemoryLoad = 0; - mem_status_.ullTotalPageFile = 0; - mem_status_.ullAvailPageFile = 0; - mem_status_.ullTotalVirtual = 0; - mem_status_.ullAvailVirtual = 0; - } - - void SetNone() { - SetMemoryFree(moderate_threshold_mb() + 1); - } - - void SetModerate() { - SetMemoryFree(moderate_threshold_mb() - 1); - } - - void SetCritical() { - SetMemoryFree(critical_threshold_mb() - 1); - } - - private: - bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status) override { - // Simply copy the memory status set by the test fixture. - *mem_status = mem_status_; - return true; - } - - MEMORYSTATUSEX mem_status_; - - DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor); -}; - -class WinMemoryPressureMonitorTest : public testing::Test { - protected: - void CalculateCurrentMemoryPressureLevelTest( - TestMemoryPressureMonitor* monitor) { - - int mod = monitor->moderate_threshold_mb(); - monitor->SetMemoryFree(mod + 1); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, - monitor->CalculateCurrentPressureLevel()); - - monitor->SetMemoryFree(mod); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor->CalculateCurrentPressureLevel()); - - monitor->SetMemoryFree(mod - 1); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor->CalculateCurrentPressureLevel()); - - int crit = monitor->critical_threshold_mb(); - monitor->SetMemoryFree(crit + 1); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor->CalculateCurrentPressureLevel()); - - monitor->SetMemoryFree(crit); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, - monitor->CalculateCurrentPressureLevel()); - - monitor->SetMemoryFree(crit - 1); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, - monitor->CalculateCurrentPressureLevel()); - } - - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::MainThreadType::UI}; -}; - -// Tests the fundamental direct calculation of memory pressure with automatic -// small-memory thresholds. -TEST_F(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevelSmall) { - static const int kModerateMb = - MemoryPressureMonitor::kSmallMemoryDefaultModerateThresholdMb; - static const int kCriticalMb = - MemoryPressureMonitor::kSmallMemoryDefaultCriticalThresholdMb; - - TestMemoryPressureMonitor monitor(false); // Small-memory model. - - EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb()); - EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb()); - - ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor)); -} - -// Tests the fundamental direct calculation of memory pressure with automatic -// large-memory thresholds. -TEST_F(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevelLarge) { - static const int kModerateMb = - MemoryPressureMonitor::kLargeMemoryDefaultModerateThresholdMb; - static const int kCriticalMb = - MemoryPressureMonitor::kLargeMemoryDefaultCriticalThresholdMb; - - TestMemoryPressureMonitor monitor(true); // Large-memory model. - - EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb()); - EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb()); - - ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor)); -} - -// Tests the fundamental direct calculation of memory pressure with manually -// specified threshold levels. -TEST_F(WinMemoryPressureMonitorTest, - CalculateCurrentMemoryPressureLevelCustom) { - static const int kSystemMb = 512; - static const int kModerateMb = 256; - static const int kCriticalMb = 128; - - TestMemoryPressureMonitor monitor(kSystemMb, kModerateMb, kCriticalMb); - - EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb()); - EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb()); - - ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor)); -} - -// 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(WinMemoryPressureMonitorTest, CheckMemoryPressure) { - // Large-memory. - testing::StrictMock<TestMemoryPressureMonitor> monitor(true); - MemoryPressureListener listener( - base::BindRepeating(&TestMemoryPressureMonitor::OnMemoryPressure, - base::Unretained(&monitor))); - - // Checking the memory pressure at 0% load should not produce any - // events. - monitor.SetNone(); - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, - monitor.GetCurrentPressureLevel()); - - // Setting the memory level to 80% should produce a moderate pressure level. - EXPECT_CALL(monitor, - OnMemoryPressure(MemoryPressureListener:: - MEMORY_PRESSURE_LEVEL_MODERATE)); - monitor.SetModerate(); - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); - - // Check that the event gets reposted after a while. - const int kModeratePressureCooldownCycles = - monitor.kModeratePressureCooldownMs / - base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod - .InMilliseconds(); - - for (int i = 0; i < kModeratePressureCooldownCycles; ++i) { - if (i + 1 == kModeratePressureCooldownCycles) { - EXPECT_CALL(monitor, - OnMemoryPressure(MemoryPressureListener:: - MEMORY_PRESSURE_LEVEL_MODERATE)); - } - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); - } - - // Setting the memory usage to 99% should produce critical levels. - EXPECT_CALL(monitor, - OnMemoryPressure(MemoryPressureListener:: - MEMORY_PRESSURE_LEVEL_CRITICAL)); - monitor.SetCritical(); - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); - - // Calling it again should immediately produce a second call. - EXPECT_CALL(monitor, - OnMemoryPressure(MemoryPressureListener:: - MEMORY_PRESSURE_LEVEL_CRITICAL)); - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); - - // When lowering the pressure again there should be a notification and the - // pressure should go back to moderate. - EXPECT_CALL(monitor, - OnMemoryPressure(MemoryPressureListener:: - MEMORY_PRESSURE_LEVEL_MODERATE)); - monitor.SetModerate(); - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); - - // Check that the event gets reposted after a while. - for (int i = 0; i < kModeratePressureCooldownCycles; ++i) { - if (i + 1 == kModeratePressureCooldownCycles) { - EXPECT_CALL(monitor, - OnMemoryPressure(MemoryPressureListener:: - MEMORY_PRESSURE_LEVEL_MODERATE)); - } - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); - } - - // Going down to no pressure should not produce an notification. - monitor.SetNone(); - monitor.CheckMemoryPressure(); - RunLoop().RunUntilIdle(); - EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, - monitor.GetCurrentPressureLevel()); - testing::Mock::VerifyAndClearExpectations(&monitor); -} - -} // namespace win -} // namespace base
diff --git a/base/memory/platform_shared_memory_region_fuchsia.cc b/base/memory/platform_shared_memory_region_fuchsia.cc index ee4087b..35c5fecd 100644 --- a/base/memory/platform_shared_memory_region_fuchsia.cc +++ b/base/memory/platform_shared_memory_region_fuchsia.cc
@@ -147,6 +147,12 @@ return {}; } + // TODO(crbug.com/991805): Take base::Location from the caller and use it to + // generate the name here. + constexpr char kVmoName[] = "cr-shared-memory-region"; + status = vmo.set_property(ZX_PROP_NAME, kVmoName, strlen(kVmoName)); + ZX_DCHECK(status == ZX_OK, status); + const int kNoExecFlags = ZX_DEFAULT_VMO_RIGHTS & ~ZX_RIGHT_EXECUTE; status = vmo.replace(kNoExecFlags, &vmo); if (status != ZX_OK) {
diff --git a/base/memory/shared_memory_fuchsia.cc b/base/memory/shared_memory_fuchsia.cc index 878906a..8c76f548 100644 --- a/base/memory/shared_memory_fuchsia.cc +++ b/base/memory/shared_memory_fuchsia.cc
@@ -52,6 +52,10 @@ return false; } + static const char kVmoName[] = "cr-shared-memory"; + status = vmo.set_property(ZX_PROP_NAME, kVmoName, strlen(kVmoName)); + ZX_DCHECK(status == ZX_OK, status); + if (!options.executable) { // If options.executable isn't set, drop that permission by replacement. const int kNoExecFlags = ZX_DEFAULT_VMO_RIGHTS & ~ZX_RIGHT_EXECUTE;
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index fe1864b..98435f93 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -170,6 +170,8 @@ sources += [ "launcher/test_launcher.cc", "launcher/test_launcher.h", + "launcher/test_launcher_test_utils.cc", + "launcher/test_launcher_test_utils.h", "launcher/test_launcher_tracer.cc", "launcher/test_launcher_tracer.h", "launcher/test_results_tracker.cc",
diff --git a/base/test/launcher/test_launcher_test_utils.cc b/base/test/launcher/test_launcher_test_utils.cc new file mode 100644 index 0000000..2a535c61 --- /dev/null +++ b/base/test/launcher/test_launcher_test_utils.cc
@@ -0,0 +1,115 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/launcher/test_launcher_test_utils.h" + +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/optional.h" +#include "base/test/launcher/test_result.h" + +namespace base { + +namespace test_launcher_utils { + +namespace { + +// Helper function to return |Value::FindStringKey| by value instead of +// pointer to string, or empty string if nullptr. +std::string FindStringKeyOrEmpty(const Value& dict_value, + const std::string& key) { + const std::string* value = dict_value.FindStringKey(key); + return value ? *value : std::string(); +} + +} // namespace + +bool ValidateKeyValue(const Value& dict_value, + const std::string& key, + const std::string& expected_value) { + std::string actual_value = FindStringKeyOrEmpty(dict_value, key); + bool result = !actual_value.compare(expected_value); + if (!result) + ADD_FAILURE() << key << " expected value: " << expected_value + << ", actual: " << actual_value; + return result; +} + +bool ValidateKeyValue(const Value& dict_value, + const std::string& key, + int64_t expected_value) { + int actual_value = dict_value.FindIntKey(key).value_or(0); + bool result = (actual_value == expected_value); + if (!result) + ADD_FAILURE() << key << " expected value: " << expected_value + << ", actual: " << actual_value; + return result; +} + +bool ValidateTestResult(const Value* iteration_data, + const std::string& test_name, + const std::string& status, + size_t result_part_count) { + const Value* results = iteration_data->FindListKey(test_name); + if (!results) { + ADD_FAILURE() << "Cannot find result"; + return false; + } + if (1u != results->GetList().size()) { + ADD_FAILURE() << "Expected one result"; + return false; + } + + const Value& val = results->GetList().at(0); + if (!val.is_dict()) { + ADD_FAILURE() << "Value must be of type DICTIONARY"; + return false; + } + + if (!ValidateKeyValue(val, "status", status)) + return false; + + const Value* value = val.FindListKey("result_parts"); + if (!value) { + ADD_FAILURE() << "Result must contain 'result_parts' key"; + return false; + } + + if (result_part_count != value->GetList().size()) { + ADD_FAILURE() << "result_parts count expected: " << result_part_count + << ", actual:" << value->GetList().size(); + return false; + } + return true; +} + +bool ValidateTestLocation(const Value* test_locations, + const std::string& test_name, + const std::string& file, + int line) { + const Value* val = test_locations->FindDictKey(test_name); + if (!val) { + ADD_FAILURE() << "|test_locations| missing location for " << test_name; + return false; + } + + bool result = ValidateKeyValue(*val, "file", file); + result &= ValidateKeyValue(*val, "line", line); + return result; +} + +Optional<Value> ReadSummary(const FilePath& path) { + Optional<Value> result; + File resultFile(path, File::FLAG_OPEN | File::FLAG_READ); + const int size = 2e7; + std::string json; + CHECK(ReadFileToStringWithMaxSize(path, &json, size)); + result = JSONReader::Read(json); + return result; +} + +} // namespace test_launcher_utils + +} // namespace base \ No newline at end of file
diff --git a/base/test/launcher/test_launcher_test_utils.h b/base/test/launcher/test_launcher_test_utils.h new file mode 100644 index 0000000..f6b17d5 --- /dev/null +++ b/base/test/launcher/test_launcher_test_utils.h
@@ -0,0 +1,53 @@ +// 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 BASE_TEST_LAUNCHER_TEST_LAUNCHER_TEST_UTILS_H_ +#define BASE_TEST_LAUNCHER_TEST_LAUNCHER_TEST_UTILS_H_ + +#include <stddef.h> + +#include <string> +#include <vector> + +#include "base/optional.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +class Value; +class FilePath; + +namespace test_launcher_utils { + +// Validate |dict_value| value in |key| is equal to |expected_value| +bool ValidateKeyValue(const Value& dict_value, + const std::string& key, + const std::string& expected_value); + +// Validate |dict_value| value in |key| is equal to |expected_value| +bool ValidateKeyValue(const Value& dict_value, + const std::string& key, + int64_t expected_value); + +// Validate |iteration_data| contains one test result under |test_name| +// with |status|, and |result_part_count| number of result parts. +bool ValidateTestResult(const Value* iteration_data, + const std::string& test_name, + const std::string& status, + size_t result_part_count); + +// Validate test_locations contains the correct file name and line number. +bool ValidateTestLocation(const Value* test_locations, + const std::string& test_name, + const std::string& file, + int line); + +// Read json output file of test launcher. +Optional<Value> ReadSummary(const FilePath& path); + +} // namespace test_launcher_utils + +} // namespace base + +#endif // BASE_TEST_LAUNCHER_TEST_LAUNCHER_TEST_UTILS_H_ \ No newline at end of file
diff --git a/base/test/launcher/test_launcher_unittest.cc b/base/test/launcher/test_launcher_unittest.cc index 870144c..353dfb7c 100644 --- a/base/test/launcher/test_launcher_unittest.cc +++ b/base/test/launcher/test_launcher_unittest.cc
@@ -9,11 +9,10 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" #include "base/process/launch.h" #include "base/strings/string_split.h" #include "base/test/launcher/test_launcher.h" +#include "base/test/launcher/test_launcher_test_utils.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/scoped_task_environment.h" #include "base/test/test_timeouts.h" @@ -422,98 +421,87 @@ EXPECT_TRUE(test_launcher.Run(command_line.get())); } -void ValidateKeyValue(Value* dict_value, - const std::string& key, - const std::string& expected_value) { - const std::string* value = dict_value->FindStringKey(key); - ASSERT_TRUE(value); - EXPECT_EQ(expected_value, *value); -} +// Validate |iteration_data| contains one test result matching |result|. +bool ValidateTestResultObject(const Value* iteration_data, + TestResult& test_result) { + const Value* results = iteration_data->FindListKey(test_result.full_name); + if (!results) { + ADD_FAILURE() << "Results not found"; + return false; + } + if (1u != results->GetList().size()) { + ADD_FAILURE() << "Expected one result, actual: " + << results->GetList().size(); + return false; + } + const Value& val = results->GetList().at(0); + if (!val.is_dict()) { + ADD_FAILURE() << "Unexpected type"; + return false; + } -// Validate a json child node for a particular test result. -void ValidateTestResult(Value* root, TestResult& result) { - Value* val = root->FindListKey(result.full_name); - ASSERT_TRUE(val); - ASSERT_EQ(1u, val->GetList().size()); - val = &val->GetList().at(0); - ASSERT_TRUE(val->is_dict()); + using test_launcher_utils::ValidateKeyValue; + bool result = ValidateKeyValue(val, "elapsed_time_ms", + test_result.elapsed_time.InMilliseconds()); - EXPECT_EQ(result.elapsed_time.InMilliseconds(), - val->FindIntKey("elapsed_time_ms").value_or(0)); - EXPECT_EQ(true, val->FindBoolKey("losless_snippet").value_or(false)); - ValidateKeyValue(val, "output_snippet", result.output_snippet); + if (!val.FindBoolKey("losless_snippet").value_or(false)) { + ADD_FAILURE() << "losless_snippet expected to be true"; + result = false; + } + + result &= ValidateKeyValue(val, "output_snippet", test_result.output_snippet); std::string base64_output_snippet; - Base64Encode(result.output_snippet, &base64_output_snippet); - ValidateKeyValue(val, "output_snippet_base64", base64_output_snippet); - ValidateKeyValue(val, "status", result.StatusAsString()); + Base64Encode(test_result.output_snippet, &base64_output_snippet); + result &= + ValidateKeyValue(val, "output_snippet_base64", base64_output_snippet); - Value* value = val->FindListKey("result_parts"); - ASSERT_TRUE(value); - EXPECT_EQ(result.test_result_parts.size(), value->GetList().size()); - for (unsigned i = 0; i < result.test_result_parts.size(); i++) { - TestResultPart result_part = result.test_result_parts.at(0); - Value* part_dict = &(value->GetList().at(i)); - ASSERT_TRUE(part_dict); - ASSERT_TRUE(part_dict->is_dict()); - ValidateKeyValue(part_dict, "type", result_part.TypeAsString()); - ValidateKeyValue(part_dict, "file", result_part.file_name); - EXPECT_EQ(result_part.line_number, - part_dict->FindIntKey("line").value_or(0)); - ValidateKeyValue(part_dict, "summary", result_part.summary); - ValidateKeyValue(part_dict, "message", result_part.message); + result &= ValidateKeyValue(val, "status", test_result.StatusAsString()); + + const Value* value = val.FindListKey("result_parts"); + if (test_result.test_result_parts.size() != value->GetList().size()) { + ADD_FAILURE() << "test_result_parts count is not valid"; + return false; } + + for (unsigned i = 0; i < test_result.test_result_parts.size(); i++) { + TestResultPart result_part = test_result.test_result_parts.at(i); + const Value& part_dict = value->GetList().at(i); + + result &= ValidateKeyValue(part_dict, "type", result_part.TypeAsString()); + result &= ValidateKeyValue(part_dict, "file", result_part.file_name); + result &= ValidateKeyValue(part_dict, "line", result_part.line_number); + result &= ValidateKeyValue(part_dict, "summary", result_part.summary); + result &= ValidateKeyValue(part_dict, "message", result_part.message); + } + return result; } -// Validate vital information of actual test results. -void ValidateTestResult(Value* root, - const std::string& test_name, - const std::string& status, - size_t result_part_count) { - Value* val = root->FindListKey(test_name); - ASSERT_TRUE(val) << test_name; - ASSERT_EQ(1u, val->GetList().size()); - val = &val->GetList().at(0); - ASSERT_TRUE(val->is_dict()) << test_name; - - ValidateKeyValue(val, "status", status); - - Value* value = val->FindListKey("result_parts"); - ASSERT_TRUE(value) << test_name; - EXPECT_EQ(result_part_count, value->GetList().size()) << test_name; -} - -void ValidateStringList(Optional<Value>& root, +// Validate |root| dictionary value contains a list with |values| +// at |key| value. +bool ValidateStringList(const Optional<Value>& root, const std::string& key, std::vector<const char*> values) { - Value* val = root->FindListKey(key); - ASSERT_TRUE(val); - ASSERT_EQ(values.size(), val->GetList().size()); - for (unsigned i = 0; i < values.size(); i++) { - ASSERT_TRUE(val->GetList().at(i).is_string()); - EXPECT_EQ(values.at(i), val->GetList().at(i).GetString()); + const Value* val = root->FindListKey(key); + if (!val) { + ADD_FAILURE() << "|root| has no list_value in key: " << key; + return false; } -} -void ValidateTestLocation(Value* root, - const std::string& key, - const std::string& file, - int line) { - Value* val = root->FindDictKey(key); - ASSERT_TRUE(val); - EXPECT_EQ(2u, val->DictSize()); - ValidateKeyValue(val, "file", file); - EXPECT_EQ(line, val->FindIntKey("line").value_or(0)); -} + if (values.size() != val->GetList().size()) { + ADD_FAILURE() << "expected size: " << values.size() + << ", actual size:" << val->GetList().size(); + return false; + } -Optional<Value> ReadSummary(FilePath path) { - Optional<Value> result; - File resultFile(path, File::FLAG_OPEN | File::FLAG_READ); - const int size = 2e7; - std::string json; - CHECK(ReadFileToStringWithMaxSize(path, &json, size)); - result = JSONReader::Read(json); - return result; + for (unsigned i = 0; i < values.size(); i++) { + if (!val->GetList().at(i).is_string() && + val->GetList().at(i).GetString().compare(values.at(i))) { + ADD_FAILURE() << "Expected list values do not match actual list"; + return false; + } + } + return true; } // Unit tests to validate TestLauncher outputs the correct JSON file. @@ -547,30 +535,34 @@ EXPECT_TRUE(test_launcher.Run(command_line.get())); // Validate the resulting JSON file is the expected output. - Optional<Value> root = ReadSummary(path); + Optional<Value> root = test_launcher_utils::ReadSummary(path); ASSERT_TRUE(root); - ValidateStringList(root, "all_tests", - {"Test.firstTest", "Test.firstTestDisabled", - "Test.secondTest", "TestDisabled.firstTest"}); - ValidateStringList(root, "disabled_tests", - {"Test.firstTestDisabled", "TestDisabled.firstTest"}); + EXPECT_TRUE( + ValidateStringList(root, "all_tests", + {"Test.firstTest", "Test.firstTestDisabled", + "Test.secondTest", "TestDisabled.firstTest"})); + EXPECT_TRUE( + ValidateStringList(root, "disabled_tests", + {"Test.firstTestDisabled", "TestDisabled.firstTest"})); - Value* val = root->FindDictKey("test_locations"); + const Value* val = root->FindDictKey("test_locations"); ASSERT_TRUE(val); EXPECT_EQ(2u, val->DictSize()); - ValidateTestLocation(val, "Test.firstTest", "File", 100); - ValidateTestLocation(val, "Test.secondTest", "File", 100); + ASSERT_TRUE(test_launcher_utils::ValidateTestLocation(val, "Test.firstTest", + "File", 100)); + ASSERT_TRUE(test_launcher_utils::ValidateTestLocation(val, "Test.secondTest", + "File", 100)); val = root->FindListKey("per_iteration_data"); ASSERT_TRUE(val); ASSERT_EQ(2u, val->GetList().size()); for (size_t i = 0; i < val->GetList().size(); i++) { - Value* iteration_val = &(val->GetList().at(i)); + const Value* iteration_val = &(val->GetList().at(i)); ASSERT_TRUE(iteration_val); ASSERT_TRUE(iteration_val->is_dict()); EXPECT_EQ(2u, iteration_val->DictSize()); - ValidateTestResult(iteration_val, first_result); - ValidateTestResult(iteration_val, second_result); + EXPECT_TRUE(ValidateTestResultObject(iteration_val, first_result)); + EXPECT_TRUE(ValidateTestResultObject(iteration_val, second_result)); } } @@ -596,12 +588,13 @@ EXPECT_TRUE(test_launcher.Run(command_line.get())); // Validate the resulting JSON file is the expected output. - Optional<Value> root = ReadSummary(path); + Optional<Value> root = test_launcher_utils::ReadSummary(path); ASSERT_TRUE(root); Value* val = root->FindDictKey("test_locations"); ASSERT_TRUE(val); EXPECT_EQ(1u, val->DictSize()); - ValidateTestLocation(val, "Test.DISABLED_Test", "File", 100); + EXPECT_TRUE(test_launcher_utils::ValidateTestLocation( + val, "Test.DISABLED_Test", "File", 100)); val = root->FindListKey("per_iteration_data"); ASSERT_TRUE(val); @@ -613,7 +606,7 @@ EXPECT_EQ(1u, iteration_val->DictSize()); // We expect the result to be stripped of disabled prefix. test_result.full_name = "Test.Test"; - ValidateTestResult(iteration_val, test_result); + EXPECT_TRUE(ValidateTestResultObject(iteration_val, test_result)); } // Unit tests to validate UnitTestLauncherDelegate implementation. @@ -678,8 +671,8 @@ IMMEDIATE_CRASH(); } -// Using UnitTestLauncherDelegate and TestLauncher (with minor mocks) -// to launch 3 basic tests, and validate the resulting json file. +// Using TestLauncher to launch 3 simple unitests +// and validate the resulting json file. TEST_F(UnitTestLauncherDelegateTester, RunMockTests) { CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram()); command_line.AppendSwitchASCII("gtest_filter", "MockUnitTests.DISABLED_*"); @@ -701,7 +694,7 @@ GetAppOutputAndError(command_line, &output); // Validate the resulting JSON file is the expected output. - Optional<Value> root = ReadSummary(path); + Optional<Value> root = test_launcher_utils::ReadSummary(path); ASSERT_TRUE(root); Value* val = root->FindDictKey("test_locations"); @@ -710,9 +703,12 @@ // If path or test location changes, the following expectation // will need to change accordingly. std::string file_name = "../../base/test/launcher/test_launcher_unittest.cc"; - ValidateTestLocation(val, "MockUnitTests.DISABLED_PassTest", file_name, 669); - ValidateTestLocation(val, "MockUnitTests.DISABLED_FailTest", file_name, 673); - ValidateTestLocation(val, "MockUnitTests.DISABLED_CrashTest", file_name, 677); + EXPECT_TRUE(test_launcher_utils::ValidateTestLocation( + val, "MockUnitTests.DISABLED_PassTest", file_name, 662)); + EXPECT_TRUE(test_launcher_utils::ValidateTestLocation( + val, "MockUnitTests.DISABLED_FailTest", file_name, 666)); + EXPECT_TRUE(test_launcher_utils::ValidateTestLocation( + val, "MockUnitTests.DISABLED_CrashTest", file_name, 670)); val = root->FindListKey("per_iteration_data"); ASSERT_TRUE(val); @@ -723,9 +719,12 @@ ASSERT_TRUE(iteration_val->is_dict()); EXPECT_EQ(3u, iteration_val->DictSize()); // We expect the result to be stripped of disabled prefix. - ValidateTestResult(iteration_val, "MockUnitTests.PassTest", "SUCCESS", 0u); - ValidateTestResult(iteration_val, "MockUnitTests.FailTest", "FAILURE", 1u); - ValidateTestResult(iteration_val, "MockUnitTests.CrashTest", "CRASH", 0u); + EXPECT_TRUE(test_launcher_utils::ValidateTestResult( + iteration_val, "MockUnitTests.PassTest", "SUCCESS", 0u)); + EXPECT_TRUE(test_launcher_utils::ValidateTestResult( + iteration_val, "MockUnitTests.FailTest", "FAILURE", 1u)); + EXPECT_TRUE(test_launcher_utils::ValidateTestResult( + iteration_val, "MockUnitTests.CrashTest", "CRASH", 0u)); } } // namespace
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc index 93a54d2..7807d031 100644 --- a/base/test/test_suite.cc +++ b/base/test/test_suite.cc
@@ -27,8 +27,6 @@ #include "base/path_service.h" #include "base/process/launch.h" #include "base/process/memory.h" -#include "base/process/process.h" -#include "base/process/process_handle.h" #include "base/task/thread_pool/thread_pool.h" #include "base/test/gtest_xml_unittest_result_printer.h" #include "base/test/gtest_xml_util.h" @@ -45,7 +43,6 @@ #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" -#include "base/process/port_provider_mac.h" #if defined(OS_IOS) #include "base/test/test_listener_ios.h" #endif // OS_IOS @@ -147,47 +144,6 @@ DISALLOW_COPY_AND_ASSIGN(CheckForLeakedGlobals); }; -// base::Process is not available on iOS -#if !defined(OS_IOS) -class CheckProcessPriority : public testing::EmptyTestEventListener { - public: - CheckProcessPriority() { CHECK(!IsProcessBackgrounded()); } - - void OnTestStart(const testing::TestInfo& test) override { - EXPECT_FALSE(IsProcessBackgrounded()); - } - void OnTestEnd(const testing::TestInfo& test) override { -#if !defined(OS_MACOSX) - // Flakes are found on Mac OS 10.11. See https://crbug.com/931721#c7. - EXPECT_FALSE(IsProcessBackgrounded()); -#endif - } - - private: -#if defined(OS_MACOSX) - // Returns the calling process's task port, ignoring its argument. - class CurrentProcessPortProvider : public PortProvider { - mach_port_t TaskForPid(ProcessHandle process) const override { - // This PortProvider implementation only works for the current process. - CHECK_EQ(process, base::GetCurrentProcessHandle()); - return mach_task_self(); - } - }; -#endif - - bool IsProcessBackgrounded() const { -#if defined(OS_MACOSX) - CurrentProcessPortProvider port_provider; - return Process::Current().IsProcessBackgrounded(&port_provider); -#else - return Process::Current().IsProcessBackgrounded(); -#endif - } - - DISALLOW_COPY_AND_ASSIGN(CheckProcessPriority); -}; -#endif // !defined(OS_IOS) - const std::string& GetProfileName() { static const NoDestructor<std::string> profile_name([]() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); @@ -232,7 +188,7 @@ } // namespace -int RunUnitTestsUsingBaseTestSuite(int argc, char** argv) { +int RunUnitTestsUsingBaseTestSuite(int argc, char **argv) { TestSuite test_suite(argc, argv); return LaunchUnitTests(argc, argv, BindOnce(&TestSuite::Run, Unretained(&test_suite))); @@ -445,8 +401,9 @@ void TestSuite::SuppressErrorDialogs() { #if defined(OS_WIN) - UINT new_flags = - SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX; + UINT new_flags = SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX; // Preserve existing error mode, as discussed at // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx @@ -562,9 +519,6 @@ listeners.Append(new ResetCommandLineBetweenTests); if (check_for_leaked_globals_) listeners.Append(new CheckForLeakedGlobals); -#if !defined(OS_IOS) - listeners.Append(new CheckProcessPriority); -#endif AddTestLauncherResultPrinter();
diff --git a/base/util/memory_pressure/BUILD.gn b/base/util/memory_pressure/BUILD.gn index a1dca12..b507c71 100644 --- a/base/util/memory_pressure/BUILD.gn +++ b/base/util/memory_pressure/BUILD.gn
@@ -8,6 +8,10 @@ "memory_pressure_voter.h", "multi_source_memory_pressure_monitor.cc", "multi_source_memory_pressure_monitor.h", + "system_memory_pressure_evaluator.cc", + "system_memory_pressure_evaluator.h", + "system_memory_pressure_evaluator_win.cc", + "system_memory_pressure_evaluator_win.h", ] deps = [ @@ -20,12 +24,14 @@ sources = [ "memory_pressure_voter_unittest.cc", "multi_source_memory_pressure_monitor_unittest.cc", + "system_memory_pressure_evaluator_win_unittest.cc", ] deps = [ ":memory_pressure", "//base", "//base/test:test_support", + "//testing/gmock", "//testing/gtest", ] }
diff --git a/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc b/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc index 098ed72e..867bd32 100644 --- a/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc +++ b/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/util/memory_pressure/system_memory_pressure_evaluator.h" namespace util { @@ -16,6 +17,11 @@ dispatch_callback_(base::BindRepeating( &base::MemoryPressureListener::NotifyMemoryPressure)), aggregator_(this) { + // This can't be in the parameter list because |sequence_checker_| wouldn't be + // available, which would be needed by the |system_evaluator_|'s constructor's + // call to CreateVoter(). + system_evaluator_ = + SystemMemoryPressureEvaluator::CreateDefaultSystemEvaluator(this); StartMetricsTimer(); } @@ -63,4 +69,8 @@ dispatch_callback_.Run(current_pressure_level_); } +void MultiSourceMemoryPressureMonitor::ResetSystemEvaluatorForTesting() { + system_evaluator_.reset(); +} + } // namespace util
diff --git a/base/util/memory_pressure/multi_source_memory_pressure_monitor.h b/base/util/memory_pressure/multi_source_memory_pressure_monitor.h index 5cfbe61..e028900 100644 --- a/base/util/memory_pressure/multi_source_memory_pressure_monitor.h +++ b/base/util/memory_pressure/multi_source_memory_pressure_monitor.h
@@ -11,6 +11,8 @@ namespace util { +class SystemMemoryPressureEvaluator; + // This is a specialization of a MemoryPressureMonitor that relies on a set of // MemoryPressureVoters to determine the memory pressure state. The // MemoryPressureVoteAggregator is in charge of receiving votes from these @@ -40,6 +42,8 @@ return &aggregator_; } + void ResetSystemEvaluatorForTesting(); + protected: void StartMetricsTimer(); void StopMetricsTimer(); @@ -58,6 +62,8 @@ MemoryPressureVoteAggregator aggregator_; + std::unique_ptr<SystemMemoryPressureEvaluator> system_evaluator_; + // A periodic timer to record UMA metrics. base::RepeatingTimer metric_timer_;
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator.cc b/base/util/memory_pressure/system_memory_pressure_evaluator.cc new file mode 100644 index 0000000..9197e06 --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator.cc
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/util/memory_pressure/system_memory_pressure_evaluator.h" + +#include "build/build_config.h" + +#if defined(OS_WIN) +#include "base/util/memory_pressure/system_memory_pressure_evaluator_win.h" +#endif + +namespace util { + +// static +std::unique_ptr<SystemMemoryPressureEvaluator> +SystemMemoryPressureEvaluator::CreateDefaultSystemEvaluator( + MultiSourceMemoryPressureMonitor* monitor) { +#if defined(OS_WIN) + return std::make_unique<util::win::SystemMemoryPressureEvaluator>( + monitor->CreateVoter()); +#endif + return nullptr; +} + +SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator() = default; + +} // namespace util
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator.h b/base/util/memory_pressure/system_memory_pressure_evaluator.h new file mode 100644 index 0000000..d13599f3 --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator.h
@@ -0,0 +1,30 @@ +// 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 BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_H_ +#define BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_H_ + +#include "base/util/memory_pressure/memory_pressure_voter.h" +#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h" + +namespace util { + +// Base class for the platform SystemMemoryPressureEvaluators, which use +// MemoryPressureVoters to cast their vote on the overall MemoryPressureLevel. +class SystemMemoryPressureEvaluator { + public: + // Used by the MemoryPressureMonitor to create the correct Evaluator for the + // platform in use. + static std::unique_ptr<SystemMemoryPressureEvaluator> + CreateDefaultSystemEvaluator(MultiSourceMemoryPressureMonitor* monitor); + + virtual ~SystemMemoryPressureEvaluator() = default; + + protected: + SystemMemoryPressureEvaluator(); +}; + +} // namespace util + +#endif // BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_H_
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator_win.cc b/base/util/memory_pressure/system_memory_pressure_evaluator_win.cc new file mode 100644 index 0000000..75b929f --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_win.cc
@@ -0,0 +1,214 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/util/memory_pressure/system_memory_pressure_evaluator_win.h" + +#include <windows.h> + +#include "base/bind.h" +#include "base/single_thread_task_runner.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 util { +namespace win { + +namespace { + +static const DWORDLONG kMBBytes = 1024 * 1024; + +} // namespace + +// The following constants have been lifted from similar values in the ChromeOS +// memory pressure monitor. The values were determined experimentally to ensure +// sufficient responsiveness of the memory pressure subsystem, and minimal +// overhead. +const int SystemMemoryPressureEvaluator::kModeratePressureCooldownMs = 10000; + +// TODO(chrisha): Explore the following constants further with an experiment. + +// A system is considered 'high memory' if it has more than 1.5GB of system +// memory available for use by the memory manager (not reserved for hardware +// and drivers). This is a fuzzy version of the ~2GB discussed below. +const int SystemMemoryPressureEvaluator::kLargeMemoryThresholdMb = 1536; + +// These are the default thresholds used for systems with < ~2GB of physical +// memory. Such systems have been observed to always maintain ~100MB of +// available memory, paging until that is the case. To try to avoid paging a +// threshold slightly above this is chosen. The moderate threshold is slightly +// less grounded in reality and chosen as 2.5x critical. +const int + SystemMemoryPressureEvaluator::kSmallMemoryDefaultModerateThresholdMb = 500; +const int + SystemMemoryPressureEvaluator::kSmallMemoryDefaultCriticalThresholdMb = 200; + +// These are the default thresholds used for systems with >= ~2GB of physical +// memory. Such systems have been observed to always maintain ~300MB of +// available memory, paging until that is the case. +const int + SystemMemoryPressureEvaluator::kLargeMemoryDefaultModerateThresholdMb = + 1000; +const int + SystemMemoryPressureEvaluator::kLargeMemoryDefaultCriticalThresholdMb = 400; + +SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( + std::unique_ptr<MemoryPressureVoter> voter) + : moderate_threshold_mb_(0), + critical_threshold_mb_(0), + moderate_pressure_repeat_count_(0), + voter_(std::move(voter)), + current_vote_(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), + weak_ptr_factory_(this) { + InferThresholds(); + StartObserving(); +} + +SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( + int moderate_threshold_mb, + int critical_threshold_mb, + std::unique_ptr<MemoryPressureVoter> voter) + : moderate_threshold_mb_(moderate_threshold_mb), + critical_threshold_mb_(critical_threshold_mb), + moderate_pressure_repeat_count_(0), + voter_(std::move(voter)), + current_vote_(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE), + weak_ptr_factory_(this) { + DCHECK_GE(moderate_threshold_mb_, critical_threshold_mb_); + DCHECK_LE(0, critical_threshold_mb_); + StartObserving(); +} + +SystemMemoryPressureEvaluator::~SystemMemoryPressureEvaluator() { + StopObserving(); +} + +void SystemMemoryPressureEvaluator::CheckMemoryPressureSoon() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, BindOnce(&SystemMemoryPressureEvaluator::CheckMemoryPressure, + weak_ptr_factory_.GetWeakPtr())); +} + +void SystemMemoryPressureEvaluator::InferThresholds() { + // Default to a 'high' memory situation, which uses more conservative + // thresholds. + bool high_memory = true; + MEMORYSTATUSEX mem_status = {}; + if (GetSystemMemoryStatus(&mem_status)) { + static const DWORDLONG kLargeMemoryThresholdBytes = + static_cast<DWORDLONG>(kLargeMemoryThresholdMb) * kMBBytes; + high_memory = mem_status.ullTotalPhys >= kLargeMemoryThresholdBytes; + } + + if (high_memory) { + moderate_threshold_mb_ = kLargeMemoryDefaultModerateThresholdMb; + critical_threshold_mb_ = kLargeMemoryDefaultCriticalThresholdMb; + } else { + moderate_threshold_mb_ = kSmallMemoryDefaultModerateThresholdMb; + critical_threshold_mb_ = kSmallMemoryDefaultCriticalThresholdMb; + } +} + +void SystemMemoryPressureEvaluator::StartObserving() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + timer_.Start( + FROM_HERE, base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod, + BindRepeating(&SystemMemoryPressureEvaluator::CheckMemoryPressure, + weak_ptr_factory_.GetWeakPtr())); +} + +void SystemMemoryPressureEvaluator::StopObserving() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // If StartObserving failed, StopObserving will still get called. + timer_.Stop(); + weak_ptr_factory_.InvalidateWeakPtrs(); +} + +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_; + current_vote_ = 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 = + kModeratePressureCooldownMs / + base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod + .InMilliseconds(); + 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; + } + + voter_->SetVote(current_vote_, notify); +} + +base::MemoryPressureListener::MemoryPressureLevel +SystemMemoryPressureEvaluator::CalculateCurrentPressureLevel() { + MEMORYSTATUSEX mem_status = {}; + if (!GetSystemMemoryStatus(&mem_status)) + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; + + // How much system memory is actively available for use right now, in MBs. + int phys_free = static_cast<int>(mem_status.ullAvailPhys / kMBBytes); + + // TODO(chrisha): This should eventually care about address space pressure, + // but the browser process (where this is running) effectively never runs out + // of address space. Renderers occasionally do, but it does them no good to + // have the browser process monitor address space pressure. Long term, + // renderers should run their own address space pressure monitors and act + // accordingly, with the browser making cross-process decisions based on + // system memory pressure. + + // Determine if the physical memory is under critical memory pressure. + if (phys_free <= critical_threshold_mb_) + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; + + // Determine if the physical memory is under moderate memory pressure. + if (phys_free <= moderate_threshold_mb_) + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; + + // No memory pressure was detected. + return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; +} + +bool SystemMemoryPressureEvaluator::GetSystemMemoryStatus( + MEMORYSTATUSEX* mem_status) { + DCHECK(mem_status != nullptr); + mem_status->dwLength = sizeof(*mem_status); + if (!::GlobalMemoryStatusEx(mem_status)) + return false; + return true; +} + +} // namespace win +} // namespace util
diff --git a/base/memory/memory_pressure_monitor_win.h b/base/util/memory_pressure/system_memory_pressure_evaluator_win.h similarity index 66% rename from base/memory/memory_pressure_monitor_win.h rename to base/util/memory_pressure/system_memory_pressure_evaluator_win.h index 6d9df60..25c3f15 100644 --- a/base/memory/memory_pressure_monitor_win.h +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_win.h
@@ -1,28 +1,32 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. +// 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 BASE_MEMORY_MEMORY_PRESSURE_MONITOR_WIN_H_ -#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_WIN_H_ +#ifndef BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_WIN_H_ +#define BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_WIN_H_ #include "base/base_export.h" #include "base/macros.h" #include "base/memory/memory_pressure_listener.h" -#include "base/memory/memory_pressure_monitor.h" #include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.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" // To not pull in windows.h. typedef struct _MEMORYSTATUSEX MEMORYSTATUSEX; -namespace base { +namespace util { namespace win { -// Windows memory pressure monitor. Because there is no OS provided signal this -// polls at a low frequency (once per second), and applies internal hysteresis. -class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor { +// Windows memory pressure voter. Because there is no OS provided signal this +// polls at a low frequency, and applies internal hysteresis. +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, in milliseconds. @@ -40,24 +44,24 @@ static const int kLargeMemoryDefaultModerateThresholdMb; static const int kLargeMemoryDefaultCriticalThresholdMb; - // Default constructor. Will choose thresholds automatically basd on the + // Default constructor. Will choose thresholds automatically based on the // actual amount of system memory. - MemoryPressureMonitor(); + 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. - MemoryPressureMonitor(int moderate_threshold_mb, int critical_threshold_mb); + // For testing purposes. + SystemMemoryPressureEvaluator(int moderate_threshold_mb, + int critical_threshold_mb, + std::unique_ptr<MemoryPressureVoter> voter); - ~MemoryPressureMonitor() override; + ~SystemMemoryPressureEvaluator() override; // Schedules a memory pressure check to run soon. This must be called on the - // same thread where the monitor was instantiated. + // same sequence where the monitor was instantiated. void CheckMemoryPressureSoon(); - // Get the current memory pressure level. This can be called from any thread. - MemoryPressureLevel GetCurrentPressureLevel() const override; - void SetDispatchCallback(const DispatchCallback& callback) override; - // Returns the moderate pressure level free memory threshold, in MB. int moderate_threshold_mb() const { return moderate_threshold_mb_; } @@ -83,23 +87,18 @@ // 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. This is split out from CheckMemoryPressureAndRecordStatistics so - // that it may be called by CheckMemoryPressureSoon and not invoke UMA - // logging. Must be called from the same thread on which the monitor was + // pressure. Must be called from the same thread on which the monitor was // instantiated. void CheckMemoryPressure(); - // Wrapper to CheckMemoryPressure that also records the observed memory - // pressure level via an UMA enumeration. This is the function that is called - // periodically by the timer. Must be called from the same thread on which the - // monitor was instantiated. - void CheckMemoryPressureAndRecordStatistics(); - // 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(); + // Gets the most recently cast vote. + MemoryPressureLevel current_vote_for_testing() const { return current_vote_; } + // Gets system memory status. This is virtual as a unittesting hook. Returns // true if the system call succeeds, false otherwise. Can be called on any // thread. @@ -114,28 +113,29 @@ // A periodic timer to check for memory pressure changes. base::RepeatingTimer timer_; - // The current memory pressure. - MemoryPressureLevel current_memory_pressure_level_; - // To slow down the amount of moderate pressure event calls, this gets used to - // count the number of events since the last event occured. This is used by + // 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 thread. - base::ThreadChecker thread_checker_; + // In charge of forwarding votes from here to the + // MemoryPressureVoteAggregator. + std::unique_ptr<MemoryPressureVoter> voter_; - DispatchCallback dispatch_callback_; + MemoryPressureLevel current_vote_; + + // Ensures that this object is used from a single sequence. + SEQUENCE_CHECKER(sequence_checker_); // Weak pointer factory to ourself used for scheduling calls to // CheckMemoryPressure/CheckMemoryPressureAndRecordStatistics via |timer_|. - base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_; + base::WeakPtrFactory<SystemMemoryPressureEvaluator> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor); + DISALLOW_COPY_AND_ASSIGN(SystemMemoryPressureEvaluator); }; } // namespace win -} // namespace base +} // namespace util -#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_WIN_H_ +#endif // BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_WIN_H_
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc b/base/util/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc new file mode 100644 index 0000000..9df64d1 --- /dev/null +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc
@@ -0,0 +1,321 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/util/memory_pressure/system_memory_pressure_evaluator_win.h" + +#include "base/bind.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "base/test/scoped_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" + +#if defined(OS_WIN) +#include <windows.h> +#endif + +namespace util { +namespace win { + +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; + using SystemMemoryPressureEvaluator::current_vote_for_testing; + + static const DWORDLONG kMBBytes = 1024 * 1024; + + explicit TestSystemMemoryPressureEvaluator( + bool large_memory, + std::unique_ptr<MemoryPressureVoter> voter) + : SystemMemoryPressureEvaluator(std::move(voter)), mem_status_() { + // Generate a plausible amount of memory. + mem_status_.ullTotalPhys = + static_cast<DWORDLONG>(GenerateTotalMemoryMb(large_memory)) * kMBBytes; + + // Rerun InferThresholds using the test fixture's GetSystemMemoryStatus. + 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), + mem_status_() { + // Set the amount of system memory. + mem_status_.ullTotalPhys = + static_cast<DWORDLONG>(system_memory_mb * kMBBytes); + + // Stop the timer. + StopObserving(); + } + + MOCK_METHOD1(OnMemoryPressure, + void(base::MemoryPressureListener::MemoryPressureLevel level)); + + // Generates an amount of total memory that is consistent with the requested + // memory model. + int GenerateTotalMemoryMb(bool large_memory) { + int total_mb = 64; + while (total_mb < SystemMemoryPressureEvaluator::kLargeMemoryThresholdMb) + total_mb *= 2; + if (large_memory) + return total_mb * 2; + return total_mb / 2; + } + + // 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_.ullAvailPhys = static_cast<DWORDLONG>(phys_left_mb) * kMBBytes; + DCHECK_LT(mem_status_.ullAvailPhys, mem_status_.ullTotalPhys); + + // These fields are unused. + mem_status_.dwMemoryLoad = 0; + mem_status_.ullTotalPageFile = 0; + mem_status_.ullAvailPageFile = 0; + mem_status_.ullTotalVirtual = 0; + mem_status_.ullAvailVirtual = 0; + } + + void SetNone() { SetMemoryFree(moderate_threshold_mb() + 1); } + + void SetModerate() { SetMemoryFree(moderate_threshold_mb() - 1); } + + void SetCritical() { SetMemoryFree(critical_threshold_mb() - 1); } + + private: + bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status) override { + // Simply copy the memory status set by the test fixture. + *mem_status = mem_status_; + return true; + } + + MEMORYSTATUSEX mem_status_; + + DISALLOW_COPY_AND_ASSIGN(TestSystemMemoryPressureEvaluator); +}; + +class WinSystemMemoryPressureEvaluatorTest : 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::MessageLoopForUI message_loop_; +}; + +// Tests the fundamental direct calculation of memory pressure with automatic +// small-memory thresholds. +TEST_F(WinSystemMemoryPressureEvaluatorTest, + CalculateCurrentMemoryPressureLevelSmall) { + static const int kModerateMb = + SystemMemoryPressureEvaluator::kSmallMemoryDefaultModerateThresholdMb; + static const int kCriticalMb = + SystemMemoryPressureEvaluator::kSmallMemoryDefaultCriticalThresholdMb; + + // Small-memory model. + TestSystemMemoryPressureEvaluator evaluator(false, nullptr); + + EXPECT_EQ(kModerateMb, evaluator.moderate_threshold_mb()); + EXPECT_EQ(kCriticalMb, evaluator.critical_threshold_mb()); + + ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&evaluator)); +} + +// Tests the fundamental direct calculation of memory pressure with automatic +// large-memory thresholds. +TEST_F(WinSystemMemoryPressureEvaluatorTest, + CalculateCurrentMemoryPressureLevelLarge) { + static const int kModerateMb = + SystemMemoryPressureEvaluator::kLargeMemoryDefaultModerateThresholdMb; + static const int kCriticalMb = + SystemMemoryPressureEvaluator::kLargeMemoryDefaultCriticalThresholdMb; + + // Large-memory model. + TestSystemMemoryPressureEvaluator evaluator(true, nullptr); + + EXPECT_EQ(kModerateMb, evaluator.moderate_threshold_mb()); + EXPECT_EQ(kCriticalMb, evaluator.critical_threshold_mb()); + + ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&evaluator)); +} + +// Tests the fundamental direct calculation of memory pressure with manually +// specified threshold levels. +TEST_F(WinSystemMemoryPressureEvaluatorTest, + 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(WinSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) { + MultiSourceMemoryPressureMonitor monitor; + monitor.ResetSystemEvaluatorForTesting(); + + // Large-memory. + testing::StrictMock<TestSystemMemoryPressureEvaluator> evaluator( + true, monitor.CreateVoter()); + + base::MemoryPressureListener listener( + 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_for_testing()); + + // 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_for_testing()); + testing::Mock::VerifyAndClearExpectations(&evaluator); + + // Check that the event gets reposted after a while. + const int kModeratePressureCooldownCycles = + evaluator.kModeratePressureCooldownMs / + base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod + .InMilliseconds(); + + 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_for_testing()); + 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_for_testing()); + 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_for_testing()); + 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_for_testing()); + 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_for_testing()); + 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_for_testing()); + testing::Mock::VerifyAndClearExpectations(&evaluator); +} + +} // namespace win +} // namespace util
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py index e3a7493..04bc3646 100644 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -582,7 +582,7 @@ def handle_coverage_data(): if self._test_instance.coverage_directory: try: - device.PullFile(coverage_directory, + device.PullFile(coverage_device_file, self._test_instance.coverage_directory) device.RunShellCommand( 'rm -f %s' % posixpath.join(coverage_directory, '*'),
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc index d911d35e..6093114 100644 --- a/cc/paint/paint_op_buffer_serializer.cc +++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -46,18 +46,6 @@ return PlaybackParams(nullptr, canvas->getTotalMatrix()); } -SkTextBlobCacheDiffCanvas::Settings MakeCanvasSettings( - bool context_supports_distance_field_text, - int max_texture_size, - size_t max_texture_bytes) { - SkTextBlobCacheDiffCanvas::Settings settings; - settings.fContextSupportsDistanceFieldText = - context_supports_distance_field_text; - settings.fMaxTextureSize = max_texture_size; - settings.fMaxTextureBytes = max_texture_bytes; - return settings; -} - // Use half of the max int as the extent for the SkNoDrawCanvas. The correct // clip is applied to the canvas during serialization. const int kMaxExtent = std::numeric_limits<int>::max() >> 1; @@ -91,9 +79,7 @@ ComputeSurfaceProps(can_use_lcd_text), strike_server, std::move(color_space), - MakeCanvasSettings(context_supports_distance_field_text, - max_texture_size, - max_texture_bytes)) { + context_supports_distance_field_text) { DCHECK(serialize_cb_); }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 40b569c..81f1d73 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -579,7 +579,6 @@ "//chrome/browser/ntp_snippets/ntp_snippets_metrics.h", "//chrome/browser/profiles/profile_metrics.h", "//chrome/browser/translate/android/translate_utils.h", - "//chrome/browser/ui/android/device_dialog/bluetooth_scanning_prompt_android.h", "//chrome/browser/ui/android/infobars/infobar_android.h", ] } @@ -2642,7 +2641,6 @@ "java/src/org/chromium/chrome/browser/tab/TabState.java", "java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java", "java/src/org/chromium/chrome/browser/tab/TrustedCdn.java", - "java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java", "java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java", "java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java", "java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java index e06424e..5adcb6a 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java
@@ -72,6 +72,10 @@ /** Default value for whether to use menu options to launch interest management page. */ public static final boolean MANAGE_INTERESTS_ENABLED_DEFAULT = false; + private static final String MAXIMUM_GC_ATTEMPTS = "maximum_gc_attempts"; + /** Default value for the maximum number of times that the GC task can re-enqueue itself. */ + public static final long MAXIMUM_GC_ATTEMPTS_DEFAULT = 10; + private static final String NON_CACHED_MIN_PAGE_SIZE = "non_cached_min_page_size"; /** Default value for non cached minimum page size. */ public static final long NON_CACHED_MIN_PAGE_SIZE_DEFAULT = 5; @@ -216,7 +220,7 @@ (int) LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS_DEFAULT); } - /** return Whether to show context menu option to launch to customization page. */ + /** @return Whether to show context menu option to launch to customization page. */ @VisibleForTesting static boolean getManageInterestsEnabled() { return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( @@ -224,6 +228,14 @@ MANAGE_INTERESTS_ENABLED_DEFAULT); } + /** @return The maximum number of times that the GC task can re-enqueue itself. */ + @VisibleForTesting + static long getMaximumGcAttempts() { + return (long) ChromeFeatureList.getFieldTrialParamByFeatureAsInt( + ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, MAXIMUM_GC_ATTEMPTS, + (int) MAXIMUM_GC_ATTEMPTS_DEFAULT); + } + /** @return Used to decide where to place the more button. */ @VisibleForTesting static int getNonCachedMinPageSize() { @@ -355,6 +367,7 @@ FeedConfiguration.getLoggingImmediateContentThresholdMs()) .put(ConfigKey.MANAGE_INTERESTS_ENABLED, FeedConfiguration.getManageInterestsEnabled()) + .put(ConfigKey.MAXIMUM_GC_ATTEMPTS, FeedConfiguration.getMaximumGcAttempts()) .put(ConfigKey.NON_CACHED_MIN_PAGE_SIZE, FeedConfiguration.getNonCachedMinPageSize()) .put(ConfigKey.NON_CACHED_PAGE_SIZE, FeedConfiguration.getNonCachedPageSize())
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java index bf66412..6f3b264 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
@@ -38,17 +38,17 @@ @Override protected TabModelSelector createTabModelSelector() { - return new SingleTabModelSelector(this, this, false, false); + return new SingleTabModelSelector(this, this, false); } @Override protected Pair<? extends TabCreator, ? extends TabCreator> createTabCreators() { - return Pair.create(createTabCreator(false), createTabCreator(true)); + return Pair.create(createNormalTabCreator(), null); } /** Creates TabDelegates for opening new Tabs. */ - protected TabCreator createTabCreator(boolean incognito) { - return new TabDelegate(incognito); + protected TabCreator createNormalTabCreator() { + return new TabDelegate(false /* incognito */); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java index c39dd10c..a041d032 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
@@ -262,7 +262,7 @@ if (mSwipeType == OverscrollAction.PULL_TO_REFRESH) { mSwipeRefreshLayout.pull(yDelta); } else if (mSwipeType == OverscrollAction.HISTORY_NAVIGATION) { - mNavigationHandler.pull(xDelta); + if (mNavigationHandler != null) mNavigationHandler.pull(xDelta); } TraceEvent.end("SwipeRefreshHandler.pull"); } @@ -273,7 +273,7 @@ if (mSwipeType == OverscrollAction.PULL_TO_REFRESH) { mSwipeRefreshLayout.release(allowRefresh); } else if (mSwipeType == OverscrollAction.HISTORY_NAVIGATION) { - mNavigationHandler.release(allowRefresh); + if (mNavigationHandler != null) mNavigationHandler.release(allowRefresh); } TraceEvent.end("SwipeRefreshHandler.release"); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/OWNERS new file mode 100644 index 0000000..1b0fad7 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/OWNERS
@@ -0,0 +1,4 @@ +mheikal@chromium.org +hanxi@chromium.org + +file://components/background_task_scheduler/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java index f987e70d..0a989ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java
@@ -218,8 +218,10 @@ }); // Turn on the highlight for the currently highlighted bookmark. if (id.equals(mHighlightedBookmark)) { - ViewHighlighter.turnOnHighlight(holder.itemView, false); + ViewHighlighter.pulseHighlight(holder.itemView, false, 1); + clearHighlight(); } else { + // We need this in case we are change state during a pulse. ViewHighlighter.turnOffHighlight(holder.itemView); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialog.java index 28fb7c4e..8625679 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialog.java
@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.util.MathUtils; +import org.chromium.content_public.browser.bluetooth_scanning.Event; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.widget.TextViewWithClickableSpans; @@ -149,7 +150,7 @@ blockButton.setText(blockButtonText); blockButton.setEnabled(true); blockButton.setOnClickListener(v -> { - finishDialog(BluetoothScanningPermissionEvent.BLOCK); + finishDialog(Event.BLOCK); mDialog.setOnDismissListener(null); mDialog.dismiss(); }); @@ -158,7 +159,7 @@ allowButton.setText(allowButtonText); allowButton.setEnabled(true); allowButton.setOnClickListener(v -> { - finishDialog(BluetoothScanningPermissionEvent.ALLOW); + finishDialog(Event.ALLOW); mDialog.setOnDismissListener(null); mDialog.dismiss(); }); @@ -229,8 +230,7 @@ mDialog.addContentView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); - mDialog.setOnCancelListener( - dialog -> finishDialog(BluetoothScanningPermissionEvent.CANCELED)); + mDialog.setOnCancelListener(dialog -> finishDialog(Event.CANCELED)); Window window = mDialog.getWindow(); if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java index 39393a2..9ca664e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java
@@ -8,6 +8,7 @@ import android.app.ActivityManager; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; @@ -100,6 +101,12 @@ } @Override + public void onPictureInPictureModeChanged( + boolean isInPictureInPictureMode, Configuration newConfig) { + if (!isInPictureInPictureMode) this.finish(); + } + + @Override protected ActivityWindowAndroid createWindowAndroid() { return new ActivityWindowAndroid(this); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java index fd57101..ddecd26 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
@@ -26,8 +26,9 @@ * The URL schemes that should be displayed complete with path. */ public static final HashSet<String> UNSUPPORTED_SCHEMES_TO_SPLIT = - CollectionUtil.newHashSet(UrlConstants.FILE_SCHEME, UrlConstants.JAVASCRIPT_SCHEME, - UrlConstants.DATA_SCHEME, UrlConstants.CONTENT_SCHEME); + CollectionUtil.newHashSet(ContentUrlConstants.ABOUT_SCHEME, UrlConstants.DATA_SCHEME, + UrlConstants.FILE_SCHEME, UrlConstants.FTP_SCHEME, UrlConstants.INLINE_SCHEME, + UrlConstants.JAVASCRIPT_SCHEME, UrlConstants.CHROME_SCHEME); /** * URI schemes that ContentView can handle. *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java index 22e08e19..bef3135 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModel.java
@@ -24,12 +24,10 @@ private Tab mTab; private boolean mIsIncognito; - private boolean mBlockNewWindows; - SingleTabModel(Activity activity, boolean incognito, boolean blockNewWindows) { + SingleTabModel(Activity activity, boolean incognito) { mActivity = activity; mIsIncognito = incognito; - mBlockNewWindows = blockNewWindows; } /** @@ -39,21 +37,25 @@ void setTab(Tab tab) { Tab oldTab = mTab; mTab = tab; - assert mTab.isIncognito() == mIsIncognito; - if (mBlockNewWindows) nativePermanentlyBlockAllNewWindows(mTab); + if (tab != null) { + assert mTab.isIncognito() == mIsIncognito; - for (TabModelObserver observer : mObservers) { - observer.didAddTab(tab, TabLaunchType.FROM_LINK); - observer.didSelectTab(tab, TabSelectionType.FROM_USER, Tab.INVALID_TAB_ID); - } + for (TabModelObserver observer : mObservers) { + observer.didAddTab(tab, TabLaunchType.FROM_LINK); + observer.didSelectTab(tab, TabSelectionType.FROM_USER, Tab.INVALID_TAB_ID); + } - int state = ApplicationStatus.getStateForActivity(mActivity); - if (state == ActivityState.CREATED || state == ActivityState.STARTED - || state == ActivityState.RESUMED) { - mTab.show(TabSelectionType.FROM_USER); + int state = ApplicationStatus.getStateForActivity(mActivity); + if (state == ActivityState.CREATED || state == ActivityState.STARTED + || state == ActivityState.RESUMED) { + mTab.show(TabSelectionType.FROM_USER); + } } if (oldTab != null && oldTab.isInitialized()) { for (TabModelObserver observer : mObservers) { + observer.willCloseTab(oldTab, false); + } + for (TabModelObserver observer : mObservers) { observer.didCloseTab(oldTab.getId(), oldTab.isIncognito()); } oldTab.destroy(); @@ -93,11 +95,9 @@ @Override public boolean closeTab(Tab tab, boolean animate, boolean uponExit, boolean canUndo) { - if (mTab != null && mTab.getId() == tab.getId()) { - completeActivity(); - return true; - } - return false; + if (mTab == null || mTab.getId() != tab.getId()) return false; + closeTabAndFinish(); + return true; } @Override @@ -106,22 +106,20 @@ return closeTab(tab, animate, uponExit, canUndo); } - /** - * In webapps, calls finish on the activity, but keeps it in recents. In Document mode, - * finishes and removes from recents. We use mBlockNewWindows flag to distinguish the user - * of this model. - */ - private void completeActivity() { - if (mBlockNewWindows) { - mActivity.finish(); - } else { - ApiCompatibilityUtils.finishAndRemoveTask(mActivity); - } + private void closeTabAndFinish() { + setTab(null); + ApiCompatibilityUtils.finishAndRemoveTask(mActivity); } @Override public void closeMultipleTabs(List<Tab> tabs, boolean canUndo) { - completeActivity(); + if (mTab == null) return; + for (Tab tab : tabs) { + if (tab.getId() == mTab.getId()) { + closeTabAndFinish(); + return; + } + } } @Override @@ -131,7 +129,7 @@ @Override public void closeAllTabs(boolean allowDelegation, boolean uponExit) { - completeActivity(); + closeTabAndFinish(); } // Tab retrieval functions. @@ -211,8 +209,6 @@ mObservers.removeObserver(observer); } - private static native void nativePermanentlyBlockAllNewWindows(Tab nativeTabAndroid); - @Override public void openMostRecentlyClosedTab() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModelSelector.java index a995381..7099a7f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModelSelector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/SingleTabModelSelector.java
@@ -12,10 +12,23 @@ * Simple TabModelSelector that assumes that only a single TabModel exists at a time. */ public class SingleTabModelSelector extends TabModelSelectorBase { - public SingleTabModelSelector(Activity activity, TabCreatorManager tabCreatorManager, - boolean incognito, boolean blockNewWindows) { + public SingleTabModelSelector( + Activity activity, TabCreatorManager tabCreatorManager, boolean incognito) { super(tabCreatorManager); - initialize(incognito, new SingleTabModel(activity, incognito, blockNewWindows)); + initialize(incognito, new SingleTabModel(activity, incognito)); + + TabModelObserver tabModelObserver = new EmptyTabModelObserver() { + @Override + public void didCloseTab(int tabId, boolean incognito) { + // TabModelSelectorImpl handles the equivalent case of closing the last tab in + // TabModelSelectorImpl#requestToShowTab, which we don't have for this + // TabModelSelector, so we do it here instead. + if (getCurrentModel().getTabAt(0) == null) notifyChanged(); + } + }; + for (TabModel model : getModels()) { + model.addObserver(tabModelObserver); + } } public void setTab(Tab tab) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java index d0c5d9639..06ca83a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -360,9 +360,8 @@ (canUseSplashFromContentProvider && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && hasContentProviderForSplash(webApkPackageName)); - return create(WebApkConstants.WEBAPK_ID_PREFIX + webApkPackageName, url, scope, - new Icon(primaryIcon), new Icon(badgeIcon), new Icon(splashIcon), name, shortName, - displayMode, orientation, source, themeColor, backgroundColor, + return create(url, scope, new Icon(primaryIcon), new Icon(badgeIcon), new Icon(splashIcon), + name, shortName, displayMode, orientation, source, themeColor, backgroundColor, defaultBackgroundColor, isPrimaryIconMaskable, webApkPackageName, shellApkVersion, manifestUrl, manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName, forceNavigation, isSplashProvidedByWebApk, shareData, @@ -371,7 +370,6 @@ /** * Construct a {@link WebApkInfo} instance. - * @param id ID for the WebAPK. * @param url URL that the WebAPK should navigate to when launched. * @param scope Scope for the WebAPK. * @param primaryIcon Primary icon to show for the WebAPK. @@ -407,18 +405,17 @@ * @param shareData Shared information from the share intent. * @param webApkVersionCode WebAPK's version code. */ - public static WebApkInfo create(String id, String url, String scope, Icon primaryIcon, - Icon badgeIcon, Icon splashIcon, String name, String shortName, - @WebDisplayMode int displayMode, int orientation, int source, long themeColor, - long backgroundColor, int defaultBackgroundColor, boolean isPrimaryIconMaskable, - String webApkPackageName, int shellApkVersion, String manifestUrl, - String manifestStartUrl, @WebApkDistributor int distributor, - Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget, - String shareTargetActivityName, boolean forceNavigation, + public static WebApkInfo create(String url, String scope, Icon primaryIcon, Icon badgeIcon, + Icon splashIcon, String name, String shortName, @WebDisplayMode int displayMode, + int orientation, int source, long themeColor, long backgroundColor, + int defaultBackgroundColor, boolean isPrimaryIconMaskable, String webApkPackageName, + int shellApkVersion, String manifestUrl, String manifestStartUrl, + @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap, + ShareTarget shareTarget, String shareTargetActivityName, boolean forceNavigation, boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) { - if (id == null || url == null || manifestStartUrl == null || webApkPackageName == null) { + if (url == null || manifestStartUrl == null || webApkPackageName == null) { Log.e(TAG, - "Incomplete data provided: " + id + ", " + url + ", " + manifestStartUrl + ", " + "Incomplete data provided: " + url + ", " + manifestStartUrl + ", " + webApkPackageName); return null; } @@ -430,7 +427,7 @@ scope = ShortcutHelper.getScopeFromUrl(manifestStartUrl); } - return new WebApkInfo(id, url, scope, primaryIcon, badgeIcon, splashIcon, name, shortName, + return new WebApkInfo(url, scope, primaryIcon, badgeIcon, splashIcon, name, shortName, displayMode, orientation, source, themeColor, backgroundColor, defaultBackgroundColor, isPrimaryIconMaskable, webApkPackageName, shellApkVersion, manifestUrl, manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget, @@ -438,7 +435,7 @@ webApkVersionCode); } - protected WebApkInfo(String id, String url, String scope, Icon primaryIcon, Icon badgeIcon, + protected WebApkInfo(String url, String scope, Icon primaryIcon, Icon badgeIcon, Icon splashIcon, String name, String shortName, @WebDisplayMode int displayMode, int orientation, int source, long themeColor, long backgroundColor, int defaultBackgroundColor, boolean isPrimaryIconMaskable, String webApkPackageName, @@ -446,8 +443,9 @@ @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget, String shareTargetActivityName, boolean forceNavigation, boolean isSplashProvidedByWebApk, ShareData shareData, int webApkVersionCode) { - super(id, url, scope, primaryIcon, name, shortName, displayMode, orientation, source, - themeColor, backgroundColor, defaultBackgroundColor, false /* isIconGenerated */, + super(WebApkConstants.WEBAPK_ID_PREFIX + webApkPackageName, url, scope, primaryIcon, name, + shortName, displayMode, orientation, source, themeColor, backgroundColor, + defaultBackgroundColor, false /* isIconGenerated */, isPrimaryIconMaskable /* isIconAdaptive */, forceNavigation); mBadgeIcon = badgeIcon; mSplashIcon = splashIcon;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java index c8b2b63..5cdbbfe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java
@@ -127,7 +127,7 @@ shareParamsFileNames, shareParamsAccepts); int defaultBackgroundColor = SplashLayout.getDefaultBackgroundColor(appContext); - WebApkInfo info = WebApkInfo.create(mOldInfo.id(), mOldInfo.url(), scopeUrl, + WebApkInfo info = WebApkInfo.create(mOldInfo.url(), scopeUrl, new WebApkInfo.Icon(primaryIconBitmap), new WebApkInfo.Icon(badgeIconBitmap), null, name, shortName, displayMode, orientation, mOldInfo.source(), themeColor, backgroundColor, defaultBackgroundColor, isPrimaryIconMaskable,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 02bfd8c..30bcecdb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -832,8 +832,8 @@ } @Override - protected TabCreator createTabCreator(boolean incognito) { - return new WebappTabDelegate(incognito, mWebappInfo); + protected TabCreator createNormalTabCreator() { + return new WebappTabDelegate(false /* incognito */, mWebappInfo); } // We're temporarily disable CS on webapp since there are some issues. (http://crbug.com/471950)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java index 43ec1f5..ed335ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -112,6 +112,10 @@ public static WebappInfo create(Intent intent) { String id = idFromIntent(intent); String url = urlFromIntent(intent); + if (id == null || url == null) { + Log.e(TAG, "Incomplete data provided: " + id + ", " + url); + return null; + } String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON); String scope = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SCOPE); @@ -137,9 +141,11 @@ String name = nameFromIntent(intent); String shortName = shortNameFromIntent(intent); - return create(id, url, scope, new Icon(icon), name, shortName, displayMode, orientation, - source, themeColor, backgroundColor, isIconGenerated, isIconAdaptive, - forceNavigation); + int defaultBackgroundColor = + SplashLayout.getDefaultBackgroundColor(ContextUtils.getApplicationContext()); + return new WebappInfo(id, url, scope, new Icon(icon), name, shortName, displayMode, + orientation, source, themeColor, backgroundColor, defaultBackgroundColor, + isIconGenerated, isIconAdaptive, forceNavigation); } /** @@ -160,22 +166,6 @@ * @param forceNavigation Whether the webapp should navigate to {@link url} if the * webapp is already open. */ - public static WebappInfo create(String id, String url, String scope, Icon icon, String name, - String shortName, @WebDisplayMode int displayMode, int orientation, int source, - long themeColor, long backgroundColor, boolean isIconGenerated, boolean isIconAdaptive, - boolean forceNavigation) { - if (id == null || url == null) { - Log.e(TAG, "Incomplete data provided: " + id + ", " + url); - return null; - } - - int defaultBackgroundColor = - SplashLayout.getDefaultBackgroundColor(ContextUtils.getApplicationContext()); - return new WebappInfo(id, url, scope, icon, name, shortName, displayMode, orientation, - source, themeColor, backgroundColor, defaultBackgroundColor, isIconGenerated, - isIconAdaptive, forceNavigation); - } - protected WebappInfo(String id, String url, String scope, Icon icon, String name, String shortName, @WebDisplayMode int displayMode, int orientation, int source, long themeColor, long backgroundColor, int defaultBackgroundColor,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java index c87b5f88..d9cfb5de 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
@@ -34,6 +34,32 @@ private static final long FRAME_RATE = 60; /** + * Informs the PulseDrawable about whether it can continue pulsing, and specifies a callback to + * be run when the PulseDrawable is finished pulsing. + */ + public interface PulseEndAuthority { + /** + * Called at the end of one pulse animation, to decide whether the PulseDrawable can pulse + * again. + * + * @return True iff the PulseDrawable can continue pulsing. + */ + boolean canPulseAgain(); + } + + /** + * A PulseEndAuthority which allows the PulseDrawable to pulse forever. + */ + private static class EndlessPulser implements PulseEndAuthority { + // PulseEndAuthority implementation. + + @Override + public boolean canPulseAgain() { + return true; + } + } + + /** * An interface that does the actual drawing work for this {@link Drawable}. Not meant to be * stateful, as this could be shared across multiple instances of this drawable if it gets * copied or mutated. @@ -80,7 +106,7 @@ } private static Painter createCirclePainter(Bounds boundsFn) { - return new PulseDrawable.Painter() { + return new Painter() { @Override public void modifyDrawable(PulseDrawable drawable, float interpolation) { drawable.invalidateSelf(); @@ -93,7 +119,8 @@ float minRadiusPx = boundsFn.getMinRadiusPx(bounds); float maxRadiusPx = boundsFn.getMaxRadiusPx(bounds); - float radius = MathUtils.interpolate(minRadiusPx, maxRadiusPx, interpolation); + float radius = + MathUtils.interpolate(minRadiusPx, maxRadiusPx, 1.0f - interpolation); canvas.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), radius, paint); } @@ -103,13 +130,15 @@ /** * Creates a {@link PulseDrawable} that will fill the bounds with a pulsing color. * @param context The {@link Context} under which the drawable is created. + * @param pulseEndAuthority The {@link PulseEndAuthority} associated with this drawable. * @return A new {@link PulseDrawable} instance. */ - public static PulseDrawable createHighlight(Context context) { - PulseDrawable.Painter painter = new PulseDrawable.Painter() { + public static PulseDrawable createHighlight( + Context context, PulseEndAuthority pulseEndAuthority) { + Painter painter = new Painter() { @Override public void modifyDrawable(PulseDrawable drawable, float interpolation) { - drawable.setAlpha((int) MathUtils.interpolate(12, 75, 1.f - interpolation)); + drawable.setAlpha((int) MathUtils.interpolate(12, 75, interpolation)); } @Override @@ -119,15 +148,28 @@ } }; - return new PulseDrawable(context, new FastOutSlowInInterpolator(), painter); + return new PulseDrawable( + context, new FastOutSlowInInterpolator(), painter, pulseEndAuthority); + } + + /** + * Creates a {@link PulseDrawable} that will fill the bounds with a pulsing color. The {@link + * PulseDrawable} will continue pulsing forever (if this is not the desired behavior, please use + * {@link PulseEndAuthority}). + * @param context The {@link Context} under which the drawable is created. + * @return A new {@link PulseDrawable} instance. + */ + public static PulseDrawable createHighlight(Context context) { + return createHighlight(context, new EndlessPulser()); } /** * Creates a {@link PulseDrawable} that will draw a pulsing circle inside the bounds. * @param context The {@link Context} under which the drawable is created. + * @param pulseEndAuthority The {@link PulseEndAuthority} associated with this drawable. * @return A new {@link PulseDrawable} instance. */ - public static PulseDrawable createCircle(Context context) { + public static PulseDrawable createCircle(Context context, PulseEndAuthority pulseEndAuthority) { final int startingPulseRadiusPx = context.getResources().getDimensionPixelSize(R.dimen.iph_pulse_baseline_radius); @@ -142,7 +184,34 @@ return Math.min( startingPulseRadiusPx, Math.min(bounds.width(), bounds.height()) / 2.f); } - }); + }, pulseEndAuthority); + } + + /** + * Creates a {@link PulseDrawable} that will draw a pulsing circle inside the bounds. The {@link + * PulseDrawable} will continue pulsing forever (if this is not the desired behavior, please use + * {@link PulseEndAuthority}). + * @param context The {@link Context} under which the drawable is created. + * @return A new {@link PulseDrawable} instance. + */ + public static PulseDrawable createCircle(Context context) { + return createCircle(context, new EndlessPulser()); + } + + /** + * Creates a {@link PulseDrawable} that will draw a pulsing circle as large as possible inside + * the bounds. + * @param context The {@link Context} under which the drawable is created. + * @return A new {@link PulseDrawable} instance. + */ + public static PulseDrawable createCustomCircle( + Context context, Bounds boundsfn, PulseEndAuthority pulseEndAuthority) { + Painter painter = createCirclePainter(boundsfn); + + PulseDrawable drawable = new PulseDrawable(context, + PathInterpolatorCompat.create(.8f, 0.f, .6f, 1.f), painter, pulseEndAuthority); + drawable.setAlpha(76); + return drawable; } /** @@ -152,12 +221,7 @@ * @return A new {@link PulseDrawable} instance. */ public static PulseDrawable createCustomCircle(Context context, Bounds boundsfn) { - Painter painter = createCirclePainter(boundsfn); - - PulseDrawable drawable = new PulseDrawable( - context, PathInterpolatorCompat.create(.8f, 0.f, .6f, 1.f), painter); - drawable.setAlpha(76); - return drawable; + return createCustomCircle(context, boundsfn, new EndlessPulser()); } private final Runnable mNextFrame = new Runnable() { @@ -176,20 +240,30 @@ private PulseState mState; private boolean mMutated; private boolean mRunning; + private long mLastUpdateTime; + + private final PulseEndAuthority mPulseEndAuthority; /** * Creates a new {@link PulseDrawable} instance. * @param context The {@link Context} under which the drawable is created. * @param interpolator An {@link Interpolator} that defines how the pulse will fade in and out. * @param painter The {@link Painter} that will be responsible for drawing the pulse. + * @param pulseEndAuthority The {@link PulseEndAuthority} that is associated with this drawable. */ - private PulseDrawable(Context context, Interpolator interpolator, Painter painter) { - this(new PulseState(interpolator, painter)); + private PulseDrawable(Context context, Interpolator interpolator, Painter painter, + PulseEndAuthority pulseEndAuthority) { + this(new PulseState(interpolator, painter), pulseEndAuthority); setUseLightPulseColor(context.getResources(), false); } - private PulseDrawable(PulseState state) { + private PulseDrawable(PulseState state, PulseEndAuthority pulseEndAuthority) { mState = state; + mPulseEndAuthority = pulseEndAuthority; + } + + private PulseDrawable(PulseState state) { + this(state, new EndlessPulser()); } /** @@ -222,7 +296,10 @@ scheduleSelf(mNextFrame, SystemClock.uptimeMillis() + 1000 / FRAME_RATE); } else { mRunning = true; - if (mState.startTime == 0) mState.startTime = SystemClock.uptimeMillis(); + if (mState.startTime == 0) { + mState.startTime = SystemClock.uptimeMillis(); + mLastUpdateTime = mState.startTime; + } mNextFrame.run(); } } @@ -312,16 +389,25 @@ private void stepPulse() { long curTime = SystemClock.uptimeMillis(); + // If we are on a new pulse + if ((mLastUpdateTime - mState.startTime) / PULSE_DURATION_MS + != (curTime - mState.startTime) / PULSE_DURATION_MS) { + if (!(mPulseEndAuthority.canPulseAgain())) { + stop(); + return; + } + } long msIntoAnim = (curTime - mState.startTime) % PULSE_DURATION_MS; - float progress = ((float) msIntoAnim) / ((float) PULSE_DURATION_MS); - mState.progress = mState.interpolator.getInterpolation(progress); + float timeProgress = ((float) msIntoAnim) / ((float) PULSE_DURATION_MS); + mState.progress = mState.interpolator.getInterpolation(timeProgress); mState.painter.modifyDrawable(PulseDrawable.this, mState.progress); + mLastUpdateTime = curTime; } /** * The {@link ConstantState} subclass for this {@link PulseDrawable}. */ - private static final class PulseState extends ConstantState { + static final class PulseState extends ConstantState { // Current Paint State. /** The current color, including alpha, to draw. */ public int drawColor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseInterpolator.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseInterpolator.java index 169208d6..be8f108 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseInterpolator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseInterpolator.java
@@ -23,8 +23,8 @@ @Override public float getInterpolation(float input) { - if (input < 0.4f) return 0.f; - if (input < 0.8f) return mInterpolator.getInterpolation((input - 0.4f) / 0.4f); - return mInterpolator.getInterpolation(1.f - (input - 0.8f) / 0.2f); + if (input < 0.2) return mInterpolator.getInterpolation(input / 0.2f); + if (input < 0.6) return 1.f; + return mInterpolator.getInterpolation(1.f - (input - 0.6f) / 0.4f); } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java index 3267efa..4a7eb04 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.widget; +import static org.chromium.chrome.browser.widget.PulseDrawable.createCircle; + import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; @@ -28,12 +30,43 @@ public static final int IPH_MIN_DELAY_BETWEEN_TWO_HIGHLIGHTS = 200; /** + * Allows its associated PulseDrawable to pulse a specified number of times, then turns off the + * PulseDrawable highlight. + */ + public static class NumberPulser implements PulseDrawable.PulseEndAuthority { + private final View mView; + private int mNumPulsesRemaining; + + NumberPulser(View view, int numPulses) { + mView = view; + mNumPulsesRemaining = numPulses; + } + + @Override + public boolean canPulseAgain() { + mNumPulsesRemaining--; + if (mNumPulsesRemaining == 0) ViewHighlighter.turnOffHighlight(mView); + return mNumPulsesRemaining > 0; + } + } + + public static void pulseHighlight(View view, boolean circular, int numPulses) { + if (view == null) return; + + PulseDrawable pulseDrawable = circular + ? createCircle(view.getContext(), new NumberPulser(view, numPulses)) + : PulseDrawable.createHighlight( + view.getContext(), new NumberPulser(view, numPulses)); + + attachViewAsHighlight(view, pulseDrawable); + } + + /** * Create a highlight layer over the view. * @param view The view to be highlighted. * @param circular Whether the highlight should be a circle or rectangle. */ public static void turnOnHighlight(View view, boolean circular) { - if (view == null) return; PulseDrawable pulseDrawable = circular ? PulseDrawable.createCircle(view.getContext()) : PulseDrawable.createHighlight(view.getContext());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java index 1865425..0abcb909 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser; +import android.content.Intent; import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; @@ -17,9 +18,12 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.base.test.util.UrlUtils; +import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; +import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.util.FeatureUtilities; +import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.content_public.browser.test.util.JavaScriptUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -33,7 +37,11 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class JavaScriptEvalChromeTest { @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule = + ChromeActivityTestRule.forMainActivity(); + + @Rule + public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule(); private static final String JSTEST_URL = UrlUtils.encodeHtmlDataUri( "<html><head><script>" @@ -59,12 +67,28 @@ public void testJavaScriptEvalIsCorrectlyOrderedWithinOneTab() throws InterruptedException, TimeoutException { Tab tab1 = mActivityTestRule.getActivity().getActivityTab(); - ChromeTabUtils.newTabFromMenu( - InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity()); - Tab tab2 = mActivityTestRule.getActivity().getActivityTab(); - mActivityTestRule.loadUrl(JSTEST_URL); + Tab tab2; + if (mActivityTestRule.getActivity() instanceof ChromeTabbedActivity) { + ChromeTabUtils.newTabFromMenu( + InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity()); + tab2 = mActivityTestRule.getActivity().getActivityTab(); + mActivityTestRule.loadUrl(JSTEST_URL); + ChromeTabUtils.switchTabInCurrentTabModel( + mActivityTestRule.getActivity(), tab1.getId()); + } else { + // For now, only NoTouchMode should hit this path. + // In NoTouchMode, multiple tabs are only supported though CCT, so use a CCT instead of + // a second tab. + Assert.assertTrue(FeatureUtilities.isNoTouchModeEnabled()); + Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent( + InstrumentationRegistry.getTargetContext(), "about:blank"); + // NoTouchMode only allows CCT for 1p use-cases. + IntentHandler.addTrustedIntentExtras(intent); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + tab2 = mCustomTabActivityTestRule.getActivity().getActivityTab(); + mCustomTabActivityTestRule.loadUrl(JSTEST_URL); + } - ChromeTabUtils.switchTabInCurrentTabModel(mActivityTestRule.getActivity(), tab1.getId()); Assert.assertFalse("Tab didn't open", tab1 == tab2); JavaScriptUtils.executeJavaScriptAndWaitForResult(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ViewHighlighterTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ViewHighlighterTestUtils.java index bc27f18..96728a4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ViewHighlighterTestUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ViewHighlighterTestUtils.java
@@ -9,6 +9,7 @@ import android.view.View; import org.chromium.chrome.browser.widget.PulseDrawable; +import org.chromium.content_public.browser.test.util.CriteriaHelper; /** * Allows for testing of views which are highlightable via ViewHighlighter. @@ -40,4 +41,39 @@ public static boolean checkHighlightOff(View view) { return !(view.getBackground() instanceof LayerDrawable); } + + /** + * Checks that the view is highlighted with a pulse highlight. + * + * @param view The view of interest. + * @param timeoutDuration The timeout duration (should be set depending on the number of pulses + * and the pulse duration). + * @return True iff the view was highlighted, and then turned off. + */ + public static boolean checkHighlightPulse(View view, long timeoutDuration) { + try { + CriteriaHelper.pollUiThread(() + -> checkHighlightOn(view), + "Expected highlight to pulse on!", timeoutDuration, + CriteriaHelper.DEFAULT_POLLING_INTERVAL); + CriteriaHelper.pollUiThread(() + -> checkHighlightOff(view), + "Expected highlight to turn off!", timeoutDuration, + CriteriaHelper.DEFAULT_POLLING_INTERVAL); + } catch (AssertionError e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * Checks that the view is highlighted with a pulse highlight. + * + * @param view The view of interest. + * @return True iff the view was highlighted, and then turned off. + */ + public static boolean checkHighlightPulse(View view) { + return checkHighlightPulse(view, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL); + } } \ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java index ec4ea21..3d710ee1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java
@@ -10,7 +10,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.chromium.chrome.browser.ViewHighlighterTestUtils.checkHighlightOff; -import static org.chromium.chrome.browser.ViewHighlighterTestUtils.checkHighlightOn; +import static org.chromium.chrome.browser.ViewHighlighterTestUtils.checkHighlightPulse; import android.support.test.filters.MediumTest; import android.support.v7.widget.RecyclerView.ViewHolder; @@ -628,9 +628,9 @@ TestThreadUtils.runOnUiThreadBlocking(more::performClick); onView(withText("Show in folder")).perform(click()); - Assert.assertTrue( - "Expected bookmark row to be highlighted after clicking \"show in folder\"", - checkHighlightOn(testFolder)); + // Assert that the view pulses. + Assert.assertTrue("Expected bookmark row to pulse after clicking \"show in folder\"!", + checkHighlightPulse(testFolder)); // Enter search mode again. searchButton = mManager.getToolbarForTests().findViewById(R.id.search_menu_id); @@ -645,11 +645,9 @@ // Click "Show in folder" again. TestThreadUtils.runOnUiThreadBlocking(more::performClick); onView(withText("Show in folder")).perform(click()); - - // Check that the highlight is on. - Assert.assertTrue("Expected highlight to successfully come back on" - + " after clicking \"show in folder\" a 2nd time", - checkHighlightOn(testFolder)); + Assert.assertTrue( + "Expected bookmark row to pulse after clicking \"show in folder\" a 2nd time!", + checkHighlightPulse(testFolder)); } @Test @@ -691,8 +689,8 @@ "Expected list to scroll bookmark item into view", testFolderInList == null); Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, ((BookmarkFolderRow) testFolderInList.itemView).getTitle()); - Assert.assertTrue("Expected bookmark item to be highlighted after scrolling to it.", - checkHighlightOn(testFolderInList.itemView)); + Assert.assertTrue("Expected highlight to pulse on after scrolling to the item!", + checkHighlightPulse(testFolderInList.itemView)); } @Test @@ -726,9 +724,9 @@ View itemA = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_TITLE_A, ((BookmarkItemRow) itemA).getTitle()); - Assert.assertTrue( - "Expected bookmark item to be highlighted after opening it in new folder.", - checkHighlightOn(itemA)); + + Assert.assertTrue("Expected highlight to pulse after opening an item in another folder!", + checkHighlightPulse(itemA)); // Open mobile bookmarks folder, then go back to the subfolder. TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -737,12 +735,12 @@ }); RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); - itemA = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; + View itemASecondView = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_TITLE_A, - ((BookmarkItemRow) itemA).getTitle()); - Assert.assertTrue("Expected bookmark item to not be highlighted after " - + "exiting and re-entering folder.", - checkHighlightOff(itemA)); + ((BookmarkItemRow) itemASecondView).getTitle()); + Assert.assertTrue( + "Expected highlight to not be highlighted after exiting and re-entering folder!", + checkHighlightOff(itemASecondView)); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialogTest.java index 3045a1a..ae681731 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialogTest.java
@@ -24,6 +24,7 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.security_state.ConnectionSecurityLevel; +import org.chromium.content_public.browser.bluetooth_scanning.Event; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -120,7 +121,6 @@ dialog.cancel(); - CriteriaHelper.pollUiThread(Criteria.equals( - BluetoothScanningPermissionEvent.CANCELED, () -> mFinishedEventType)); + CriteriaHelper.pollUiThread(Criteria.equals(Event.CANCELED, () -> mFinishedEventType)); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java index 8c741fc..2062db6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java
@@ -21,11 +21,14 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MinAndroidSdkLevel; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector; +import org.chromium.chrome.browser.tabmodel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; @@ -37,7 +40,8 @@ @MinAndroidSdkLevel(Build.VERSION_CODES.N) public class CloseTabDirectActionHandlerTest { @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule = + ChromeActivityTestRule.forMainActivity(); private TabModelSelector mSelector; private CloseTabDirectActionHandler mHandler; @@ -46,7 +50,8 @@ public void setUp() throws Exception { // Setup an activity with two blank tabs. mActivityTestRule.startMainActivityOnBlankPage(); - mActivityTestRule.loadUrlInNewTab("about:blank"); + mActivityTestRule.loadUrlInNewTab( + "about:blank", false /* incognito */, TabLaunchType.FROM_CHROME_UI); mSelector = mActivityTestRule.getActivity().getTabModelSelector(); mHandler = new CloseTabDirectActionHandler(mSelector); @@ -62,12 +67,16 @@ // Close current tab Tab initiallyCurrent = mSelector.getCurrentTab(); performAction("close_tab"); - assertEquals(1, mSelector.getTotalTabCount()); assertThat( mSelector.getCurrentTab(), Matchers.not(Matchers.sameInstance(initiallyCurrent))); - // Close last tab - performAction("close_tab"); + if (!(mSelector instanceof SingleTabModelSelector)) { + assertEquals(1, mSelector.getTotalTabCount()); + // Close last tab + performAction("close_tab"); + } else { + assertEquals(0, mSelector.getTotalTabCount()); + } // No tabs are left, so actions aren't available anymore. assertThat(getDirectActions(), Matchers.empty());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java index 1961cdd..786b0520 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -20,6 +20,8 @@ import android.support.test.filters.SmallTest; import android.test.mock.MockPackageManager; +import androidx.browser.customtabs.CustomTabsIntent; + import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -31,9 +33,9 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.DisableIf; -import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.IntentHandler; +import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.chrome.browser.instantapps.InstantAppsHandler; @@ -41,6 +43,7 @@ import org.chromium.chrome.browser.tab.TabRedirectHandler; import org.chromium.chrome.browser.webapps.WebappInfo; import org.chromium.chrome.browser.webapps.WebappScopePolicy; +import org.chromium.chrome.test.util.browser.WebappTestHelper; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.ui.base.PageTransition; import org.chromium.webapk.lib.common.WebApkConstants; @@ -51,8 +54,6 @@ import java.util.List; import java.util.regex.Pattern; -import androidx.browser.customtabs.CustomTabsIntent; - /** * Instrumentation tests for {@link ExternalNavigationHandler}. */ @@ -1566,8 +1567,9 @@ } private static WebappInfo newWebappInfoFromScope(String scope) { - return WebappInfo.create("", "", scope, null, null, null, WebDisplayMode.STANDALONE, 0, 0, - 0, 0, false, false, false); + Intent webappIntent = WebappTestHelper.createMinimalWebappIntent("" /* id */, "" /* url */); + webappIntent.putExtra(ShortcutHelper.EXTRA_SCOPE, scope); + return WebappInfo.create(webappIntent); } private static class IntentActivity {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java index 5e451e8..de505e7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java
@@ -58,6 +58,8 @@ FeedConfiguration.getLoggingImmediateContentThresholdMs()); Assert.assertEquals(FeedConfiguration.MANAGE_INTERESTS_ENABLED_DEFAULT, FeedConfiguration.getManageInterestsEnabled()); + Assert.assertEquals(FeedConfiguration.MAXIMUM_GC_ATTEMPTS_DEFAULT, + FeedConfiguration.getMaximumGcAttempts()); Assert.assertEquals(FeedConfiguration.NON_CACHED_MIN_PAGE_SIZE_DEFAULT, FeedConfiguration.getNonCachedMinPageSize()); Assert.assertEquals(FeedConfiguration.NON_CACHED_PAGE_SIZE_DEFAULT, @@ -211,6 +213,16 @@ @Feature({"Feed"}) @CommandLineFlags. Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group", + "force-fieldtrial-params=Trial.Group:maximum_gc_attempts/5"}) + public void + testMaximumGcAttempts() { + Assert.assertEquals(5, FeedConfiguration.getMaximumGcAttempts()); + } + + @Test + @Feature({"Feed"}) + @CommandLineFlags. + Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group", "force-fieldtrial-params=Trial.Group:non_cached_min_page_size/100"}) public void testNonCachedMinPageSize() { @@ -356,6 +368,8 @@ ConfigKey.LOGGING_IMMEDIATE_CONTENT_THRESHOLD_MS, 0l)); Assert.assertFalse( configuration.getValueOrDefault(ConfigKey.MANAGE_INTERESTS_ENABLED, true)); + Assert.assertEquals((long) FeedConfiguration.MAXIMUM_GC_ATTEMPTS_DEFAULT, + configuration.getValueOrDefault(ConfigKey.MAXIMUM_GC_ATTEMPTS, 0l)); Assert.assertEquals((long) FeedConfiguration.NON_CACHED_MIN_PAGE_SIZE_DEFAULT, configuration.getValueOrDefault(ConfigKey.NON_CACHED_MIN_PAGE_SIZE, 0)); Assert.assertEquals((long) FeedConfiguration.NON_CACHED_PAGE_SIZE_DEFAULT,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java index ffdc964..5eff0966 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandlerTest.java
@@ -4,10 +4,12 @@ package org.chromium.chrome.browser.login; +import android.content.Intent; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -17,11 +19,18 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.IntentHandler; +import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; +import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils; import org.chromium.chrome.browser.tab.SadTab; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabLaunchType; +import org.chromium.chrome.browser.util.FeatureUtilities; +import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -38,7 +47,12 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class ChromeHttpAuthHandlerTest { @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule = + ChromeActivityTestRule.forMainActivity(); + + @Rule + public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule(); + private EmbeddedTestServer mTestServer; @Before @@ -74,8 +88,10 @@ public void authDialogDismissOnTabSwitched() throws Exception { ChromeHttpAuthHandler handler = triggerAuth(); verifyAuthDialogVisibility(handler, true); - ChromeTabUtils.newTabFromMenu( - InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity()); + TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity().getTabCreator(false).launchUrl( + "about:blank", TabLaunchType.FROM_CHROME_UI)); verifyAuthDialogVisibility(handler, false); } @@ -94,8 +110,20 @@ @Restriction(Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void authDialogSuppressedOnBackgroundTab() throws Exception { Tab firstTab = mActivityTestRule.getActivity().getActivityTab(); - ChromeTabUtils.newTabFromMenu( - InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity()); + if (mActivityTestRule.getActivity() instanceof ChromeTabbedActivity) { + ChromeTabUtils.newTabFromMenu( + InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity()); + } else { + // For now, only NoTouchMode should hit this path. + // In NoTouchMode, multiple tabs are only supported though CCT, so use a CCT instead of + // a second tab. + Assert.assertTrue(FeatureUtilities.isNoTouchModeEnabled()); + Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent( + InstrumentationRegistry.getTargetContext(), "about:blank"); + // NoTouchMode only allows CCT for 1p use-cases. + IntentHandler.addTrustedIntentExtras(intent); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + } // If the first tab was closed due to OOM, then just exit the test. if (TestThreadUtils.runOnUiThreadBlocking( () -> firstTab.isClosing() || SadTab.isShowing(firstTab))) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java index 5f9a5e4..308ac67 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -9,7 +9,6 @@ import android.annotation.SuppressLint; import android.os.Build; import android.os.SystemClock; -import android.support.annotation.Nullable; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.filters.SmallTest; @@ -724,58 +723,6 @@ } } - // TODO(bauerb): Move this to a Robolectric test. - @Test - @SmallTest - @SkipCommandLineParameterization - public void testOriginSpan() { - verifyOriginSpan("", null, ""); - verifyOriginSpan("https:", null, "https:"); - verifyOriginSpan("about:blank", null, "about:blank"); - - verifyOriginSpan("chrome://flags", null, "chrome://flags"); - verifyOriginSpan("chrome://flags", "/?egads", "chrome://flags/?egads"); - - verifyOriginSpan("www.google.com", null, "www.google.com"); - verifyOriginSpan("www.google.com", null, "www.google.com/"); - verifyOriginSpan("www.google.com", "/?q=blah", "www.google.com/?q=blah"); - - verifyOriginSpan("https://www.google.com", null, "https://www.google.com"); - verifyOriginSpan("https://www.google.com", null, "https://www.google.com/"); - verifyOriginSpan("https://www.google.com", "/?q=blah", "https://www.google.com/?q=blah"); - - // crbug.com/414990 - String testUrl = "https://disneyworld.disney.go.com/special-offers/" - + "?CMP=KNC-WDW_FY15_DOM_Q1RO_BR_Gold_SpOffer|G|4141300.RR.AM.01.47" - + "&keyword_id=s6JyxRifG_dm|walt%20disney%20world|37174067873|e|1540wwa14043"; - verifyOriginSpan("https://disneyworld.disney.go.com", - "/special-offers/?CMP=KNC-WDW_FY15_DOM_Q1RO_BR_Gold_SpOffer|G|4141300.RR.AM.01.47" - + "&keyword_id=s6JyxRifG_dm|walt%20disney%20world|37174067873|e|" - + "1540wwa14043", - testUrl); - - // crbug.com/415387 - verifyOriginSpan("ftp://example.com", "/ftp.html", "ftp://example.com/ftp.html"); - - // crbug.com/447416 - verifyOriginSpan("file:///dev/blah", null, "file:///dev/blah"); - verifyOriginSpan( - "javascript:window.alert('hello');", null, "javascript:window.alert('hello');"); - verifyOriginSpan("data:text/html;charset=utf-8,Page%201", null, - "data:text/html;charset=utf-8,Page%201"); - } - - private void verifyOriginSpan( - String expectedOrigin, @Nullable String expectedOriginSuffix, String url) { - UrlBarData urlBarData = UrlBarData.forUrl(url); - String displayText = urlBarData.displayText.toString(); - Assert.assertEquals(expectedOriginSuffix == null ? expectedOrigin - : expectedOrigin + expectedOriginSuffix, - displayText); - Assert.assertEquals(expectedOrigin, - displayText.substring(urlBarData.originStartIndex, urlBarData.originEndIndex)); - } - @Test @MediumTest @Feature({"Omnibox"})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java index 51b00d80..959a215 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkActivityTest.java
@@ -21,13 +21,10 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; -import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.DeferredStartupHandler; -import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.ShortcutSource; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid; @@ -37,11 +34,11 @@ import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeTabUtils; +import org.chromium.chrome.test.util.browser.WebApkInfoBuilder; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.JavaScriptUtils; -import org.chromium.content_public.common.ScreenOrientationValues; import org.chromium.webapk.lib.common.WebApkConstants; /** Tests for WebApkActivity. */ @@ -230,16 +227,10 @@ } private WebApkInfo createWebApkInfo(String startUrl, String scopeUrl) { - return WebApkInfo.create(TEST_WEBAPK_ID, startUrl, scopeUrl, null /* primaryIcon */, - null /* badgeIcon */, null /* splashIcon */, "" /* name */, "" /* short_name */, - WebDisplayMode.STANDALONE, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING /* themeColor */, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING /* backgroundColor */, - 0 /* defaultBackgroundColor */, false /* isPrimaryIconMaskable */, - TEST_WEBAPK_PACKAGE_NAME, 10 /* packageVersion */, "" /* manifestURL */, - "" /* manifestStartURL */, WebApkInfo.WebApkDistributor.BROWSER, null, null, - null /*shareTargetActivityName*/, false /* forceNavigation */, - false /* isSplashProvidedByWebApk */, null /* shareData */, 1 /* apkVersionCode */); + WebApkInfoBuilder webApkInfoBuilder = + new WebApkInfoBuilder(TEST_WEBAPK_PACKAGE_NAME, startUrl); + webApkInfoBuilder.setScope(scopeUrl); + return webApkInfoBuilder.build(); } private String getTestServerUrl(String relativeUrl) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java index 1f6f644..e5b8f3c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
@@ -22,12 +22,11 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.util.browser.WebApkInfoBuilder; import org.chromium.chrome.test.util.browser.WebappTestPage; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.test.EmbeddedTestServerRule; -import java.util.HashMap; - /** * Tests the WebApkUpdateDataFetcher. */ @@ -112,13 +111,11 @@ final String manifestUrl, final WebApkUpdateDataFetcher.Observer observer) { final WebApkUpdateDataFetcher fetcher = new WebApkUpdateDataFetcher(); PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { - WebApkInfo oldInfo = WebApkInfo.create("", "", scopeUrl, null, null, null, null, null, - -1, -1, -1, -1, -1, -1, false, "random.package", -1, manifestUrl, "", - WebApkInfo.WebApkDistributor.BROWSER, new HashMap<String, String>(), null, - null /*shareTargetActivityName*/, false /* forceNavigation */, - false /* isSplashProvidedByWebApk */, null /* shareData */, - 1 /* webApkVersionCode */); - fetcher.start(mTab, oldInfo, observer); + WebApkInfoBuilder oldWebApkInfoBuilder = + new WebApkInfoBuilder("random.package", "" /* url */); + oldWebApkInfoBuilder.setScope(scopeUrl); + oldWebApkInfoBuilder.setManifestUrl(manifestUrl); + fetcher.start(mTab, oldWebApkInfoBuilder.build(), observer); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java index c75647d..60d2a22 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -158,7 +158,7 @@ final TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(waiter, storage); TestThreadUtils.runOnUiThreadBlocking(() -> { - WebApkInfo info = WebApkInfo.create(WEBAPK_ID, "", creationData.scope, null, null, null, + WebApkInfo info = WebApkInfo.create("", creationData.scope, null, null, null, creationData.name, creationData.shortName, creationData.displayMode, creationData.orientation, 0, creationData.themeColor, creationData.backgroundColor, 0, creationData.isPrimaryIconMaskable, "",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java index 87481abd..94616eea 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -26,21 +26,19 @@ import org.chromium.base.test.util.RetryOnFailure; import org.chromium.base.test.util.ScalableTimeout; import org.chromium.base.test.util.UrlUtils; -import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.DeferredStartupHandler; import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.ShortcutSource; import org.chromium.chrome.browser.tab.TabIdManager; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.MultiActivityTestRule; import org.chromium.chrome.test.util.ApplicationTestUtils; +import org.chromium.chrome.test.util.browser.WebappTestHelper; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; -import org.chromium.content_public.common.ScreenOrientationValues; /** * Tests that WebappActivities are launched correctly. @@ -75,7 +73,7 @@ + "ggR0lNUFeBDhcAAAAMSURBVAjXY2AUawEAALcAnI/TkI8AAAAASUVORK5CYII="; private Intent createIntent(String id, String url, String title, String icon, boolean addMac) { - Intent intent = new Intent(); + Intent intent = WebappTestHelper.createMinimalWebappIntent(id, url); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setPackage(InstrumentationRegistry.getTargetContext().getPackageName()); intent.setAction(WebappLauncherActivity.ACTION_START_WEBAPP); @@ -86,13 +84,8 @@ intent.putExtra(ShortcutHelper.EXTRA_MAC, mac); } - WebappInfo webappInfo = WebappInfo.create(id, url, null, new WebappInfo.Icon(icon), title, - null, WebDisplayMode.STANDALONE, ScreenOrientationValues.PORTRAIT, - ShortcutSource.UNKNOWN, ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */); - webappInfo.setWebappIntentExtras(intent); - + intent.putExtra(ShortcutHelper.EXTRA_ICON, icon); + intent.putExtra(ShortcutHelper.EXTRA_NAME, title); return intent; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java index 54c9d4a..47ebea0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.webapps; +import android.content.Intent; import android.support.test.filters.MediumTest; import android.support.test.rule.UiThreadTestRule; @@ -16,6 +17,9 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Feature; import org.chromium.blink_public.platform.WebDisplayMode; +import org.chromium.chrome.browser.ShortcutHelper; +import org.chromium.chrome.test.util.browser.WebApkInfoBuilder; +import org.chromium.chrome.test.util.browser.WebappTestHelper; import org.chromium.components.security_state.ConnectionSecurityLevel; import org.chromium.content_public.browser.test.NativeLibraryTestRule; @@ -128,17 +132,15 @@ private static WebappInfo createWebappInfo(String webappStartUrlOrScopeUrl, @WebappScopePolicy.Type int scopePolicy, @WebDisplayMode int displayMode) { - return scopePolicy == WebappScopePolicy.Type.LEGACY - ? WebappInfo.create("", webappStartUrlOrScopeUrl, null, null, null, null, - displayMode, 0, 0, 0, 0, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */) - : WebApkInfo.create( - "", "", webappStartUrlOrScopeUrl, null, null, null, null, null, displayMode, - 0, 0, 0, 0, 0, false, "", 0, null, "", WebApkInfo.WebApkDistributor.BROWSER, - null, null, null /*shareTargetActivityName*/, false /* forceNavigation */, - false /* isSplashProvidedByWebApk */, null /* shareData */, - 1 /* webApkVersionCode */ - - ); + if (scopePolicy == WebappScopePolicy.Type.LEGACY) { + Intent webappIntent = WebappTestHelper.createMinimalWebappIntent( + "" /* id */, webappStartUrlOrScopeUrl); + webappIntent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, displayMode); + return WebappInfo.create(webappIntent); + } + WebApkInfoBuilder webApkInfoBuilder = new WebApkInfoBuilder("random.package", "" /* url */); + webApkInfoBuilder.setScope(webappStartUrlOrScopeUrl); + webApkInfoBuilder.setDisplayMode(displayMode); + return webApkInfoBuilder.build(); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java index 0f62e8c..242ca32 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.omnibox; +import android.support.annotation.Nullable; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -18,7 +20,7 @@ @Config(manifest = Config.NONE) public class UrlBarDataTest { @Test - public void forUrlAndText_nonHttpOrHttps() { + public void forUrlAndText_nonHttpOrHttps_DisplayTextDiffersFromUrl() { UrlBarData data = UrlBarData.forUrlAndText("data:text/html,blah,blah", "data:text/html,blah", "BLAH"); Assert.assertEquals("data:text/html,blah,blah", data.url); @@ -27,4 +29,76 @@ // Ensure that the end index is the length of the display text and not the URL. Assert.assertEquals(data.displayText.length(), data.originEndIndex); } + + @Test + public void forUrlAndText_aboutUri_NoSlashes() { + final String aboutUrl = "about:blank#verylongurl.totallylegit.notsuspicious.url.com"; + UrlBarData data = UrlBarData.forUrlAndText(aboutUrl, aboutUrl); + Assert.assertEquals(aboutUrl, data.url); + Assert.assertEquals(aboutUrl, data.displayText); + Assert.assertEquals(0, data.originStartIndex); + // Ensure that the end index is the length of the display text and not the URL. + Assert.assertEquals(aboutUrl.length(), data.originEndIndex); + } + + @Test + public void forUrlAndText_aboutUri_WithSlashes() { + final String aboutUrl = "about://blank#verylongurl.totallylegit.notsuspicious.url.com"; + UrlBarData data = UrlBarData.forUrlAndText(aboutUrl, aboutUrl); + Assert.assertEquals(aboutUrl, data.url); + Assert.assertEquals(aboutUrl, data.displayText); + Assert.assertEquals(0, data.originStartIndex); + // Ensure that the end index is the length of the display text and not the URL. + Assert.assertEquals(aboutUrl.length(), data.originEndIndex); + } + + @Test + public void originSpans() { + verifyOriginSpan("", null, ""); + verifyOriginSpan("https:", null, "https:"); + verifyOriginSpan("about:blank", null, "about:blank"); + + verifyOriginSpan("chrome://flags", null, "chrome://flags"); + verifyOriginSpan("chrome://flags/?egads", null, "chrome://flags/?egads"); + + verifyOriginSpan("www.google.com", null, "www.google.com"); + verifyOriginSpan("www.google.com", null, "www.google.com/"); + verifyOriginSpan("www.google.com", "/?q=blah", "www.google.com/?q=blah"); + + verifyOriginSpan("https://www.google.com", null, "https://www.google.com"); + verifyOriginSpan("https://www.google.com", null, "https://www.google.com/"); + verifyOriginSpan("https://www.google.com", "/?q=blah", "https://www.google.com/?q=blah"); + + // crbug.com/414990 + String testUrl = "https://disneyworld.disney.go.com/special-offers/" + + "?CMP=KNC-WDW_FY15_DOM_Q1RO_BR_Gold_SpOffer|G|4141300.RR.AM.01.47" + + "&keyword_id=s6JyxRifG_dm|walt%20disney%20world|37174067873|e|1540wwa14043"; + verifyOriginSpan("https://disneyworld.disney.go.com", + "/special-offers/?CMP=KNC-WDW_FY15_DOM_Q1RO_BR_Gold_SpOffer|G|4141300.RR.AM.01.47" + + "&keyword_id=s6JyxRifG_dm|walt%20disney%20world|37174067873|e|" + + "1540wwa14043", + testUrl); + + // crbug.com/415387 + verifyOriginSpan("ftp://example.com/ftp.html", null, "ftp://example.com/ftp.html"); + + // crbug.com/447416 + verifyOriginSpan("file:///dev/blah", null, "file:///dev/blah"); + verifyOriginSpan( + "javascript:window.alert('hello');", null, "javascript:window.alert('hello');"); + verifyOriginSpan("data:text/html;charset=utf-8,Page%201", null, + "data:text/html;charset=utf-8,Page%201"); + } + + private void verifyOriginSpan( + String expectedOrigin, @Nullable String expectedOriginSuffix, String url) { + UrlBarData urlBarData = UrlBarData.forUrl(url); + String displayText = urlBarData.displayText.toString(); + Assert.assertEquals(expectedOriginSuffix == null ? expectedOrigin + : expectedOrigin + expectedOriginSuffix, + displayText); + Assert.assertEquals("Origina start index, end index did not generate expected origin", + expectedOrigin, + displayText.substring(urlBarData.originStartIndex, urlBarData.originEndIndex)); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java index 52fadaa9..669b7f4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
@@ -82,7 +82,7 @@ } @Test - public void setUrlData_ScrollStateForNonHttpOrHttps() { + public void setUrlData_ScrollStateForDataUrl() { PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS); UrlBarMediator mediator = new UrlBarMediator(model); @@ -98,6 +98,22 @@ } @Test + public void setUrlData_ScrollStateForAboutUrl() { + PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS); + UrlBarMediator mediator = new UrlBarMediator(model); + + String displayText = "about:blank#verylongurl.totallylegit.notsuspicious.url.com"; + UrlBarData data = UrlBarData.create( + displayText, spannable(displayText), 0, displayText.length(), null); + Assert.assertTrue(mediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD, + UrlBarCoordinator.SelectionState.SELECT_ALL)); + + // The scroll state should be overridden to SCROLL_TO_BEGINNING for file-type schemes. + Assert.assertEquals(UrlBar.ScrollType.SCROLL_TO_BEGINNING, + model.get(UrlBarProperties.TEXT_STATE).scrollType); + } + + @Test public void urlDataComparison_equals() { Assert.assertTrue(UrlBarMediator.isNewTextEquivalentToExistingText(null, null));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java index 4438bc56..3c8b40b7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -358,7 +358,7 @@ if (manifestData == null) return null; final String kPackageName = "org.random.webapk"; - return WebApkInfo.create(getWebApkId(kPackageName), "", manifestData.scopeUrl, + return WebApkInfo.create("", manifestData.scopeUrl, new WebApkInfo.Icon(manifestData.primaryIcon), new WebApkInfo.Icon(manifestData.badgeIcon), null, manifestData.name, manifestData.shortName, manifestData.displayMode, manifestData.orientation, -1,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java index 7425ce4..43c6fa8 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java
@@ -15,6 +15,7 @@ import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.ShortcutSource; +import org.chromium.chrome.test.util.browser.WebappTestHelper; import org.chromium.content_public.common.ScreenOrientationValues; /** @@ -30,11 +31,10 @@ String shortName = "name"; String url = "about:blank"; - WebappInfo info = WebappInfo.create(id, url, null, null, name, shortName, - WebDisplayMode.STANDALONE, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */); + Intent intent = WebappTestHelper.createMinimalWebappIntent(id, url); + intent.putExtra(ShortcutHelper.EXTRA_NAME, name); + intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName); + WebappInfo info = WebappInfo.create(intent); Assert.assertNotNull(info); } @@ -45,11 +45,10 @@ String shortName = "name"; String url = "http://google.com"; - WebappInfo info = WebappInfo.create(id, url, null, null, name, shortName, - WebDisplayMode.STANDALONE, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */); + Intent intent = WebappTestHelper.createMinimalWebappIntent(id, url); + intent.putExtra(ShortcutHelper.EXTRA_NAME, name); + intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName); + WebappInfo info = WebappInfo.create(intent); Assert.assertNotNull(info); } @@ -124,16 +123,16 @@ @Test public void testDisplayModeAndOrientationAndSource() { - String id = "webapp id"; String name = "longName"; String shortName = "name"; - String url = "http://money.cnn.com"; - WebappInfo info = WebappInfo.create(id, url, null, null, name, shortName, - WebDisplayMode.FULLSCREEN, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */); + Intent intent = createIntentWithUrlAndId(); + intent.putExtra(ShortcutHelper.EXTRA_NAME, name); + intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName); + intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.FULLSCREEN); + intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.DEFAULT); + intent.putExtra(ShortcutHelper.EXTRA_SOURCE, ShortcutSource.UNKNOWN); + WebappInfo info = WebappInfo.create(intent); Assert.assertEquals(WebDisplayMode.FULLSCREEN, info.displayMode()); Assert.assertEquals(ScreenOrientationValues.DEFAULT, info.orientation()); Assert.assertEquals(ShortcutSource.UNKNOWN, info.source()); @@ -141,33 +140,30 @@ @Test public void testNormalColors() { - String id = "webapp id"; String name = "longName"; String shortName = "name"; - String url = "http://money.cnn.com"; long themeColor = 0xFF00FF00L; long backgroundColor = 0xFF0000FFL; - WebappInfo info = WebappInfo.create(id, url, null, null, name, shortName, - WebDisplayMode.STANDALONE, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, - themeColor, backgroundColor, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */); + Intent intent = createIntentWithUrlAndId(); + intent.putExtra(ShortcutHelper.EXTRA_NAME, name); + intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName); + intent.putExtra(ShortcutHelper.EXTRA_THEME_COLOR, themeColor); + intent.putExtra(ShortcutHelper.EXTRA_BACKGROUND_COLOR, backgroundColor); + WebappInfo info = WebappInfo.create(intent); Assert.assertEquals(themeColor, info.themeColor()); Assert.assertEquals(backgroundColor, info.backgroundColor()); } @Test public void testInvalidOrMissingColors() { - String id = "webapp id"; String name = "longName"; String shortName = "name"; - String url = "http://money.cnn.com"; - WebappInfo info = WebappInfo.create(id, url, null, null, name, shortName, - WebDisplayMode.STANDALONE, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, - ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, false /* isIconGenerated */, - false /* isIconAdaptive */, false /* forceNavigation */); + Intent intent = createIntentWithUrlAndId(); + intent.putExtra(ShortcutHelper.EXTRA_NAME, name); + intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName); + WebappInfo info = WebappInfo.create(intent); Assert.assertEquals(ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, info.themeColor()); Assert.assertEquals( ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, info.backgroundColor()); @@ -337,9 +333,7 @@ */ @Test public void testForceNavigationNotSpecified() { - Intent intent = new Intent(); - intent.putExtra(ShortcutHelper.EXTRA_ID, "webapp_id"); - intent.putExtra(ShortcutHelper.EXTRA_URL, "about:blank"); + Intent intent = createIntentWithUrlAndId(); Assert.assertFalse(WebappInfo.create(intent).shouldForceNavigation()); }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java index 22b026f..811476e 100644 --- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java +++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
@@ -287,7 +287,7 @@ } @Override - protected TabCreator createTabCreator(boolean incognito) { - return new TouchlessTabCreator(this, getWindowAndroid(), incognito); + protected TabCreator createNormalTabCreator() { + return new TouchlessTabCreator(this, getWindowAndroid(), false /* incognito */); } }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cb2ddee..d374ef0 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -305,6 +305,9 @@ <message name="IDS_HOVER_CARD_FILE_URL_SOURCE" desc="The text to be displayed in the source line of a hover card when viewing a local file."> local or shared file </message> + <message name="IDS_HOVER_CARD_CRASHED_TITLE" desc="The title text to display on a hover card when a tab has crashed without loading."> + Crashed. + </message> <!-- History Strings --> <message name="IDS_HISTORY_SEARCH_PROMPT" desc="Placeholder text/label for the search input field in the history page">
diff --git a/chrome/app/global_media_controls_strings.grdp b/chrome/app/global_media_controls_strings.grdp index 4ee94f6..10cdb83 100644 --- a/chrome/app/global_media_controls_strings.grdp +++ b/chrome/app/global_media_controls_strings.grdp
@@ -2,6 +2,6 @@ <!-- Global Media Controls-specific strings (included from generated_resources.grd). --> <grit-part> <message name="IDS_GLOBAL_MEDIA_CONTROLS_ICON_TOOLTIP_TEXT" desc="Tooltip for the Global Media Controls icon, which appears in the toolbar. The tooltip appears on mouseover of the icon."> - Global Media Controls + Control your music, videos, and more </message> </grit-part>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 4c8b6c7..2cd335e 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2682,8 +2682,6 @@ "android/webapps/add_to_homescreen_data_fetcher.h", "android/webapps/add_to_homescreen_manager.cc", "android/webapps/add_to_homescreen_manager.h", - "android/webapps/single_tab_mode_tab_helper.cc", - "android/webapps/single_tab_mode_tab_helper.h", "android/webapps/webapk_ukm_recorder.cc", "android/webapps/webapk_ukm_recorder.h", "android/webapps/webapp_registry.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0a23728..e97199d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3526,6 +3526,12 @@ flag_descriptions::kHappinessTrackingSurveysForDesktopDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kHappinessTrackingSurveysForDesktop)}, + + {"happiness-tracking-surveys-for-desktop-demo", + flag_descriptions::kHappinessTrackingSurveysForDesktopDemoName, + flag_descriptions::kHappinessTrackingSurveysForDesktopDemoDescription, + kOsDesktop, + FEATURE_VALUE_TYPE(features::kHappinessTrackingSurveysForDesktopDemo)}, #endif // !defined(OS_ANDROID) {"enable-service-worker-imported-script-update-check",
diff --git a/chrome/browser/android/compositor/decoration_title.cc b/chrome/browser/android/compositor/decoration_title.cc index 9012ec8..d1f4bc3 100644 --- a/chrome/browser/android/compositor/decoration_title.cc +++ b/chrome/browser/android/compositor/decoration_title.cc
@@ -11,7 +11,6 @@ #include "cc/layers/layer.h" #include "cc/layers/ui_resource_layer.h" #include "cc/resources/scoped_ui_resource.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/resource_manager.h" #include "ui/base/l10n/l10n_util_android.h" #include "ui/gfx/android/java_bitmap.h"
diff --git a/chrome/browser/android/compositor/layer/content_layer.cc b/chrome/browser/android/compositor/layer/content_layer.cc index 798f132a..9712692 100644 --- a/chrome/browser/android/compositor/layer/content_layer.cc +++ b/chrome/browser/android/compositor/layer/content_layer.cc
@@ -10,7 +10,6 @@ #include "cc/paint/filter_operations.h" #include "chrome/browser/android/compositor/layer/thumbnail_layer.h" #include "chrome/browser/android/compositor/tab_content_manager.h" -#include "content/public/browser/android/compositor.h" #include "ui/gfx/geometry/size.h" namespace android {
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.cc b/chrome/browser/android/compositor/layer/contextual_search_layer.cc index 5879f929..d670660 100644 --- a/chrome/browser/android/compositor/layer/contextual_search_layer.cc +++ b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
@@ -9,7 +9,6 @@ #include "cc/layers/solid_color_layer.h" #include "cc/layers/ui_resource_layer.h" #include "cc/resources/scoped_ui_resource.h" -#include "content/public/browser/android/compositor.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/nine_patch_resource.h" #include "ui/android/resources/resource_manager.h"
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc index 278a4953..7ccf3c63 100644 --- a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc +++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc
@@ -9,7 +9,6 @@ #include "cc/layers/solid_color_layer.h" #include "cc/layers/ui_resource_layer.h" #include "cc/resources/scoped_ui_resource.h" -#include "content/public/browser/android/compositor.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/nine_patch_resource.h" #include "ui/android/resources/resource_manager.h"
diff --git a/chrome/browser/android/compositor/layer/tab_handle_layer.cc b/chrome/browser/android/compositor/layer/tab_handle_layer.cc index 35f95ee..524ec4b 100644 --- a/chrome/browser/android/compositor/layer/tab_handle_layer.cc +++ b/chrome/browser/android/compositor/layer/tab_handle_layer.cc
@@ -10,7 +10,6 @@ #include "cc/resources/scoped_ui_resource.h" #include "chrome/browser/android/compositor/decoration_title.h" #include "chrome/browser/android/compositor/layer_title_cache.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/nine_patch_resource.h" #include "ui/android/resources/resource_manager.h" #include "ui/base/l10n/l10n_util_android.h"
diff --git a/chrome/browser/android/compositor/layer/tab_layer.cc b/chrome/browser/android/compositor/layer/tab_layer.cc index 53b2300..7f7da6c 100644 --- a/chrome/browser/android/compositor/layer/tab_layer.cc +++ b/chrome/browser/android/compositor/layer/tab_layer.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/android/compositor/layer/toolbar_layer.h" #include "chrome/browser/android/compositor/layer_title_cache.h" #include "chrome/browser/android/compositor/tab_content_manager.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/nine_patch_resource.h" #include "ui/android/resources/resource_manager.h" #include "ui/base/l10n/l10n_util_android.h"
diff --git a/chrome/browser/android/compositor/layer/thumbnail_layer.cc b/chrome/browser/android/compositor/layer/thumbnail_layer.cc index 0d304c4..3f385c0 100644 --- a/chrome/browser/android/compositor/layer/thumbnail_layer.cc +++ b/chrome/browser/android/compositor/layer/thumbnail_layer.cc
@@ -6,7 +6,6 @@ #include "cc/layers/ui_resource_layer.h" #include "chrome/browser/android/thumbnail/thumbnail.h" -#include "content/public/browser/android/compositor.h" #include "ui/gfx/geometry/size_conversions.h" namespace android {
diff --git a/chrome/browser/android/compositor/layer/toolbar_layer.cc b/chrome/browser/android/compositor/layer/toolbar_layer.cc index 90dbb2a..ada6e07 100644 --- a/chrome/browser/android/compositor/layer/toolbar_layer.cc +++ b/chrome/browser/android/compositor/layer/toolbar_layer.cc
@@ -9,7 +9,6 @@ #include "cc/layers/ui_resource_layer.h" #include "cc/resources/scoped_ui_resource.h" #include "chrome/browser/android/compositor/resources/toolbar_resource.h" -#include "content/public/browser/android/compositor.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/nine_patch_resource.h" #include "ui/android/resources/resource_manager.h"
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc index 1956b0d..252387b4 100644 --- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -12,7 +12,6 @@ #include "chrome/browser/android/compositor/layer/contextual_search_layer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" -#include "content/public/browser/android/compositor.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "net/base/load_flags.h"
diff --git a/chrome/browser/android/compositor/scene_layer/scene_layer.cc b/chrome/browser/android/compositor/scene_layer/scene_layer.cc index f5af23e..d2f22ad 100644 --- a/chrome/browser/android/compositor/scene_layer/scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/scene_layer.cc
@@ -6,7 +6,6 @@ #include "cc/layers/layer.h" #include "chrome/android/chrome_jni_headers/SceneLayer_jni.h" -#include "content/public/browser/android/compositor.h" using base::android::JavaParamRef; using base::android::JavaRef;
diff --git a/chrome/browser/android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc index 72ae9ca..8317761 100644 --- a/chrome/browser/android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc
@@ -8,7 +8,6 @@ #include "base/android/jni_array.h" #include "cc/layers/ui_resource_layer.h" #include "chrome/android/chrome_jni_headers/ScrollingBottomViewSceneLayer_jni.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/resource_manager_impl.h" using base::android::JavaParamRef;
diff --git a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc index 0aa9654..6a25093 100644 --- a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/android/compositor/layer/content_layer.h" #include "chrome/browser/android/compositor/layer_title_cache.h" #include "chrome/browser/android/compositor/tab_content_manager.h" -#include "content/public/browser/android/compositor.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/resource_manager_impl.h"
diff --git a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc index 191e2cf..b1304d7 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/android/compositor/layer/tab_layer.h" #include "chrome/browser/android/compositor/layer_title_cache.h" #include "chrome/browser/android/compositor/tab_content_manager.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/resource_manager_impl.h" using base::android::JavaParamRef;
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc index 765e4da..519868f7 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
@@ -9,7 +9,6 @@ #include "chrome/android/chrome_jni_headers/TabStripSceneLayer_jni.h" #include "chrome/browser/android/compositor/layer/tab_handle_layer.h" #include "chrome/browser/android/compositor/layer_title_cache.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/nine_patch_resource.h" #include "ui/android/resources/resource_manager_impl.h" #include "ui/gfx/transform.h"
diff --git a/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc index 0152a06..837a6df 100644 --- a/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc
@@ -9,7 +9,6 @@ #include "cc/layers/solid_color_layer.h" #include "chrome/android/chrome_jni_headers/ToolbarSceneLayer_jni.h" #include "chrome/browser/android/compositor/layer/toolbar_layer.h" -#include "content/public/browser/android/compositor.h" #include "ui/android/resources/resource_manager_impl.h" #include "ui/gfx/android/java_bitmap.h"
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index 1d37311..0f20ef9 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -52,7 +52,6 @@ #include "components/sessions/content/content_live_tab.h" #include "components/sessions/core/tab_restore_service.h" #include "components/url_formatter/url_fixer.h" -#include "content/public/browser/android/compositor.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/interstitial_page.h"
diff --git a/chrome/browser/android/webapps/single_tab_mode_tab_helper.cc b/chrome/browser/android/webapps/single_tab_mode_tab_helper.cc deleted file mode 100644 index 9a0dabf..0000000 --- a/chrome/browser/android/webapps/single_tab_mode_tab_helper.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h" - -SingleTabModeTabHelper::SingleTabModeTabHelper( - content::WebContents* web_contents) {} - -SingleTabModeTabHelper::~SingleTabModeTabHelper() {} - -void SingleTabModeTabHelper::PermanentlyBlockAllNewWindows() { - block_all_new_windows_ = true; -} - -WEB_CONTENTS_USER_DATA_KEY_IMPL(SingleTabModeTabHelper)
diff --git a/chrome/browser/android/webapps/single_tab_mode_tab_helper.h b/chrome/browser/android/webapps/single_tab_mode_tab_helper.h deleted file mode 100644 index f97dd30..0000000 --- a/chrome/browser/android/webapps/single_tab_mode_tab_helper.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ANDROID_WEBAPPS_SINGLE_TAB_MODE_TAB_HELPER_H_ -#define CHROME_BROWSER_ANDROID_WEBAPPS_SINGLE_TAB_MODE_TAB_HELPER_H_ - -#include "base/macros.h" -#include "chrome/browser/ui/blocked_content/blocked_window_params.h" -#include "content/public/browser/web_contents_user_data.h" - -namespace content { -class WebContents; -} - -// Tracks tabs in single tab mode, which are disallowed from opening new windows -// via ChromeContentBrowserClient::CanCreateWindow(). -class SingleTabModeTabHelper - : public content::WebContentsUserData<SingleTabModeTabHelper> { - public: - ~SingleTabModeTabHelper() override; - - bool block_all_new_windows() const { return block_all_new_windows_; } - - // Permanently block this WebContents from creating new windows -- there is no - // current need to allow toggling this flag on or off. - void PermanentlyBlockAllNewWindows(); - - private: - explicit SingleTabModeTabHelper(content::WebContents* web_contents); - friend class content::WebContentsUserData<SingleTabModeTabHelper>; - - bool block_all_new_windows_ = false; - - WEB_CONTENTS_USER_DATA_KEY_DECL(); - - DISALLOW_COPY_AND_ASSIGN(SingleTabModeTabHelper); -}; - -#endif // CHROME_BROWSER_ANDROID_WEBAPPS_SINGLE_TAB_MODE_TAB_HELPER_H_
diff --git a/chrome/browser/android/webapps/webapk_ukm_recorder.cc b/chrome/browser/android/webapps/webapk_ukm_recorder.cc index 3cdaabb..9d1ee21 100644 --- a/chrome/browser/android/webapps/webapk_ukm_recorder.cc +++ b/chrome/browser/android/webapps/webapk_ukm_recorder.cc
@@ -39,6 +39,9 @@ jint distributor, jint version_code, jlong duration) { + if (!manifest_url) + return; + WebApkUkmRecorder::RecordSessionDuration( GURL(base::android::ConvertJavaStringToUTF8(env, manifest_url)), distributor, version_code, duration);
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc index 31cfdf4c..4f3c2de 100644 --- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -110,20 +110,20 @@ // Press the down key to highlight the first choice in the autofill // suggestion drop down. - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kPreviewFormData}, + autofill_wait_for_action_interval); SendKeyToPopup(frame, ui::DomKey::ARROW_DOWN); - if (!test_delegate()->Wait({ObservedUiEvents::kPreviewFormData}, - autofill_wait_for_action_interval)) { + if (!test_delegate()->Wait()) { LOG(WARNING) << "Failed to select an option from the " << "autofill suggestion drop down."; continue; } // Press the enter key to invoke autofill using the first suggestion. - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kFormDataFilled}, + autofill_wait_for_action_interval); SendKeyToPopup(frame, ui::DomKey::ENTER); - if (!test_delegate()->Wait({ObservedUiEvents::kFormDataFilled}, - autofill_wait_for_action_interval)) { + if (!test_delegate()->Wait()) { LOG(WARNING) << "Failed to fill the form."; continue; } @@ -263,13 +263,13 @@ frame, &rect)) return false; - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionShown}, + autofill_wait_for_action_interval); if (!captured_sites_test_utils::TestRecipeReplayer:: SimulateLeftMouseClickAt(rect.CenterPoint(), frame)) return false; - return test_delegate()->Wait({ObservedUiEvents::kSuggestionShown}, - autofill_wait_for_action_interval); + return test_delegate()->Wait(); } bool StringToFieldType(const std::string& str, ServerFieldType* type) {
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 2aca452..e5c09f8 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -1104,9 +1104,9 @@ ASSERT_NO_FATAL_FAILURE(FocusFirstNameField()); // Now click it. - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionShown}); ASSERT_NO_FATAL_FAILURE(ClickFirstNameField()); - test_delegate()->Wait({ObservedUiEvents::kSuggestionShown}); + EXPECT_TRUE(test_delegate()->Wait()); // Press the down arrow to select the suggestion and preview the autofilled // form. @@ -1157,9 +1157,9 @@ ui_test_utils::NavigateToURL(browser(), GetTestUrl())); // This click should activate the autofill popup. - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionShown}); ASSERT_NO_FATAL_FAILURE(ClickFirstNameField()); - test_delegate()->Wait({ObservedUiEvents::kSuggestionShown}); + EXPECT_TRUE(test_delegate()->Wait()); // Press the down arrow to select the suggestion and preview the autofilled // form. @@ -1194,9 +1194,9 @@ ASSERT_NO_FATAL_FAILURE(ClickElementWithId("disabled-button")); ASSERT_NO_FATAL_FAILURE(MakeSurePopupDoesntAppear()); - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionShown}); ASSERT_NO_FATAL_FAILURE(ClickFirstNameField()); - test_delegate()->Wait({ObservedUiEvents::kSuggestionShown}); + EXPECT_TRUE(test_delegate()->Wait()); } // Test that a field is still autofillable after the previously autofilled @@ -2038,11 +2038,11 @@ FocusFieldByName("company"); // Now click it. - test_delegate()->Reset(); + test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionShown}, + base::TimeDelta::FromSeconds(3)); ASSERT_NO_FATAL_FAILURE(ClickElementWithId("company")); - bool found = test_delegate()->Wait({ObservedUiEvents::kSuggestionShown}, - base::TimeDelta::FromSeconds(3)); + bool found = test_delegate()->Wait(); if (!company_name_enabled_) { EXPECT_FALSE(found);
diff --git a/chrome/browser/autofill/autofill_uitest.cc b/chrome/browser/autofill/autofill_uitest.cc index 6c2fe45..198135c 100644 --- a/chrome/browser/autofill/autofill_uitest.cc +++ b/chrome/browser/autofill/autofill_uitest.cc
@@ -50,15 +50,14 @@ void AutofillManagerTestDelegateImpl::OnTextFieldChanged() {} -void AutofillManagerTestDelegateImpl::Reset() { - event_waiter_.reset(); -} - -bool AutofillManagerTestDelegateImpl::Wait( +void AutofillManagerTestDelegateImpl::SetExpectations( std::list<ObservedUiEvents> expected_events, base::TimeDelta timeout) { event_waiter_ = std::make_unique<EventWaiter<ObservedUiEvents>>(expected_events, timeout); +} + +bool AutofillManagerTestDelegateImpl::Wait() { return event_waiter_->Wait(); } @@ -118,10 +117,10 @@ ui::DomCode code, ui::KeyboardCode key_code, std::list<ObservedUiEvents> expected_events) { - test_delegate()->Reset(); + test_delegate()->SetExpectations(std::move(expected_events)); content::SimulateKeyPress(GetWebContents(), key, code, key_code, false, false, false, false); - test_delegate()->Wait(std::move(expected_events)); + test_delegate()->Wait(); } void AutofillUiTest::SendKeyToPopup(content::RenderFrameHost* render_frame_host, @@ -168,19 +167,19 @@ event.windows_key_code = key_code; event.dom_code = static_cast<int>(code); event.dom_key = key; - test_delegate()->Reset(); + test_delegate()->SetExpectations(std::move(expected_events)); // Install the key press event sink to ensure that any events that are not // handled by the installed callbacks do not end up crashing the test. widget->AddKeyPressEventCallback(key_press_event_sink_); widget->ForwardKeyboardEvent(event); - test_delegate()->Wait(std::move(expected_events)); + test_delegate()->Wait(); widget->RemoveKeyPressEventCallback(key_press_event_sink_); } void AutofillUiTest::DoNothingAndWait(unsigned seconds) { - test_delegate()->Reset(); - ASSERT_FALSE(test_delegate()->Wait({ObservedUiEvents::kNoEvent}, - base::TimeDelta::FromSeconds(seconds))); + test_delegate()->SetExpectations({ObservedUiEvents::kNoEvent}, + base::TimeDelta::FromSeconds(seconds)); + ASSERT_FALSE(test_delegate()->Wait()); } void AutofillUiTest::SendKeyToDataListPopup(ui::DomKey key) {
diff --git a/chrome/browser/autofill/autofill_uitest.h b/chrome/browser/autofill/autofill_uitest.h index 50d4a86..7dcbd09 100644 --- a/chrome/browser/autofill/autofill_uitest.h +++ b/chrome/browser/autofill/autofill_uitest.h
@@ -41,10 +41,10 @@ void DidShowSuggestions() override; void OnTextFieldChanged() override; - void Reset(); - - bool Wait(std::list<ObservedUiEvents> expected_events, - base::TimeDelta timeout = base::TimeDelta::FromSeconds(0)); + void SetExpectations( + std::list<ObservedUiEvents> expected_events, + base::TimeDelta timeout = base::TimeDelta::FromSeconds(0)); + bool Wait(); void SetIsExpectingDynamicRefill(bool expect_refill) { is_expecting_dynamic_refill_ = expect_refill;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 52820c8..0e9a19e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -414,7 +414,6 @@ #include "chrome/browser/android/service_tab_launcher.h" #include "chrome/browser/android/tab_android.h" #include "chrome/browser/android/tab_web_contents_delegate_android.h" -#include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h" #include "chrome/browser/chrome_browser_main_android.h" #include "chrome/browser/offline_pages/android/offline_page_auto_fetcher.h" #include "chrome/browser/ui/android/tab_model/tab_model_list.h" @@ -1253,6 +1252,8 @@ base::OnceClosure task) { AfterStartupTaskUtils::PostTask(from_here, task_runner, std::move(task)); + InitNetworkContextsParentDirectory(); + DCHECK_CURRENTLY_ON(BrowserThread::UI); safe_browsing_service_ = g_browser_process->safe_browsing_service(); } @@ -2941,17 +2942,6 @@ blocked_params.features())) { return false; } - -#if defined(OS_ANDROID) - auto* single_tab_mode_helper = - SingleTabModeTabHelper::FromWebContents(web_contents); - if (single_tab_mode_helper && - single_tab_mode_helper->block_all_new_windows()) { - TabModelList::HandlePopupNavigation(&nav_params); - return false; - } -#endif - return true; } @@ -4383,6 +4373,30 @@ #endif } +void ChromeContentBrowserClient::InitNetworkContextsParentDirectory() { + base::FilePath user_data_dir; + base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); + DCHECK(!user_data_dir.empty()); + network_contexts_parent_directory_.push_back(user_data_dir); + + base::FilePath cache_dir; + chrome::GetUserCacheDirectory(user_data_dir, &cache_dir); + DCHECK(!cache_dir.empty()); + // On some platforms, the cache is a child of the user_data_dir so only + // return the one path. + if (!user_data_dir.IsParent(cache_dir)) + network_contexts_parent_directory_.push_back(cache_dir); + + // If the cache location has been overridden by a switch or preference, + // include that as well. + if (auto* local_state = g_browser_process->local_state()) { + base::FilePath pref_cache_dir = + local_state->GetFilePath(prefs::kDiskCacheDir); + if (!pref_cache_dir.empty() && !user_data_dir.IsParent(cache_dir)) + network_contexts_parent_directory_.push_back(pref_cache_dir); + } +} + void ChromeContentBrowserClient::MaybeCopyDisableWebRtcEncryptionSwitch( base::CommandLine* to_command_line, const base::CommandLine& from_command_line, @@ -4903,20 +4917,8 @@ std::vector<base::FilePath> ChromeContentBrowserClient::GetNetworkContextsParentDirectory() { - base::FilePath user_data_dir; - base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); - DCHECK(!user_data_dir.empty()); - - base::FilePath cache_dir; - chrome::GetUserCacheDirectory(user_data_dir, &cache_dir); - DCHECK(!cache_dir.empty()); - - // On some platforms, the cache is a child of the user_data_dir so only - // return the one path. - if (user_data_dir.IsParent(cache_dir)) - return {user_data_dir}; - - return {user_data_dir, cache_dir}; + DCHECK(!network_contexts_parent_directory_.empty()); + return network_contexts_parent_directory_; } bool ChromeContentBrowserClient::AllowRenderingMhtmlOverHttp(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 9fb5ed4..3cb4363 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -632,6 +632,9 @@ // |worker_interfaces_parameterized_|. void InitWebContextInterfaces(); + // Initializes |network_contexts_parent_directory_| on the UI thread. + void InitNetworkContextsParentDirectory(); + // Copies disable WebRTC encryption switch depending on the channel. static void MaybeCopyDisableWebRtcEncryptionSwitch( base::CommandLine* to_command_line, @@ -700,6 +703,10 @@ std::unique_ptr<ChromeHidDelegate> hid_delegate_; #endif + // Returned from GetNetworkContextsParentDirectory() but created on the UI + // thread because it needs to access the Local State prefs. + std::vector<base::FilePath> network_contexts_parent_directory_; + base::WeakPtrFactory<ChromeContentBrowserClient> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClient);
diff --git a/chrome/browser/chromeos/assistant/assistant_util.cc b/chrome/browser/chromeos/assistant/assistant_util.cc index ba9b93ec6..1133834f 100644 --- a/chrome/browser/chromeos/assistant/assistant_util.cc +++ b/chrome/browser/chromeos/assistant/assistant_util.cc
@@ -63,6 +63,7 @@ ULOC_US, "da", "en_AU", + "en_IN", "en_NZ", "es_ES", "es_MX",
diff --git a/chrome/browser/chromeos/login/auth/auth_prewarmer.cc b/chrome/browser/chromeos/login/auth/auth_prewarmer.cc index 5edb3975..36b3730 100644 --- a/chrome/browser/chromeos/login/auth/auth_prewarmer.cc +++ b/chrome/browser/chromeos/login/auth/auth_prewarmer.cc
@@ -16,7 +16,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "google_apis/gaia/gaia_urls.h" -#include "net/base/load_flags.h" #include "net/base/network_isolation_key.h" #include "services/network/public/mojom/network_context.mojom.h" #include "url/gurl.h" @@ -59,16 +58,14 @@ void AuthPrewarmer::DoPrewarm() { const int kConnectionsNeeded = 1; - const int kLoadFlags = net::LOAD_NORMAL; - const bool kShouldUsePrivacyMode = false; + const bool kAllowCredentials = true; const GURL& url = GaiaUrls::GetInstance()->service_login_url(); network::mojom::NetworkContext* network_context = login::GetSigninNetworkContext(); if (network_context) { // Do nothing if NetworkContext isn't available. - network_context->PreconnectSockets(kConnectionsNeeded, url, kLoadFlags, - kShouldUsePrivacyMode, - net::NetworkIsolationKey()); + network_context->PreconnectSockets( + kConnectionsNeeded, url, kAllowCredentials, net::NetworkIsolationKey()); } if (!completion_callback_.is_null()) { base::PostTask(FROM_HERE, {content::BrowserThread::UI},
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc index 679bbbe..b1c5550 100644 --- a/chrome/browser/content_settings/content_settings_browsertest.cc +++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -471,6 +471,47 @@ } } +IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BlockCookiesAlsoBlocksIndexedDB) { + ui_test_utils::NavigateToURL(browser(), GetPageURL()); + content_settings::CookieSettings* settings = + CookieSettingsFactory::GetForProfile(browser()->profile()).get(); + settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_BLOCK); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + + const char kBaseScript[] = + "(async function() {" + " const name = `%s`;" + " function wrap(req) {" + " return new Promise((resolve, reject) => {" + " req.onerror = function() { reject(req.error); };" + " req.onsuccess = function() { resolve(); };" + " });" + " }" + " try {" + " await wrap(%s);" + " } catch(e) {" + " return `${name} - ${e.toString()}`;" + " }" + " return `${name} - success`;" + "}())"; + + const std::vector<std::string> kTestOps({ + "indexedDB.open('foo', 1)", + "indexedDB.deleteDatabase('foo')", + }); + + const char kBaseExpected[] = + "%s - UnknownError: The user denied permission to access the database."; + + for (auto& op : kTestOps) { + EXPECT_EQ( + base::StringPrintf(kBaseExpected, op.data()), + EvalJs(tab, base::StringPrintf(kBaseScript, op.data(), op.data()))); + } +} + INSTANTIATE_TEST_SUITE_P( /* no prefix */, CookieSettingsTest,
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.cc b/chrome/browser/extensions/theme_installed_infobar_delegate.cc index 5f6a70f..f539add 100644 --- a/chrome/browser/extensions/theme_installed_infobar_delegate.cc +++ b/chrome/browser/extensions/theme_installed_infobar_delegate.cc
@@ -29,14 +29,14 @@ ThemeService* theme_service, const std::string& theme_name, const std::string& theme_id, - base::OnceClosure revert_theme_callback) { + std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller) { // Create the new infobar. std::unique_ptr<infobars::InfoBar> new_infobar( infobar_service->CreateConfirmInfoBar( std::unique_ptr<ConfirmInfoBarDelegate>( new ThemeInstalledInfoBarDelegate( theme_service, theme_name, theme_id, - std::move(revert_theme_callback))))); + std::move(prev_theme_reinstaller))))); // If there's a previous theme infobar, just replace that instead of adding a // new one. @@ -52,27 +52,24 @@ // don't show an infobar, it's valid in this case. if (theme_infobar->theme_id_ != theme_id) { infobar_service->ReplaceInfoBar(old_infobar, std::move(new_infobar)); - theme_service->OnInfobarDisplayed(); } return; } } - // No previous theme infobar, so add this. infobar_service->AddInfoBar(std::move(new_infobar)); - theme_service->OnInfobarDisplayed(); } ThemeInstalledInfoBarDelegate::ThemeInstalledInfoBarDelegate( ThemeService* theme_service, const std::string& theme_name, const std::string& theme_id, - base::OnceClosure revert_theme_callback) + std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller) : ConfirmInfoBarDelegate(), theme_service_(theme_service), theme_name_(theme_name), theme_id_(theme_id), - revert_theme_callback_(std::move(revert_theme_callback)) { + prev_theme_reinstaller_(std::move(prev_theme_reinstaller)) { registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, content::Source<ThemeService>(theme_service_)); } @@ -80,8 +77,6 @@ ThemeInstalledInfoBarDelegate::~ThemeInstalledInfoBarDelegate() { // We don't want any notifications while we're running our destructor. registrar_.RemoveAll(); - - theme_service_->OnInfobarDestroyed(); } infobars::InfoBarDelegate::InfoBarIdentifier @@ -114,8 +109,8 @@ } bool ThemeInstalledInfoBarDelegate::Cancel() { - if (!revert_theme_callback_.is_null()) - std::move(revert_theme_callback_).Run(); + if (prev_theme_reinstaller_) + prev_theme_reinstaller_->Reinstall(); return false; // The theme change will close us. }
diff --git a/chrome/browser/extensions/theme_installed_infobar_delegate.h b/chrome/browser/extensions/theme_installed_infobar_delegate.h index b2d211c9..036deb3 100644 --- a/chrome/browser/extensions/theme_installed_infobar_delegate.h +++ b/chrome/browser/extensions/theme_installed_infobar_delegate.h
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/compiler_specific.h" +#include "chrome/browser/themes/theme_service.h" #include "components/infobars/core/confirm_infobar_delegate.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -16,7 +17,6 @@ #include "third_party/skia/include/core/SkColor.h" class InfoBarService; -class ThemeService; // When a user installs a theme, we display it immediately, but provide an // infobar allowing them to cancel. @@ -25,17 +25,19 @@ public: // Creates a theme installed infobar and delegate and adds the infobar to // |infobar_service|, replacing any previous theme infobar. - static void Create(InfoBarService* infobar_service, - ThemeService* theme_service, - const std::string& theme_name, - const std::string& theme_id, - base::OnceClosure revert_theme_callback); + static void Create( + InfoBarService* infobar_service, + ThemeService* theme_service, + const std::string& theme_name, + const std::string& theme_id, + std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller); private: - ThemeInstalledInfoBarDelegate(ThemeService* theme_service, - const std::string& theme_name, - const std::string& theme_id, - base::OnceClosure revert_theme_callback); + ThemeInstalledInfoBarDelegate( + ThemeService* theme_service, + const std::string& theme_name, + const std::string& theme_id, + std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller); ~ThemeInstalledInfoBarDelegate() override; // ConfirmInfoBarDelegate: @@ -61,7 +63,7 @@ std::string theme_id_; // Used to undo theme install. - base::OnceClosure revert_theme_callback_; + std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller_; // Registers and unregisters us for notifications. content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 303ac0f..1b89e3dd 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -775,8 +775,8 @@ }, { "name": "enable-android-night-mode", - "owners": [ "huayinz", "twellington", "tedchoc" ], - "expiry_milestone": 76 + "owners": [ "twellington", "tedchoc" ], + "expiry_milestone": 80 }, { "name": "enable-android-spellchecker", @@ -785,8 +785,8 @@ }, { "name": "enable-android-web-contents-dark-mode", - "owners": [ "huayinz", "tedchoc" ], - "expiry_milestone": 76 + "owners": [ "tedchoc" ], + "expiry_milestone": 80 }, { "name": "enable-app-data-search", @@ -1537,7 +1537,7 @@ { "name": "enable-revamped-context-menu", "owners": [ "twellington" ], - "expiry_milestone": 77 + "expiry_milestone": 80 }, { "name": "enable-safe-browsing-ap-download-verdicts", @@ -1703,27 +1703,27 @@ { "name": "enable-tab-grid-layout", "owners": [ "memex-team@google.com" ], - "expiry_milestone": 76 + "expiry_milestone": 82 }, { "name": "enable-tab-groups", "owners": [ "memex-team@google.com" ], - "expiry_milestone": 80 + "expiry_milestone": 82 }, { "name": "enable-tab-groups-ui-improvements", "owners": [ "memex-team@google.com" ], - "expiry_milestone": 80 + "expiry_milestone": 82 }, { "name": "enable-tab-switcher-on-return", "owners": [ "memex-team@google.com" ], - "expiry_milestone": 76 + "expiry_milestone": 82 }, { "name": "enable-tab-to-gts-animation", "owners": [ "memex-team@google.com" ], - "expiry_milestone": 80 + "expiry_milestone": 82 }, { "name": "enable-text-fragment-anchor", @@ -2070,7 +2070,7 @@ { "name": "force-enable-home-page-button", "owners": [ "twellington", "chrome-android-app" ], - "expiry_milestone": 78 + "expiry_milestone": 81 }, { "name": "force-enable-system-aec", @@ -2164,7 +2164,15 @@ }, { "name": "happiness-tracking-surveys-for-desktop", - "owners": [ "robliao" ], + "owners": [ "//chrome/browser/ui/hats/OWNERS" ], + "expiry_milestone": 78 + }, + { + "name": "happiness-tracking-surveys-for-desktop-demo", + "owners": [ "//chrome/browser/ui/hats/OWNERS" ], + // A debugging and demo flag to allow UI/dev/testing team to always show the UI + // components for the survey without being limited by the triggering mechanism. + // This flag should expire along with the above feature flag. "expiry_milestone": 78 }, {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index e94d38f..333b299 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2780,6 +2780,11 @@ const char kHappinessTrackingSurveysForDesktopDescription[] = "Enable showing Happiness Tracking Surveys to users on Desktop"; +const char kHappinessTrackingSurveysForDesktopDemoName[] = + "Happiness Tracking Surveys Demo"; +const char kHappinessTrackingSurveysForDesktopDemoDescription[] = + "Enable showing Happiness Tracking Surveys Demo to users on Desktop"; + const char kIntentPickerName[] = "Intent picker"; const char kIntentPickerDescription[] = "When going to a site that has URL managable by a PWA, show the intent"
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 82363486..a9bc084 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1639,6 +1639,9 @@ extern const char kHappinessTrackingSurveysForDesktopName[]; extern const char kHappinessTrackingSurveysForDesktopDescription[]; +extern const char kHappinessTrackingSurveysForDesktopDemoName[]; +extern const char kHappinessTrackingSurveysForDesktopDemoDescription[]; + extern const char kIntentPickerName[]; extern const char kIntentPickerDescription[];
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc index e90c19d..e645c9c8 100644 --- a/chrome/browser/infobars/infobars_browsertest.cc +++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -269,7 +269,9 @@ ThemeInstalledInfoBarDelegate::Create( GetInfoBarService(), ThemeServiceFactory::GetForProfile(browser()->profile()), "New Theme", - "id", base::OnceClosure()); + "id", + std::make_unique<ThemeService::ThemeReinstaller>( + browser()->profile(), base::OnceClosure())); break; case IBD::NACL_INFOBAR_DELEGATE:
diff --git a/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc b/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc index 115b2af..bb77d69f 100644 --- a/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc +++ b/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc
@@ -143,10 +143,6 @@ class NetworkQualityEstimatorPrefsBrowserTest : public InProcessBrowserTest { public: - NetworkQualityEstimatorPrefsBrowserTest() { - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - } - // Simulates a network quality change. void SimulateNetworkQualityChange(net::EffectiveConnectionType type) { if (!content::IsOutOfProcessNetworkService()) { @@ -173,12 +169,7 @@ run_loop.Run(); } - base::FilePath GetTempDirectory() { return temp_dir_.GetPath(); } - base::HistogramTester histogram_tester; - - private: - base::ScopedTempDir temp_dir_; }; // Verify that prefs are read at startup, and the read prefs are notified to the @@ -206,7 +197,8 @@ network::mojom::NetworkContextParamsPtr context_params = network::mojom::NetworkContextParams::New(); context_params->http_server_properties_path = - GetTempDirectory().Append(FILE_PATH_LITERAL("Network Persistent State")); + browser()->profile()->GetPath().Append( + FILE_PATH_LITERAL("Temp Network Persistent State")); auto state = base::MakeRefCounted<JsonPrefStore>( context_params->http_server_properties_path.value());
diff --git a/chrome/browser/notifications/proto/notification_data.proto b/chrome/browser/notifications/proto/notification_data.proto index 0d2ba6a..e15c0a6d4 100644 --- a/chrome/browser/notifications/proto/notification_data.proto +++ b/chrome/browser/notifications/proto/notification_data.proto
@@ -22,7 +22,7 @@ } // Stores data used to display a notification in the UI. -// Next tag: 6 +// Next tag: 7 message NotificationData { // Represents the button on the notification. // Next tag: 4 @@ -38,13 +38,17 @@ // Body text of the notification. optional string message = 2; - // The unique identifiers of the icons on the notification. Each time we - // should only load icons asynchronously into memory. - repeated string icon_uuid = 3; - // Custom data associated with a notification. - repeated CustomData custom_data = 4; + repeated CustomData custom_data = 3; // A list of buttons on the notification. - repeated Button buttons = 5; + repeated Button buttons = 4; + + // The unique identifier of the small icon on notification, which must be + // loaded asynchronously into memory. + optional string small_icon_uuid = 5; + + // The unique identifier of the large icon on notification, which must be + // loaded asynchronously into memory. + optional string large_icon_uuid = 6; }
diff --git a/chrome/browser/notifications/scheduler/internal/BUILD.gn b/chrome/browser/notifications/scheduler/internal/BUILD.gn index 22124525..961c5db9 100644 --- a/chrome/browser/notifications/scheduler/internal/BUILD.gn +++ b/chrome/browser/notifications/scheduler/internal/BUILD.gn
@@ -82,6 +82,7 @@ "icon_store_unittest.cc", "impression_history_tracker_unittest.cc", "impression_store_unittest.cc", + "impression_types_unittest.cc", "init_aware_scheduler_unittest.cc", "notification_scheduler_unittest.cc", "notification_store_unittest.cc",
diff --git a/chrome/browser/notifications/scheduler/internal/icon_store.cc b/chrome/browser/notifications/scheduler/internal/icon_store.cc index b55e998..8f4c97a1c 100644 --- a/chrome/browser/notifications/scheduler/internal/icon_store.cc +++ b/chrome/browser/notifications/scheduler/internal/icon_store.cc
@@ -37,8 +37,9 @@ using KeyVector = std::vector<std::string>; IconProtoDbStore::IconProtoDbStore( - std::unique_ptr<leveldb_proto::ProtoDatabase<proto::Icon, IconEntry>> db) - : db_(std::move(db)) {} + std::unique_ptr<leveldb_proto::ProtoDatabase<proto::Icon, IconEntry>> db, + std::unique_ptr<IconConverter> icon_converter) + : db_(std::move(db)), icon_converter_(std::move(icon_converter)) {} IconProtoDbStore::~IconProtoDbStore() = default;
diff --git a/chrome/browser/notifications/scheduler/internal/icon_store.h b/chrome/browser/notifications/scheduler/internal/icon_store.h index 218ebbf6..df31d9fc 100644 --- a/chrome/browser/notifications/scheduler/internal/icon_store.h +++ b/chrome/browser/notifications/scheduler/internal/icon_store.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/notifications/proto/icon.pb.h" +#include "chrome/browser/notifications/scheduler/internal/icon_converter.h" #include "chrome/browser/notifications/scheduler/internal/icon_entry.h" #include "components/leveldb_proto/public/proto_database.h" @@ -74,7 +75,8 @@ class IconProtoDbStore : public IconStore { public: explicit IconProtoDbStore( - std::unique_ptr<leveldb_proto::ProtoDatabase<proto::Icon, IconEntry>> db); + std::unique_ptr<leveldb_proto::ProtoDatabase<proto::Icon, IconEntry>> db, + std::unique_ptr<IconConverter> icon_converter); ~IconProtoDbStore() override; private: @@ -108,6 +110,9 @@ // The proto database instance that persists data. std::unique_ptr<leveldb_proto::ProtoDatabase<proto::Icon, IconEntry>> db_; + // Help serializing icons to disk and deserializing encoded data to icons. + std::unique_ptr<IconConverter> icon_converter_; + base::WeakPtrFactory<IconProtoDbStore> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(IconProtoDbStore);
diff --git a/chrome/browser/notifications/scheduler/internal/icon_store_unittest.cc b/chrome/browser/notifications/scheduler/internal/icon_store_unittest.cc index 2fce91d3..9d3aa88 100644 --- a/chrome/browser/notifications/scheduler/internal/icon_store_unittest.cc +++ b/chrome/browser/notifications/scheduler/internal/icon_store_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/notifications/proto/icon.pb.h" #include "chrome/browser/notifications/scheduler/internal/icon_entry.h" #include "components/leveldb_proto/testing/fake_db.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace notifications { @@ -25,6 +26,18 @@ const char kEntryData[] = "data_1"; const char kEntryData2[] = "data_2"; +class MockIconConverter : public IconConverter { + public: + MockIconConverter() = default; + MOCK_METHOD2(ConvertIconToString, + void(std::vector<SkBitmap>, IconConverter::EncodeCallback)); + MOCK_METHOD2(ConvertStringToIcon, + void(std::vector<std::string>, IconConverter::DecodeCallback)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockIconConverter); +}; + class IconStoreTest : public testing::Test { public: IconStoreTest() : load_result_(false), db_(nullptr) {} @@ -42,7 +55,10 @@ std::make_unique<leveldb_proto::test::FakeDB<proto::Icon, IconEntry>>( &db_entries_); db_ = db.get(); - store_ = std::make_unique<IconProtoDbStore>(std::move(db)); + auto icon_converter = std::make_unique<MockIconConverter>(); + icon_converter_ = icon_converter.get(); + store_ = std::make_unique<IconProtoDbStore>(std::move(db), + std::move(icon_converter)); } void InitDb() { @@ -68,6 +84,7 @@ const std::vector<IconEntry>* loaded_entries() { return loaded_entries_.get(); } + MockIconConverter* icon_converter() { return icon_converter_; } void VerifyEntries(std::vector<std::pair<std::string, std::string>> inputs) { EXPECT_EQ(inputs.size(), loaded_entries_->size()); @@ -84,6 +101,7 @@ std::unique_ptr<std::vector<IconEntry>> loaded_entries_; bool load_result_; leveldb_proto::test::FakeDB<proto::Icon, IconEntry>* db_; + MockIconConverter* icon_converter_; DISALLOW_COPY_AND_ASSIGN(IconStoreTest); };
diff --git a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc index b82ca33..e3a8332 100644 --- a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc +++ b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
@@ -15,11 +15,6 @@ namespace notifications { namespace { -// Comparator used to sort notification entries based on creation time. -bool CreateTimeCompare(const Impression& lhs, const Impression& rhs) { - return lhs.create_time < rhs.create_time; -} - std::string ToDatabaseKey(SchedulerClientType type) { switch (type) { case SchedulerClientType::kTest1: @@ -151,16 +146,25 @@ initialized_ = true; - // Load the data to memory, and sort the impression list. + // Load the data to memory, and prune expired impressions. + auto now = clock_->Now(); for (auto it = entries.begin(); it != entries.end(); ++it) { auto& entry = (*it); auto type = entry->type; - std::sort(entry->impressions.begin(), entry->impressions.end(), - &CreateTimeCompare); + ClientState::Impressions impressions; for (auto& impression : entry->impressions) { - impression_map_.emplace(impression.guid, &impression); + bool expired = + now - impression.create_time > config_.impression_expiration; + if (expired) { + SetNeedsUpdate(type, true); + } else { + impressions.emplace_back(impression); + impression_map_.emplace(impression.guid, &impressions.back()); + } } + entry->impressions.swap(impressions); client_states_.emplace(type, std::move(*it)); + MaybeUpdateDb(type); } SyncRegisteredClients(); @@ -200,22 +204,9 @@ ClientState* client_state) { DCHECK(client_state); base::circular_deque<Impression*> dismisses; - base::Time now = clock_->Now(); - for (auto it = client_state->impressions.begin(); - it != client_state->impressions.end();) { + it != client_state->impressions.end(); ++it) { auto* impression = &*it; - - // Prune out expired impression. - if (now - impression->create_time > config_.impression_expiration) { - impression_map_.erase(impression->guid); - client_state->impressions.erase(it++); - SetNeedsUpdate(client_state->type, true); - continue; - } else { - ++it; - } - switch (impression->feedback) { case UserFeedback::kDismiss: dismisses.emplace_back(impression);
diff --git a/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc b/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc index 986eaf5..08656561 100644 --- a/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc +++ b/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc
@@ -210,20 +210,13 @@ Impression expired = CreateImpression(expired_create_time, "guid1"); Impression not_expired = CreateImpression(not_expired_time, "guid2"); - // The impressions in the input should be sorted by creation time when gets - // loaded to memory. test_case.input.back().impressions = {expired, not_expired, expired}; - - // Expired impression created in |expired_create_time| should be deleted. - // No change expected on the next impression, which is not expired and no user - // feedback . test_case.expected.back().impressions = {not_expired}; CreateTracker(test_case); - InitTrackerWithData(test_case); EXPECT_CALL(*store(), Update(_, _, _)); - EXPECT_CALL(*delegate(), OnImpressionUpdated()); - tracker()->AnalyzeImpressionHistory(); + InitTrackerWithData(test_case); + EXPECT_CALL(*delegate(), OnImpressionUpdated()).Times(0); VerifyClientStates(test_case); }
diff --git a/chrome/browser/notifications/scheduler/internal/impression_types.cc b/chrome/browser/notifications/scheduler/internal/impression_types.cc index 09517cb..88b6aa1 100644 --- a/chrome/browser/notifications/scheduler/internal/impression_types.cc +++ b/chrome/browser/notifications/scheduler/internal/impression_types.cc
@@ -48,9 +48,16 @@ ClientState::~ClientState() = default; bool ClientState::operator==(const ClientState& other) const { + if (impressions.size() != other.impressions.size()) + return false; + + for (size_t i = 0; i < impressions.size(); ++i) { + if (!(impressions[i] == other.impressions[i])) + return false; + } + return type == other.type && current_max_daily_show == other.current_max_daily_show && - impressions == other.impressions && suppression_info == other.suppression_info; }
diff --git a/chrome/browser/notifications/scheduler/internal/impression_types.h b/chrome/browser/notifications/scheduler/internal/impression_types.h index 711885b..f7bc753 100644 --- a/chrome/browser/notifications/scheduler/internal/impression_types.h +++ b/chrome/browser/notifications/scheduler/internal/impression_types.h
@@ -5,10 +5,10 @@ #ifndef CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_IMPRESSION_TYPES_H_ #define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_IMPRESSION_TYPES_H_ -#include <deque> #include <map> #include <string> +#include "base/containers/circular_deque.h" #include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/notifications/scheduler/public/notification_scheduler_types.h" @@ -97,7 +97,7 @@ // to the user and the history of user interactions to a particular notification // client. struct ClientState { - using Impressions = std::deque<Impression>; + using Impressions = base::circular_deque<Impression>; ClientState(); explicit ClientState(const ClientState& other); ~ClientState();
diff --git a/chrome/browser/notifications/scheduler/internal/impression_types_unittest.cc b/chrome/browser/notifications/scheduler/internal/impression_types_unittest.cc new file mode 100644 index 0000000..4687cae6 --- /dev/null +++ b/chrome/browser/notifications/scheduler/internal/impression_types_unittest.cc
@@ -0,0 +1,24 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/notifications/scheduler/internal/impression_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace notifications { +namespace { + +// Verifies equal operator of ClientState. +TEST(ImpressionTypesTest, ClientStateEqual) { + ClientState client_state0, client_state1; + EXPECT_EQ(client_state0, client_state1); + client_state0.impressions.emplace_back(Impression()); + EXPECT_FALSE(client_state0 == client_state1); + client_state1.impressions.emplace_back(Impression()); + EXPECT_EQ(client_state0, client_state1); + client_state0.impressions.front().guid = "guid"; + EXPECT_FALSE(client_state0 == client_state1); +} + +} // namespace +} // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/internal/notification_entry.cc b/chrome/browser/notifications/scheduler/internal/notification_entry.cc index d33b804f..108595b 100644 --- a/chrome/browser/notifications/scheduler/internal/notification_entry.cc +++ b/chrome/browser/notifications/scheduler/internal/notification_entry.cc
@@ -21,7 +21,8 @@ return type == other.type && guid == other.guid && create_time == other.create_time && notification_data == other.notification_data && - icons_uuid == other.icons_uuid && + small_icon_uuid == other.small_icon_uuid && + large_icon_uuid == other.large_icon_uuid && schedule_params == other.schedule_params; }
diff --git a/chrome/browser/notifications/scheduler/internal/notification_entry.h b/chrome/browser/notifications/scheduler/internal/notification_entry.h index 48b373c..1b42d7a 100644 --- a/chrome/browser/notifications/scheduler/internal/notification_entry.h +++ b/chrome/browser/notifications/scheduler/internal/notification_entry.h
@@ -37,9 +37,13 @@ // shown. NotificationData notification_data; - // The unique identifier of the icons, which must be loaded asynchronously - // into memory. - std::vector<std::string> icons_uuid; + // The unique identifier of the small icon on notification, which must be + // loaded asynchronously into memory. + std::string small_icon_uuid; + + // The unique identifier of the large icon on notification, which must be + // loaded asynchronously into memory. + std::string large_icon_uuid; // Scheduling details. ScheduleParams schedule_params;
diff --git a/chrome/browser/notifications/scheduler/internal/proto_conversion.cc b/chrome/browser/notifications/scheduler/internal/proto_conversion.cc index a318812..8eb7e08f 100644 --- a/chrome/browser/notifications/scheduler/internal/proto_conversion.cc +++ b/chrome/browser/notifications/scheduler/internal/proto_conversion.cc
@@ -415,11 +415,8 @@ proto->set_create_time(TimeToMilliseconds(entry->create_time)); auto* proto_notification_data = proto->mutable_notification_data(); NotificationDataToProto(&entry->notification_data, proto_notification_data); - for (const auto& icon_id : entry->icons_uuid) { - auto* proto_icon_id = proto_notification_data->add_icon_uuid(); - *proto_icon_id = icon_id; - } - + proto_notification_data->set_small_icon_uuid(entry->small_icon_uuid); + proto_notification_data->set_large_icon_uuid(entry->large_icon_uuid); auto* proto_schedule_params = proto->mutable_schedule_params(); ScheduleParamsToProto(&entry->schedule_params, proto_schedule_params); } @@ -431,10 +428,8 @@ entry->create_time = MillisecondsToTime(proto->create_time()); NotificationDataFromProto(proto->mutable_notification_data(), &entry->notification_data); - for (int i = 0; i < proto->notification_data().icon_uuid_size(); ++i) { - entry->icons_uuid.emplace_back(proto->notification_data().icon_uuid(i)); - } - + entry->small_icon_uuid = proto->notification_data().small_icon_uuid(); + entry->large_icon_uuid = proto->notification_data().large_icon_uuid(); ScheduleParamsFromProto(proto->mutable_schedule_params(), &entry->schedule_params); }
diff --git a/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc b/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc index 42f81d93..2599af4 100644 --- a/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc +++ b/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc
@@ -191,7 +191,8 @@ // Test notification data. entry.notification_data.title = base::UTF8ToUTF16("title"); entry.notification_data.message = base::UTF8ToUTF16("message"); - entry.icons_uuid = {"icon_uuid_0", "icon_uuid_1"}; + entry.small_icon_uuid = "small_icon_uuid"; + entry.large_icon_uuid = "large_icon_uuid"; entry.notification_data.custom_data = {{"url", "https://www.example.com"}}; TestNotificationEntryConversion(&entry);
diff --git a/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.cc b/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.cc index f4302c69..8e71f0f 100644 --- a/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.cc +++ b/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.cc
@@ -57,16 +57,12 @@ NotificationStore notification_store, std::unique_ptr<IconStore> icon_store, const std::vector<SchedulerClientType>& clients, - const SchedulerConfig& config, - EncodeIconsCallback encode_icons_callback, - DecodeIconsCallback decode_icons_callback) + const SchedulerConfig& config) : notification_store_(std::move(notification_store)), icon_store_(std::move(icon_store)), clients_(clients.begin(), clients.end()), delegate_(nullptr), - config_(config), - encode_icons_callback_(std::move(encode_icons_callback)), - decode_icons_callback_(std::move(decode_icons_callback)) {} + config_(config) {} private: void Init(Delegate* delegate, InitCallback callback) override { @@ -130,7 +126,7 @@ notification_store_->Delete( guid, base::BindOnce(&ScheduledNotificationManagerImpl::OnNotificationDeleted, - weak_ptr_factory_.GetWeakPtr(), entry->icons_uuid)); + weak_ptr_factory_.GetWeakPtr())); if (delegate_) delegate_->DisplayNotification(std::move(entry)); @@ -176,7 +172,7 @@ entry.guid, base::BindOnce( &ScheduledNotificationManagerImpl::OnNotificationDeleted, - weak_ptr_factory_.GetWeakPtr(), entry.icons_uuid)); + weak_ptr_factory_.GetWeakPtr())); } notifications_.erase(type); } @@ -213,7 +209,7 @@ entry->guid, base::BindOnce( &ScheduledNotificationManagerImpl::OnNotificationDeleted, - weak_ptr_factory_.GetWeakPtr(), entry->icons_uuid)); + weak_ptr_factory_.GetWeakPtr())); } else if (clients_.count(entry->type)) { notifications_[entry->type].emplace(entry->guid, std::move(*it)); } @@ -242,55 +238,16 @@ notifications_.erase(type); return; } - - // TODO(hesen): Address only first icon for now. Handle all icons situation - // in following CLs. - if (entry->notification_data.icons.empty()) - return; - - encode_icons_callback_.Run( - std::move(entry->notification_data.icons.front()), - base::BindOnce(&ScheduledNotificationManagerImpl::OnIconEncoded, - weak_ptr_factory_.GetWeakPtr(), type, std::move(guid))); - } - - void OnIconEncoded(SchedulerClientType type, - std::string guid, - std::string encoded_data) { - IconEntry icon_entry; - auto icon_uuid = base::GenerateGUID(); - icon_entry.uuid = icon_uuid; - icon_entry.data = std::move(encoded_data); - icon_store_->Add( - std::move(icon_entry), - base::BindOnce(&ScheduledNotificationManagerImpl::OnIconAdded, - weak_ptr_factory_.GetWeakPtr(), type, std::move(guid), - std::move(icon_uuid))); } void OnIconAdded(SchedulerClientType type, std::string guid, std::string icon_uuid, bool success) { - auto* entry = FindNotificationEntry(type, std::move(guid)); - // TODO(hesen): Error handling. - if (!entry || !success) - return; - entry->icons_uuid.emplace_back(std::move(icon_uuid)); + NOTIMPLEMENTED(); } - void OnNotificationDeleted(const std::vector<std::string>& icon_uuids, - bool success) { - // TODO(hesen): Error handling. - if (!success) - return; - for (const auto& icon_uuid : icon_uuids) { - icon_store_->Delete( - std::move(icon_uuid), - base::BindOnce(&ScheduledNotificationManagerImpl::OnIconDeleted, - weak_ptr_factory_.GetWeakPtr())); - } - } + void OnNotificationDeleted(bool success) { NOTIMPLEMENTED(); } void OnIconDeleted(bool success) { NOTIMPLEMENTED(); } @@ -327,8 +284,6 @@ std::map<std::string, std::unique_ptr<NotificationEntry>>> notifications_; const SchedulerConfig& config_; - EncodeIconsCallback encode_icons_callback_; - DecodeIconsCallback decode_icons_callback_; base::WeakPtrFactory<ScheduledNotificationManagerImpl> weak_ptr_factory_{ this}; DISALLOW_COPY_AND_ASSIGN(ScheduledNotificationManagerImpl); @@ -341,12 +296,9 @@ std::unique_ptr<CollectionStore<NotificationEntry>> notification_store, std::unique_ptr<IconStore> icon_store, const std::vector<SchedulerClientType>& clients, - const SchedulerConfig& config, - EncodeIconsCallback encode_icons_callback, - DecodeIconsCallback decode_icons_callback) { + const SchedulerConfig& config) { return std::make_unique<ScheduledNotificationManagerImpl>( - std::move(notification_store), std::move(icon_store), clients, config, - std::move(encode_icons_callback), std::move(decode_icons_callback)); + std::move(notification_store), std::move(icon_store), clients, config); } ScheduledNotificationManager::ScheduledNotificationManager() = default;
diff --git a/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h b/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h index b7cba887..593f88f 100644 --- a/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h +++ b/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h
@@ -29,12 +29,6 @@ using Notifications = std::map<SchedulerClientType, std::vector<const NotificationEntry*>>; using InitCallback = base::OnceCallback<void(bool)>; - using EncodeIconsCallback = - base::RepeatingCallback<void(SkBitmap, - base::OnceCallback<void(std::string)>)>; - using DecodeIconsCallback = - base::RepeatingCallback<void(std::string, - base::OnceCallback<void(SkBitmap)>)>; // Delegate that receives events from the manager. class Delegate { @@ -55,9 +49,7 @@ std::unique_ptr<CollectionStore<NotificationEntry>> notification_store, std::unique_ptr<IconStore> icon_store, const std::vector<SchedulerClientType>& clients, - const SchedulerConfig& config, - EncodeIconsCallback encode_icons_callback, - DecodeIconsCallback decode_icons_callback); + const SchedulerConfig& config); // Initializes the notification store. virtual void Init(Delegate* delegate, InitCallback callback) = 0;
diff --git a/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager_unittest.cc b/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager_unittest.cc index fbf8a5b..e91c924 100644 --- a/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager_unittest.cc +++ b/chrome/browser/notifications/scheduler/internal/scheduled_notification_manager_unittest.cc
@@ -31,16 +31,6 @@ const char kGuid[] = "test_guid_1234"; const char kTitle[] = "test_title"; -void NoopConvertIconToString(SkBitmap image, - base::OnceCallback<void(std::string)> callback) { - // TODO(hesen): Need to implement and then move a mock class. -} - -void NoopConvertStringToIcon(std::string data, - base::OnceCallback<void(SkBitmap)> callback) { - // TODO(hesen): Need to implement and then move a mock class. -} - NotificationEntry CreateNotificationEntry(SchedulerClientType type) { return NotificationEntry(type, base::GenerateGUID()); } @@ -113,8 +103,7 @@ std::move(notification_store), std::move(icon_store), {SchedulerClientType::kTest1, SchedulerClientType::kTest2, SchedulerClientType::kTest3}, - config_, base::BindRepeating(&NoopConvertIconToString), - base::BindRepeating(&NoopConvertStringToIcon)); + config_); } protected:
diff --git a/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc b/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc index 6db1d94..f9f86f3 100644 --- a/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc +++ b/chrome/browser/notifications/scheduler/internal/scheduler_utils.cc
@@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/containers/circular_deque.h" #include "base/task/post_task.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/notifications/scheduler/internal/impression_types.h" @@ -16,11 +17,13 @@ namespace notifications { namespace { -using FirstAndLastIters = std::pair<std::deque<Impression>::const_iterator, - std::deque<Impression>::const_iterator>; + +using FirstAndLastIters = + std::pair<base::circular_deque<Impression>::const_iterator, + base::circular_deque<Impression>::const_iterator>; base::Optional<FirstAndLastIters> FindFirstAndLastNotificationShownToday( - const std::deque<Impression>& impressions, + const base::circular_deque<Impression>& impressions, const base::Time& now, const base::Time& beginning_of_today) { if (impressions.empty() || impressions.cbegin()->create_time > now || @@ -41,22 +44,6 @@ return base::make_optional<FirstAndLastIters>(first, last - 1); } -// Converts SkBitmap to String. -std::string ConvertIconToStringOnIOThread(SkBitmap image) { - base::AssertLongCPUWorkAllowed(); - std::vector<unsigned char> image_data; - gfx::PNGCodec::EncodeBGRASkBitmap(std::move(image), false, &image_data); - std::string result(image_data.begin(), image_data.end()); - return result; -} - -// Converts SkBitmap to String. -SkBitmap ConvertStringToIconOnIOThread(std::string data) { - SkBitmap image; - gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(data.data()), - data.length(), &image); - return image; -} } // namespace bool ToLocalHour(int hour, @@ -135,26 +122,4 @@ return client_state; } -// Converts SkBitmap to String. -void ConvertIconToString(SkBitmap image, - base::OnceCallback<void(std::string)> callback) { - DCHECK(callback); - base::PostTaskAndReplyWithResult( - FROM_HERE, - {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING}, - base::BindOnce(&ConvertIconToStringOnIOThread, std::move(image)), - std::move(callback)); -} - -// Converts String to SkBitmap. -void ConvertStringToIcon(std::string data, - base::OnceCallback<void(SkBitmap)> callback) { - DCHECK(callback); - base::PostTaskAndReplyWithResult( - FROM_HERE, - {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING}, - base::BindOnce(&ConvertStringToIconOnIOThread, std::move(data)), - std::move(callback)); -} - } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/internal/scheduler_utils.h b/chrome/browser/notifications/scheduler/internal/scheduler_utils.h index 5389ed5..6e112da 100644 --- a/chrome/browser/notifications/scheduler/internal/scheduler_utils.h +++ b/chrome/browser/notifications/scheduler/internal/scheduler_utils.h
@@ -5,7 +5,6 @@ #ifndef CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_SCHEDULER_UTILS_H_ #define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_SCHEDULER_UTILS_H_ -#include <deque> #include <map> #include <memory> #include <string> @@ -50,14 +49,6 @@ SchedulerClientType type, const SchedulerConfig& config); -// Converts SkBitmap icon to String. -void ConvertIconToString(SkBitmap image, - base::OnceCallback<void(std::string)> callback); - -// Converts String to SkBitmap icon. -void ConvertStringToIcon(std::string data, - base::OnceCallback<void(SkBitmap)> callback); - } // namespace notifications #endif // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_SCHEDULER_UTILS_H_
diff --git a/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc b/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc index 6afb00b..241d8b0 100644 --- a/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc +++ b/chrome/browser/notifications/scheduler/internal/scheduler_utils_unittest.cc
@@ -6,6 +6,7 @@ #include <algorithm> +#include "base/containers/circular_deque.h" #include "base/guid.h" #include "base/test/scoped_task_environment.h" #include "chrome/browser/notifications/scheduler/internal/impression_types.h" @@ -31,9 +32,9 @@ } void CreateFakeImpressions(std::vector<base::Time> times, - std::deque<Impression>& impressions) { + base::circular_deque<Impression>& impressions) { impressions.clear(); - for (auto time : times) { + for (const auto& time : times) { impressions.emplace_back(SchedulerClientType::kTest1, base::GenerateGUID(), time); }
diff --git a/chrome/browser/notifications/scheduler/public/notification_data.cc b/chrome/browser/notifications/scheduler/public/notification_data.cc index 76578bc..5d573d7 100644 --- a/chrome/browser/notifications/scheduler/public/notification_data.cc +++ b/chrome/browser/notifications/scheduler/public/notification_data.cc
@@ -15,13 +15,15 @@ NotificationData::Button::~Button() = default; +NotificationData::Icon::Icon() = default; +NotificationData::Icon::~Icon() = default; + NotificationData::NotificationData() = default; NotificationData::NotificationData(const NotificationData& other) = default; bool NotificationData::operator==(const NotificationData& other) const { return title == other.title && message == other.message && - icons.size() == other.icons.size() && custom_data == other.custom_data && buttons == other.buttons; }
diff --git a/chrome/browser/notifications/scheduler/public/notification_data.h b/chrome/browser/notifications/scheduler/public/notification_data.h index 16c0f745..f7cdd73 100644 --- a/chrome/browser/notifications/scheduler/public/notification_data.h +++ b/chrome/browser/notifications/scheduler/public/notification_data.h
@@ -38,6 +38,14 @@ std::string id; }; + struct Icon { + Icon(); + ~Icon(); + + // The icon bitmap. + SkBitmap bitmap; + }; + using CustomData = std::map<std::string, std::string>; NotificationData(); NotificationData(const NotificationData& other); @@ -50,9 +58,11 @@ // The body text of the notification. base::string16 message; - // A list of icons. On Android, the first element will be used as small icon, - // the second as large icon(optional). - std::vector<SkBitmap> icons; + // The small icon of the notification. + Icon small_icon; + + // The large icon of the notification. + Icon large_icon; // Custom key value pair data associated with each notification. Will be sent // back after user interaction.
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc index 7ea1305..f125b1b 100644 --- a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc +++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/notifications/scheduler/internal/background_task_coordinator.h" #include "chrome/browser/notifications/scheduler/internal/display_decider.h" #include "chrome/browser/notifications/scheduler/internal/distribution_policy.h" +#include "chrome/browser/notifications/scheduler/internal/icon_converter_impl.h" #include "chrome/browser/notifications/scheduler/internal/icon_store.h" #include "chrome/browser/notifications/scheduler/internal/impression_history_tracker.h" #include "chrome/browser/notifications/scheduler/internal/impression_store.h" @@ -64,7 +65,8 @@ auto icon_db = db_provider->GetDB<proto::Icon, IconEntry>( leveldb_proto::ProtoDbType::NOTIFICATION_SCHEDULER_ICON_STORE, icon_store_dir, task_runner); - auto icon_store = std::make_unique<IconProtoDbStore>(std::move(icon_db)); + auto icon_store = std::make_unique<IconProtoDbStore>( + std::move(icon_db), std::make_unique<IconConverterImpl>()); // Build impression tracker. base::FilePath impression_store_dir = storage_dir.Append(kImpressionDBName); @@ -89,15 +91,9 @@ auto notification_store = std::make_unique<NotificationStore>(std::move(notification_db)); - auto encode_icons_callback = - base::BindRepeating(¬ifications::ConvertIconToString); - auto decode_icons_callback = - base::BindRepeating(¬ifications::ConvertStringToIcon); - auto notification_manager = ScheduledNotificationManager::Create( std::move(notification_store), std::move(icon_store), registered_clients, - *config.get(), std::move(encode_icons_callback), - std::move(decode_icons_callback)); + *config.get()); auto background_task_coordinator = BackgroundTaskCoordinator::Create( std::move(background_task_scheduler), config.get(),
diff --git a/chrome/browser/notifications/scheduler/test/test_utils.cc b/chrome/browser/notifications/scheduler/test/test_utils.cc index c12399d7..4e1da96 100644 --- a/chrome/browser/notifications/scheduler/test/test_utils.cc +++ b/chrome/browser/notifications/scheduler/test/test_utils.cc
@@ -105,10 +105,8 @@ << " : " << static_cast<int>(mapping.second); } - stream << " \n icons_id:"; - for (const auto& icon_id : entry->icons_uuid) - stream << icon_id << " "; - + stream << " \n small_icons_id:" << entry->small_icon_uuid << " "; + stream << " \n large_icons_id:" << entry->large_icon_uuid << " "; return stream.str(); }
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc index 499aed57..bca3d5c 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -408,7 +408,8 @@ if (!hints_fetcher_) { hints_fetcher_ = std::make_unique<optimization_guide::HintsFetcher>( url_loader_factory_, - optimization_guide::features::GetOptimizationGuideServiceURL()); + optimization_guide::features::GetOptimizationGuideServiceURL(), + pref_service_); } hints_fetcher_->FetchOptimizationGuideServiceHints( top_hosts, base::BindOnce(&OptimizationGuideHintsManager::OnHintsFetched, @@ -648,4 +649,6 @@ void OptimizationGuideHintsManager::ClearFetchedHints() { hint_cache_->ClearFetchedHints(); + optimization_guide::HintsFetcher::ClearHostsSuccessfullyFetched( + pref_service_); }
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc index b9a47bbf..274c1b7 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
@@ -130,8 +130,11 @@ TestHintsFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GURL optimization_guide_service_url, - HintsFetcherEndState fetch_state) - : HintsFetcher(url_loader_factory, optimization_guide_service_url), + HintsFetcherEndState fetch_state, + PrefService* pref_service) + : HintsFetcher(url_loader_factory, + optimization_guide_service_url, + pref_service), fetch_state_(fetch_state) {} bool FetchOptimizationGuideServiceHints( @@ -265,8 +268,9 @@ std::unique_ptr<TestHintsFetcher> BuildTestHintsFetcher( HintsFetcherEndState end_state) { std::unique_ptr<TestHintsFetcher> hints_fetcher = - std::make_unique<TestHintsFetcher>( - url_loader_factory_, GURL("https://hintsserver.com"), end_state); + std::make_unique<TestHintsFetcher>(url_loader_factory_, + GURL("https://hintsserver.com"), + end_state, pref_service()); return hints_fetcher; }
diff --git a/chrome/browser/predictors/preconnect_manager.cc b/chrome/browser/predictors/preconnect_manager.cc index 7f42bd7..c3c7d42 100644 --- a/chrome/browser/predictors/preconnect_manager.cc +++ b/chrome/browser/predictors/preconnect_manager.cc
@@ -14,7 +14,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" -#include "net/base/load_flags.h" #include "services/network/public/mojom/network_context.mojom.h" namespace predictors { @@ -169,16 +168,7 @@ if (!network_context) return; - bool privacy_mode = false; - int load_flags = net::LOAD_NORMAL; - - if (!allow_credentials) { - privacy_mode = true; - load_flags = net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA; - } - - network_context->PreconnectSockets(num_sockets, url, load_flags, privacy_mode, + network_context->PreconnectSockets(num_sockets, url, allow_credentials, network_isolation_key); }
diff --git a/chrome/browser/predictors/preconnect_manager_unittest.cc b/chrome/browser/predictors/preconnect_manager_unittest.cc index 5420498..c69e9a2 100644 --- a/chrome/browser/predictors/preconnect_manager_unittest.cc +++ b/chrome/browser/predictors/preconnect_manager_unittest.cc
@@ -35,11 +35,6 @@ namespace { -constexpr int kNormalLoadFlags = net::LOAD_NORMAL; -constexpr int kPrivateLoadFlags = net::LOAD_DO_NOT_SEND_COOKIES | - net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA; - net::ProxyInfo GetIndirectProxyInfo() { net::ProxyInfo proxy_info; proxy_info.UseNamedProxy("proxy.com"); @@ -137,11 +132,10 @@ void EnableProxyTesting() { enabled_proxy_testing_ = true; } MOCK_METHOD1(ResolveHostProxy, void(const std::string& host)); - MOCK_METHOD5(PreconnectSockets, + MOCK_METHOD4(PreconnectSockets, void(uint32_t num_streams, const GURL& url, - int32_t load_flags, - bool privacy_mode_enabled, + bool allow_credentials, const net::NetworkIsolationKey& network_isolation_key)); private: @@ -227,10 +221,10 @@ preconnect_manager_->Start( main_frame_url, {PreconnectRequest(url_to_preconnect, 1, network_isolation_key)}); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK); } @@ -247,10 +241,10 @@ preconnect_manager_->Start( main_frame_url, {PreconnectRequest(url_to_preconnect, 1, network_isolation_key)}); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK); } @@ -286,17 +280,17 @@ VerifyAndClearExpectations(); // Now, restart the preconnect request. - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, requests.back().origin, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, requests.back().origin, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_network_context_, ResolveHostProxy(requests.back().origin.host())); for (size_t i = 0; i < count; ++i) { - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, requests[i].origin, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, requests[i].origin, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_network_context_, ResolveHostProxy(requests[i].origin.host())); } @@ -336,10 +330,10 @@ } EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url_1)); for (size_t i = 0; i < count - 1; ++i) { - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, requests[i].origin, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key_1)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, requests[i].origin, true /* allow credentials */, + network_isolation_key_1)); } preconnect_manager_->Start( @@ -375,14 +369,14 @@ std::vector<PreconnectRequest>( requests.begin() + count - 1, requests.end())); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, requests[count - 1].origin, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key_2)); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, requests[count].origin, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key_2)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, requests[count - 1].origin, + true /* allow credentials */, network_isolation_key_2)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, requests[count].origin, true /* allow credentials */, + network_isolation_key_2)); mock_network_context_->CompleteHostLookup(requests[count - 1].origin.host(), net::OK); @@ -445,14 +439,14 @@ EXPECT_CALL(*mock_network_context_, ResolveHostProxy(url_to_preconnect_2.host())); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url_2)); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect_1, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key_2)); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect_2, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key_2)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect_1, true /* allow credentials */, + network_isolation_key_2)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect_2, true /* allow credentials */, + network_isolation_key_2)); preconnect_manager_->Start( main_frame_url_2, {PreconnectRequest(url_to_preconnect_1, 1, network_isolation_key_2), @@ -497,14 +491,14 @@ ResolveHostProxy(url_to_preconnect_1.host())); EXPECT_CALL(*mock_network_context_, ResolveHostProxy(url_to_preconnect_2.host())); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect_1, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect_2, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect_1, true /* allow credentials */, + network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect_2, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); preconnect_manager_->Start( main_frame_url, @@ -602,10 +596,10 @@ preconnect_manager_->Stop(main_frame_url2); // Stopping the second url shouldn't stop the first one. - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect1, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key1)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect1, true /* allow credentials */, + network_isolation_key1)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url1)); mock_network_context_->CompleteHostLookup(url_to_preconnect1.host(), net::OK); // No preconnect for the second url. @@ -636,10 +630,10 @@ main_frame_url2, {PreconnectRequest(url_to_preconnect2, 1, network_isolation_key2)}); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect1, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key1)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect1, true /* allow credentials */, + network_isolation_key1)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url1)); mock_network_context_->CompleteHostLookup(url_to_preconnect1.host(), net::OK); } @@ -680,9 +674,9 @@ preconnect_manager_->StartPreconnectUrl(url, allow_credentials, network_isolation_key); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, origin, kPrivateLoadFlags, - !allow_credentials, network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, origin, allow_credentials, network_isolation_key)); mock_network_context_->CompleteHostLookup(origin.host(), net::OK); // Non http url shouldn't be preconnected. @@ -703,9 +697,9 @@ preconnect_manager_->StartPreconnectUrl(url, allow_credentials, network_isolation_key); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, origin, kPrivateLoadFlags, - !allow_credentials, network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, origin, allow_credentials, network_isolation_key)); mock_network_context_->CompleteHostLookup(origin.host(), net::OK); } @@ -760,10 +754,10 @@ main_frame_url, {PreconnectRequest(url_to_preconnect, 1, network_isolation_key)}); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); mock_network_context_->CompleteProxyLookup(url_to_preconnect, GetIndirectProxyInfo()); @@ -792,14 +786,14 @@ mock_network_context_->CompleteProxyLookup(url_to_preconnect2, base::nullopt); Mock::VerifyAndClearExpectations(mock_network_context_.get()); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); - EXPECT_CALL(*mock_network_context_, - PreconnectSockets(1, url_to_preconnect2, kNormalLoadFlags, - false /* privacy_mode_enabled */, - network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect, true /* allow credentials */, + network_isolation_key)); + EXPECT_CALL( + *mock_network_context_, + PreconnectSockets(1, url_to_preconnect2, true /* allow credentials */, + network_isolation_key)); EXPECT_CALL(*mock_delegate_, PreconnectFinishedProxy(main_frame_url)); mock_network_context_->CompleteHostLookup(url_to_preconnect.host(), net::OK); mock_network_context_->CompleteHostLookup(url_to_preconnect2.host(), net::OK);
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 1e5e963b..b00c2af0 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -31,6 +31,8 @@ #include "chrome/browser/download/chrome_download_manager_delegate.h" #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" +#include "chrome/browser/native_file_system/chrome_native_file_system_permission_context.h" +#include "chrome/browser/native_file_system/native_file_system_permission_context_factory.h" #include "chrome/browser/permissions/permission_manager.h" #include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/plugins/chrome_plugin_service_filter.h" @@ -525,6 +527,11 @@ return profile_->GetSharedCorsOriginAccessList(); } +content::NativeFileSystemPermissionContext* +OffTheRecordProfileImpl::GetNativeFileSystemPermissionContext() { + return NativeFileSystemPermissionContextFactory::GetForProfile(this).get(); +} + bool OffTheRecordProfileImpl::IsSameProfile(Profile* profile) { return (profile == this) || (profile == profile_); }
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h index 534ff351..78d0d26 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.h +++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -124,6 +124,8 @@ std::vector<network::mojom::CorsOriginPatternPtr> block_patterns, base::OnceClosure closure) override; content::SharedCorsOriginAccessList* GetSharedCorsOriginAccessList() override; + content::NativeFileSystemPermissionContext* + GetNativeFileSystemPermissionContext() override; private: void InitIoData();
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index e3691e7..d1b6a8b 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -3,7 +3,6 @@ # found in the LICENSE file. import("//chrome/common/features.gni") -import("//chrome/test/base/js2gtest.gni") import("//tools/grit/grit_rule.gni") assert(!is_ios, "Chromium/iOS shouldn't use anything in //chrome") @@ -328,28 +327,3 @@ ] } } - -js2gtest("resources_unitjs_tests") { - test_type = "webui" - sources = [ - "gaia_auth_host/password_change_authenticator_test.unitjs", - ] - - # This has to be a gen_include, so it doesn't collide with other js2gtests - gen_include_files = [ "//ui/webui/resources/js/cr.js" ] - - # But these have to be extra_js_files, since it uses a native object - # EventTarget, which doesn't work at compile time. - extra_js_files = [ - "//ui/webui/resources/js/cr/event_target.js", - "gaia_auth_host/password_change_authenticator.js", - ] - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] -} - -source_set("browser_tests") { - testonly = true - deps = [ - ":resources_unitjs_tests", - ] -}
diff --git a/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js b/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js index 4aa27d7..0f5fa46 100644 --- a/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js +++ b/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js
@@ -15,54 +15,6 @@ const BLANK_PAGE_URL = 'about:blank'; /** - * @param {string?} str A string that should be a valid URL. - * @return {URL?} A valid URL object, or null. - */ - function safeParseUrl_(str) { - try { - return new URL(str); - } catch (error) { - console.error('Invalid url: ' + str); - return null; - } - } - - /** - * @param {Object} details The web-request details. - * @return {boolean} True if we detect that a password change was successful. - */ - function detectPasswordChangeSuccess(details) { - const url = safeParseUrl_(details.url); - if (!url) { - return false; - } - - // These heuristics work for the following SAML IdPs: - // ADFS: - if (url.pathname.match(/\/updatepassword\/?$/)) { - return url.searchParams.get('status') == '0'; - } - // Azure: - if (url.pathname.endsWith('/ChangePassword.aspx')) { - return url.searchParams.get('ReturnCode') == '0'; - } - // Okta: - if (url.pathname.match(/\/internal_login\/password\/?$/)) { - // TODO(https://crbug.com/930109): This assumes all Okta password change - // attempts succeed. To check properly, we need to inspect the response. - return details.method == 'POST'; - } - // Ping: - if (url.pathname.includes('/password/chg/')) { - // TODO(https://crbug.com/930109): This assumes all Ping password change - // attempts succeed. To check properly, we need to inspect the response. - return details.method == 'POST'; - } - - return false; - } - - /** * Initializes the authenticator component. */ class Authenticator extends cr.EventTarget { @@ -115,9 +67,8 @@ this.samlHandler_, 'authPageLoaded', this.onAuthPageLoaded_.bind(this)); - this.webviewEventManager_.addWebRequestEventListener( - this.webview_.request.onCompleted, this.onCompleted_.bind(this), - {urls: ['http://*/*', 'https://*/*'], types: ['main_frame']}); + this.webviewEventManager_.addEventListener( + this.webview_, 'contentload', this.onContentLoad_.bind(this)); } /** @@ -200,19 +151,17 @@ } /** - * Invoked when a new document loading completes. - * @param {Object} details The web-request details. + * Invoked when a new document is loaded. * @private */ - onCompleted_(details) { - if (passwordChangeSuccessDetected(details)) { + onContentLoad_(e) { + const currentUrl = this.webview_.src; + // TODO(rsorokin): Implement more robust check. + if (currentUrl.lastIndexOf('status=0') != -1) { this.completeAuth_(); } } } - return { - Authenticator: Authenticator, - detectPasswordChangeSuccess: detectPasswordChangeSuccess, - }; + return {Authenticator: Authenticator}; });
diff --git a/chrome/browser/resources/gaia_auth_host/password_change_authenticator_test.unitjs b/chrome/browser/resources/gaia_auth_host/password_change_authenticator_test.unitjs deleted file mode 100644 index b8dd250..0000000 --- a/chrome/browser/resources/gaia_auth_host/password_change_authenticator_test.unitjs +++ /dev/null
@@ -1,102 +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. - -GEN_INCLUDE(['//ui/webui/resources/js/cr.js']); - -const EXAMPLE_ADFS_ENDPOINT = - 'https://example.com/adfs/portal/updatepassword/'; - -const EXAMPLE_AZURE_ENDPOINT = - 'https://example.windowsazure.com/ChangePassword.aspx'; - -const EXAMPLE_OKTA_ENDPOINT = - 'https://example.okta.com/user/profile/internal_login/password'; - -const EXAMPLE_PING_ENDPOINT = - 'https://login.pingone.com/idp/directory/a/12345/password/chg/67890'; - -PasswordChangeAuthenticatorUnitTest = class extends testing.Test { - get browsePreload() { - return DUMMY_URL; - } - - // No need to run these checks - see comment in SamlPasswordAttributesTest. - get runAccessibilityChecks() { - return false; - } - - get extraLibraries() { - return [ - '//ui/webui/resources/js/cr/event_target.js', - 'password_change_authenticator.js', - ]; - } - - assertSuccess(input) { - assertTrue(this.detectSuccess(input)); - } - - assertNotSuccess(input) { - assertFalse(this.detectSuccess(input)); - } - - detectSuccess(input) { - let details; - if (typeof input == 'string') { - details = {'url': input}; - } else { - details = input; - } - return cr.samlPasswordChange.detectPasswordChangeSuccess(details); - } -} - -TEST_F('PasswordChangeAuthenticatorUnitTest', 'DetectAdfsSuccess', function() { - const endpointUrl = EXAMPLE_ADFS_ENDPOINT; - - this.assertNotSuccess(endpointUrl); - this.assertNotSuccess(endpointUrl + '?status=1'); - this.assertNotSuccess(EXAMPLE_AZURE_ENDPOINT + '?status=0'); - - this.assertSuccess(endpointUrl + '?status=0'); -}); - -TEST_F('PasswordChangeAuthenticatorUnitTest', 'DetectAzureSuccess', function() { - const endpointUrl = EXAMPLE_AZURE_ENDPOINT; - const extraParam = 'BrandContextID=O123'; - - this.assertNotSuccess(endpointUrl); - this.assertNotSuccess(endpointUrl + '?' + extraParam); - this.assertNotSuccess(endpointUrl + '?ReturnCode=1&' + extraParam); - this.assertNotSuccess(endpointUrl + '?' + extraParam + '&ReturnCode=1'); - this.assertNotSuccess(EXAMPLE_PING_ENDPOINT + '?ReturnCode=0'); - - this.assertSuccess(endpointUrl + '?ReturnCode=0&' + extraParam); - this.assertSuccess(endpointUrl + '?' + extraParam + '&ReturnCode=0'); -}); - -TEST_F('PasswordChangeAuthenticatorUnitTest', 'DetectOktaSuccess', function() { - const endpointUrl = EXAMPLE_OKTA_ENDPOINT - - let details = {url: endpointUrl, method: 'GET'}; - this.assertNotSuccess(details); - - details = {url: EXAMPLE_ADFS_ENDPOINT, method: 'POST'}; - this.assertNotSuccess(details); - - details = {url: endpointUrl, method: 'POST'}; - this.assertSuccess(details); -}); - -TEST_F('PasswordChangeAuthenticatorUnitTest', 'DetectPingSuccess', function() { - const endpointUrl = EXAMPLE_PING_ENDPOINT; - - let details = {url: endpointUrl, method: 'GET'}; - this.assertNotSuccess(details); - details = {url: EXAMPLE_AZURE_ENDPOINT, method: 'POST'}; - this.assertNotSuccess(details); - - details = {url: endpointUrl, method: 'POST'}; - this.assertSuccess(details); -});
diff --git a/chrome/browser/resources/local_ntp/customize.css b/chrome/browser/resources/local_ntp/customize.css index 7e0e808d..ec34586 100644 --- a/chrome/browser/resources/local_ntp/customize.css +++ b/chrome/browser/resources/local_ntp/customize.css
@@ -95,6 +95,7 @@ color: rgb(var(--GB600-rgb)); display: none; font-size: 14px; + line-height: 1; padding-inline-end: 12px; padding-inline-start: 8px; user-select: none;
diff --git a/chrome/browser/resources/local_ntp/customize.js b/chrome/browser/resources/local_ntp/customize.js index c814868..6b4770b 100644 --- a/chrome/browser/resources/local_ntp/customize.js +++ b/chrome/browser/resources/local_ntp/customize.js
@@ -322,8 +322,6 @@ $(customize.IDS.UPLOAD_IMAGE).hidden = false; $(customize.IDS.RESTORE_DEFAULT).hidden = false; $(customize.IDS.EDIT_BG_DIVIDER).hidden = false; - $(customize.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).hidden = - configData.hideShortcuts; $(customize.IDS.COLORS_BUTTON).hidden = !configData.chromeColors; $(customize.IDS.COLOR_PICKER_CONTAINER) .classList.toggle( @@ -971,8 +969,6 @@ return; } - $(customize.IDS.REFRESH_TOGGLE).checked = false; - if (customize.selectedOptions.background && customize.selectedOptions.background.id == tile.id) { // If the clicked tile is already selected do nothing. @@ -983,6 +979,8 @@ customize.selectedOptions.background); } + $(customize.IDS.REFRESH_TOGGLE).checked = false; + // Remove any existing preview. customize.richerPicker_unpreviewImage(); @@ -1056,6 +1054,7 @@ customize.selectedOptions.background); } + customize.selectedOptions.background = null; customize.selectedOptions.backgroundData = { id: '', url: '',
diff --git a/chrome/browser/resources/local_ntp/externs.js b/chrome/browser/resources/local_ntp/externs.js index 6f8042f..56213db 100644 --- a/chrome/browser/resources/local_ntp/externs.js +++ b/chrome/browser/resources/local_ntp/externs.js
@@ -29,7 +29,6 @@ * @typedef {{chromeColors: boolean, * enableShortcutsGrid: boolean, * googleBaseUrl: string, - * hideShortcuts: boolean, * isAccessibleBrowser: boolean, * isGooglePage: boolean, * richerPicker: boolean,
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css index def03ea..430f7b4 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.css +++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -36,7 +36,6 @@ /* These can be overridden by themes. */ --text-color: #000; --text-color-light: #fff; - --text-color-link: rgb(17, 85, 204); height: 100%; } @@ -46,7 +45,6 @@ /* These can be overridden by themes. */ --text-color: rgb(var(--GG200-rgb)); --text-color-light: rgb(var(--GG200-rgb)); - --text-color-link: rgb(var(--GB400-dark-rgb)); } } @@ -700,7 +698,6 @@ box-shadow: 0 1px 3px 0 rgba(var(--GG800-rgb), .3), 0 4px 8px 3px rgba(var(--GG800-rgb), .15); color: rgb(var(--GG700-rgb)); - font-size: 0; /* Remove extra spacing between inline-block elements. */ height: 528px; min-width: 800px; padding: 0; @@ -715,10 +712,6 @@ } } -#customization-menu > div { - font-size: 13px; -} - #menu-nav-panel { display: inline-block; height: 384px; @@ -887,8 +880,11 @@ margin-inline-end: 8px; } +#menu-inner { + display: flex; +} + #menu-contents { - display: inline-block; height: 464px; margin-inline-start: 40px; position: relative; @@ -896,6 +892,8 @@ } .menu-panel { + display: flex; + flex-flow: wrap; height: 384px; left: 0; /* Pad the content by 5px top/left. This will prevent the focus outline on @@ -918,6 +916,7 @@ #backgrounds-menu .bg-sel-tile-bg, #backgrounds-image-menu .bg-sel-tile-bg { border-radius: 4px; + display: block; height: 176px; margin-bottom: 45px; margin-inline-end: 8px; @@ -1003,12 +1002,6 @@ } } -#backgrounds-menu, -#colors-menu { - /* Remove extra spacing between inline-block elements. */ - font-size: 0; -} - #backgrounds-upload.bg-sel-tile-bg { background-color: transparent; vertical-align: top; @@ -1576,6 +1569,7 @@ border-radius: 50%; box-sizing: border-box; cursor: pointer; + display: block; height: var(--tile-size); margin-bottom: var(--tile-margin); margin-inline-end: var(--tile-margin);
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index a20cc58..8ad247f 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -170,172 +170,176 @@ </dialog> <dialog id="customization-menu" class="customize-dialog"> - <div id="menu-nav-panel" role="tablist" aria-label="$i18n{customizeMenu}"> - <button id="backgrounds-button" class="menu-option" tabindex="0" - role="tab" aria-controls="backgrounds-menu backgrounds-image-menu" - aria-selected="true" aria-labelledby="backgrounds-menu-option" - title="$i18n{backgroundsOption}"> - <div class="menu-option-icon-wrapper"> - <div id="backgrounds-icon" class="menu-option-icon"></div> - </div> - <div id="backgrounds-menu-option" class="menu-option-label"> - $i18n{backgroundsOption} - </div> - </button> - <button id="shortcuts-button" class="menu-option" tabindex="0" role="tab" - aria-controls="shortcuts-menu" aria-selected="false" - aria-labelledby="shortcuts-menu-option" - title="$i18n{shortcutsOption}"> - <div class="menu-option-icon-wrapper"> - <div id="shortcuts-icon" class="menu-option-icon"></div> - </div> - <div id="shortcuts-menu-option" class="menu-option-label"> - $i18n{shortcutsOption} - </div> - </button> - <button id="colors-button" class="menu-option" tabindex="0" role="tab" - aria-controls="colors-menu" aria-selected="false" - aria-labelledby="colors-menu-option" title="$i18n{colorsOption}"> - <div class="menu-option-icon-wrapper"> - <div id="colors-icon" class="menu-option-icon"></div> - </div> - <div id="colors-menu-option" class="menu-option-label"> - $i18n{colorsOption} - </div> - </button> - </div> - <div id="menu-contents"> - <div id="menu-header"> - <div id="menu-back-circle" tabindex="0" role="button" - aria-label="$i18n{backLabel}" title="$i18n{backLabel}"> - <div id="menu-back"></div> - </div> - <div id="menu-title">$i18n{customizeMenu}</div> - <div id="refresh-daily-wrapper"> - <div id="refresh-toggle-wrapper" title="$i18n{refreshDaily}"> - <label class="switch"> - <input id="refresh-daily-toggle" type="checkbox" - aria-labelledby="refresh-text"></input> - <span class="toggle"> - <div class="knob"></div> - <div class="highlight"></div> - </span> - </label> + <div id="menu-inner"> + <div id="menu-nav-panel" role="tablist" aria-label="$i18n{customizeMenu}"> + <button id="backgrounds-button" class="menu-option" tabindex="0" + role="tab" aria-controls="backgrounds-menu backgrounds-image-menu" + aria-selected="true" aria-labelledby="backgrounds-menu-option" + title="$i18n{backgroundsOption}"> + <div class="menu-option-icon-wrapper"> + <div id="backgrounds-icon" class="menu-option-icon"></div> </div> - <div id="refresh-text">$i18n{refreshDaily}</div> - </div> + <div id="backgrounds-menu-option" class="menu-option-label"> + $i18n{backgroundsOption} + </div> + </button> + <button id="shortcuts-button" class="menu-option" tabindex="0" + role="tab" aria-controls="shortcuts-menu" aria-selected="false" + aria-labelledby="shortcuts-menu-option" + title="$i18n{shortcutsOption}"> + <div class="menu-option-icon-wrapper"> + <div id="shortcuts-icon" class="menu-option-icon"></div> + </div> + <div id="shortcuts-menu-option" class="menu-option-label"> + $i18n{shortcutsOption} + </div> + </button> + <button id="colors-button" class="menu-option" tabindex="0" role="tab" + aria-controls="colors-menu" aria-selected="false" + aria-labelledby="colors-menu-option" title="$i18n{colorsOption}"> + <div class="menu-option-icon-wrapper"> + <div id="colors-icon" class="menu-option-icon"></div> + </div> + <div id="colors-menu-option" class="menu-option-label"> + $i18n{colorsOption} + </div> + </button> </div> - <div id="backgrounds-menu" class="menu-panel" tabindex="0" - role="tabpanel" aria-label="$i18n{backgroundsOption}"> - <div id="backgrounds-upload" class="bg-sel-tile-bg"> - <div id="backgrounds-upload-icon" class="bg-sel-tile" tabindex="-1" - role="button" aria-label="$i18n{uploadImage}" - aria-pressed="false" title="$i18n{uploadImage}"> - <div id="backgrounds-upload-arrow"></div> - <div id="backgrounds-upload-text">$i18n{uploadImage}</div> + <div id="menu-contents"> + <div id="menu-header"> + <div id="menu-back-circle" tabindex="0" role="button" + aria-label="$i18n{backLabel}" title="$i18n{backLabel}"> + <div id="menu-back"></div> + </div> + <div id="menu-title">$i18n{customizeMenu}</div> + <div id="refresh-daily-wrapper"> + <div id="refresh-toggle-wrapper" title="$i18n{refreshDaily}"> + <label class="switch"> + <input id="refresh-daily-toggle" type="checkbox" + aria-labelledby="refresh-text"></input> + <span class="toggle"> + <div class="knob"></div> + <div class="highlight"></div> + </span> + </label> + </div> + <div id="refresh-text">$i18n{refreshDaily}</div> </div> </div> - <div id="backgrounds-default" class="bg-sel-tile-bg"> - <div id="backgrounds-default-icon" class="bg-sel-tile" tabindex="-1" - role="button" aria-label="$i18n{noBackground}" - title="$i18n{noBackground}" aria-pressed="false"> - <div class="mini-page"> - <div class="mini-header-colorful"></div> - <div class="mini-shortcuts"></div> + <div id="backgrounds-menu" class="menu-panel" tabindex="0" + role="tabpanel" aria-label="$i18n{backgroundsOption}"> + <div id="backgrounds-upload" class="bg-sel-tile-bg"> + <div id="backgrounds-upload-icon" class="bg-sel-tile" tabindex="-1" + role="button" aria-label="$i18n{uploadImage}" + aria-pressed="false" title="$i18n{uploadImage}"> + <div id="backgrounds-upload-arrow"></div> + <div id="backgrounds-upload-text">$i18n{uploadImage}</div> </div> </div> - <div class="bg-sel-tile-title">$i18n{noBackground}</div> - </div> - </div> - <div id="backgrounds-image-menu" class="menu-panel" tabindex="0" - role="tabpanel" aria-label="$i18n{backgroundsOption}"></div> - <div id="shortcuts-menu" class="menu-panel" tabindex="0" role="tabpanel" - aria-label="$i18n{shortcutsOption}"> - <div id="sh-options"> - <div class="sh-option"> - <div id="sh-option-cl" class="sh-option-image" tabindex="-1" - role="button" aria-pressed="false" - aria-labelledby="sh-option-cl-title" title="$i18n{myShortcuts}"> - <div class="sh-option-icon"></div> - <div class="sh-option-mini"> - <div class="mini-page"> - <div class="mini-header"></div> - <div class="mini-shortcuts"></div> - </div> + <div id="backgrounds-default" class="bg-sel-tile-bg"> + <div id="backgrounds-default-icon" class="bg-sel-tile" tabindex="-1" + role="button" aria-label="$i18n{noBackground}" + title="$i18n{noBackground}" aria-pressed="false"> + <div class="mini-page"> + <div class="mini-header-colorful"></div> + <div class="mini-shortcuts"></div> </div> </div> - <div id="sh-option-cl-title" class="sh-option-title"> - $i18n{myShortcuts} - </div> - $i18n{shortcutsCurated} + <div class="bg-sel-tile-title">$i18n{noBackground}</div> </div> - <div class="sh-option"> - <div id="sh-option-mv" class="sh-option-image" tabindex="-1" - role="button" aria-pressed="false" - aria-labelledby="sh-option-mv-title" title="$i18n{mostVisited}"> - <div class="sh-option-icon"></div> - <div class="sh-option-mini"> - <div class="mini-page"> - <div class="mini-header"></div> - <div class="mini-shortcuts"></div> + </div> + <div id="backgrounds-image-menu" class="menu-panel" tabindex="0" + role="tabpanel" aria-label="$i18n{backgroundsOption}"></div> + <div id="shortcuts-menu" class="menu-panel" tabindex="0" role="tabpanel" + aria-label="$i18n{shortcutsOption}"> + <div id="sh-options"> + <div class="sh-option"> + <div id="sh-option-cl" class="sh-option-image" tabindex="-1" + role="button" aria-pressed="false" + aria-labelledby="sh-option-cl-title" + title="$i18n{myShortcuts}"> + <div class="sh-option-icon"></div> + <div class="sh-option-mini"> + <div class="mini-page"> + <div class="mini-header"></div> + <div class="mini-shortcuts"></div> + </div> </div> </div> + <div id="sh-option-cl-title" class="sh-option-title"> + $i18n{myShortcuts} + </div> + $i18n{shortcutsCurated} </div> - <div id="sh-option-mv-title" class="sh-option-title"> - $i18n{mostVisited} + <div class="sh-option"> + <div id="sh-option-mv" class="sh-option-image" tabindex="-1" + role="button" aria-pressed="false" + aria-labelledby="sh-option-mv-title" + title="$i18n{mostVisited}"> + <div class="sh-option-icon"></div> + <div class="sh-option-mini"> + <div class="mini-page"> + <div class="mini-header"></div> + <div class="mini-shortcuts"></div> + </div> + </div> + </div> + <div id="sh-option-mv-title" class="sh-option-title"> + $i18n{mostVisited} + </div> + $i18n{shortcutsSuggested} </div> - $i18n{shortcutsSuggested} </div> - </div> - <div id="sh-hide"> - <div id="sh-hide-icon"></div> - <div> - <div id="sh-hide-title">$i18n{hideShortcuts}</div> - $i18n{hideShortcutsDesc} - </div> - <div id="sh-hide-toggle-wrapper" title="$i18n{hideShortcuts}"> - <label class="switch"> - <input id="sh-hide-toggle" type="checkbox" tabindex="-1" - aria-labelledby="sh-hide-title"></input> - <span class="toggle"> - <div class="knob"></div> - <div class="highlight"></div> - </span> - </label> - </div> - </div> - </div> - <div id="colors-menu" class="menu-panel" tabindex="0" role="tabpanel" - aria-label="$i18n{colorsOption}"> - <div id="colors-theme" tabindex="0"> - <div id="colors-theme-icon"></div> + <div id="sh-hide"> + <div id="sh-hide-icon"></div> <div> - <div id="colors-theme-name"></div> - $i18n{installedThemeDesc} + <div id="sh-hide-title">$i18n{hideShortcuts}</div> + $i18n{hideShortcutsDesc} </div> - <a id="colors-theme-link" target="_blank"> - <div id="colors-theme-link-icon" > </div> - </a> - <button id="colors-theme-uninstall" class="paper secondary"> - $i18n{uninstallButton} - </button> - </div> - <div id="color-picker-container" class="bg-sel-tile-bg"> - <div id="color-picker-tile" class="bg-sel-tile" tabindex="-1" - aria-label="$i18n{colorPickerLabel}" - title="$i18n{colorPickerLabel}" - role="button" aria-pressed="false"> - <div id="left-semicircle"></div> - <div id="color-picker-icon"></div> - <input id="color-picker" type="color" style="display:none"> - </input> + <div id="sh-hide-toggle-wrapper" title="$i18n{hideShortcuts}"> + <label class="switch"> + <input id="sh-hide-toggle" type="checkbox" tabindex="-1" + aria-labelledby="sh-hide-title"></input> + <span class="toggle"> + <div class="knob"></div> + <div class="highlight"></div> + </span> + </label> + </div> </div> </div> - <div id="colors-default" class="bg-sel-tile-bg"> - <div id="colors-default-icon" class="bg-sel-tile" tabindex="-1" - aria-label="$i18n{defaultThemeLabel}" - title="$i18n{defaultThemeLabel}" tabindex="-1" + <div id="colors-menu" class="menu-panel" tabindex="0" role="tabpanel" + aria-label="$i18n{colorsOption}"> + <div id="colors-theme" tabindex="0"> + <div id="colors-theme-icon"></div> + <div> + <div id="colors-theme-name"></div> + $i18n{installedThemeDesc} + </div> + <a id="colors-theme-link" target="_blank"> + <div id="colors-theme-link-icon" > </div> + </a> + <button id="colors-theme-uninstall" class="paper secondary"> + $i18n{uninstallButton} + </button> + </div> + <div id="color-picker-container" class="bg-sel-tile-bg"> + <div id="color-picker-tile" class="bg-sel-tile" tabindex="-1" + aria-label="$i18n{colorPickerLabel}" + title="$i18n{colorPickerLabel}" role="button" aria-pressed="false"> + <div id="left-semicircle"></div> + <div id="color-picker-icon"></div> + <input id="color-picker" type="color" style="display:none"> + </input> + </div> + </div> + <div id="colors-default" class="bg-sel-tile-bg"> + <div id="colors-default-icon" class="bg-sel-tile" tabindex="-1" + aria-label="$i18n{defaultThemeLabel}" + title="$i18n{defaultThemeLabel}" tabindex="-1" + role="button" aria-pressed="false"> + </div> </div> </div> </div>
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index 8d5565e..8430b5ad 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -508,8 +508,6 @@ document.body.style.setProperty('--text-color', textColor); document.body.style.setProperty('--text-color-light', textColorLight); - // Themes reuse the "light" text color for links too. - document.body.style.setProperty('--text-color-link', textColorLight); } /** @@ -922,7 +920,7 @@ if ($(IDS.PROMO)) { $(IDS.PROMO).classList.add(CLASSES.SHOW_ELEMENT); } - if (customLinksEnabled() && !configData.hideShortcuts) { + if (customLinksEnabled()) { $(customize.IDS.CUSTOM_LINKS_RESTORE_DEFAULT) .classList.toggle( customize.CLASSES.OPTION_DISABLED, !args.showRestoreDefault); @@ -1243,11 +1241,6 @@ clIframeDialog.classList.add(CLASSES.CUSTOMIZE_DIALOG); clIframeDialog.appendChild(clIframe); document.body.appendChild(clIframeDialog); - - if (configData.hideShortcuts) { - $(IDS.TILES).style.display = 'none'; - clIframeDialog.style.display = 'none'; - } } window.addEventListener('message', handlePostMessage);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html index 92967db..1e2b6f7 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
@@ -49,6 +49,13 @@ --cr-toolbar-search-field-input-color: var(--google-grey-refresh-700); } + cr-drawer { + --cr-separator-line: none; + --cr-drawer-header-color: var(--google-grey-refresh-700); + --cr-drawer-header-font-weight: 500; + --cr-drawer-header-padding: 20px; + } + #cr-container-shadow-top { /* Needs to be higher than #container's z-index to appear above * scrollbars. */
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html index dfe3e958..51b11bf 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
@@ -59,22 +59,22 @@ on-change="onProtocolChange_" disabled="[[!protocolSelectEnabled(isOnline_, networkProtocolActive_)]]"> - <option value="ipp" disabled="[[!networkProtocolActive_]]"> + <option value="ipp"> $i18n{printerProtocolIpp} </option> - <option value="ipps" disabled="[[!networkProtocolActive_]]"> + <option value="ipps"> $i18n{printerProtocolIpps} </option> - <option value="http" disabled="[[!networkProtocolActive_]]"> + <option value="http"> $i18n{printerProtocolHttp} </option> - <option value="https" disabled="[[!networkProtocolActive_]]"> + <option value="https"> $i18n{printerProtocolHttps} </option> - <option value="socket" disabled="[[!networkProtocolActive_]]"> + <option value="socket"> $i18n{printerProtocolAppSocket} </option> - <option value="lpd" disabled="[[!networkProtocolActive_]]"> + <option value="lpd"> $i18n{printerProtocolLpd} </option> <option value="usb" disabled="[[networkProtocolActive_]]">
diff --git a/chrome/browser/resources/tab_strip/tab_strip.html b/chrome/browser/resources/tab_strip/tab_strip.html index c2054bff..697744b 100644 --- a/chrome/browser/resources/tab_strip/tab_strip.html +++ b/chrome/browser/resources/tab_strip/tab_strip.html
@@ -27,6 +27,10 @@ margin: 0; padding: 0; } + + ::-webkit-scrollbar { + display: none; + } </style> </head> <body>
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn b/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn index 63d5e72b..630f878 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn +++ b/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn
@@ -5,14 +5,6 @@ import("//build/config/jumbo.gni") import("//third_party/protobuf/proto_library.gni") -proto_library("test_only_proto") { - testonly = true - generate_python = false - sources = [ - "chrome_prompt_for_tests.proto", - ] -} - source_set("public") { sources = [ "chrome_cleaner_controller_win.cc",
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_channel_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_channel_win_unittest.cc index be96802..bf67578 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_channel_win_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_channel_win_unittest.cc
@@ -28,8 +28,8 @@ #include "base/win/scoped_handle.h" #include "base/win/win_util.h" #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_actions_win.h" -#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_for_tests.pb.h" #include "components/chrome_cleaner/public/constants/constants.h" +#include "components/chrome_cleaner/public/proto/chrome_prompt_for_tests.pb.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/search/chrome_colors/chrome_colors_service.cc b/chrome/browser/search/chrome_colors/chrome_colors_service.cc index 9a13ba7..d1ed6cb 100644 --- a/chrome/browser/search/chrome_colors/chrome_colors_service.cc +++ b/chrome/browser/search/chrome_colors/chrome_colors_service.cc
@@ -85,15 +85,15 @@ void ChromeColorsService::ConfirmThemeChanges() { if (!search_provider_observer_ || !search_provider_observer_->is_google()) return; - revert_theme_changes_.Reset(); + prev_theme_reinstaller_ = nullptr; dialog_tab_ = nullptr; RecordChangesConfirmedHistogram(true); } void ChromeColorsService::RevertThemeChangesWithReason(RevertReason reason) { - if (!revert_theme_changes_.is_null()) { - std::move(revert_theme_changes_).Run(); - revert_theme_changes_.Reset(); + if (prev_theme_reinstaller_) { + prev_theme_reinstaller_->Reinstall(); + prev_theme_reinstaller_ = nullptr; dialog_tab_ = nullptr; UMA_HISTOGRAM_ENUMERATION("ChromeColors.RevertReason", reason); RecordChangesConfirmedHistogram(false); @@ -107,8 +107,8 @@ void ChromeColorsService::SaveThemeRevertState(content::WebContents* tab) { // TODO(crbug.com/980745): Support theme reverting for multiple tabs. - if (revert_theme_changes_.is_null()) { - revert_theme_changes_ = theme_service_->GetRevertThemeCallback(); + if (!prev_theme_reinstaller_) { + prev_theme_reinstaller_ = theme_service_->BuildReinstallerForCurrentTheme(); dialog_tab_ = tab; } }
diff --git a/chrome/browser/search/chrome_colors/chrome_colors_service.h b/chrome/browser/search/chrome_colors/chrome_colors_service.h index 020cded..34e25e5 100644 --- a/chrome/browser/search/chrome_colors/chrome_colors_service.h +++ b/chrome/browser/search/chrome_colors/chrome_colors_service.h
@@ -83,9 +83,8 @@ // The first tab that used Apply* and hasn't Confirm/Revert the changes. content::WebContents* dialog_tab_ = nullptr; - // Callback that will revert the theme to the state it was at the time of this - // callback's creation. - base::OnceClosure revert_theme_changes_; + // Used for reverting back to the previously installed theme. + std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller_; // Keeps track of any changes in search engine provider. May be null. std::unique_ptr<SearchProviderObserver> search_provider_observer_;
diff --git a/chrome/browser/search/chrome_colors/chrome_colors_service_unittest.cc b/chrome/browser/search/chrome_colors/chrome_colors_service_unittest.cc index c9865b0..108b857 100644 --- a/chrome/browser/search/chrome_colors/chrome_colors_service_unittest.cc +++ b/chrome/browser/search/chrome_colors/chrome_colors_service_unittest.cc
@@ -34,8 +34,8 @@ tab_ = browser()->tab_strip_model()->GetActiveWebContents(); } - bool HasThemeRevertCallback() { - return !chrome_colors_service_->revert_theme_changes_.is_null(); + bool HasThemeReinstaller() { + return !!chrome_colors_service_->prev_theme_reinstaller_; } void SetUserSelectedDefaultSearchProvider(const std::string& base_url) { @@ -74,18 +74,18 @@ SkColor theme_color1 = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(theme_color1, tab_); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); SkColor theme_color2 = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(theme_color2, tab_); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); // Last color is saved. chrome_colors_service_->ConfirmThemeChanges(); EXPECT_TRUE(theme_service->UsingAutogenerated()); EXPECT_EQ(theme_color2, theme_service->GetThemeColor()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, ApplyAndRevertAutogeneratedTheme) { @@ -95,17 +95,17 @@ SkColor theme_color1 = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(theme_color1, tab_); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); SkColor theme_color2 = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(theme_color2, tab_); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); // State before first apply is restored. chrome_colors_service_->RevertThemeChanges(); EXPECT_FALSE(theme_service->UsingAutogenerated()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, @@ -118,12 +118,12 @@ SkColor new_theme_color = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(new_theme_color, tab_); EXPECT_EQ(new_theme_color, theme_service->GetThemeColor()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); chrome_colors_service_->ConfirmThemeChanges(); EXPECT_TRUE(theme_service->UsingAutogenerated()); EXPECT_EQ(new_theme_color, theme_service->GetThemeColor()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, @@ -136,12 +136,12 @@ SkColor new_theme_color = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(new_theme_color, tab_); EXPECT_EQ(new_theme_color, theme_service->GetThemeColor()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); chrome_colors_service_->RevertThemeChanges(); EXPECT_TRUE(theme_service->UsingAutogenerated()); EXPECT_EQ(prev_theme_color, theme_service->GetThemeColor()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, ApplyAndConfirmDefaultTheme_withPreviousTheme) { @@ -153,12 +153,12 @@ chrome_colors_service_->ApplyDefaultTheme(tab_); EXPECT_TRUE(theme_service->UsingDefaultTheme()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); chrome_colors_service_->ConfirmThemeChanges(); EXPECT_TRUE(theme_service->UsingDefaultTheme()); EXPECT_NE(prev_theme_color, theme_service->GetThemeColor()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, ApplyAndRevertDefaultTheme_withPreviousTheme) { @@ -170,12 +170,12 @@ chrome_colors_service_->ApplyDefaultTheme(tab_); EXPECT_TRUE(theme_service->UsingDefaultTheme()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); chrome_colors_service_->RevertThemeChanges(); EXPECT_FALSE(theme_service->UsingDefaultTheme()); EXPECT_EQ(prev_theme_color, theme_service->GetThemeColor()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, RevertThemeChangesForTab) { @@ -185,11 +185,11 @@ SkColor theme_color = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(theme_color, tab_); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); chrome_colors_service_->RevertThemeChangesForTab(nullptr); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); AddTab(browser(), GURL("chrome://newtab")); content::WebContents* second_tab = @@ -197,11 +197,11 @@ ASSERT_NE(tab_, second_tab); chrome_colors_service_->RevertThemeChangesForTab(second_tab); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); chrome_colors_service_->RevertThemeChangesForTab(tab_); EXPECT_FALSE(theme_service->UsingAutogenerated()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); } TEST_F(TestChromeColorsService, RevertThemeChangesWhenSwitchToThirdPartyNTP) { @@ -211,15 +211,15 @@ SkColor theme_color = SkColorSetRGB(100, 0, 200); chrome_colors_service_->ApplyAutogeneratedTheme(theme_color, tab_); EXPECT_TRUE(theme_service->UsingAutogenerated()); - EXPECT_TRUE(HasThemeRevertCallback()); + EXPECT_TRUE(HasThemeReinstaller()); // Switching to third-party NTP should revert current changes. SetUserSelectedDefaultSearchProvider("www.third-party-ntp.com"); EXPECT_FALSE(theme_service->UsingAutogenerated()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); // When third-party NTP is present autogenerated theme shouldn't apply. chrome_colors_service_->ApplyAutogeneratedTheme(theme_color, tab_); EXPECT_FALSE(theme_service->UsingAutogenerated()); - EXPECT_FALSE(HasThemeRevertCallback()); + EXPECT_FALSE(HasThemeReinstaller()); }
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 83a40e8..0a94821 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -605,9 +605,6 @@ "enableShortcutsGrid", base::FeatureList::IsEnabled(features::kGridLayoutForNtpShortcuts)); config_data.SetBoolean( - "hideShortcuts", - base::FeatureList::IsEnabled(features::kHideShortcutsOnNtp)); - config_data.SetBoolean( "showFakeboxPlaceholderOnFocus", base::FeatureList::IsEnabled( omnibox::kUIExperimentShowPlaceholderWhenCaretShowing));
diff --git a/chrome/browser/search/ntp_features.cc b/chrome/browser/search/ntp_features.cc index 8ed77a1..0ee86e8 100644 --- a/chrome/browser/search/ntp_features.cc +++ b/chrome/browser/search/ntp_features.cc
@@ -35,8 +35,4 @@ const base::Feature kFirstRunDefaultSearchShortcut{ "FirstRunDefaultSearchShortcut", base::FEATURE_DISABLED_BY_DEFAULT}; -// If enabled, the shortcuts will not be shown on the NTP. -const base::Feature kHideShortcutsOnNtp{"HideShortcutsOnNtp", - base::FEATURE_DISABLED_BY_DEFAULT}; - } // namespace features
diff --git a/chrome/browser/search/ntp_features.h b/chrome/browser/search/ntp_features.h index 35e8b255..9c4e8d0b 100644 --- a/chrome/browser/search/ntp_features.h +++ b/chrome/browser/search/ntp_features.h
@@ -19,7 +19,6 @@ extern const base::Feature kNtpCustomizationMenuV2; extern const base::Feature kFirstRunDefaultSearchShortcut; -extern const base::Feature kHideShortcutsOnNtp; } // namespace features
diff --git a/chrome/browser/service_process/service_process_control_browsertest.cc b/chrome/browser/service_process/service_process_control_browsertest.cc index 3e87fd2..64aea3e 100644 --- a/chrome/browser/service_process/service_process_control_browsertest.cc +++ b/chrome/browser/service_process/service_process_control_browsertest.cc
@@ -54,6 +54,26 @@ protected: void LaunchServiceProcessControl(base::RepeatingClosure on_launched) { +#if defined(OS_MACOSX) + base::ScopedAllowBlockingForTesting allow_blocking; + // browser_tests and the child processes run as standalone executables, + // rather than bundled apps. For this test, set up the CHILD_PROCESS_EXE to + // point to a bundle so that the service process has an Info.plist. + base::FilePath exe_path; + ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &exe_path)); + exe_path = exe_path.Append(chrome::kBrowserProcessExecutablePath) + .DirName() + .DirName() + .Append("Frameworks") + .Append(chrome::kFrameworkName) + .Append("Versions") + .Append(chrome::kChromeVersion) + .Append("Helpers") + .Append(chrome::kHelperProcessExecutablePath); + base::ScopedPathOverride path_override(content::CHILD_PROCESS_EXE, + exe_path); +#endif + // Launch the process asynchronously. ServiceProcessControl::GetInstance()->Launch( base::BindOnce( @@ -76,25 +96,6 @@ } void SetUp() override { -#if defined(OS_MACOSX) - // browser_tests and the child processes run as standalone executables, - // rather than bundled apps. For this test, set up the CHILD_PROCESS_EXE to - // point to a bundle so that the service process has an Info.plist. - base::FilePath exe_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &exe_path)); - exe_path = exe_path.Append(chrome::kBrowserProcessExecutablePath) - .DirName() - .DirName() - .Append("Frameworks") - .Append(chrome::kFrameworkName) - .Append("Versions") - .Append(chrome::kChromeVersion) - .Append("Helpers") - .Append(chrome::kHelperProcessExecutablePath); - child_process_exe_override_ = std::make_unique<base::ScopedPathOverride>( - content::CHILD_PROCESS_EXE, exe_path); -#endif - InProcessBrowserTest::SetUp(); // This should not be needed because TearDown() ends with a closed @@ -110,8 +111,6 @@ #if defined(OS_MACOSX) // ForceServiceProcessShutdown removes the process from launched on Mac. ForceServiceProcessShutdown("", 0); - - child_process_exe_override_.reset(); #endif // OS_MACOSX if (service_process_.IsValid()) { @@ -148,9 +147,6 @@ } private: -#if defined(OS_MACOSX) - std::unique_ptr<base::ScopedPathOverride> child_process_exe_override_; -#endif base::Process service_process_; };
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index ee4f0a5..5ffdd980 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -62,7 +62,7 @@ // change default theme assets, if you need themes to recreate their generated // images (which are cached), or if you changed how missing values are // generated. -const int kThemePackVersion = 69; +const int kThemePackVersion = 70; // IDs that are in the DataPack won't clash with the positive integer // uint16_t. kHeaderID should always have the maximum value because we want the
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc index 1d63283..aa23260 100644 --- a/chrome/browser/themes/theme_properties.cc +++ b/chrome/browser/themes/theme_properties.cc
@@ -34,14 +34,114 @@ constexpr char kTilingRepeatY[] = "repeat-y"; constexpr char kTilingRepeat[] = "repeat"; +SkColor GetLightModeColor(int id) { +#if defined(OS_WIN) + const SkColor kDefaultColorNTPBackground = + color_utils::GetSysSkColor(COLOR_WINDOW); + const SkColor kDefaultColorNTPText = + color_utils::GetSysSkColor(COLOR_WINDOWTEXT); + const SkColor kDefaultColorNTPLink = + color_utils::GetSysSkColor(COLOR_HOTLIGHT); +#else + // TODO(beng): source from theme provider. + constexpr SkColor kDefaultColorNTPBackground = SK_ColorWHITE; + constexpr SkColor kDefaultColorNTPText = SK_ColorBLACK; + constexpr SkColor kDefaultColorNTPLink = SkColorSetRGB(0x06, 0x37, 0x74); +#endif // OS_WIN + + switch (id) { + // Properties stored in theme pack. If you change these defaults, you must + // increment the version number in browser_theme_pack.cc. + case ThemeProperties::COLOR_FRAME: + case ThemeProperties::COLOR_BACKGROUND_TAB: + return SkColorSetRGB(0xDE, 0xE1, 0xE6); + case ThemeProperties::COLOR_FRAME_INACTIVE: + case ThemeProperties::COLOR_BACKGROUND_TAB_INACTIVE: + return color_utils::HSLShift( + GetLightModeColor(ThemeProperties::COLOR_FRAME), + ThemeProperties::GetDefaultTint(ThemeProperties::TINT_FRAME_INACTIVE, + false)); + case ThemeProperties::COLOR_DOWNLOAD_SHELF: + case ThemeProperties::COLOR_INFOBAR: + case ThemeProperties::COLOR_TOOLBAR: + case ThemeProperties::COLOR_STATUS_BUBBLE: + return SK_ColorWHITE; + case ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND: + return gfx::kGoogleGrey300; + case ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_BACKGROUND: + return gfx::kGoogleGrey050; + case ThemeProperties::COLOR_BACKGROUND_TAB_TEXT: + case ThemeProperties::COLOR_BACKGROUND_TAB_TEXT_INACTIVE: + case ThemeProperties::COLOR_BOOKMARK_TEXT: + case ThemeProperties::COLOR_TAB_TEXT: + return gfx::kGoogleGrey800; + case ThemeProperties::COLOR_NTP_BACKGROUND: + return kDefaultColorNTPBackground; + case ThemeProperties::COLOR_NTP_TEXT: + return kDefaultColorNTPText; + case ThemeProperties::COLOR_NTP_LINK: + return kDefaultColorNTPLink; + case ThemeProperties::COLOR_NTP_HEADER: + return SkColorSetRGB(0x96, 0x96, 0x96); + case ThemeProperties::COLOR_CONTROL_BUTTON_BACKGROUND: + return SK_ColorTRANSPARENT; + case ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON: + // If color is not explicitly specified, it should be calculated from + // TINT_BUTTONS. + NOTREACHED(); + return gfx::kPlaceholderColor; + + // Properties not stored in theme pack. + case ThemeProperties::COLOR_TAB_ALERT_AUDIO: + return gfx::kChromeIconGrey; + case ThemeProperties::COLOR_TAB_ALERT_RECORDING: + return gfx::kGoogleRed600; + case ThemeProperties::COLOR_TAB_ALERT_CAPTURING: + case ThemeProperties::COLOR_TAB_PIP_PLAYING: + return gfx::kGoogleBlue600; + case ThemeProperties::COLOR_TOOLBAR_CONTENT_AREA_SEPARATOR: + return SkColorSetRGB(0xB6, 0xB4, 0xB6); + case ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR: + case ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR_INACTIVE: + return SkColorSetA(SK_ColorBLACK, 0x40); +#if defined(OS_WIN) + case ThemeProperties::COLOR_ACCENT_BORDER: + NOTREACHED(); + return gfx::kPlaceholderColor; +#endif + case ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_TEXT: + return SK_ColorWHITE; + case ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_BACKGROUND: + return gfx::kGoogleBlue700; + + case ThemeProperties::COLOR_FRAME_INCOGNITO: + case ThemeProperties::COLOR_FRAME_INCOGNITO_INACTIVE: + case ThemeProperties::COLOR_BACKGROUND_TAB_INCOGNITO: + case ThemeProperties::COLOR_BACKGROUND_TAB_INCOGNITO_INACTIVE: + case ThemeProperties::COLOR_BACKGROUND_TAB_TEXT_INCOGNITO: + case ThemeProperties::COLOR_BACKGROUND_TAB_TEXT_INCOGNITO_INACTIVE: + NOTREACHED() << "These values should be queried via their respective " + "non-incognito equivalents and an appropriate " + "|incognito| value."; + FALLTHROUGH; + default: + return gfx::kPlaceholderColor; + } +} + base::Optional<SkColor> GetIncognitoColor(int id) { switch (id) { case ThemeProperties::COLOR_FRAME: case ThemeProperties::COLOR_BACKGROUND_TAB: - return gfx::kGoogleGrey900; + return color_utils::HSLShift( + GetLightModeColor(ThemeProperties::COLOR_FRAME), + ThemeProperties::GetDefaultTint(ThemeProperties::TINT_FRAME, true)); case ThemeProperties::COLOR_FRAME_INACTIVE: case ThemeProperties::COLOR_BACKGROUND_TAB_INACTIVE: - return gfx::kGoogleGrey800; + return color_utils::HSLShift( + GetLightModeColor(ThemeProperties::COLOR_FRAME), + ThemeProperties::GetDefaultTint(ThemeProperties::TINT_FRAME_INACTIVE, + true)); case ThemeProperties::COLOR_DOWNLOAD_SHELF: case ThemeProperties::COLOR_STATUS_BUBBLE: case ThemeProperties::COLOR_INFOBAR: @@ -153,22 +253,17 @@ DCHECK(id != TINT_FRAME_INCOGNITO && id != TINT_FRAME_INCOGNITO_INACTIVE) << "These values should be queried via their respective non-incognito " "equivalents and an appropriate |incognito| value."; - if (!incognito && - ui::NativeTheme::GetInstanceForNativeUi()->ShouldUseDarkColors() && - id == TINT_BUTTONS) { - return {0, 0, 1}; - } // If you change these defaults, you must increment the version number in // browser_theme_pack.cc. if (incognito) { if (id == TINT_FRAME) - return {-1, 0.2, 0.35}; + return {-1, 0.7, 0.075}; // #DEE1E6 -> kGoogleGrey900 if (id == TINT_FRAME_INACTIVE) - return {-1, 0.3, 0.6}; + return {0.57, 0.65, 0.1405}; // #DEE1E6 -> kGoogleGrey800 if (id == TINT_BUTTONS) - return {-1, -1, 0.96}; + return {-1, 0.57, 0.9605}; // kChromeIconGrey -> kGoogleGrey100 } else if (id == TINT_FRAME_INACTIVE) { - return {-1, -1, 0.75}; + return {-1, -1, 0.642}; // #DEE1E6 -> #E7EAED } return {-1, -1, -1}; } @@ -185,94 +280,5 @@ if (dark_mode_color.has_value()) return dark_mode_color.value(); } - -#if defined(OS_WIN) - const SkColor kDefaultColorNTPBackground = - color_utils::GetSysSkColor(COLOR_WINDOW); - const SkColor kDefaultColorNTPText = - color_utils::GetSysSkColor(COLOR_WINDOWTEXT); - const SkColor kDefaultColorNTPLink = - color_utils::GetSysSkColor(COLOR_HOTLIGHT); -#else - // TODO(beng): source from theme provider. - constexpr SkColor kDefaultColorNTPBackground = SK_ColorWHITE; - constexpr SkColor kDefaultColorNTPText = SK_ColorBLACK; - constexpr SkColor kDefaultColorNTPLink = SkColorSetRGB(0x06, 0x37, 0x74); -#endif // OS_WIN - - switch (id) { - // Properties stored in theme pack. If you change these defaults, you must - // increment the version number in browser_theme_pack.cc. - case COLOR_FRAME: - case COLOR_BACKGROUND_TAB: - return SkColorSetRGB(0xDE, 0xE1, 0xE6); - case COLOR_FRAME_INACTIVE: - case COLOR_BACKGROUND_TAB_INACTIVE: - return SkColorSetRGB(0xE7, 0xEA, 0xED); - case COLOR_DOWNLOAD_SHELF: - case COLOR_INFOBAR: - case COLOR_TOOLBAR: - case COLOR_STATUS_BUBBLE: - return SK_ColorWHITE; - case COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND: - return gfx::kGoogleGrey300; - case COLOR_HOVER_CARD_NO_PREVIEW_BACKGROUND: - return gfx::kGoogleGrey050; - case COLOR_BACKGROUND_TAB_TEXT: - case COLOR_BACKGROUND_TAB_TEXT_INACTIVE: - case COLOR_BOOKMARK_TEXT: - case COLOR_TAB_TEXT: - return gfx::kGoogleGrey800; - case COLOR_NTP_BACKGROUND: - return kDefaultColorNTPBackground; - case COLOR_NTP_TEXT: - return kDefaultColorNTPText; - case COLOR_NTP_LINK: - return kDefaultColorNTPLink; - case COLOR_NTP_HEADER: - return SkColorSetRGB(0x96, 0x96, 0x96); - case COLOR_CONTROL_BUTTON_BACKGROUND: - return SK_ColorTRANSPARENT; - case COLOR_TOOLBAR_BUTTON_ICON: - // If color is not explicitly specified, it should be calculated from - // TINT_BUTTONS. - NOTREACHED(); - return gfx::kPlaceholderColor; - - // Properties not stored in theme pack. - case COLOR_TAB_ALERT_AUDIO: - return gfx::kChromeIconGrey; - case COLOR_TAB_ALERT_RECORDING: - return gfx::kGoogleRed600; - case COLOR_TAB_ALERT_CAPTURING: - case COLOR_TAB_PIP_PLAYING: - return gfx::kGoogleBlue600; - case COLOR_TOOLBAR_CONTENT_AREA_SEPARATOR: - return SkColorSetRGB(0xB6, 0xB4, 0xB6); - case COLOR_TOOLBAR_TOP_SEPARATOR: - case COLOR_TOOLBAR_TOP_SEPARATOR_INACTIVE: - return SkColorSetA(SK_ColorBLACK, 0x40); -#if defined(OS_WIN) - case COLOR_ACCENT_BORDER: - NOTREACHED(); - return gfx::kPlaceholderColor; -#endif - case COLOR_FEATURE_PROMO_BUBBLE_TEXT: - return SK_ColorWHITE; - case COLOR_FEATURE_PROMO_BUBBLE_BACKGROUND: - return gfx::kGoogleBlue700; - - case COLOR_FRAME_INCOGNITO: - case COLOR_FRAME_INCOGNITO_INACTIVE: - case COLOR_BACKGROUND_TAB_INCOGNITO: - case COLOR_BACKGROUND_TAB_INCOGNITO_INACTIVE: - case COLOR_BACKGROUND_TAB_TEXT_INCOGNITO: - case COLOR_BACKGROUND_TAB_TEXT_INCOGNITO_INACTIVE: - NOTREACHED() << "These values should be queried via their respective " - "non-incognito equivalents and an appropriate " - "|incognito| value."; - FALLTHROUGH; - default: - return gfx::kPlaceholderColor; - } + return GetLightModeColor(id); }
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index 5e70f3c..4de56554 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -307,6 +307,25 @@ }; #endif // BUILDFLAG(ENABLE_EXTENSIONS) +// ThemeService::ThemeReinstaller ----------------------------------------- + +ThemeService::ThemeReinstaller::ThemeReinstaller(Profile* profile, + base::OnceClosure installer) + : theme_service_(ThemeServiceFactory::GetForProfile(profile)) { + theme_service_->number_of_reinstallers_++; + installer_ = std::move(installer); +} + +ThemeService::ThemeReinstaller::~ThemeReinstaller() { + theme_service_->number_of_reinstallers_--; + theme_service_->RemoveUnusedThemes(); +} + +void ThemeService::ThemeReinstaller::Reinstall() { + if (!installer_.is_null()) { + std::move(installer_).Run(); + } +} // ThemeService --------------------------------------------------------------- @@ -321,7 +340,7 @@ rb_(ui::ResourceBundle::GetSharedInstance()), profile_(nullptr), installed_pending_load_id_(kDefaultThemeID), - number_of_infobars_(0), + number_of_reinstallers_(0), original_theme_provider_(*this, false, false), incognito_theme_provider_(*this, true, false), default_theme_provider_(*this, false, true) {} @@ -467,26 +486,14 @@ return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); } -void ThemeService::OnInfobarDisplayed() { - number_of_infobars_++; -} - -void ThemeService::OnInfobarDestroyed() { - number_of_infobars_--; - - if (number_of_infobars_ == 0 && - !build_extension_task_tracker_.HasTrackedTasks()) { - RemoveUnusedThemes(false); - } -} - -void ThemeService::RemoveUnusedThemes(bool ignore_infobars) { +void ThemeService::RemoveUnusedThemes() { // We do not want to garbage collect themes on startup (|ready_| is false). // Themes will get garbage collected after |kRemoveUnusedThemesStartupDelay|. if (!profile_ || !ready_) return; - if (!ignore_infobars && number_of_infobars_ != 0) + if (number_of_reinstallers_ != 0 || !building_extension_id_.empty()) { return; + } extensions::ExtensionService* service = extensions::ExtensionSystem::Get(profile_)->extension_service(); @@ -502,8 +509,7 @@ for (extensions::ExtensionSet::const_iterator it = extensions->begin(); it != extensions->end(); ++it) { const extensions::Extension* extension = it->get(); - if (extension->is_theme() && extension->id() != current_theme && - extension->id() != building_extension_id_) { + if (extension->is_theme() && extension->id() != current_theme) { // Only uninstall themes which are not disabled or are disabled with // reason DISABLE_USER_ACTION. We cannot blanket uninstall all disabled // themes because externally installed themes are initially disabled. @@ -574,22 +580,31 @@ return profile_->GetPrefs()->GetInteger(prefs::kAutogeneratedThemeColor); } -base::OnceCallback<void()> ThemeService::GetRevertThemeCallback() { +std::unique_ptr<ThemeService::ThemeReinstaller> +ThemeService::BuildReinstallerForCurrentTheme() { + base::OnceClosure reinstall_callback; const CustomThemeSupplier* theme_supplier = get_theme_supplier(); - if (theme_supplier) { - const CustomThemeSupplier::ThemeType theme_type = - theme_supplier->get_theme_type(); - if (theme_type == CustomThemeSupplier::ThemeType::EXTENSION) { - return base::BindOnce(&ThemeService::RevertToExtensionTheme, - weak_ptr_factory_.GetWeakPtr(), GetThemeID()); - } else if (theme_type == CustomThemeSupplier::ThemeType::AUTOGENERATED) { - return base::BindOnce(&ThemeService::BuildFromColor, - weak_ptr_factory_.GetWeakPtr(), GetThemeColor()); - } + if (theme_supplier && theme_supplier->get_theme_type() == + CustomThemeSupplier::ThemeType::EXTENSION) { + reinstall_callback = + base::BindOnce(&ThemeService::RevertToExtensionTheme, + weak_ptr_factory_.GetWeakPtr(), GetThemeID()); + } else if (theme_supplier && + theme_supplier->get_theme_type() == + CustomThemeSupplier::ThemeType::AUTOGENERATED) { + reinstall_callback = + base::BindOnce(&ThemeService::BuildFromColor, + weak_ptr_factory_.GetWeakPtr(), GetThemeColor()); + } else if (UsingSystemTheme()) { + reinstall_callback = base::BindOnce(&ThemeService::UseSystemTheme, + weak_ptr_factory_.GetWeakPtr()); + } else { + reinstall_callback = base::BindOnce(&ThemeService::UseDefaultTheme, + weak_ptr_factory_.GetWeakPtr()); } - return base::BindOnce(UsingSystemTheme() ? &ThemeService::UseSystemTheme - : &ThemeService::UseDefaultTheme, - weak_ptr_factory_.GetWeakPtr()); + + return std::make_unique<ThemeReinstaller>(profile_, + std::move(reinstall_callback)); } void ThemeService::SetCustomDefaultTheme( @@ -927,7 +942,7 @@ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&ThemeService::RemoveUnusedThemes, - weak_ptr_factory_.GetWeakPtr(), false), + weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kRemoveUnusedThemesStartupDelay)); } @@ -1007,7 +1022,8 @@ extensions::GetExtensionFileTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&WritePackToDiskCallback, base::RetainedRef(pack), extension->path())); - base::OnceClosure callback = ThemeService::GetRevertThemeCallback(); + std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller = + BuildReinstallerForCurrentTheme(); base::Optional<std::string> previous_theme_id; if (UsingExtensionTheme()) previous_theme_id = GetThemeID(); @@ -1015,11 +1031,13 @@ SwapThemeSupplier(std::move(pack)); SetThemePrefsForExtension(extension); NotifyThemeChanged(); + building_extension_id_.clear(); // Same old theme, but the theme has changed (migrated) or auto-updated. if (previous_theme_id.has_value() && - previous_theme_id.value() == extension->id()) + previous_theme_id.value() == extension->id()) { return; + } base::RecordAction(UserMetricsAction("Themes_Installed")); @@ -1040,11 +1058,10 @@ ThemeInstalledInfoBarDelegate::Create( InfoBarService::FromWebContents(web_contents), ThemeServiceFactory::GetForProfile(profile_), extension->name(), - extension->id(), std::move(callback)); + extension->id(), std::move(reinstaller)); } } } - building_extension_id_.clear(); } void ThemeService::ClearThemePrefs() {
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h index cfedfeb..1ad6950 100644 --- a/chrome/browser/themes/theme_service.h +++ b/chrome/browser/themes/theme_service.h
@@ -55,6 +55,22 @@ public KeyedService, public ui::NativeThemeObserver { public: + // This class keeps track of the number of existing |ThemeReinstaller| + // objects. When that number reaches 0 then unused themes will be deleted. + class ThemeReinstaller { + public: + ThemeReinstaller(Profile* profile, base::OnceClosure installer); + ~ThemeReinstaller(); + + void Reinstall(); + + private: + base::OnceClosure installer_; + ThemeService* const theme_service_; + + DISALLOW_COPY_AND_ASSIGN(ThemeReinstaller); + }; + // Public constants used in ThemeService and its subclasses: static const char kDefaultThemeID[]; @@ -114,18 +130,8 @@ // locally customized.) virtual std::string GetThemeID() const; - // This class needs to keep track of the number of theme infobars so that we - // clean up unused themes. - void OnInfobarDisplayed(); - - // Decrements the number of theme infobars. If the last infobar has been - // destroyed, uninstalls all themes that aren't the currently selected. - void OnInfobarDestroyed(); - - // Uninstall theme extensions which are no longer in use. |ignore_infobars| is - // whether unused themes should be removed despite a theme infobar being - // visible. - void RemoveUnusedThemes(bool ignore_infobars); + // Uninstall theme extensions which are no longer in use. + void RemoveUnusedThemes(); // Returns the syncable service for syncing theme. The returned service is // owned by |this| object. @@ -149,8 +155,9 @@ virtual bool UsingAutogenerated() const; virtual SkColor GetThemeColor() const; - // Returns callback for reverting to previous theme. - base::OnceCallback<void()> GetRevertThemeCallback(); + // Returns |ThemeService::ThemeReinstaller| for the current theme. + std::unique_ptr<ThemeService::ThemeReinstaller> + BuildReinstallerForCurrentTheme(); protected: // Set a custom default theme instead of the normal default theme. @@ -317,7 +324,7 @@ std::string installed_pending_load_id_; // The number of infobars currently displayed. - int number_of_infobars_; + int number_of_reinstallers_; // A cache of already-computed values for COLOR_TOOLBAR_TOP_SEPARATOR, which // can be expensive to compute.
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc index aede2c0..842df2f 100644 --- a/chrome/browser/themes/theme_service_unittest.cc +++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -177,8 +177,10 @@ EXPECT_EQ(extension1_id, theme_service->GetThemeID()); EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id)); - // Show an infobar to prevent the current theme from being uninstalled. - theme_service->OnInfobarDisplayed(); + // Create theme reinstaller to prevent the current theme from being + // uninstalled. + std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller = + theme_service->BuildReinstallerForCurrentTheme(); const std::string& extension2_id = LoadUnpackedMinimalThemeAt(temp_dir2.GetPath()); @@ -225,7 +227,8 @@ // Let the ThemeService uninstall unused themes. base::RunLoop().RunUntilIdle(); - theme_service->OnInfobarDisplayed(); + std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller = + theme_service->BuildReinstallerForCurrentTheme(); base::ScopedTempDir temp_dir1; ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); @@ -407,39 +410,8 @@ } } -namespace { - -// NotificationObserver which emulates an infobar getting destroyed when the -// theme changes. -class InfobarDestroyerOnThemeChange : public content::NotificationObserver { - public: - explicit InfobarDestroyerOnThemeChange(Profile* profile) - : theme_service_(ThemeServiceFactory::GetForProfile(profile)) { - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, - content::Source<ThemeService>(theme_service_)); - } - - ~InfobarDestroyerOnThemeChange() override {} - - private: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - theme_service_->OnInfobarDestroyed(); - } - - // Not owned. - ThemeService* theme_service_; - - content::NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(InfobarDestroyerOnThemeChange); -}; - -} // namespace - // crbug.com/468280 -TEST_F(ThemeServiceTest, UninstallThemeOnThemeChangeNotification) { +TEST_F(ThemeServiceTest, UninstallThemeWhenNoReinstallers) { // Setup. ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile_.get()); @@ -456,24 +428,31 @@ LoadUnpackedMinimalThemeAt(temp_dir1.GetPath()); ASSERT_EQ(extension1_id, theme_service->GetThemeID()); - // Show an infobar. - theme_service->OnInfobarDisplayed(); - - // Install another theme. The first extension shouldn't be uninstalled yet as - // it should be possible to revert to it. Emulate the infobar destroying - // itself as a result of the NOTIFICATION_BROWSER_THEME_CHANGED notification. + std::string extension2_id = ""; { - InfobarDestroyerOnThemeChange destroyer(profile_.get()); - const std::string& extension2_id = - LoadUnpackedMinimalThemeAt(temp_dir2.GetPath()); + // Show an infobar. + std::unique_ptr<ThemeService::ThemeReinstaller> reinstaller = + theme_service->BuildReinstallerForCurrentTheme(); + + // Install another theme. The first extension shouldn't be uninstalled yet + // as it should be possible to revert to it. + extension2_id = LoadUnpackedMinimalThemeAt(temp_dir2.GetPath()); + EXPECT_TRUE(registry_->GetExtensionById(extension1_id, + ExtensionRegistry::DISABLED)); EXPECT_EQ(extension2_id, theme_service->GetThemeID()); + + reinstaller->Reinstall(); + WaitForThemeInstall(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(registry_->GetExtensionById(extension2_id, + ExtensionRegistry::DISABLED)); + EXPECT_EQ(extension1_id, theme_service->GetThemeID()); } - // Check that it is possible to reinstall extension1. - ThemeServiceFactory::GetForProfile(profile_.get()) - ->RevertToExtensionTheme(extension1_id); - WaitForThemeInstall(); - EXPECT_EQ(extension1_id, theme_service->GetThemeID()); + // extension 2 should get uninstalled as no reinstallers are in scope. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(registry_->GetExtensionById(extension2_id, + ExtensionRegistry::EVERYTHING)); } TEST_F(ThemeServiceTest, BuildFromColorTest) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index cc673176..c7431f0 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -737,7 +737,6 @@ "android/tab_contents/chrome_web_contents_view_delegate_android.h", "android/tab_model/android_live_tab_context.cc", "android/tab_model/android_live_tab_context.h", - "android/tab_model/single_tab_model.cc", "android/tab_model/tab_model.cc", "android/tab_model/tab_model.h", "android/tab_model/tab_model_jni_bridge.cc",
diff --git a/chrome/browser/ui/android/device_dialog/bluetooth_scanning_prompt_android.h b/chrome/browser/ui/android/device_dialog/bluetooth_scanning_prompt_android.h index 677ab41..4d745b6 100644 --- a/chrome/browser/ui/android/device_dialog/bluetooth_scanning_prompt_android.h +++ b/chrome/browser/ui/android/device_dialog/bluetooth_scanning_prompt_android.h
@@ -15,14 +15,6 @@ // devices. This implementation is for Android. class BluetoothScanningPromptAndroid : public content::BluetoothScanningPrompt { public: - // A Java counterpart will be generated for this enum. - // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.device_dialog - enum BluetoothScanningPermissionEvent { - ALLOW = 0, - BLOCK = 1, - CANCELED = 2, - }; - BluetoothScanningPromptAndroid( content::RenderFrameHost* frame, const content::BluetoothScanningPrompt::EventHandler& event_handler);
diff --git a/chrome/browser/ui/android/tab_model/single_tab_model.cc b/chrome/browser/ui/android/tab_model/single_tab_model.cc deleted file mode 100644 index 6c3d53d30..0000000 --- a/chrome/browser/ui/android/tab_model/single_tab_model.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2015 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/android/jni_android.h" -#include "chrome/android/chrome_jni_headers/SingleTabModel_jni.h" -#include "chrome/browser/android/tab_android.h" -#include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h" -#include "content/public/browser/web_contents.h" - -using base::android::JavaParamRef; - -static void JNI_SingleTabModel_PermanentlyBlockAllNewWindows( - JNIEnv* env, - const JavaParamRef<jobject>& j_tab_android) { - TabAndroid* tab = TabAndroid::GetNativeTab(env, j_tab_android); - if (!tab) - return; - - content::WebContents* web_contents = tab->web_contents(); - if (!web_contents) - return; - - SingleTabModeTabHelper* tab_helper = - SingleTabModeTabHelper::FromWebContents(web_contents); - tab_helper->PermanentlyBlockAllNewWindows(); -}
diff --git a/chrome/browser/ui/hats/hats_service.cc b/chrome/browser/ui/hats/hats_service.cc index b63f893..345eaa4 100644 --- a/chrome/browser/ui/hats/hats_service.cc +++ b/chrome/browser/ui/hats/hats_service.cc
@@ -130,6 +130,12 @@ } bool HatsService::ShouldShowSurvey(const std::string& trigger) const { + if (base::FeatureList::IsEnabled( + features::kHappinessTrackingSurveysForDesktopDemo)) { + // Always show the survey in demo mode. + return true; + } + bool consent_given = g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven(); if (!consent_given)
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc index ee753f9..4999235 100644 --- a/chrome/browser/ui/omnibox/omnibox_theme.cc +++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -49,9 +49,7 @@ // For high contrast, selected rows use inverted colors to stand out more. ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi(); bool high_contrast = native_theme && native_theme->UsesHighContrastColors(); - bool selected = state == OmniboxPartState::SELECTED || - state == OmniboxPartState::HOVERED_AND_SELECTED; - if (high_contrast && selected) + if (high_contrast && (state == OmniboxPartState::SELECTED)) dark = !dark; switch (part) { @@ -66,15 +64,15 @@ case OmniboxPart::LOCATION_BAR_SELECTED_KEYWORD: return dark ? gfx::kGoogleGrey100 : gfx::kGoogleBlue600; case OmniboxPart::RESULTS_BACKGROUND: { - // High contrast mode needs a darker base - Grey 800 with 14% white + // High contrast mode needs a darker base - Grey 800 with 16% white // overlaid on it (see below) is hard to produce good contrast ratios // against with colors other than white. const SkColor dark_base_color = high_contrast ? gfx::kGoogleGrey900 : gfx::kGoogleGrey800; const SkColor base_color = dark ? dark_base_color : SK_ColorWHITE; - // The spec calls for transparent black (or white) overlays for hover (8%) - // and select (6%), which can overlap (for 14%). Pre-blend these with the - // background for the best text AA result. + // The spec calls for transparent black (or white) overlays for hover + // (10%) and select (16%). Pre-blend these with the background for the + // best text AA result. return color_utils::BlendTowardMaxContrast( base_color, gfx::ToRoundedInt(GetOmniboxStateOpacity(state) * SK_AlphaOPAQUE)); @@ -132,18 +130,7 @@ } float GetOmniboxStateOpacity(OmniboxPartState state) { - switch (state) { - case OmniboxPartState::NORMAL: - return 0; - case OmniboxPartState::HOVERED: - return 0.08f; - case OmniboxPartState::SELECTED: - return 0.06f; - case OmniboxPartState::HOVERED_AND_SELECTED: - return GetOmniboxStateOpacity(OmniboxPartState::HOVERED) + - GetOmniboxStateOpacity(OmniboxPartState::SELECTED); - default: - NOTREACHED(); - return 0; - } + DCHECK_LE(state, OmniboxPartState::SELECTED); + constexpr float kOpacities[3] = {0.00f, 0.10f, 0.16f}; + return kOpacities[static_cast<size_t>(state)]; }
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.h b/chrome/browser/ui/omnibox/omnibox_theme.h index 0adeb47d..1ad5841 100644 --- a/chrome/browser/ui/omnibox/omnibox_theme.h +++ b/chrome/browser/ui/omnibox/omnibox_theme.h
@@ -35,7 +35,6 @@ NORMAL, HOVERED, SELECTED, - HOVERED_AND_SELECTED, // Applicable to LOCATION_BAR_SECURITY_CHIP only. CHIP_DEFAULT,
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 3222877f..3d0846a 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -102,7 +102,6 @@ #include "chrome/browser/android/chrome_feature_list.h" #include "chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h" #include "chrome/browser/android/search_permissions/search_geolocation_disclosure_tab_helper.h" -#include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h" #include "chrome/browser/banners/app_banner_manager_android.h" #include "chrome/browser/ui/android/context_menu_helper.h" #include "chrome/browser/ui/android/view_android_helper.h" @@ -287,7 +286,6 @@ } SearchGeolocationDisclosureTabHelper::CreateForWebContents(web_contents); - SingleTabModeTabHelper::CreateForWebContents(web_contents); ViewAndroidHelper::CreateForWebContents(web_contents); #else banners::AppBannerManagerDesktop::CreateForWebContents(web_contents); @@ -320,7 +318,9 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) if (base::FeatureList::IsEnabled( - features::kHappinessTrackingSurveysForDesktop)) { + features::kHappinessTrackingSurveysForDesktop) || + base::FeatureList::IsEnabled( + features::kHappinessTrackingSurveysForDesktopDemo)) { HatsHelper::CreateForWebContents(web_contents); } #endif
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_button_unittest.cc b/chrome/browser/ui/views/extensions/extensions_menu_button_unittest.cc index 322b70f..22fb243 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_button_unittest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_button_unittest.cc
@@ -60,13 +60,6 @@ BrowserWithTestWindowTest::TearDown(); } - void TriggerNotifyClick() { - ui::MouseEvent click_event(ui::ET_MOUSE_RELEASED, gfx::Point(), - gfx::Point(), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, 0); - button_->button_controller()->OnMouseReleased(click_event); - } - base::test::ScopedFeatureList scoped_feature_list_; const base::string16 initial_extension_name_; const base::string16 initial_tooltip_; @@ -86,7 +79,14 @@ TEST_F(ExtensionsMenuButtonTest, NotifyClickExecutesAction) { EXPECT_EQ(0, controller_->execute_action_count()); - TriggerNotifyClick(); + + button_->SetBounds(0, 0, 100, 100); + ui::MouseEvent click_event(ui::ET_MOUSE_RELEASED, + button_->GetLocalBounds().CenterPoint(), + button_->GetLocalBounds().CenterPoint(), + base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0); + button_->button_controller()->OnMouseReleased(click_event); + EXPECT_EQ(1, controller_->execute_action_count()); }
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc index 42bb7ad4..e32561e 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" #include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h" +#include "ui/views/controls/scrollbar/overlay_scroll_bar.h" #include "ui/views/layout/box_layout.h" namespace { @@ -18,6 +19,9 @@ contents()->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical)); ClipHeightTo(0, kMediaListMaxHeight); + + SetVerticalScrollBar(new views::OverlayScrollBar(/*horizontal=*/false)); + SetHorizontalScrollBar(new views::OverlayScrollBar(/*horizontal=*/true)); } MediaNotificationListView::~MediaNotificationListView() = default;
diff --git a/chrome/browser/ui/views/hover_button_controller.cc b/chrome/browser/ui/views/hover_button_controller.cc index 065a245..9f6805e0 100644 --- a/chrome/browser/ui/views/hover_button_controller.cc +++ b/chrome/browser/ui/views/hover_button_controller.cc
@@ -53,7 +53,9 @@ void HoverButtonController::OnMouseReleased(const ui::MouseEvent& event) { DCHECK(notify_action() == views::ButtonController::NotifyAction::NOTIFY_ON_RELEASE); - if (button()->state() != views::Button::STATE_DISABLED) { + if (button()->state() != views::Button::STATE_DISABLED && + delegate()->IsTriggerableEvent(event) && + button()->HitTestPoint(event.location()) && !delegate()->InDrag()) { if (listener_) listener_->ButtonPressed(button(), event); } else {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc index 519db4b..577e81f2 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -233,10 +233,8 @@ } OmniboxPartState OmniboxResultView::GetThemeState() const { - if (IsSelected()) { - return is_hovered_ ? OmniboxPartState::HOVERED_AND_SELECTED - : OmniboxPartState::SELECTED; - } + if (IsSelected()) + return OmniboxPartState::SELECTED; return is_hovered_ ? OmniboxPartState::HOVERED : OmniboxPartState::NORMAL; }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc index 90b25af..b6a5b60a 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
@@ -154,8 +154,7 @@ // Left button drag should select. result_view()->OnMouseDragged( CreateEvent(ui::ET_MOUSE_DRAGGED, ui::EF_LEFT_MOUSE_BUTTON)); - EXPECT_EQ(OmniboxPartState::HOVERED_AND_SELECTED, - result_view()->GetThemeState()); + EXPECT_EQ(OmniboxPartState::SELECTED, result_view()->GetThemeState()); EXPECT_TRUE(popup_view()->IsSelectedIndex(kTestResultViewIndex)); }
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index 78d332f..6455e0d 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -530,8 +530,19 @@ } void TabHoverCardBubbleView::UpdateCardContent(const Tab* tab) { - title_label_->SetText(tab->data().title); - const GURL& domain_url = tab->data().last_committed_url; + base::string16 title; + GURL domain_url; + // Use committed URL to determine if no page has yet loaded, since the title + // can be blank for some web pages. + if (tab->data().last_committed_url.is_empty()) { + domain_url = tab->data().visible_url; + title = tab->data().IsCrashed() + ? l10n_util::GetStringUTF16(IDS_HOVER_CARD_CRASHED_TITLE) + : l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); + } else { + domain_url = tab->data().last_committed_url; + title = tab->data().title; + } base::string16 domain; if (domain_url.SchemeIsFile()) { title_label_->SetMultiLine(false); @@ -548,6 +559,7 @@ url_formatter::kFormatUrlTrimAfterHost, net::UnescapeRule::NORMAL, nullptr, nullptr, nullptr); } + title_label_->SetText(title); domain_label_->SetText(domain); // If the preview image feature is not enabled, |preview_image_| will be null.
diff --git a/chrome/browser/ui/webui/welcome/helpers.cc b/chrome/browser/ui/webui/welcome/helpers.cc index 3cac3eb..8cdc524 100644 --- a/chrome/browser/ui/webui/welcome/helpers.cc +++ b/chrome/browser/ui/webui/welcome/helpers.cc
@@ -31,7 +31,7 @@ // Available modules for both new and returning users. const char kDefaultNewUserModules[] = - "nux-google-apps,nux-set-as-default,signin-view"; + "nux-google-apps,nux-ntp-background,nux-set-as-default,signin-view"; const char kDefaultReturningUserModules[] = "nux-set-as-default"; // Feature flag. @@ -49,11 +49,9 @@ &kFeature, "returning-user-modules", kDefaultReturningUserModules}; // For testing purposes const base::FeatureParam<std::string> kForceEnabledNewUserModules = { - &kForceEnabled, "new-user-modules", - "nux-google-apps,nux-ntp-background,nux-set-as-default," - "signin-view"}; + &kForceEnabled, "new-user-modules", kDefaultNewUserModules}; const base::FeatureParam<std::string> kForceEnabledReturningUserModules = { - &kForceEnabled, "returning-user-modules", "nux-set-as-default"}; + &kForceEnabled, "returning-user-modules", kDefaultReturningUserModules}; // FeatureParam for app variation. const base::FeatureParam<bool> kShowGoogleApp{&kFeature,
diff --git a/chrome/browser/upgrade_detector/OWNERS b/chrome/browser/upgrade_detector/OWNERS index 49bfcb22e..0e6e575 100644 --- a/chrome/browser/upgrade_detector/OWNERS +++ b/chrome/browser/upgrade_detector/OWNERS
@@ -1,2 +1,3 @@ grt@chromium.org xiyuan@chromium.org +# COMPONENT: Internals>Installer
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index 4b267b9..e107ed9 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -131,10 +131,8 @@ return false; #if defined(OS_WIN) + // Errors from the Windows API should not result in a Chrome error dialog. if (authenticator && authenticator->IsWinNativeApiAuthenticator()) { - // Do not display a Chrome error dialog if the user cancels out of the - // Windows UI. No other errors are reachable. - DCHECK(reason == InterestingFailureReason::kUserConsentDenied); return false; } #endif // defined(OS_WIN)
diff --git a/chrome/chrome_cleaner/ipc/BUILD.gn b/chrome/chrome_cleaner/ipc/BUILD.gn index 487b354..03fddfd 100644 --- a/chrome/chrome_cleaner/ipc/BUILD.gn +++ b/chrome/chrome_cleaner/ipc/BUILD.gn
@@ -24,14 +24,18 @@ "chrome_prompt_ipc.h", "mojo_chrome_prompt_ipc.cc", "mojo_chrome_prompt_ipc.h", + "proto_chrome_prompt_ipc.cc", + "proto_chrome_prompt_ipc.h", ] deps = [ ":mojo_task_runner", "//base", "//components/chrome_cleaner/public/interfaces", + "//components/chrome_cleaner/public/proto", "//mojo/public/cpp/platform", "//mojo/public/cpp/system", + "//third_party/protobuf:protobuf_lite", ] } @@ -67,6 +71,7 @@ ] deps = [ + ":chrome_prompt_ipc", ":mojo_task_runner", "//base", "//base/test:test_support", @@ -82,9 +87,10 @@ testonly = true sources = [ - "chrome_prompt_ipc_unittest.cc", + "mojo_chrome_prompt_ipc_unittest.cc", "mojo_sandbox_hooks_unittest.cc", "mojo_task_runner_unittest.cc", + "proto_chrome_prompt_ipc_unittest.cc", "sandbox_unittest.cc", ] @@ -100,7 +106,10 @@ "//chrome/chrome_cleaner/mojom:mojo_sandbox_hooks_test_interface", "//chrome/chrome_cleaner/os:common_os", "//chrome/chrome_cleaner/test:test_util", + "//components/chrome_cleaner/public/constants", "//components/chrome_cleaner/public/interfaces", + "//components/chrome_cleaner/public/proto", + "//components/chrome_cleaner/public/proto:test_only_proto", "//components/chrome_cleaner/test:test_name_helper", "//mojo/core/embedder", "//sandbox/win:sandbox",
diff --git a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h index ad216e5..841c1b7 100644 --- a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h +++ b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h
@@ -85,42 +85,6 @@ kDoneInteraction, }; - virtual void RunPromptUserTask( - const std::vector<base::FilePath>& files_to_delete, - const std::vector<base::string16>& registry_keys, - const std::vector<base::string16>& extension_ids, - mojom::ChromePrompt::PromptUserCallback callback) = 0; - - virtual void RunDisableExtensionsTask( - const std::vector<base::string16>& extension_ids, - mojom::ChromePrompt::DisableExtensionsCallback callback) = 0; - - // Callback for ChromePrompt::PromptUser, internal state must be - // State::kWaitingForResponseFromChrome. Invokes callback(prompt_acceptance) - // and transitions to state State::kDoneInteraction. - virtual void OnChromeResponseReceived( - mojom::ChromePrompt::PromptUserCallback callback, - mojom::PromptAcceptance prompt_acceptance) = 0; - - // Callback for ChromePrompt::DisableExtensions, internal state must be - // State::kDoneInteraction. Invokes callback(extensions_deleted_callback). - virtual void OnChromeResponseReceivedExtensions( - mojom::ChromePrompt::DisableExtensionsCallback callback, - bool extensions_deleted_callback) = 0; - - // Connection error handler. Invokes either - // error_handler_->OnConnectionClosed() or - // error_handler_->OnConnectionClosedAfterDone(), depending on the internal - // state. - virtual void OnConnectionError() = 0; - - virtual void PromptUserCheckVersion( - const std::vector<base::FilePath>& files_to_delete, - const std::vector<base::string16>& registry_keys, - const std::vector<base::string16>& extension_ids, - mojom::ChromePrompt::PromptUserCallback callback, - uint32_t version) = 0; - State state_ = State::kUninitialized; ErrorHandler* error_handler_ = nullptr;
diff --git a/chrome/chrome_cleaner/ipc/ipc_test_util.cc b/chrome/chrome_cleaner/ipc/ipc_test_util.cc index 14ea503..05fc0d02 100644 --- a/chrome/chrome_cleaner/ipc/ipc_test_util.cc +++ b/chrome/chrome_cleaner/ipc/ipc_test_util.cc
@@ -63,6 +63,14 @@ SandboxedParentProcess* parent_process_; }; +} // namespace + +namespace internal { + +base::FilePath::StringPieceType GetLogPathSuffix() { + return kIPCTestUtilLogSuffix; +} + base::FilePath GetLogPath() { return ScopedLogging::GetLogFilePath(kIPCTestUtilLogSuffix); } @@ -107,7 +115,7 @@ } } -} // namespace +} // namespace internal ParentProcess::ParentProcess(scoped_refptr<MojoTaskRunner> mojo_task_runner) : command_line_(base::GetMultiProcessTestChildBaseCommandLine()), @@ -166,7 +174,7 @@ const std::string& child_main_function, base::TimeDelta timeout, int32_t* exit_code) { - if (!DeleteChildProcessLogs()) + if (!internal::DeleteChildProcessLogs()) return false; if (!PrepareAndLaunchTestChildProcess(child_main_function)) @@ -182,7 +190,7 @@ DestroyImplOnIPCThread(); if (!success || *exit_code != 0) - PrintChildProcessLogs(); + internal::PrintChildProcessLogs(); return success; } @@ -289,4 +297,20 @@ return command_line_->GetSwitchValueASCII(kMojoPipeTokenSwitch); } +ChromePromptIPCTestErrorHandler::ChromePromptIPCTestErrorHandler( + base::OnceClosure on_closed, + base::OnceClosure on_closed_after_done) + : on_closed_(std::move(on_closed)), + on_closed_after_done_(std::move(on_closed_after_done)) {} + +ChromePromptIPCTestErrorHandler::~ChromePromptIPCTestErrorHandler() = default; + +void ChromePromptIPCTestErrorHandler::OnConnectionClosed() { + std::move(on_closed_).Run(); +} + +void ChromePromptIPCTestErrorHandler::OnConnectionClosedAfterDone() { + std::move(on_closed_after_done_).Run(); +} + } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/ipc/ipc_test_util.h b/chrome/chrome_cleaner/ipc/ipc_test_util.h index 82c5bb5..97f2072 100644 --- a/chrome/chrome_cleaner/ipc/ipc_test_util.h +++ b/chrome/chrome_cleaner/ipc/ipc_test_util.h
@@ -14,6 +14,7 @@ #include "base/process/launch.h" #include "base/process/process.h" #include "base/time/time.h" +#include "chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h" #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" #include "chrome/chrome_cleaner/logging/scoped_logging.h" #include "mojo/public/cpp/platform/platform_channel.h" @@ -126,6 +127,27 @@ bool target_services_initialized_ = false; }; +class ChromePromptIPCTestErrorHandler : public ChromePromptIPC::ErrorHandler { + public: + ChromePromptIPCTestErrorHandler(base::OnceClosure on_closed, + base::OnceClosure on_closed_after_done); + + ~ChromePromptIPCTestErrorHandler() override; + + void OnConnectionClosed() override; + void OnConnectionClosedAfterDone() override; + + private: + base::OnceClosure on_closed_; + base::OnceClosure on_closed_after_done_; +}; + +namespace internal { +base::FilePath::StringPieceType GetLogPathSuffix(); +bool DeleteChildProcessLogs(); +void PrintChildProcessLogs(); +} // namespace internal + } // namespace chrome_cleaner #endif // CHROME_CHROME_CLEANER_IPC_IPC_TEST_UTIL_H_
diff --git a/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.cc b/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.cc index 187191c3..cd77fa1 100644 --- a/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.cc +++ b/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.cc
@@ -8,8 +8,7 @@ namespace chrome_cleaner { -MockChromePromptIPC::MockChromePromptIPC() - : MojoChromePromptIPC(std::string(), nullptr) {} +MockChromePromptIPC::MockChromePromptIPC() = default; MockChromePromptIPC::~MockChromePromptIPC() = default; @@ -22,4 +21,10 @@ &callback); } +void MockChromePromptIPC::PostDisableExtensionsTask( + const std::vector<base::string16>& extension_ids, + mojom::ChromePrompt::DisableExtensionsCallback callback) { + MockPostDisableExtensionsTask(extension_ids, &callback); +} + } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.h b/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.h index 77b5bd7..495e93b7 100644 --- a/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.h +++ b/chrome/chrome_cleaner/ipc/mock_chrome_prompt_ipc.h
@@ -8,13 +8,13 @@ #include <memory> #include <vector> -#include "chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc.h" +#include "chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h" #include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h" #include "testing/gmock/include/gmock/gmock.h" namespace chrome_cleaner { -class MockChromePromptIPC : public MojoChromePromptIPC { +class MockChromePromptIPC : public ChromePromptIPC { public: MockChromePromptIPC(); ~MockChromePromptIPC() override; @@ -25,19 +25,26 @@ void(base::OnceClosure delete_allowed_callback, base::OnceClosure delete_not_allowed_callback)); - // Workaround for GMock's limitation, in which MOCK_METHOD* doesn't accept - // base::OnceCallback parameters. Will forward any calls to - // MockPostPromptUserTask() and pass along a raw pointer for |callback|. + // Workaround for GMock's limitation, in which MOCK_METHOD* doesn't + // accept base::OnceCallback parameters. Will forward any calls to + // MockPost*() and pass along a raw pointer for |callback|. void PostPromptUserTask( const std::vector<base::FilePath>& files_to_delete, const std::vector<base::string16>& registry_keys, const std::vector<base::string16>& extension_ids, mojom::ChromePrompt::PromptUserCallback callback) override; + void PostDisableExtensionsTask( + const std::vector<base::string16>& extension_ids, + mojom::ChromePrompt::DisableExtensionsCallback callback) override; + MOCK_METHOD4(MockPostPromptUserTask, void(const std::vector<base::FilePath>& files_to_delete, const std::vector<base::string16>& registry_keys, const std::vector<base::string16>& extension_ids, mojom::ChromePrompt::PromptUserCallback* callback)); + MOCK_METHOD2(MockPostDisableExtensionsTask, + void(const std::vector<base::string16>& extension_ids, + mojom::ChromePrompt::DisableExtensionsCallback* callback)); }; } // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc.h b/chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc.h index be2d66b..46ce19af 100644 --- a/chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc.h +++ b/chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc.h
@@ -1,7 +1,6 @@ // 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. - #ifndef CHROME_CHROME_CLEANER_IPC_MOJO_CHROME_PROMPT_IPC_H_ #define CHROME_CHROME_CLEANER_IPC_MOJO_CHROME_PROMPT_IPC_H_ @@ -87,41 +86,40 @@ // Runs |chrome_prompt_service_->PromptUser()|. Must be called on the IPC // thread. - void RunPromptUserTask( - const std::vector<base::FilePath>& files_to_delete, - const std::vector<base::string16>& registry_keys, - const std::vector<base::string16>& extension_ids, - mojom::ChromePrompt::PromptUserCallback callback) override; + void RunPromptUserTask(const std::vector<base::FilePath>& files_to_delete, + const std::vector<base::string16>& registry_keys, + const std::vector<base::string16>& extension_ids, + mojom::ChromePrompt::PromptUserCallback callback); void RunDisableExtensionsTask( const std::vector<base::string16>& extension_ids, - mojom::ChromePrompt::DisableExtensionsCallback callback) override; + mojom::ChromePrompt::DisableExtensionsCallback callback); // Callback for ChromePrompt::PromptUser, internal state must be // State::kWaitingForResponseFromChrome. Invokes callback(prompt_acceptance) // and transitions to state State::kDoneInteraction. void OnChromeResponseReceived( mojom::ChromePrompt::PromptUserCallback callback, - mojom::PromptAcceptance prompt_acceptance) override; + mojom::PromptAcceptance prompt_acceptance); // Callback for ChromePrompt::DisableExtensions, internal state must be // State::kDoneInteraction. Invokes callback(extensions_deleted_callback). void OnChromeResponseReceivedExtensions( mojom::ChromePrompt::DisableExtensionsCallback callback, - bool extensions_deleted_callback) override; + bool extensions_deleted_callback); // Connection error handler. Invokes either // error_handler_->OnConnectionClosed() or // error_handler_->OnConnectionClosedAfterDone(), depending on the internal // state. - void OnConnectionError() override; + void OnConnectionError(); void PromptUserCheckVersion( const std::vector<base::FilePath>& files_to_delete, const std::vector<base::string16>& registry_keys, const std::vector<base::string16>& extension_ids, mojom::ChromePrompt::PromptUserCallback callback, - uint32_t version) override; + uint32_t version); private: scoped_refptr<MojoTaskRunner> task_runner_;
diff --git a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc b/chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc_unittest.cc similarity index 95% rename from chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc rename to chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc_unittest.cc index 86b98f8..658892e 100644 --- a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc +++ b/chrome/chrome_cleaner/ipc/mojo_chrome_prompt_ipc_unittest.cc
@@ -87,7 +87,7 @@ ParentDisconnected expected_parent_disconnected; }; -// Parent process. +// Class that lives in the parent process and handles that side of the IPC. class MockChromePrompt : public mojom::ChromePrompt { public: MockChromePrompt(TestConfig test_config, mojom::ChromePromptRequest request) @@ -151,6 +151,7 @@ } if (test_config.with_registry_keys) AppendSwitch(kIncludeRegistryKeysSwitch); + AppendSwitch(kExpectedPromptResultSwitch, base::NumberToString( static_cast<int>(test_config.expected_prompt_acceptance))); @@ -178,26 +179,7 @@ std::unique_ptr<MockChromePrompt> mock_chrome_prompt_; }; -class ChromePromptIPCTestErrorHandler : public ChromePromptIPC::ErrorHandler { - public: - ChromePromptIPCTestErrorHandler(base::OnceClosure on_closed, - base::OnceClosure on_closed_after_done) - : on_closed_(std::move(on_closed)), - on_closed_after_done_(std::move(on_closed_after_done)) {} - - ~ChromePromptIPCTestErrorHandler() override = default; - - void OnConnectionClosed() override { std::move(on_closed_).Run(); } - - void OnConnectionClosedAfterDone() override { - std::move(on_closed_after_done_).Run(); - } - - base::OnceClosure on_closed_; - base::OnceClosure on_closed_after_done_; -}; - -// Child process. +// Class that lives in the child process and handles that side of the IPC. class ChromePromptIPCChildProcess : public ChildProcess { public: explicit ChromePromptIPCChildProcess( @@ -297,6 +279,7 @@ auto child_process = base::MakeRefCounted<ChromePromptIPCChildProcess>(mojo_task_runner); base::RunLoop on_done_run_loop; + // The parent process can disconnect while the pipe is required or after it's // no longer needed. In the former case, the child process will immediately // exit; in the latter, it will break |on_done_run_loop|, which will be
diff --git a/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.cc b/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.cc new file mode 100644 index 0000000..b3989db --- /dev/null +++ b/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.cc
@@ -0,0 +1,259 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.h" + +#include <windows.h> + +#include "base/strings/utf_string_conversions.h" +#include "base/win/win_util.h" +#include "components/chrome_cleaner/public/proto/chrome_prompt.pb.h" + +namespace { + +// chrome_cleaner <-> chrome protocol version. +constexpr uint8_t kVersion = 1; +} // namespace + +namespace chrome_cleaner { + +ProtoChromePromptIPC::ProtoChromePromptIPC( + base::win::ScopedHandle response_read_handle, + base::win::ScopedHandle request_write_handle) + : response_read_handle_(std::move(response_read_handle)), + request_write_handle_(std::move(request_write_handle)) { + // All uses of this class, and more specifically its state member need to + // happen on the same sequence but one that is not the construction + // sequence. + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +ProtoChromePromptIPC::~ProtoChromePromptIPC() = default; + +void ProtoChromePromptIPC::Initialize(ErrorHandler* error_handler) { + DCHECK(task_runner_); + + error_handler_ = error_handler; + + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&ProtoChromePromptIPC::InitializeImpl, + base::Unretained(this))); +} + +void ProtoChromePromptIPC::PostPromptUserTask( + const std::vector<base::FilePath>& files_to_delete, + const std::vector<base::string16>& registry_keys, + const std::vector<base::string16>& extension_ids, + PromptUserCallback callback) { + DCHECK(task_runner_); + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&ProtoChromePromptIPC::RunPromptUserTask, + base::Unretained(this), files_to_delete, registry_keys, + extension_ids, std::move(callback))); +} + +void ProtoChromePromptIPC::PostDisableExtensionsTask( + const std::vector<base::string16>& extension_ids, + DisableExtensionsCallback callback) { + NOTIMPLEMENTED(); + OnConnectionError(); +} + +void ProtoChromePromptIPC::TryDeleteExtensions( + base::OnceClosure delete_allowed_callback, + base::OnceClosure delete_not_allowed_callback) { + NOTIMPLEMENTED(); + OnConnectionError(); +} + +void ProtoChromePromptIPC::InitializeImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(State::kUninitialized, state_); + state_ = State::kWaitingForScanResults; + + // Initialize communication with chrome by sending the version. + WriteByValue(kVersion); +} + +void ProtoChromePromptIPC::RunPromptUserTask( + const std::vector<base::FilePath>& files_to_delete, + const std::vector<base::string16>& registry_keys, + const std::vector<base::string16>& extension_ids, + PromptUserCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_NE(state_, State::kUninitialized); + DCHECK_NE(state_, State::kWaitingForResponseFromChrome); + + // This can be true if any connection error occurred already in which case + // We don't not want to go forward with the prompting. + if (state_ == State::kDoneInteraction) { + return; + } + + state_ = State::kWaitingForResponseFromChrome; + + // If the contents of the message cannot be represented in a sane way avoid + // sending it on the wire. Returns a denied prompt since Chrome would run + // similar checks and deny it anyway. + + // Build the prompt message. + chrome_cleaner::PromptUserRequest prompt_user_message; + for (const base::FilePath& file_to_delete : files_to_delete) { + std::string file_path_utf8; + if (!base::UTF16ToUTF8(file_to_delete.value().c_str(), + file_to_delete.value().size(), &file_path_utf8)) { + std::move(callback).Run(PromptAcceptance::DENIED); + return; + } else { + prompt_user_message.add_files_to_delete(file_path_utf8); + } + } + + for (const base::string16& registry_key : registry_keys) { + std::string registry_key_utf8; + if (!base::UTF16ToUTF8(registry_key.c_str(), registry_key.size(), + ®istry_key_utf8)) { + std::move(callback).Run(PromptAcceptance::DENIED); + return; + } else { + prompt_user_message.add_registry_keys(registry_key_utf8); + } + } + + for (const base::string16& extension_id : extension_ids) { + std::string extension_id_utf8; + if (!base::UTF16ToUTF8(extension_id.c_str(), extension_id.size(), + &extension_id_utf8)) { + std::move(callback).Run(PromptAcceptance::DENIED); + return; + } else { + prompt_user_message.add_extension_ids(extension_id_utf8); + } + } + + // This is the top-level message that Chrome is expecting. + ChromePromptRequest chrome_prompt_request; + *chrome_prompt_request.mutable_prompt_user() = prompt_user_message; + + std::string request_content; + DCHECK(chrome_prompt_request.SerializeToString(&request_content)); + + SendBuffer(request_content); + + // Sending the request can cause communication errors. If any happened don't + // bother waiting for a response. + if (state_ == State::kDoneInteraction) { + return; + } + + // Receive the response from Chrome. + PromptAcceptance prompt_acceptance = WaitForPromptAcceptance(); + + if (state_ == State::kDoneInteraction) { + return; + } + + // Send a message confirming to Chrome that the communication is over. + chrome_cleaner::CloseConnectionRequest close_connection_request; + chrome_prompt_request = ChromePromptRequest(); + *chrome_prompt_request.mutable_close_connection() = close_connection_request; + + std::string response_content; + DCHECK(chrome_prompt_request.SerializeToString(&response_content)); + + SendBuffer(response_content); + + if (state_ == State::kDoneInteraction) { + return; + } + + // Invoke callback with the result. + std::move(callback).Run(prompt_acceptance); + + state_ = State::kDoneInteraction; +} + +void ProtoChromePromptIPC::OnConnectionError() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_NE(State::kUninitialized, state_); + DCHECK_NE(State::kDoneInteraction, state_); + + if (error_handler_) { + error_handler_->OnConnectionClosed(); + } + + state_ = State::kDoneInteraction; +} + +void ProtoChromePromptIPC::SendBuffer(const std::string& request_content) { + DCHECK_NE(State::kDoneInteraction, state_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Write the message size. + const uint32_t kMessageLength = request_content.size(); + WriteByValue(kMessageLength); + + // Writing the message length failed. Do not send body. + if (state_ == State::kDoneInteraction) { + return; + } + + // Write the message content. + WriteByPointer(request_content.data(), kMessageLength); +} + +ProtoChromePromptIPC::PromptAcceptance +ProtoChromePromptIPC::WaitForPromptAcceptance() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(State::kWaitingForResponseFromChrome, state_); + + // On any error condition, invoke the error handler. + base::ScopedClosureRunner call_connection_closed(base::BindOnce( + &ProtoChromePromptIPC::OnConnectionError, base::Unretained(this))); + + // Read the response length. + DWORD bytes_read = 0; + uint32_t response_length = 0; + if (!::ReadFile(response_read_handle_.Get(), &response_length, + sizeof(response_length), &bytes_read, nullptr)) { + PLOG(ERROR) << "Reading the prompt acceptance message length failed."; + return PromptAcceptance::DENIED; + } + if (bytes_read != sizeof(response_length)) { + PLOG(ERROR) << "Short read on the prompt acceptance message length."; + return PromptAcceptance::DENIED; + } + + if (response_length == 0 || response_length > kMaxMessageLength) { + PLOG(ERROR) << "Invalid message length received: " << response_length; + return PromptAcceptance::DENIED; + } + + // Read the response. + std::string response_content; + if (!::ReadFile(response_read_handle_.Get(), + base::WriteInto(&response_content, response_length + 1), + response_length, &bytes_read, nullptr)) { + PLOG(ERROR) << "Reading the prompt acceptance message failed"; + return PromptAcceptance::DENIED; + } + if (bytes_read != response_length) { + PLOG(ERROR) << "Short read on the prompt acceptance message."; + return PromptAcceptance::DENIED; + } + + chrome_cleaner::PromptUserResponse response; + if (!response.ParseFromString(response_content)) { + LOG(ERROR) << "Parsing of prompt acceptance failed."; + return PromptAcceptance::DENIED; + } + + // Successful execution. + call_connection_closed.ReplaceClosure(base::DoNothing()); + + return static_cast<PromptAcceptance>(response.prompt_acceptance()); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.h b/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.h new file mode 100644 index 0000000..5e9b9ea --- /dev/null +++ b/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.h
@@ -0,0 +1,113 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_IPC_PROTO_CHROME_PROMPT_IPC_H_ +#define CHROME_CHROME_CLEANER_IPC_PROTO_CHROME_PROMPT_IPC_H_ + +#include <windows.h> + +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "base/win/scoped_handle.h" +#include "chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h" +#include "components/chrome_cleaner/public/proto/chrome_prompt.pb.h" + +namespace chrome_cleaner { + +class ProtoChromePromptIPC : public ChromePromptIPC { + public: + static constexpr uint32_t kMaxMessageLength = 1 * 1024 * 1024; // 1M bytes + + // Currently some mojom types are used to provide as drop-in replacement + // for the existing mojo based implementation. Since they are very simple + // they will stay essentially identical once the PromptAcceptance enum is + // replaced with a hand rolled one. + using PromptAcceptance = mojom::PromptAcceptance; + using PromptUserCallback = base::OnceCallback<void(PromptAcceptance)>; + using DisableExtensionsCallback = base::OnceCallback<void(bool)>; + + ProtoChromePromptIPC(base::win::ScopedHandle response_read_handle, + base::win::ScopedHandle request_write_handle); + ~ProtoChromePromptIPC() override; + + void Initialize(ErrorHandler* error_handler) override; + + void PostPromptUserTask(const std::vector<base::FilePath>& files_to_delete, + const std::vector<base::string16>& registry_keys, + const std::vector<base::string16>& extension_ids, + PromptUserCallback callback) override; + + void PostDisableExtensionsTask( + const std::vector<base::string16>& extension_ids, + DisableExtensionsCallback callback) override; + + void TryDeleteExtensions( + base::OnceClosure delete_allowed_callback, + base::OnceClosure delete_not_allowed_callback) override; + + private: + // Implements the initialization that needs to happen on the task_runner + // sequence. + void InitializeImpl(); + + void RunPromptUserTask(const std::vector<base::FilePath>& files_to_delete, + const std::vector<base::string16>& registry_keys, + const std::vector<base::string16>& extension_ids, + PromptUserCallback callback); + + // Invokes error_handler_->OnConnectionClosed() and updates state_. This + // should not be called more than once. + void OnConnectionError(); + + void SendBuffer(const std::string& request_content); + + PromptAcceptance WaitForPromptAcceptance(); + + template <typename T> + void WriteByValue(T value) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + DWORD bytes_written = 0; + if (!::WriteFile(request_write_handle_.Get(), &value, sizeof(value), + &bytes_written, nullptr)) { + PLOG(ERROR) << "Writing a message to the pipe failed."; + OnConnectionError(); + return; + } + + if (bytes_written != sizeof(value)) { + LOG(ERROR) << "Incorrect number of bytes written to the pipe. Should be: " + << sizeof(value) << " but is :" << bytes_written; + OnConnectionError(); + } + } + + template <typename T> + void WriteByPointer(const T* ptr, uint32_t size) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + DWORD bytes_written = 0; + if (!::WriteFile(request_write_handle_.Get(), ptr, size, &bytes_written, + nullptr)) { + PLOG(ERROR) << "Writing a message to the pipe failed."; + OnConnectionError(); + return; + } + if (bytes_written != size) { + LOG(ERROR) << "Incorrect number of bytes written to the pipe. Should be: " + << size << " but is :" << bytes_written; + OnConnectionError(); + } + } + + base::win::ScopedHandle response_read_handle_; + base::win::ScopedHandle request_write_handle_; + + scoped_refptr<base::SequencedTaskRunner> task_runner_ = + base::CreateSequencedTaskRunner({base::MayBlock()}); +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_IPC_PROTO_CHROME_PROMPT_IPC_H_
diff --git a/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc_unittest.cc b/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc_unittest.cc new file mode 100644 index 0000000..2e3d65f1 --- /dev/null +++ b/chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc_unittest.cc
@@ -0,0 +1,1049 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <windows.h> + +#include "base/command_line.h" +#include "base/process/process.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/multiprocess_test.h" +#include "base/test/scoped_task_environment.h" +#include "base/test/test_timeouts.h" +#include "base/unguessable_token.h" +#include "base/win/scoped_handle.h" +#include "base/win/win_util.h" +#include "chrome/chrome_cleaner/ipc/ipc_test_util.h" +#include "chrome/chrome_cleaner/ipc/proto_chrome_prompt_ipc.h" +#include "chrome/chrome_cleaner/logging/scoped_logging.h" +#include "components/chrome_cleaner/public/constants/constants.h" +#include "components/chrome_cleaner/public/proto/chrome_prompt.pb.h" +#include "components/chrome_cleaner/public/proto/chrome_prompt_for_tests.pb.h" +#include "components/chrome_cleaner/test/test_name_helper.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/multiprocess_func_list.h" + +namespace chrome_cleaner { +namespace { + +using base::win::ScopedHandle; +using testing::Bool; +using testing::Values; +using PromptAcceptance = ProtoChromePromptIPC::PromptAcceptance; + +constexpr char kIncludeUwSSwitch[] = "include-uws"; +constexpr char kIncludeRegistryKeysSwitch[] = "include-registry-keys"; +constexpr char kExpectedPromptResultSwitch[] = "expected-prompt-result"; +constexpr char kExpectedChromeDisconnectPointSwitch[] = + "expected-parent-disconnected"; + +const base::char16 kInvalidUTF16String[] = {0xDC00, 0xD800, 0xD800, 0xDFFF, + 0xDFFF, 0xDBFF, 0}; +const base::FilePath kInvalidFilePath(kInvalidUTF16String); +const base::FilePath kNonASCIIFilePath(L"ééààçç"); +const base::string16 kInvalidRegistryKey(kInvalidUTF16String); +const base::string16 kInvalidExtensionID(kInvalidUTF16String); + +const base::FilePath kBadFilePath(L"/path/to/bad.dll"); +const base::string16 kBadRegistryKey(L"HKCU:32\\Software\\ugly-uws\\nasty"); + +constexpr int kEarlyDisconnectionExitCode = 100; +constexpr int kSuccessExitCode = 0; +constexpr int kFailureExitCode = -1; + +// Possible moments when the parent process can disconnect from the IPC to +// check connection error handling in the child process. +enum class ChromeDisconnectPoint { + // Invalid value to initialize to before reading from the command-line. + kUnspecified = 0, + // The parent process will not try to disconnect while the child process + // is running. + kNone, + // The parent process will disconnect before the child process sends + // the version number. + kOnStartup, + // The parent process will disconnect after reading the version. + kAfterVersion, + // The parent process will disconnect after receiving the length of the first + // request. + kAfterRequestLength, + // The parent process will disconnect after receiving the length of the close + // connection message. + kAfterCloseMessageLength, + // The parent process will disconnect after receiving a message from the + // child process and before sending out a response. + kWhileProcessingChildRequest, +}; + +std::ostream& operator<<(std::ostream& stream, + ChromeDisconnectPoint parent_disconnected) { + switch (parent_disconnected) { + case ChromeDisconnectPoint::kUnspecified: + stream << "Unspecified"; + break; + case ChromeDisconnectPoint::kNone: + stream << "NotDisconnected"; + break; + case ChromeDisconnectPoint::kOnStartup: + stream << "DisconnectedOnStartup"; + break; + case ChromeDisconnectPoint::kAfterVersion: + stream << "DisconnectedAfterVersion"; + break; + case ChromeDisconnectPoint::kAfterRequestLength: + stream << "DisconnectedAfterRequestLength"; + break; + case ChromeDisconnectPoint::kWhileProcessingChildRequest: + stream << "DisconnectedWhileProcessingChildRequest"; + break; + case ChromeDisconnectPoint::kAfterCloseMessageLength: + stream << "DisconnectedAfterCloseMessageLength"; + break; + } + return stream; +} + +struct TestConfig { + void EnhanceCommandLine(base::CommandLine* command_line) { + if (uws_expected) { + command_line->AppendSwitch(kIncludeUwSSwitch); + } + + if (with_registry_keys) { + command_line->AppendSwitch(kIncludeRegistryKeysSwitch); + } + + command_line->AppendSwitchASCII( + kExpectedPromptResultSwitch, + base::NumberToString(static_cast<int>(expected_prompt_acceptance))); + + command_line->AppendSwitchASCII( + kExpectedChromeDisconnectPointSwitch, + base::NumberToString(static_cast<int>(expected_disconnection_point))); + } + + bool uws_expected = false; + bool with_registry_keys = false; + PromptAcceptance expected_prompt_acceptance = PromptAcceptance::DENIED; + ChromeDisconnectPoint expected_disconnection_point = + ChromeDisconnectPoint::kNone; +}; + +enum class ServerPipeDirection { + kInbound, + kOutbound, +}; + +// This function is a taken from +// https://cs.chromium.org/chromium/src/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_channel_win.cc +// to get the same behavior. +std::pair<ScopedHandle, ScopedHandle> CreateMessagePipe( + ServerPipeDirection server_direction) { + SECURITY_ATTRIBUTES security_attributes = {}; + security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES); + // Use this process's default access token. + security_attributes.lpSecurityDescriptor = nullptr; + // Handles to inherit will be added to the LaunchOptions explicitly. + security_attributes.bInheritHandle = false; + + base::string16 pipe_name = base::UTF8ToUTF16( + base::StrCat({"\\\\.\\pipe\\chrome-cleaner-", + base::UnguessableToken::Create().ToString()})); + + // Create the server end of the pipe. + DWORD direction_flag = server_direction == ServerPipeDirection::kInbound + ? PIPE_ACCESS_INBOUND + : PIPE_ACCESS_OUTBOUND; + ScopedHandle server_handle(::CreateNamedPipe( + pipe_name.c_str(), direction_flag | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | + PIPE_REJECT_REMOTE_CLIENTS, + /*nMaxInstances=*/1, /*nOutBufferSize=*/0, /*nInBufferSize=*/0, + /*nDefaultTimeOut=*/0, &security_attributes)); + if (!server_handle.IsValid()) { + PLOG(ERROR) << "Error creating server pipe"; + return std::make_pair(ScopedHandle(), ScopedHandle()); + } + + // The client pipe's read/write permissions are the opposite of the server's. + DWORD client_mode = server_direction == ServerPipeDirection::kInbound + ? GENERIC_WRITE + : GENERIC_READ; + + // Create the client end of the pipe. + ScopedHandle client_handle(::CreateFile( + pipe_name.c_str(), client_mode, /*dwShareMode=*/0, + /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS, + /*hTemplateFile=*/nullptr)); + if (!client_handle.IsValid()) { + PLOG(ERROR) << "Error creating client pipe"; + return std::make_pair(ScopedHandle(), ScopedHandle()); + } + + // Wait for the client end to connect (this should return + // ERROR_PIPE_CONNECTED immediately since it's already connected). + if (::ConnectNamedPipe(server_handle.Get(), /*lpOverlapped=*/nullptr)) { + LOG(ERROR) << "ConnectNamedPipe got an unexpected connection"; + return std::make_pair(ScopedHandle(), ScopedHandle()); + } + const auto error = ::GetLastError(); + if (error != ERROR_PIPE_CONNECTED) { + LOG(ERROR) << "ConnectNamedPipe returned unexpected error: " + << logging::SystemErrorCodeToString(error); + return std::make_pair(ScopedHandle(), ScopedHandle()); + } + + return std::make_pair(std::move(server_handle), std::move(client_handle)); +} + +void AppendHandleToCommandLine(base::CommandLine* command_line, + const std::string& switch_string, + HANDLE handle) { + ASSERT_NE(command_line, nullptr); + command_line->AppendSwitchASCII( + switch_string, base::NumberToString(base::win::HandleToUint32(handle))); +} + +// In this test the class representing the cleaner is contained in the parent +// process so it needs the server ends of the pipes. The class that represents +// chrome is in the child process and gets the client end of the pipes. +bool PrepareForCleaner(base::CommandLine* command_line, + base::HandlesToInheritVector* handles_to_inherit, + ScopedHandle* request_read_handle_, + ScopedHandle* request_write_handle_, + ScopedHandle* response_read_handle_, + ScopedHandle* response_write_handle_) { + // Requests flow from the cleaner to Chrome. + std::tie(*request_write_handle_, *request_read_handle_) = + CreateMessagePipe(ServerPipeDirection::kOutbound); + + // Responses flow from Chrome to the cleaner. + std::tie(*response_read_handle_, *response_write_handle_) = + CreateMessagePipe(ServerPipeDirection::kInbound); + + if (!request_read_handle_->IsValid() || !request_write_handle_->IsValid() || + !response_read_handle_->IsValid() || !response_write_handle_->IsValid()) { + return false; + } + + DCHECK(command_line); + DCHECK(handles_to_inherit); + AppendHandleToCommandLine(command_line, + chrome_cleaner::kChromeWriteHandleSwitch, + response_write_handle_->Get()); + handles_to_inherit->push_back(response_write_handle_->Get()); + AppendHandleToCommandLine(command_line, + chrome_cleaner::kChromeReadHandleSwitch, + request_read_handle_->Get()); + handles_to_inherit->push_back(request_read_handle_->Get()); + return true; +} + +// Provides the same kind of inputs and outputs on the pipes that Chrome would +// during the prompt process. +class MockChrome { + public: + MockChrome(base::win::ScopedHandle request_read_handle, + base::win::ScopedHandle response_write_handle) + : request_read_handle_(std::move(request_read_handle)), + response_write_handle_(std::move(response_write_handle)) {} + + // This is needed for single process tests to avoid blocking on incomplete + // operations. + void CancelAllOperations() { + ::CancelIoEx(request_read_handle_.Get(), nullptr); + ::CancelIoEx(response_write_handle_.Get(), nullptr); + } + + // Read and validate the version sent by the cleaner in a blocking way. + template <typename ValueType> + void ReadValue(ValueType* value) { + uint32_t read_size = sizeof(*value); + + DWORD bytes_read = 0; + bool success = ::ReadFile(request_read_handle_.Get(), value, read_size, + &bytes_read, nullptr); + if (!success) { + PLOG(ERROR) << "Could not read value."; + FAIL(); + } + + if (bytes_read != read_size) { + LOG(ERROR) << "Read the wrong number of bytes: " << bytes_read + << ". Should have been: " << read_size; + FAIL(); + } + } + + void ReadRequest(uint32_t request_length, + chrome_cleaner::ChromePromptRequest* request) { + DCHECK(request_read_handle_.IsValid()); + + DWORD bytes_read = 0; + std::string request_content; + // Read the request. + bool success = + ::ReadFile(request_read_handle_.Get(), + base::WriteInto(&request_content, request_length + 1), + request_length, &bytes_read, nullptr); + + if (!success) { + PLOG(ERROR) << "Could not read request."; + FAIL(); + } + + if (bytes_read != request_length) { + LOG(ERROR) << "Read the wrong number of bytes: " << bytes_read + << ". Should have been: " << request_length; + FAIL(); + } + + if (!request->ParseFromString(request_content)) { + LOG(ERROR) << "Could not parse request."; + FAIL(); + } + } + + // Blocking write of anything by value on the pipe. + template <typename T> + void WriteByValue(T value) { + DWORD bytes_written = 0; + bool success = ::WriteFile(response_write_handle_.Get(), &value, + sizeof(value), &bytes_written, nullptr); + + if (!success) { + PLOG(ERROR) << "Could not write to pipe."; + FAIL(); + } + + if (bytes_written != sizeof(value)) { + LOG(ERROR) << "Wrote the wrong number of bytes"; + FAIL(); + } + } + + // Blocking write of anything by pointer on the pipe. + // Does not own the memory. + // Set |should_succeed|=false when testing a failed operation. + template <typename T> + void WriteByPointer(const T* ptr, uint32_t size, bool should_succeed = true) { + DWORD bytes_written = 0; + bool success = ::WriteFile(response_write_handle_.Get(), ptr, size, + &bytes_written, nullptr); + + if (should_succeed && !success) { + PLOG(ERROR) << "Could not write to pipe."; + FAIL(); + } + + // We should not validate |bytes_written| if we know the call will fail. + if (should_succeed) { + if (bytes_written != size) { + LOG(ERROR) << "Wrote the wrong number of bytes"; + FAIL(); + } + } + } + + void SendMessage(google::protobuf::MessageLite& message) { + std::string message_content; + if (!message.SerializeToString(&message_content)) { + LOG(ERROR) << "Could not serialize message for sending"; + FAIL(); + } + + uint32_t message_size = message_content.size(); + WriteByValue(message_size); + WriteByPointer(message_content.data(), message_content.size()); + } + + // Send a response to the cleaner with the expected values. + void SendResponse(PromptAcceptance prompt_acceptance) { + DCHECK(response_write_handle_.IsValid()); + + chrome_cleaner::PromptUserResponse response; + + switch (prompt_acceptance) { + case PromptAcceptance::DENIED: + response.set_prompt_acceptance( + chrome_cleaner::PromptUserResponse::DENIED); + break; + case PromptAcceptance::ACCEPTED_WITH_LOGS: + response.set_prompt_acceptance( + chrome_cleaner::PromptUserResponse::ACCEPTED_WITH_LOGS); + break; + case PromptAcceptance::ACCEPTED_WITHOUT_LOGS: + response.set_prompt_acceptance( + chrome_cleaner::PromptUserResponse::ACCEPTED_WITHOUT_LOGS); + break; + case PromptAcceptance::UNSPECIFIED: + default: + response.set_prompt_acceptance( + chrome_cleaner::PromptUserResponse::UNSPECIFIED); + break; + } + + SendMessage(response); + } + + private: + base::win::ScopedHandle request_read_handle_; + base::win::ScopedHandle response_write_handle_; +}; + +// This class mocks the Chrome side of the IPC. +// A note on logging: We want errors to be logged using LOG(*) calls so they are +// captured by the ScopedLogging member. This in turn ensures that all messages +// are visible on buildbot outputs. This is why LOG(*) statements are used even +// though it would have been more readable to use the facilities provided by +// Gtest to log. +class ChildProcess { + public: + ChildProcess() + : scopped_logging_( + std::make_unique<ScopedLogging>(internal::GetLogPathSuffix())) { + mock_chrome_ = std::make_unique<MockChrome>( + ExtractHandleFromCommandLine(chrome_cleaner::kChromeReadHandleSwitch), + ExtractHandleFromCommandLine(chrome_cleaner::kChromeWriteHandleSwitch)); + + expected_disconnect_point_ = GetEnumFromCommandLine<ChromeDisconnectPoint>( + kExpectedChromeDisconnectPointSwitch); + + expected_prompt_acceptance_ = + GetEnumFromCommandLine<PromptAcceptance>(kExpectedPromptResultSwitch); + } + + base::win::ScopedHandle ExtractHandleFromCommandLine( + const std::string& handle_switch) { + uint32_t handle_value = 0; + if (!base::StringToUint(command_line_->GetSwitchValueNative(handle_switch), + &handle_value)) { + LOG(ERROR) << handle_switch << " not found on commandline"; + return base::win::ScopedHandle(); + } + HANDLE handle = base::win::Uint32ToHandle(handle_value); + return base::win::ScopedHandle(handle); + } + + template <typename Enum> + Enum GetEnumFromCommandLine(const std::string& flag) { + int val = 0; + if (!base::StringToInt(command_line_->GetSwitchValueASCII(flag), &val)) { + LOG(ERROR) << "Could not get flag:" << flag << " from the command line"; + } + return static_cast<Enum>(val); + } + + // This simulates the pipes getting cut for any reason. + void CloseConnectionIfDisconectionPointReached( + ChromeDisconnectPoint disconnect_point) { + if (expected_disconnect_point_ == disconnect_point) { + // Immediately exit the child process. Destructors do not get called so we + // do not properly clean up. This mimics a real spurious disconnect. + exit(kEarlyDisconnectionExitCode); + } + } + + // Execute all steps of the prompt according to passed in test config. + void Run() { + DCHECK_NE(expected_disconnect_point_, ChromeDisconnectPoint::kUnspecified); + DCHECK_NE(expected_prompt_acceptance_, PromptAcceptance::UNSPECIFIED); + + CloseConnectionIfDisconectionPointReached( + ChromeDisconnectPoint::kOnStartup); + + // Read the incoming version number, this is NOT echoed back. + constexpr uint8_t kExpectedVersion = 1; + uint8_t version = 0; + mock_chrome_->ReadValue(&version); + + if (version != kExpectedVersion) { + LOG(ERROR) << "Wrong version received: " << version; + FAIL(); + } + + CloseConnectionIfDisconectionPointReached( + ChromeDisconnectPoint::kAfterVersion); + + uint32_t request_length = 0; + mock_chrome_->ReadValue(&request_length); + + CloseConnectionIfDisconectionPointReached( + ChromeDisconnectPoint::kAfterRequestLength); + + chrome_cleaner::ChromePromptRequest request; + mock_chrome_->ReadRequest(request_length, &request); + + CloseConnectionIfDisconectionPointReached( + ChromeDisconnectPoint::kWhileProcessingChildRequest); + + int32_t expected_files_to_delete_size = + command_line_->HasSwitch(kIncludeUwSSwitch) ? 1 : 0; + if (request.prompt_user().files_to_delete_size() != + expected_files_to_delete_size) { + LOG(ERROR) << "Wrong number of files to delete received."; + FAIL(); + } + if (expected_files_to_delete_size == 1) { + std::string file_path_utf8; + base::UTF16ToUTF8(kBadFilePath.value().c_str(), + kBadFilePath.value().size(), &file_path_utf8); + if (request.prompt_user().files_to_delete(0) != file_path_utf8) { + LOG(ERROR) << "Wrong value for file to delete"; + FAIL(); + } + } + + int32_t expecteed_registry_keys_size = + command_line_->HasSwitch(kIncludeRegistryKeysSwitch) ? 1 : 0; + if (request.prompt_user().registry_keys_size() != + expecteed_registry_keys_size) { + LOG(ERROR) << "Wrong number of registry keys to delete"; + FAIL(); + } + if (expecteed_registry_keys_size == 1) { + if (request.prompt_user().registry_keys(0) != + base::UTF16ToUTF8(kBadRegistryKey)) { + LOG(ERROR) << "Wrong value for registry key"; + FAIL(); + } + } + + if (request.prompt_user().extension_ids_size() != 0) { + LOG(ERROR) << "Cleaning of UwsE not supported. None should be present in " + "message"; + FAIL(); + } + + // Send back a success message. + mock_chrome_->SendResponse(expected_prompt_acceptance_); + + // Receive the close connection message. + uint32_t close_message_length = 0; + mock_chrome_->ReadValue(&close_message_length); + + CloseConnectionIfDisconectionPointReached( + ChromeDisconnectPoint::kAfterCloseMessageLength); + + chrome_cleaner::ChromePromptRequest close_message; + mock_chrome_->ReadRequest(close_message_length, &close_message); + if (!close_message.has_close_connection()) { + LOG(ERROR) << "Wrong close connection message type"; + FAIL(); + } + } + + private: + std::unique_ptr<MockChrome> mock_chrome_; + std::unique_ptr<ScopedLogging> scopped_logging_; + + ChromeDisconnectPoint expected_disconnect_point_ = + ChromeDisconnectPoint::kUnspecified; + + PromptAcceptance expected_prompt_acceptance_ = PromptAcceptance::UNSPECIFIED; + const base::CommandLine* command_line_ = + base::CommandLine::ForCurrentProcess(); +}; + +// This mimics the Chrome side of the IPC. +MULTIPROCESS_TEST_MAIN(ProtoChromePromptIPCClientMain) { + base::test::ScopedTaskEnvironment scoped_task_environment; + + ChildProcess child_process; + child_process.Run(); + + return ::testing::Test::HasFailure() ? kFailureExitCode : kSuccessExitCode; +} + +class ProtoChromePromptIPCTest + : public ::testing::TestWithParam< + std::tuple<bool, bool, PromptAcceptance, ChromeDisconnectPoint>> { + private: + base::test::ScopedTaskEnvironment scoped_task_environment; +}; + +class ParentProcess { + public: + bool Initialize() { + // Inject the flags related to the the config in the command line. + test_config_.EnhanceCommandLine(&command_line_); + + return PrepareForCleaner(&command_line_, + &launch_options_.handles_to_inherit, + &request_read_handle_, &request_write_handle_, + &response_read_handle_, &response_write_handle_); + } + + void ValidateAcceptance(PromptAcceptance prompt_acceptance) { + EXPECT_EQ(prompt_acceptance, test_config_.expected_prompt_acceptance); + main_runloop_.Quit(); + } + + // A call to this function indicates that the connection was closed + // prematurely which signifies an error. + void ConnectionWasClosed() { + error_occurred_ = true; + main_runloop_.Quit(); + } + + void ConnectionWasClosedAfterDone() { + main_runloop_.Quit(); + FAIL() << "ConnectionWasClosedAfterDone should only be called in the Mojo " + "IPC implementation"; + } + + void Run() { + ASSERT_TRUE(internal::DeleteChildProcessLogs()); + + // Pass the command to the child process and launch the child process. + base::Process child_process = base::SpawnMultiProcessTestChild( + "ProtoChromePromptIPCClientMain", command_line_, launch_options_); + ASSERT_TRUE(child_process.IsRunning()); + + // Close our references to the handles as they are now handled by the child + // process. + request_read_handle_.Close(); + response_write_handle_.Close(); + + ProtoChromePromptIPC chrome_prompt_ipc(std::move(response_read_handle_), + std::move(request_write_handle_)); + + // Send the protocol version, blocking the child process until it is read. + auto error_handler = std::make_unique<ChromePromptIPCTestErrorHandler>( + base::BindOnce(&ParentProcess::ConnectionWasClosed, + base::Unretained(this)), + base::BindOnce(&ParentProcess::ConnectionWasClosedAfterDone, + base::Unretained(this))); + + chrome_prompt_ipc.Initialize(error_handler.get()); + + std::vector<base::FilePath> files_to_delete; + if (test_config_.uws_expected) { + files_to_delete.push_back(kBadFilePath); + } + + std::vector<base::string16> registry_keys; + if (test_config_.with_registry_keys) { + registry_keys.push_back(kBadRegistryKey); + } + + // Send the user prompt, blocking the child process until it is read. + // The test thread will block too until a response is received. + chrome_prompt_ipc.PostPromptUserTask( + files_to_delete, registry_keys, {}, + base::BindOnce(&ParentProcess::ValidateAcceptance, + base::Unretained(this))); + + main_runloop_.Run(); + + // During a normal execution where the full prompt exchange takes place + // there should be no errors. + bool should_have_errors = test_config_.expected_disconnection_point != + ChromeDisconnectPoint::kNone; + EXPECT_EQ(error_occurred_, should_have_errors); + + WaitForChildProcess(child_process); + } + + void WaitForChildProcess(const base::Process& child_process) { + // Expect the return code that can indicate one of three outcomes + // 1: Success + // 2: Early disconnection which is expected if we simulate Chrome crashing. + // 3: Failure which will be triggered if any EXPECT or ASSERT call fails in + // the child process. + int rv = -1; + bool success = base::WaitForMultiprocessTestChildExit( + child_process, TestTimeouts::action_timeout(), &rv); + ASSERT_TRUE(success); + + int expected_exit_code = kSuccessExitCode; + if (test_config_.expected_disconnection_point != + ChromeDisconnectPoint::kNone) { + expected_exit_code = kEarlyDisconnectionExitCode; + } + + EXPECT_EQ(expected_exit_code, rv); + + if (!success || rv != 0) { + internal::PrintChildProcessLogs(); + } + } + + TestConfig& GetTestConfig() { return test_config_; } + + private: + // Handles for Chrome. + ScopedHandle request_read_handle_; + ScopedHandle response_write_handle_; + + // Handles for the cleaner. + ScopedHandle request_write_handle_; + ScopedHandle response_read_handle_; + + TestConfig test_config_; + + base::CommandLine command_line_ = + base::GetMultiProcessTestChildBaseCommandLine(); + + base::LaunchOptions launch_options_; + + // Blocks until we receive the response from Chrome or an error occurs. + base::RunLoop main_runloop_; + bool error_occurred_ = false; +}; + +// This contains calls to the chrome_cleaner_ipc implementation. +TEST_P(ProtoChromePromptIPCTest, Communication) { + ParentProcess parent_process; + TestConfig& test_config = parent_process.GetTestConfig(); + std::tie(test_config.uws_expected, test_config.with_registry_keys, + test_config.expected_prompt_acceptance, + test_config.expected_disconnection_point) = GetParam(); + + ASSERT_TRUE(parent_process.Initialize()); + parent_process.Run(); +} + +INSTANTIATE_TEST_SUITE_P(NoUwSPresent, + ProtoChromePromptIPCTest, + testing::Combine( + /*[>uws_expected=<]*/ Values(false), + /*[>with_registry_keys=<]*/ Values(false), + Values(PromptAcceptance::DENIED), + Values(ChromeDisconnectPoint::kNone, + ChromeDisconnectPoint::kOnStartup)), + GetParamNameForTest()); + +INSTANTIATE_TEST_SUITE_P( + UwSPresent, + ProtoChromePromptIPCTest, + testing::Combine( + /*uws_expected=*/Values(true), + /*with_registry_keys=*/Bool(), + Values(PromptAcceptance::ACCEPTED_WITH_LOGS, + PromptAcceptance::ACCEPTED_WITHOUT_LOGS, + PromptAcceptance::DENIED), + Values(ChromeDisconnectPoint::kNone, + ChromeDisconnectPoint::kOnStartup, + ChromeDisconnectPoint::kAfterVersion, + ChromeDisconnectPoint::kAfterRequestLength, + ChromeDisconnectPoint::kAfterCloseMessageLength, + ChromeDisconnectPoint::kWhileProcessingChildRequest)), + GetParamNameForTest()); + +class ProtoChromePromptSameProcessTest : public ::testing::Test { + public: + void SetUp() override { + // Requests flow from the cleaner to Chrome. + base::win::ScopedHandle request_read_handle; + base::win::ScopedHandle request_write_handle; + std::tie(request_write_handle, request_read_handle) = + CreateMessagePipe(ServerPipeDirection::kOutbound); + + // Responses flow from Chrome to the cleaner. + base::win::ScopedHandle response_read_handle; + base::win::ScopedHandle response_write_handle; + std::tie(response_read_handle, response_write_handle) = + CreateMessagePipe(ServerPipeDirection::kInbound); + + EXPECT_TRUE(request_read_handle.IsValid()); + EXPECT_TRUE(request_write_handle.IsValid()); + EXPECT_TRUE(response_read_handle.IsValid()); + EXPECT_TRUE(response_write_handle.IsValid()); + + mock_chrome_ = std::make_unique<MockChrome>( + std::move(request_read_handle), std::move(response_write_handle)); + + chrome_prompt_ipc_ = std::make_unique<ProtoChromePromptIPC>( + std::move(response_read_handle), std::move(request_write_handle)); + + error_handler_ = std::make_unique<ChromePromptIPCTestErrorHandler>( + base::BindOnce(&ProtoChromePromptSameProcessTest ::ConnectionWasClosed, + base::Unretained(this)), + base::BindOnce( + &ProtoChromePromptSameProcessTest::ConnectionWasClosedAfterDone, + base::Unretained(this))); + } + + void InitCommunication() { + chrome_prompt_ipc_->Initialize(error_handler_.get()); + uint8_t version = 0; + mock_chrome_->ReadValue(&version); + } + + // A call to this function indicates that the connection was closed + // prematurely which signifies an error. + void ConnectionWasClosed() { + // Unblock the main test thread is there are pending operations. + mock_chrome_->CancelAllOperations(); + + error_occurred_ = true; + main_runloop_.Quit(); + } + + void ConnectionWasClosedAfterDone() { + main_runloop_.Quit(); + FAIL() << "ConnectionWasClosedAfterDone should only be called in the Mojo " + "IPC implementation"; + } + + void ExpectMessage() { + uint32_t request_length = 0; + mock_chrome_->ReadValue(&request_length); + + chrome_cleaner::ChromePromptRequest request; + mock_chrome_->ReadRequest(request_length, &request); + } + + void ValidateAcceptance(PromptAcceptance expected_prompt_acceptance, + PromptAcceptance prompt_acceptance) { + EXPECT_EQ(prompt_acceptance, expected_prompt_acceptance); + main_runloop_.Quit(); + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment; + + std::unique_ptr<MockChrome> mock_chrome_; + std::unique_ptr<ProtoChromePromptIPC> chrome_prompt_ipc_; + std::unique_ptr<ChromePromptIPCTestErrorHandler> error_handler_; + bool error_occurred_ = false; + + // Blocks until we receive the response from Chrome. + base::RunLoop main_runloop_; +}; + +TEST_F(ProtoChromePromptSameProcessTest, InvalidUTF16Path) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kInvalidFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::DENIED)); + + // Providing an invalid file path will trigger an immediate denial from the + // cleaner side. No communication will happen with Chrome so we do not call + // ExpectMessage() as it would timeout waiting for the prompt message. + main_runloop_.Run(); + // This is not considered an error but validation of user provided input. + ASSERT_FALSE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, InvalidUTF16RegistryKey) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {}, {kInvalidRegistryKey}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::DENIED)); + + // Providing an invalid registry key will trigger an immediate denial from the + // cleaner side. No communication will happen with Chrome so we do not call + // ExpectMessage() as it would timeout waiting for the prompt message. + main_runloop_.Run(); + + // This is not considered an error but validation of user provided input. + ASSERT_FALSE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, InvalidUTF16ExtensionID) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {}, {}, {kInvalidExtensionID}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::DENIED)); + + // Providing an invalid extension id will trigger an immediate denial from the + // cleaner side. No communication will happen with Chrome so we do not call + // ExpectMessage() as it would timeout waiting for the prompt message. + main_runloop_.Run(); + + // This is not considered an error but validation of user provided input. + ASSERT_FALSE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, ValidNonASCIIPath) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kNonASCIIFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::ACCEPTED_WITH_LOGS)); + + // Expect the prompt message. + ExpectMessage(); + + // Send back the response. + mock_chrome_->SendResponse(PromptAcceptance::ACCEPTED_WITH_LOGS); + // Expect the close connection message. + ExpectMessage(); + + main_runloop_.Run(); + // There are no errors here. Non-ASCII characters are supported. + ASSERT_FALSE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, ReponseSizeOverMax) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kNonASCIIFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::ACCEPTED_WITH_LOGS)); + + // Expect the prompt message. + ExpectMessage(); + + // Size over max. + uint32_t invalid_size = ProtoChromePromptIPC::kMaxMessageLength + 1; + mock_chrome_->WriteByValue(invalid_size); + + // Notice the absence of ExpectMessage() here. The cleaner will never get to + // sending a close connection message. + + main_runloop_.Run(); + + // This is an error scenario. + ASSERT_TRUE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, ReponseSizeZero) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kNonASCIIFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::ACCEPTED_WITH_LOGS)); + + // Expect the prompt message. + ExpectMessage(); + + // Size of zero. + uint32_t invalid_size = 0; + mock_chrome_->WriteByValue(invalid_size); + + // Notice the absence of ExpectMessage() here. The cleaner will never get to + // sending a close connection message. + + main_runloop_.Run(); + + // This is an error scenario. + ASSERT_TRUE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, ReponseSizeSentTooSmall) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kNonASCIIFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::ACCEPTED_WITH_LOGS)); + + // Expect the prompt message. + ExpectMessage(); + + chrome_cleaner::PromptUserResponse response; + response.set_prompt_acceptance( + chrome_cleaner::PromptUserResponse::ACCEPTED_WITH_LOGS); + + std::string response_content; + response.SerializeToString(&response_content); + + // Size too small. + uint32_t invalid_size = response_content.size() - 1; + mock_chrome_->WriteByValue(invalid_size); + + // Send the correct data. + mock_chrome_->WriteByPointer(response_content.data(), response_content.size(), + /*should_succeed=*/false); + + // Notice the absence of ExpectMessage() here. The cleaner will never get to + // sending a close connection message. + + main_runloop_.Run(); + + // This is an error scenario. + ASSERT_TRUE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, ReponseSizeSentTooBig) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kNonASCIIFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::ACCEPTED_WITH_LOGS)); + + // Expect the prompt message. + ExpectMessage(); + + chrome_cleaner::PromptUserResponse response; + response.set_prompt_acceptance( + chrome_cleaner::PromptUserResponse::ACCEPTED_WITH_LOGS); + + std::string response_content; + response.SerializeToString(&response_content); + + // Size too big. + uint32_t invalid_size = response_content.size() + 1; + mock_chrome_->WriteByValue(invalid_size); + + // Send the correct data. + mock_chrome_->WriteByPointer(response_content.data(), + response_content.size()); + + // Notice the absence of ExpectMessage() here. The cleaner will never get to + // sending a close connection message. + + main_runloop_.Run(); + + // This is an error scenario. + ASSERT_TRUE(error_occurred_); +} + +TEST_F(ProtoChromePromptSameProcessTest, OutOfRangeAcceptance) { + InitCommunication(); + + chrome_prompt_ipc_->PostPromptUserTask( + {kNonASCIIFilePath}, {}, {}, + base::BindOnce(&ProtoChromePromptSameProcessTest::ValidateAcceptance, + base::Unretained(this), + chrome_cleaner::PromptAcceptance::UNSPECIFIED)); + + // Expect the prompt message. + ExpectMessage(); + + // Send back the response with an out of range acceptance. + chrome_cleaner_test_only::PromptUserResponse response; + response.set_prompt_acceptance( + chrome_cleaner_test_only:: + PromptUserResponse_PromptAcceptance_FOR_TESTS_ONLY); + mock_chrome_->SendMessage(response); + + // Expect the close connection message. + ExpectMessage(); + + main_runloop_.Run(); + + // There are no errors here. An out of range PromptAcceptance value means + // that the protocol evolved and parsing it as UNSPECIFIED will not trigger + // a cleaning that the user actually denied. + ASSERT_FALSE(error_occurred_); +} + +} // namespace +} // namespace chrome_cleaner
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 521ff92..3b726c8d 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -378,6 +378,12 @@ // Enables or disables the Happiness Tracking System for Desktop Chrome. const base::Feature kHappinessTrackingSurveysForDesktop{ "HappinessTrackingSurveysForDesktop", base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables or disables the Happiness Tracking System demo mode for Desktop +// Chrome. +const base::Feature kHappinessTrackingSurveysForDesktopDemo{ + "HappinessTrackingSurveysForDesktopDemo", + base::FEATURE_DISABLED_BY_DEFAULT}; #endif // !defined(OS_ANDROID) // Enables committed error pages instead of transient navigation entries for
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 0a45fb2..2330e10f 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -243,6 +243,9 @@ #if !defined(OS_ANDROID) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kHappinessTrackingSurveysForDesktop; + +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kHappinessTrackingSurveysForDesktopDemo; #endif COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/client_hints/OWNERS b/chrome/common/client_hints/OWNERS index 7ad3493f..22542699 100644 --- a/chrome/common/client_hints/OWNERS +++ b/chrome/common/client_hints/OWNERS
@@ -4,4 +4,5 @@ # For IPC security review per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS +# COMPONENT: Blink>Loader
diff --git a/chrome/renderer/page_load_metrics/OWNERS b/chrome/renderer/page_load_metrics/OWNERS index 9021361e..1984ff7 100644 --- a/chrome/renderer/page_load_metrics/OWNERS +++ b/chrome/renderer/page_load_metrics/OWNERS
@@ -1 +1,2 @@ file://chrome/browser/page_load_metrics/OWNERS +# COMPONENT: Speed>Metrics
diff --git a/chrome/renderer/searchbox/OWNERS b/chrome/renderer/searchbox/OWNERS index d81b034..fa6ab8f1 100644 --- a/chrome/renderer/searchbox/OWNERS +++ b/chrome/renderer/searchbox/OWNERS
@@ -1,3 +1,4 @@ file://chrome/browser/search/OWNERS dcblack@chromium.org +# COMPONENT: UI>Browser>NewTabPage
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 32b54d1..c2bf13f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -643,7 +643,6 @@ "//chrome/browser", "//chrome/browser/devtools:test_support", "//chrome/browser/profiling_host:profiling_browsertests", - "//chrome/browser/resources:browser_tests", "//chrome/browser/web_applications:browser_tests", "//chrome/browser/web_applications/extensions:browser_tests", "//chrome/renderer", @@ -3860,8 +3859,7 @@ "//ui/native_theme:test_support", ] if (is_win) { - deps += - [ "//chrome/browser/safe_browsing/chrome_cleaner:test_only_proto" ] + deps += [ "//components/chrome_cleaner/public/proto:test_only_proto" ] } if (is_mac) { deps += [ ":firefox_importer_interface" ]
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 02f735e..0bba8cbc 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -132,7 +132,9 @@ "javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabModel.java", "javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabModelSelector.java", "javatests/src/org/chromium/chrome/test/util/browser/TabTitleObserver.java", + "javatests/src/org/chromium/chrome/test/util/browser/WebApkInfoBuilder.java", "javatests/src/org/chromium/chrome/test/util/browser/WebappTestPage.java", + "javatests/src/org/chromium/chrome/test/util/browser/WebappTestHelper.java", "javatests/src/org/chromium/chrome/test/util/ChromeRestriction.java", "javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java", "javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java", @@ -182,6 +184,7 @@ "//third_party/android_sdk:android_test_base_java", "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/blink/public:blink_headers_java", "//third_party/hamcrest:hamcrest_core_java", "//third_party/jsr-305:jsr_305_javalib", "//third_party/junit",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java index ff60d54d..efb33e45 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -370,8 +370,7 @@ * Returns when the tab has been created and has finished navigating. */ public static void newTabFromMenu(Instrumentation instrumentation, - final ChromeTabbedActivity activity) - throws InterruptedException { + final ChromeActivity activity) throws InterruptedException { newTabFromMenu(instrumentation, activity, false, true); } @@ -381,7 +380,7 @@ * Returns when the tab has been created and has finished navigating. */ public static void newTabFromMenu(Instrumentation instrumentation, - final ChromeTabbedActivity activity, boolean incognito, boolean waitForNtpLoad) + final ChromeActivity activity, boolean incognito, boolean waitForNtpLoad) throws InterruptedException { final CallbackHelper createdCallback = new CallbackHelper(); final CallbackHelper selectedCallback = new CallbackHelper(); @@ -488,8 +487,7 @@ * Returns after the tab has been closed. */ public static void closeCurrentTab(final Instrumentation instrumentation, - final ChromeTabbedActivity activity) - throws InterruptedException { + final ChromeActivity activity) throws InterruptedException { closeTabWithAction(instrumentation, activity, new Runnable() { @Override public void run() { @@ -507,7 +505,7 @@ * Closes a tab with the given action and waits for a tab closure to be observed. */ public static void closeTabWithAction(Instrumentation instrumentation, - final ChromeTabbedActivity activity, Runnable action) throws InterruptedException { + final ChromeActivity activity, Runnable action) throws InterruptedException { final CallbackHelper closeCallback = new CallbackHelper(); final TabModelObserver observer = new EmptyTabModelObserver() { @Override
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WebApkInfoBuilder.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WebApkInfoBuilder.java new file mode 100644 index 0000000..bef51b92 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WebApkInfoBuilder.java
@@ -0,0 +1,57 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.test.util.browser; + +import android.graphics.Color; + +import org.chromium.blink_public.platform.WebDisplayMode; +import org.chromium.chrome.browser.ShortcutHelper; +import org.chromium.chrome.browser.ShortcutSource; +import org.chromium.chrome.browser.webapps.WebApkInfo; +import org.chromium.chrome.browser.webapps.WebApkInfo.WebApkDistributor; +import org.chromium.content_public.common.ScreenOrientationValues; + +import java.util.HashMap; + +/** Builder class for {@link WebApkInfo} objects. */ +public class WebApkInfoBuilder { + private String mWebApkPackageName; + private String mUrl; + private String mScope; + private @WebDisplayMode int mDisplayMode = WebDisplayMode.STANDALONE; + private String mManifestUrl; + + public WebApkInfoBuilder(String webApkPackageName, String url) { + mWebApkPackageName = webApkPackageName; + mUrl = url; + } + + public void setScope(String scope) { + mScope = scope; + } + + public void setDisplayMode(@WebDisplayMode int displayMode) { + mDisplayMode = displayMode; + } + + public void setManifestUrl(String manifestUrl) { + mManifestUrl = manifestUrl; + } + + /** + * Builds {@link WebApkInfo} object using options that have been set. + */ + public WebApkInfo build() { + return WebApkInfo.create(mUrl, mScope, null, null, null, null, null, mDisplayMode, + ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN, + ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, + ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, Color.WHITE, + false /* isPrimaryIconMaskable */, mWebApkPackageName, /* shellApkVersion */ 1, + mManifestUrl, mUrl, WebApkDistributor.BROWSER, + new HashMap<String, String>() /* iconUrlToMurmur2HashMap */, null, null, + false /* forceNavigation */, false /* isSplashProvidedByWebApk */, null, + 1 /* webApkVersionCode */); + } +}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WebappTestHelper.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WebappTestHelper.java new file mode 100644 index 0000000..1bc10a71 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WebappTestHelper.java
@@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.test.util.browser; + +import android.content.Intent; + +import org.chromium.chrome.browser.ShortcutHelper; + +/** Helper class for webapp tests. */ +public class WebappTestHelper { + /** + * Returns simplest intent which builds valid WebappInfo via {@link WebappInfo#create()}. + */ + public static Intent createMinimalWebappIntent(String id, String url) { + Intent intent = new Intent(); + intent.putExtra(ShortcutHelper.EXTRA_ID, id); + intent.putExtra(ShortcutHelper.EXTRA_URL, url); + return intent; + } +}
diff --git a/chrome/test/data/local_ntp/local_ntp_browsertest.html b/chrome/test/data/local_ntp/local_ntp_browsertest.html index 16ae52e..4d2839dd 100644 --- a/chrome/test/data/local_ntp/local_ntp_browsertest.html +++ b/chrome/test/data/local_ntp/local_ntp_browsertest.html
@@ -160,174 +160,177 @@ </dialog> <dialog id="customization-menu" class="customize-dialog"> - <div id="menu-nav-panel" role="tablist" aria-label="$i18n{customizeMenu}"> - <button id="backgrounds-button" class="menu-option" tabindex="0" - role="tab" aria-controls="backgrounds-menu backgrounds-image-menu" - aria-selected="true" aria-labelledby="backgrounds-menu-option" - title="$i18n{backgroundsOption}"> - <div class="menu-option-icon-wrapper"> - <div id="backgrounds-icon" class="menu-option-icon"></div> - </div> - <div id="backgrounds-menu-option" class="menu-option-label"> - $i18n{backgroundsOption} - </div> - </button> - <button id="shortcuts-button" class="menu-option" tabindex="0" - role="tab" aria-controls="shortcuts-menu" aria-selected="false" - aria-labelledby="shortcuts-menu-option" - title="$i18n{shortcutsOption}"> - <div class="menu-option-icon-wrapper"> - <div id="shortcuts-icon" class="menu-option-icon"></div> - </div> - <div id="shortcuts-menu-option" class="menu-option-label"> - $i18n{shortcutsOption} - </div> - </button> - <button id="colors-button" class="menu-option" tabindex="0" role="tab" - aria-controls="colors-menu" aria-selected="false" - aria-labelledby="colors-menu-option" title="$i18n{colorsOption}"> - <div class="menu-option-icon-wrapper"> - <div id="colors-icon" class="menu-option-icon"></div> - </div> - <div id="colors-menu-option" class="menu-option-label"> - $i18n{colorsOption} - </div> - </button> - </div> - <div id="menu-contents"> - <div id="menu-header"> - <div id="menu-back-circle" tabindex="0" role="button" - aria-label="$i18n{backLabel}" title="$i18n{backLabel}"> - <div id="menu-back"></div> - </div> - <div id="menu-title">$i18n{customizeMenu}</div> - <div id="refresh-daily-wrapper"> - <div id="refresh-toggle-wrapper" title="$i18n{refreshDaily}"> - <label class="switch"> - <input id="refresh-daily-toggle" type="checkbox" - aria-labelledby="refresh-text"></input> - <span class="toggle"> - <div class="knob"></div> - <div class="highlight"></div> - </span> - </label> + <div id="menu-inner"> + <div id="menu-nav-panel" role="tablist" + aria-label="$i18n{customizeMenu}"> + <button id="backgrounds-button" class="menu-option" tabindex="0" + role="tab" aria-controls="backgrounds-menu backgrounds-image-menu" + aria-selected="true" aria-labelledby="backgrounds-menu-option" + title="$i18n{backgroundsOption}"> + <div class="menu-option-icon-wrapper"> + <div id="backgrounds-icon" class="menu-option-icon"></div> </div> - <div id="refresh-text">$i18n{refreshDaily}</div> - </div> + <div id="backgrounds-menu-option" class="menu-option-label"> + $i18n{backgroundsOption} + </div> + </button> + <button id="shortcuts-button" class="menu-option" tabindex="0" + role="tab" aria-controls="shortcuts-menu" aria-selected="false" + aria-labelledby="shortcuts-menu-option" + title="$i18n{shortcutsOption}"> + <div class="menu-option-icon-wrapper"> + <div id="shortcuts-icon" class="menu-option-icon"></div> + </div> + <div id="shortcuts-menu-option" class="menu-option-label"> + $i18n{shortcutsOption} + </div> + </button> + <button id="colors-button" class="menu-option" tabindex="0" role="tab" + aria-controls="colors-menu" aria-selected="false" + aria-labelledby="colors-menu-option" title="$i18n{colorsOption}"> + <div class="menu-option-icon-wrapper"> + <div id="colors-icon" class="menu-option-icon"></div> + </div> + <div id="colors-menu-option" class="menu-option-label"> + $i18n{colorsOption} + </div> + </button> </div> - <div id="backgrounds-menu" class="menu-panel" tabindex="0" - role="tabpanel" aria-label="$i18n{backgroundsOption}"> - <div id="backgrounds-upload" class="bg-sel-tile-bg"> - <div id="backgrounds-upload-icon" class="bg-sel-tile" tabindex="-1" - role="button" aria-label="$i18n{uploadImage}" - aria-pressed="false" title="$i18n{uploadImage}"> - <div id="backgrounds-upload-arrow"></div> - <div id="backgrounds-upload-text">$i18n{uploadImage}</div> + <div id="menu-contents"> + <div id="menu-header"> + <div id="menu-back-circle" tabindex="0" role="button" + aria-label="$i18n{backLabel}" title="$i18n{backLabel}"> + <div id="menu-back"></div> + </div> + <div id="menu-title">$i18n{customizeMenu}</div> + <div id="refresh-daily-wrapper"> + <div id="refresh-toggle-wrapper" title="$i18n{refreshDaily}"> + <label class="switch"> + <input id="refresh-daily-toggle" type="checkbox" + aria-labelledby="refresh-text"></input> + <span class="toggle"> + <div class="knob"></div> + <div class="highlight"></div> + </span> + </label> + </div> + <div id="refresh-text">$i18n{refreshDaily}</div> </div> </div> - <div id="backgrounds-default" class="bg-sel-tile-bg"> - <div id="backgrounds-default-icon" class="bg-sel-tile" tabindex="-1" - role="button" aria-label="$i18n{noBackground}" - title="$i18n{noBackground}" aria-pressed="false"> - <div class="mini-page"> - <div class="mini-header-colorful"></div> - <div class="mini-shortcuts"></div> + <div id="backgrounds-menu" class="menu-panel" tabindex="0" + role="tabpanel" aria-label="$i18n{backgroundsOption}"> + <div id="backgrounds-upload" class="bg-sel-tile-bg"> + <div id="backgrounds-upload-icon" class="bg-sel-tile" + tabindex="-1" role="button" aria-label="$i18n{uploadImage}" + aria-pressed="false" title="$i18n{uploadImage}"> + <div id="backgrounds-upload-arrow"></div> + <div id="backgrounds-upload-text">$i18n{uploadImage}</div> </div> </div> - <div class="bg-sel-tile-title">$i18n{noBackground}</div> - </div> - </div> - <div id="backgrounds-image-menu" class="menu-panel" tabindex="0" - role="tabpanel" aria-label="$i18n{backgroundsOption}"></div> - <div id="shortcuts-menu" class="menu-panel" tabindex="0" role="tabpanel" - aria-label="$i18n{shortcutsOption}"> - <div id="sh-options"> - <div class="sh-option"> - <div id="sh-option-cl" class="sh-option-image" tabindex="-1" - role="button" aria-pressed="false" - aria-labelledby="sh-option-cl-title" - title="$i18n{myShortcuts}"> - <div class="sh-option-icon"></div> - <div class="sh-option-mini"> - <div class="mini-page"> - <div class="mini-header"></div> - <div class="mini-shortcuts"></div> - </div> + <div id="backgrounds-default" class="bg-sel-tile-bg"> + <div id="backgrounds-default-icon" class="bg-sel-tile" + tabindex="-1" role="button" aria-label="$i18n{noBackground}" + title="$i18n{noBackground}" aria-pressed="false"> + <div class="mini-page"> + <div class="mini-header-colorful"></div> + <div class="mini-shortcuts"></div> </div> </div> - <div id="sh-option-cl-title" class="sh-option-title"> - $i18n{myShortcuts} - </div> - $i18n{shortcutsCurated} + <div class="bg-sel-tile-title">$i18n{noBackground}</div> </div> - <div class="sh-option"> - <div id="sh-option-mv" class="sh-option-image" tabindex="-1" - role="button" aria-pressed="false" - aria-labelledby="sh-option-mv-title" - title="$i18n{mostVisited}"> - <div class="sh-option-icon"></div> - <div class="sh-option-mini"> - <div class="mini-page"> - <div class="mini-header"></div> - <div class="mini-shortcuts"></div> + </div> + <div id="backgrounds-image-menu" class="menu-panel" tabindex="0" + role="tabpanel" aria-label="$i18n{backgroundsOption}"></div> + <div id="shortcuts-menu" class="menu-panel" tabindex="0" + role="tabpanel" aria-label="$i18n{shortcutsOption}"> + <div id="sh-options"> + <div class="sh-option"> + <div id="sh-option-cl" class="sh-option-image" tabindex="-1" + role="button" aria-pressed="false" + aria-labelledby="sh-option-cl-title" + title="$i18n{myShortcuts}"> + <div class="sh-option-icon"></div> + <div class="sh-option-mini"> + <div class="mini-page"> + <div class="mini-header"></div> + <div class="mini-shortcuts"></div> + </div> </div> </div> + <div id="sh-option-cl-title" class="sh-option-title"> + $i18n{myShortcuts} + </div> + $i18n{shortcutsCurated} </div> - <div id="sh-option-mv-title" class="sh-option-title"> - $i18n{mostVisited} + <div class="sh-option"> + <div id="sh-option-mv" class="sh-option-image" tabindex="-1" + role="button" aria-pressed="false" + aria-labelledby="sh-option-mv-title" + title="$i18n{mostVisited}"> + <div class="sh-option-icon"></div> + <div class="sh-option-mini"> + <div class="mini-page"> + <div class="mini-header"></div> + <div class="mini-shortcuts"></div> + </div> + </div> + </div> + <div id="sh-option-mv-title" class="sh-option-title"> + $i18n{mostVisited} + </div> + $i18n{shortcutsSuggested} </div> - $i18n{shortcutsSuggested} </div> - </div> - <div id="sh-hide"> - <div id="sh-hide-icon"></div> - <div> - <div id="sh-hide-title">$i18n{hideShortcuts}</div> - $i18n{hideShortcutsDesc} - </div> - <div id="sh-hide-toggle-wrapper" title="$i18n{hideShortcuts}"> - <label class="switch"> - <input id="sh-hide-toggle" type="checkbox" tabindex="-1" - aria-labelledby="sh-hide-title"></input> - <span class="toggle"> - <div class="knob"></div> - <div class="highlight"></div> - </span> - </label> - </div> - </div> - </div> - <div id="colors-menu" class="menu-panel" tabindex="0" role="tabpanel" - aria-label="$i18n{colorsOption}"> - <div id="colors-theme" tabindex="0"> - <div id="colors-theme-icon"></div> + <div id="sh-hide"> + <div id="sh-hide-icon"></div> <div> - <div id="colors-theme-name"></div> - $i18n{installedThemeDesc} + <div id="sh-hide-title">$i18n{hideShortcuts}</div> + $i18n{hideShortcutsDesc} </div> - <a id="colors-theme-link" target="_blank"> - <div id="colors-theme-link-icon" > </div> - </a> - <button id="colors-theme-uninstall" class="paper secondary"> - $i18n{uninstallButton} - </button> - </div> - <div id="color-picker-container" class="bg-sel-tile-bg"> - <div id="color-picker-tile" class="bg-sel-tile" tabindex="-1" - aria-label="$i18n{colorPickerLabel}" - title="$i18n{colorPickerLabel}" - role="button" aria-pressed="false"> - <div id="left-semicircle"></div> - <div id="color-picker-icon"></div> - <input id="color-picker" type="color" style="display:none"> - </input> + <div id="sh-hide-toggle-wrapper" title="$i18n{hideShortcuts}"> + <label class="switch"> + <input id="sh-hide-toggle" type="checkbox" tabindex="-1" + aria-labelledby="sh-hide-title"></input> + <span class="toggle"> + <div class="knob"></div> + <div class="highlight"></div> + </span> + </label> + </div> </div> </div> - <div id="colors-default" class="bg-sel-tile-bg"> - <div id="colors-default-icon" class="bg-sel-tile" tabindex="-1" - aria-label="$i18n{defaultThemeLabel}" - title="$i18n{defaultThemeLabel}" tabindex="-1" + <div id="colors-menu" class="menu-panel" tabindex="0" role="tabpanel" + aria-label="$i18n{colorsOption}"> + <div id="colors-theme" tabindex="0"> + <div id="colors-theme-icon"></div> + <div> + <div id="colors-theme-name"></div> + $i18n{installedThemeDesc} + </div> + <a id="colors-theme-link" target="_blank"> + <div id="colors-theme-link-icon" > </div> + </a> + <button id="colors-theme-uninstall" class="paper secondary"> + $i18n{uninstallButton} + </button> + </div> + <div id="color-picker-container" class="bg-sel-tile-bg"> + <div id="color-picker-tile" class="bg-sel-tile" tabindex="-1" + aria-label="$i18n{colorPickerLabel}" + title="$i18n{colorPickerLabel}" role="button" aria-pressed="false"> + <div id="left-semicircle"></div> + <div id="color-picker-icon"></div> + <input id="color-picker" type="color" style="display:none"> + </input> + </div> + </div> + <div id="colors-default" class="bg-sel-tile-bg"> + <div id="colors-default-icon" class="bg-sel-tile" tabindex="-1" + aria-label="$i18n{defaultThemeLabel}" + title="$i18n{defaultThemeLabel}" tabindex="-1" + role="button" aria-pressed="false"> + </div> </div> </div> </div>
diff --git a/chrome/tools/build/android/FILES.cfg b/chrome/tools/build/android/FILES.cfg index a2413a6..86eca16 100644 --- a/chrome/tools/build/android/FILES.cfg +++ b/chrome/tools/build/android/FILES.cfg
@@ -35,4 +35,8 @@ 'filename': 'apks/ChromePublic.apk', 'buildtype': ['dev', 'official'], }, + { + 'filename': 'apks/SystemWebViewShell.apk', + 'buildtype': ['dev', 'official'], + }, ]
diff --git a/chromecast/bindings/bindings_manager_fuchsia.cc b/chromecast/bindings/bindings_manager_fuchsia.cc index fe88955..b08c90c7 100644 --- a/chromecast/bindings/bindings_manager_fuchsia.cc +++ b/chromecast/bindings/bindings_manager_fuchsia.cc
@@ -22,7 +22,7 @@ void BindingsManagerFuchsia::AddBinding(base::StringPiece binding_name, base::StringPiece binding_script) { bindings_[binding_name.as_string()] = - cr_fuchsia::MemBufferFromString(binding_script); + cr_fuchsia::MemBufferFromString(binding_script, "cast-binding-script"); } void BindingsManagerFuchsia::GetAll(GetAllCallback callback) {
diff --git a/chromecast/media/cma/backend/buffering_mixer_source.cc b/chromecast/media/cma/backend/buffering_mixer_source.cc index 65495f3..c7e5da6 100644 --- a/chromecast/media/cma/backend/buffering_mixer_source.cc +++ b/chromecast/media/cma/backend/buffering_mixer_source.cc
@@ -99,67 +99,6 @@ } // namespace -BufferingMixerSource::LockedMembers::Members::Members( - BufferingMixerSource* source, - int input_samples_per_second, - int num_channels, - int64_t playback_start_timestamp, - int64_t playback_start_pts) - : fader_(source, - kFadeTime, - num_channels, - input_samples_per_second, - 1.0 /* playback_rate */), - playback_start_timestamp_(playback_start_timestamp), - playback_start_pts_(playback_start_pts), - audio_resampler_(num_channels) { - buffers_to_be_freed_.reserve(kFreeBufferListSize); -} - -BufferingMixerSource::LockedMembers::Members::~Members() = default; - -BufferingMixerSource::LockedMembers::AcquiredLock::AcquiredLock( - LockedMembers* members) - : locked_(members) { - DCHECK(locked_); - locked_->member_lock_.Acquire(); -} - -BufferingMixerSource::LockedMembers::AcquiredLock::~AcquiredLock() { - locked_->member_lock_.Release(); -} - -BufferingMixerSource::LockedMembers::AssertedLock::AssertedLock( - LockedMembers* members) - : locked_(members) { - DCHECK(locked_); - locked_->member_lock_.AssertAcquired(); -} - -BufferingMixerSource::LockedMembers::LockedMembers( - BufferingMixerSource* source, - int input_samples_per_second, - int num_channels, - int64_t playback_start_timestamp, - int64_t playback_start_pts) - : members_(source, - input_samples_per_second, - num_channels, - playback_start_timestamp, - playback_start_pts) {} - -BufferingMixerSource::LockedMembers::~LockedMembers() = default; - -BufferingMixerSource::LockedMembers::AcquiredLock -BufferingMixerSource::LockedMembers::Lock() { - return AcquiredLock(this); -} - -BufferingMixerSource::LockedMembers::AssertedLock -BufferingMixerSource::LockedMembers::AssertAcquired() { - return AssertedLock(this); -} - BufferingMixerSource::BufferingMixerSource(Delegate* delegate, int num_channels, int input_samples_per_second, @@ -181,11 +120,14 @@ max_queued_frames_(MaxQueuedFrames(device_id, input_samples_per_second)), start_threshold_frames_( StartThreshold(device_id, input_samples_per_second)), - locked_members_(this, - input_samples_per_second, - num_channels_, - start_playback_asap ? INT64_MIN : INT64_MAX, - playback_start_pts), + fader_(this, + kFadeTime, + num_channels_, + input_samples_per_second_, + 1.0 /* playback_rate */), + playback_start_timestamp_(start_playback_asap ? INT64_MIN : INT64_MAX), + playback_start_pts_(playback_start_pts), + audio_resampler_(num_channels_), weak_factory_(this) { LOG(INFO) << "Create " << device_id_ << " (" << this << "), content type = " << AudioContentTypeToString(content_type_) @@ -196,6 +138,7 @@ DCHECK_LE(start_threshold_frames_, max_queued_frames_); weak_this_ = weak_factory_.GetWeakPtr(); + buffers_to_be_freed_.reserve(kFreeBufferListSize); old_buffers_to_be_freed_.reserve(kFreeBufferListSize); pcm_completion_task_ = @@ -217,10 +160,10 @@ LOG(INFO) << __func__ << " playback_start_timestamp=" << playback_start_timestamp; - auto locked = locked_members_.Lock(); - DCHECK(!locked->started_); - DCHECK(locked->playback_start_timestamp_ == INT64_MAX); - locked->playback_start_timestamp_ = playback_start_timestamp; + base::AutoLock lock(lock_); + DCHECK(!started_); + DCHECK_EQ(playback_start_timestamp_, INT64_MAX); + playback_start_timestamp_ = playback_start_timestamp; } void BufferingMixerSource::RestartPlaybackAt(int64_t timestamp, int64_t pts) { @@ -228,17 +171,17 @@ LOG(INFO) << __func__ << " timestamp=" << timestamp << " pts=" << pts; { - auto locked = locked_members_.Lock(); - DCHECK(locked->started_); + base::AutoLock lock(lock_); + DCHECK(started_); - locked->playback_start_pts_ = pts; - locked->playback_start_timestamp_ = timestamp; - locked->started_ = false; - locked->queued_frames_ += locked->current_buffer_offset_; - locked->current_buffer_offset_ = 0; + playback_start_pts_ = pts; + playback_start_timestamp_ = timestamp; + started_ = false; + queued_frames_ += current_buffer_offset_; + current_buffer_offset_ = 0; - while (!locked->queue_.empty()) { - DecoderBufferBase* data = locked->queue_.front().get(); + while (!queue_.empty()) { + DecoderBufferBase* data = queue_.front().get(); int64_t frames = DataToFrames(data->data_size()); if (data->timestamp() + SamplesToMicroseconds(frames, input_samples_per_second_) >= @@ -246,8 +189,8 @@ break; } - locked->queued_frames_ -= frames; - locked->queue_.pop_front(); + queued_frames_ -= frames; + queue_.pop_front(); } } } @@ -257,22 +200,22 @@ LOG(INFO) << __func__ << " rate=" << rate; DCHECK_GT(rate, 0); - auto locked = locked_members_.Lock(); - locked->playback_rate_ = rate; + base::AutoLock lock(lock_); + playback_rate_ = rate; } float BufferingMixerSource::SetAvSyncPlaybackRate(float rate) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); LOG(INFO) << __func__ << " rate=" << rate; - auto locked = locked_members_.Lock(); - return locked->audio_resampler_.SetMediaClockRate(rate); + base::AutoLock lock(lock_); + return audio_resampler_.SetMediaClockRate(rate); } BufferingMixerSource::RenderingDelay BufferingMixerSource::GetMixerRenderingDelay() { - auto locked = locked_members_.Lock(); - return locked->mixer_rendering_delay_; + base::AutoLock lock(lock_); + return mixer_rendering_delay_; } int BufferingMixerSource::num_channels() { @@ -303,13 +246,12 @@ RenderingDelay delay; bool queued; { - auto locked = locked_members_.Lock(); - old_buffers_to_be_freed_.swap(locked->buffers_to_be_freed_); - if (locked->state_ == State::kUninitialized || - locked->queued_frames_ + locked->fader_.buffered_frames() >= - max_queued_frames_) { - DCHECK(!locked->pending_data_); - locked->pending_data_ = std::move(data); + base::AutoLock lock(lock_); + old_buffers_to_be_freed_.swap(buffers_to_be_freed_); + if (state_ == State::kUninitialized || + queued_frames_ + fader_.buffered_frames() >= max_queued_frames_) { + DCHECK(!pending_data_); + pending_data_ = std::move(data); queued = false; } else { delay = QueueData(std::move(data)); @@ -324,37 +266,34 @@ BufferingMixerSource::RenderingDelay BufferingMixerSource::QueueData( scoped_refptr<DecoderBufferBase> data) { - auto locked = locked_members_.AssertAcquired(); if (data->end_of_stream()) { LOG(INFO) << "End of stream for " << device_id_ << " (" << this << ")"; - locked->state_ = State::kGotEos; - if (!locked->started_ && locked->playback_start_timestamp_ != INT64_MIN) { + state_ = State::kGotEos; + if (!started_ && playback_start_timestamp_ != INT64_MIN) { caller_task_runner_->PostTask(FROM_HERE, ready_for_playback_task_); } - } else if (locked->started_ || + } else if (started_ || data->timestamp() + SamplesToMicroseconds(DataToFrames(data->data_size()), input_samples_per_second_) >= - locked->playback_start_pts_) { + playback_start_pts_) { scoped_refptr<DecoderBufferBase> buffer = - locked->audio_resampler_.ResampleBuffer(std::move(data)); - locked->queued_frames_ += DataToFrames(buffer->data_size()); - locked->queue_.push_back(std::move(buffer)); + audio_resampler_.ResampleBuffer(std::move(data)); + queued_frames_ += DataToFrames(buffer->data_size()); + queue_.push_back(std::move(buffer)); - if (!locked->started_ && - locked->queued_frames_ >= start_threshold_frames_ && - locked->playback_start_timestamp_ != INT64_MIN) { + if (!started_ && queued_frames_ >= start_threshold_frames_ && + playback_start_timestamp_ != INT64_MIN) { caller_task_runner_->PostTask(FROM_HERE, ready_for_playback_task_); } } // Otherwise, drop |data| since it is before the start PTS. RenderingDelay delay; - if (locked->started_ && !locked->paused_) { - delay = locked->mixer_rendering_delay_; + if (started_ && !paused_) { + delay = mixer_rendering_delay_; delay.delay_microseconds += SamplesToMicroseconds( - locked->queued_frames_ + locked->extra_delay_frames_, - input_samples_per_second_); + queued_frames_ + extra_delay_frames_, input_samples_per_second_); } return delay; } @@ -362,13 +301,13 @@ void BufferingMixerSource::SetPaused(bool paused) { LOG(INFO) << (paused ? "Pausing " : "Unpausing ") << device_id_ << " (" << this << ")"; - auto locked = locked_members_.Lock(); + base::AutoLock lock(lock_); // Clear start timestamp, since a pause should invalidate the start timestamp // anyway. The AV sync code can restart (hard correction) on resume if // needed. - locked->playback_start_timestamp_ = INT64_MIN; - locked->mixer_rendering_delay_ = RenderingDelay(); - locked->paused_ = paused; + playback_start_timestamp_ = INT64_MIN; + mixer_rendering_delay_ = RenderingDelay(); + paused_ = paused; } void BufferingMixerSource::SetVolumeMultiplier(float multiplier) { @@ -381,18 +320,17 @@ // Start accepting buffers into the queue. bool queued_data = false; { - auto locked = locked_members_.Lock(); - locked->mixer_rendering_delay_ = initial_rendering_delay; - if (locked->state_ == State::kUninitialized) { - locked->state_ = State::kNormalPlayback; + base::AutoLock lock(lock_); + mixer_rendering_delay_ = initial_rendering_delay; + if (state_ == State::kUninitialized) { + state_ = State::kNormalPlayback; } else { - DCHECK(locked->state_ == State::kRemoved); + DCHECK_EQ(state_, State::kRemoved); } - if (locked->pending_data_ && - locked->queued_frames_ + locked->fader_.buffered_frames() < - max_queued_frames_) { - locked->last_buffer_delay_ = QueueData(std::move(locked->pending_data_)); + if (pending_data_ && + queued_frames_ + fader_.buffered_frames() < max_queued_frames_) { + last_buffer_delay_ = QueueData(std::move(pending_data_)); queued_data = true; } } @@ -405,64 +343,58 @@ void BufferingMixerSource::CheckAndStartPlaybackIfNecessary( int num_frames, int64_t playback_absolute_timestamp) { - auto locked = locked_members_.AssertAcquired(); - - DCHECK(locked->state_ == State::kNormalPlayback || - locked->state_ == State::kGotEos); - DCHECK(!locked->started_); + DCHECK(state_ == State::kNormalPlayback || state_ == State::kGotEos); + DCHECK(!started_); const bool have_enough_queued_frames = - (locked->state_ == State::kGotEos || - (locked->queued_frames_ >= start_threshold_frames_ && - locked->queued_frames_ >= - locked->fader_.FramesNeededFromSource(num_frames))); + (state_ == State::kGotEos || + (queued_frames_ >= start_threshold_frames_ && + queued_frames_ >= fader_.FramesNeededFromSource(num_frames))); if (!have_enough_queued_frames) { return; } remaining_silence_frames_ = 0; - if (locked->playback_start_timestamp_ == INT64_MIN || - (locked->queue_.empty() && locked->state_ == State::kGotEos)) { + if (playback_start_timestamp_ == INT64_MIN || + (queue_.empty() && state_ == State::kGotEos)) { // No start timestamp, so start as soon as there are enough queued frames. - locked->started_ = true; + started_ = true; return; } if (playback_absolute_timestamp + SamplesToMicroseconds(num_frames, input_samples_per_second_) < - locked->playback_start_timestamp_) { + playback_start_timestamp_) { // Haven't reached the start timestamp yet. return; } - DCHECK(!locked->queue_.empty()); + DCHECK(!queue_.empty()); // Reset the current buffer offset to 0 so we can ignore it below. We need to // do this here because we may not have started playback even after dropping // all necessary frames the last time we checked. - locked->queued_frames_ += locked->current_buffer_offset_; - locked->current_buffer_offset_ = 0; + queued_frames_ += current_buffer_offset_; + current_buffer_offset_ = 0; - int64_t desired_pts_now = - locked->playback_start_pts_ + - (playback_absolute_timestamp - locked->playback_start_timestamp_) * - locked->playback_rate_; - int64_t actual_pts_now = locked->queue_.front()->timestamp(); - int64_t drop_us = (desired_pts_now - actual_pts_now) / locked->playback_rate_; + int64_t desired_pts_now = playback_start_pts_ + (playback_absolute_timestamp - + playback_start_timestamp_) * + playback_rate_; + int64_t actual_pts_now = queue_.front()->timestamp(); + int64_t drop_us = (desired_pts_now - actual_pts_now) / playback_rate_; if (drop_us >= 0) { LOG(INFO) << "Dropping audio, duration = " << drop_us; DropAudio(::media::AudioTimestampHelper::TimeToFrames( base::TimeDelta::FromMicroseconds(drop_us), input_samples_per_second_)); // Only start if we still have enough data to do so. - locked->started_ = (locked->queued_frames_ >= start_threshold_frames_ && - locked->queued_frames_ >= - locked->fader_.FramesNeededFromSource(num_frames)); + started_ = (queued_frames_ >= start_threshold_frames_ && + queued_frames_ >= fader_.FramesNeededFromSource(num_frames)); - if (locked->started_) { - int64_t start_pts = locked->queue_.front()->timestamp() + - SamplesToMicroseconds(locked->current_buffer_offset_, + if (started_) { + int64_t start_pts = queue_.front()->timestamp() + + SamplesToMicroseconds(current_buffer_offset_, input_samples_per_second_) * - locked->playback_rate_; + playback_rate_; LOG(INFO) << "Start playback of PTS " << start_pts << " at " << playback_absolute_timestamp; } @@ -472,30 +404,27 @@ remaining_silence_frames_ = ::media::AudioTimestampHelper::TimeToFrames( base::TimeDelta::FromMicroseconds(silence_duration), input_samples_per_second_); - locked->started_ = true; - LOG(INFO) << "Should start playback of PTS " - << locked->queue_.front()->timestamp() << " at " - << (playback_absolute_timestamp + silence_duration); + started_ = true; + LOG(INFO) << "Should start playback of PTS " << queue_.front()->timestamp() + << " at " << (playback_absolute_timestamp + silence_duration); } } void BufferingMixerSource::DropAudio(int64_t frames_to_drop) { - auto locked = locked_members_.AssertAcquired(); - DCHECK_EQ(locked->current_buffer_offset_, 0); + DCHECK_EQ(current_buffer_offset_, 0); - while (frames_to_drop && !locked->queue_.empty()) { - int64_t first_buffer_frames = - DataToFrames(locked->queue_.front()->data_size()); + while (frames_to_drop && !queue_.empty()) { + int64_t first_buffer_frames = DataToFrames(queue_.front()->data_size()); if (first_buffer_frames > frames_to_drop) { - locked->current_buffer_offset_ = frames_to_drop; - locked->queued_frames_ -= frames_to_drop; + current_buffer_offset_ = frames_to_drop; + queued_frames_ -= frames_to_drop; frames_to_drop = 0; break; } - locked->queued_frames_ -= first_buffer_frames; + queued_frames_ -= first_buffer_frames; frames_to_drop -= first_buffer_frames; - locked->queue_.pop_front(); + queue_.pop_front(); } if (frames_to_drop > 0) { @@ -519,28 +448,27 @@ bool signal_eos = false; bool remove_self = false; { - auto locked = locked_members_.Lock(); + base::AutoLock lock(lock_); // Playback start check. - if (!locked->started_ && (locked->state_ == State::kNormalPlayback || - locked->state_ == State::kGotEos)) { + if (!started_ && + (state_ == State::kNormalPlayback || state_ == State::kGotEos)) { CheckAndStartPlaybackIfNecessary(num_frames, playback_absolute_timestamp); } // In normal playback, don't pass data to the fader if we can't satisfy the // full request. This will allow us to buffer up more data so we can fully // fade in. - if (locked->state_ == State::kNormalPlayback && locked->started_ && - locked->queued_frames_ < - locked->fader_.FramesNeededFromSource(num_frames)) { - LOG_IF(INFO, !locked->zero_fader_frames_) + if (state_ == State::kNormalPlayback && started_ && + queued_frames_ < fader_.FramesNeededFromSource(num_frames)) { + LOG_IF(INFO, !zero_fader_frames_) << "Stream underrun for " << device_id_ << " (" << this << ")"; - locked->zero_fader_frames_ = true; + zero_fader_frames_ = true; } else { - LOG_IF(INFO, locked->started_ && locked->zero_fader_frames_) + LOG_IF(INFO, started_ && zero_fader_frames_) << "Stream underrun recovered for " << device_id_ << " (" << this << ")"; - locked->zero_fader_frames_ = false; + zero_fader_frames_ = false; } DCHECK_GE(remaining_silence_frames_, 0); @@ -562,29 +490,27 @@ for (int c = 0; c < num_channels_; ++c) { channels[c] = buffer->channel(c) + write_offset; } - filled = locked->fader_.FillFrames(num_frames, rendering_delay, channels); + filled = fader_.FillFrames(num_frames, rendering_delay, channels); - locked->mixer_rendering_delay_ = rendering_delay; - locked->extra_delay_frames_ = num_frames + locked->fader_.buffered_frames(); + mixer_rendering_delay_ = rendering_delay; + extra_delay_frames_ = num_frames + fader_.buffered_frames(); // See if we can accept more data into the queue. - if (locked->pending_data_ && - locked->queued_frames_ + locked->fader_.buffered_frames() < - max_queued_frames_) { - locked->last_buffer_delay_ = QueueData(std::move(locked->pending_data_)); + if (pending_data_ && + queued_frames_ + fader_.buffered_frames() < max_queued_frames_) { + last_buffer_delay_ = QueueData(std::move(pending_data_)); queued_more_data = true; } // Check if we have played out EOS. - if (locked->state_ == State::kGotEos && locked->queued_frames_ == 0 && - locked->fader_.buffered_frames() == 0) { + if (state_ == State::kGotEos && queued_frames_ == 0 && + fader_.buffered_frames() == 0) { signal_eos = true; - locked->state_ = State::kSignaledEos; + state_ = State::kSignaledEos; } // If the caller has removed this source, delete once we have faded out. - if (locked->state_ == State::kRemoved && - locked->fader_.buffered_frames() == 0) { + if (state_ == State::kRemoved && fader_.buffered_frames() == 0) { remove_self = true; } } @@ -610,46 +536,44 @@ RenderingDelay rendering_delay, float* const* channels) { DCHECK(channels); - auto locked = locked_members_.AssertAcquired(); - if (locked->zero_fader_frames_ || !locked->started_ || locked->paused_ || - locked->state_ == State::kRemoved) { + if (zero_fader_frames_ || !started_ || paused_ || state_ == State::kRemoved) { return 0; } int num_filled = 0; while (num_frames) { - if (locked->queue_.empty()) { + if (queue_.empty()) { return num_filled; } - DecoderBufferBase* buffer = locked->queue_.front().get(); + DecoderBufferBase* buffer = queue_.front().get(); const int buffer_frames = DataToFrames(buffer->data_size()); const int frames_to_copy = - std::min(num_frames, buffer_frames - locked->current_buffer_offset_); + std::min(num_frames, buffer_frames - current_buffer_offset_); DCHECK(frames_to_copy >= 0 && frames_to_copy <= num_frames) << " frames_to_copy=" << frames_to_copy << " num_frames=" << num_frames << " buffer_frames=" << buffer_frames << " num_filled=" << num_filled - << " locked->current_buffer_offset_=" << locked->current_buffer_offset_ + << " current_buffer_offset_=" << current_buffer_offset_ << " buffer=" << buffer->data_size(); const float* buffer_samples = reinterpret_cast<const float*>(buffer->data()); for (int c = 0; c < num_channels_; ++c) { const float* buffer_channel = buffer_samples + (buffer_frames * c); - std::copy_n(buffer_channel + locked->current_buffer_offset_, - frames_to_copy, channels[c] + num_filled); + std::copy_n(buffer_channel + current_buffer_offset_, frames_to_copy, + channels[c] + num_filled); } num_frames -= frames_to_copy; - locked->queued_frames_ -= frames_to_copy; + queued_frames_ -= frames_to_copy; num_filled += frames_to_copy; - locked->current_buffer_offset_ += frames_to_copy; - if (locked->current_buffer_offset_ == buffer_frames) { - locked->buffers_to_be_freed_.push_back(std::move(locked->queue_.front())); - locked->queue_.pop_front(); - locked->current_buffer_offset_ = 0; + current_buffer_offset_ += frames_to_copy; + if (current_buffer_offset_ == buffer_frames) { + buffers_to_be_freed_.push_back(std::move(queue_.front())); + queue_.pop_front(); + current_buffer_offset_ = 0; } } @@ -660,8 +584,8 @@ DCHECK(caller_task_runner_->BelongsToCurrentThread()); RenderingDelay delay; { - auto locked = locked_members_.Lock(); - delay = locked->last_buffer_delay_; + base::AutoLock lock(lock_); + delay = last_buffer_delay_; } delegate_->OnWritePcmCompletion(delay); } @@ -690,9 +614,9 @@ FROM_HERE, base::BindOnce(&BufferingMixerSource::PostError, weak_this_, error)); - auto locked = locked_members_.Lock(); - locked->mixer_error_ = true; - if (locked->state_ == State::kRemoved) { + base::AutoLock lock(lock_); + mixer_error_ = true; + if (state_ == State::kRemoved) { mixer_->RemoveInput(this); } } @@ -709,10 +633,10 @@ LOG(INFO) << "Remove " << device_id_ << " (" << this << ")"; bool remove_self = false; { - auto locked = locked_members_.Lock(); - locked->pending_data_ = nullptr; - locked->state_ = State::kRemoved; - remove_self = locked->mixer_error_; + base::AutoLock lock(lock_); + pending_data_ = nullptr; + state_ = State::kRemoved; + remove_self = mixer_error_; } if (remove_self) {
diff --git a/chromecast/media/cma/backend/buffering_mixer_source.h b/chromecast/media/cma/backend/buffering_mixer_source.h index 44e0787..bddbaa53 100644 --- a/chromecast/media/cma/backend/buffering_mixer_source.h +++ b/chromecast/media/cma/backend/buffering_mixer_source.h
@@ -14,6 +14,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" +#include "base/thread_annotations.h" #include "chromecast/media/cma/backend/audio_fader.h" #include "chromecast/media/cma/backend/audio_resampler.h" #include "chromecast/media/cma/backend/mixer_input.h" @@ -130,93 +131,6 @@ kRemoved, // The caller has removed this source; finish playing out. }; - // Class to wrap members that must be used only when a lock is held. Usage: - // { - // auto locked = locked_members_.Lock(); - // locked->paused_ = true; // or other member access - // } - class LockedMembers { - public: - struct Members { - Members(BufferingMixerSource* source, - int input_samples_per_second, - int num_channels, - int64_t playback_start_timestamp, - int64_t playback_start_pts); - ~Members(); - - State state_ = State::kUninitialized; - bool paused_ = false; - bool mixer_error_ = false; - scoped_refptr<DecoderBufferBase> pending_data_; - base::circular_deque<scoped_refptr<DecoderBufferBase>> queue_; - // We let the caller thread free audio buffers since freeing memory can - // be expensive sometimes; we want to avoid potentially long-running - // operations on the mixer thread. - std::vector<scoped_refptr<DecoderBufferBase>> buffers_to_be_freed_; - int queued_frames_ = 0; - RenderingDelay mixer_rendering_delay_; - RenderingDelay last_buffer_delay_; - int extra_delay_frames_ = 0; - int current_buffer_offset_ = 0; - AudioFader fader_; - bool zero_fader_frames_ = false; - bool started_ = false; - double playback_rate_ = 1.0; - // The absolute timestamp relative to clock monotonic (raw) at which the - // playback should start. INT64_MIN indicates playback should start ASAP. - // INT64_MAX indicates playback should start at a specified timestamp, - // but we don't know what that timestamp is. - int64_t playback_start_timestamp_ = INT64_MIN; - // The PTS the playback should start at. We will drop audio pushed to us - // with PTS values below this value. If the audio doesn't have a starting - // PTS, then this value can be INT64_MIN, to play whatever audio is sent - // to us. - int64_t playback_start_pts_ = INT64_MIN; - AudioResampler audio_resampler_; - - private: - DISALLOW_COPY_AND_ASSIGN(Members); - }; - - class AcquiredLock { - public: - explicit AcquiredLock(LockedMembers* locked); - ~AcquiredLock(); - - Members* operator->() { return &(locked_->members_); } - - private: - LockedMembers* const locked_; - }; - - class AssertedLock { - public: - explicit AssertedLock(LockedMembers* locked); - - Members* operator->() { return &(locked_->members_); } - - private: - LockedMembers* const locked_; - }; - - LockedMembers(BufferingMixerSource* source, - int input_samples_per_second, - int num_channels, - int64_t playback_start_timestamp, - int64_t playback_start_pts); - ~LockedMembers(); - - AcquiredLock Lock(); - AssertedLock AssertAcquired(); - - private: - base::Lock member_lock_; - Members members_; - - DISALLOW_COPY_AND_ASSIGN(LockedMembers); - }; - ~BufferingMixerSource() override; // MixerInput::Source implementation: @@ -239,18 +153,21 @@ // AudioFader::Source implementation: int FillFaderFrames(int num_frames, RenderingDelay rendering_delay, - float* const* channels) override; + float* const* channels) + EXCLUSIVE_LOCKS_REQUIRED(lock_) override; - RenderingDelay QueueData(scoped_refptr<DecoderBufferBase> data); + RenderingDelay QueueData(scoped_refptr<DecoderBufferBase> data) + EXCLUSIVE_LOCKS_REQUIRED(lock_); void PostPcmCompletion(); void PostEos(); void PostError(MixerError error); void PostAudioReadyForPlayback(); - void DropAudio(int64_t frames); + void DropAudio(int64_t frames) EXCLUSIVE_LOCKS_REQUIRED(lock_); int64_t DataToFrames(int64_t size); void CheckAndStartPlaybackIfNecessary(int num_frames, - int64_t playback_absolute_timestamp); + int64_t playback_absolute_timestamp) + EXCLUSIVE_LOCKS_REQUIRED(lock_); Delegate* const delegate_; const int num_channels_; const int input_samples_per_second_; @@ -263,14 +180,44 @@ const int max_queued_frames_; // Minimum number of frames buffered before starting to fill data. const int start_threshold_frames_; - bool audio_ready_for_playback_fired_ = false; // Only used on the caller thread. std::vector<scoped_refptr<DecoderBufferBase>> old_buffers_to_be_freed_; + bool audio_ready_for_playback_fired_ = false; - LockedMembers locked_members_; - - int remaining_silence_frames_ = 0; + base::Lock lock_; + State state_ GUARDED_BY(lock_) = State::kUninitialized; + bool paused_ GUARDED_BY(lock_) = false; + bool mixer_error_ GUARDED_BY(lock_) = false; + scoped_refptr<DecoderBufferBase> pending_data_ GUARDED_BY(lock_); + base::circular_deque<scoped_refptr<DecoderBufferBase>> queue_ + GUARDED_BY(lock_); + // We let the caller thread free audio buffers since freeing memory can + // be expensive sometimes; we want to avoid potentially long-running + // operations on the mixer thread. + std::vector<scoped_refptr<DecoderBufferBase>> buffers_to_be_freed_ + GUARDED_BY(lock_); + int queued_frames_ GUARDED_BY(lock_) = 0; + RenderingDelay mixer_rendering_delay_ GUARDED_BY(lock_); + RenderingDelay last_buffer_delay_ GUARDED_BY(lock_); + int extra_delay_frames_ GUARDED_BY(lock_) = 0; + int current_buffer_offset_ GUARDED_BY(lock_) = 0; + AudioFader fader_ GUARDED_BY(lock_); + bool zero_fader_frames_ GUARDED_BY(lock_) = false; + bool started_ GUARDED_BY(lock_) = false; + double playback_rate_ GUARDED_BY(lock_) = 1.0; + // The absolute timestamp relative to clock monotonic (raw) at which the + // playback should start. INT64_MIN indicates playback should start ASAP. + // INT64_MAX indicates playback should start at a specified timestamp, + // but we don't know what that timestamp is. + int64_t playback_start_timestamp_ GUARDED_BY(lock_) = INT64_MIN; + // The PTS the playback should start at. We will drop audio pushed to us + // with PTS values below this value. If the audio doesn't have a starting + // PTS, then this value can be INT64_MIN, to play whatever audio is sent + // to us. + int64_t playback_start_pts_ GUARDED_BY(lock_) = INT64_MIN; + AudioResampler audio_resampler_ GUARDED_BY(lock_); + int remaining_silence_frames_ GUARDED_BY(lock_) = 0; base::RepeatingClosure pcm_completion_task_; base::RepeatingClosure eos_task_;
diff --git a/chromecast/media/cma/backend/stream_mixer.cc b/chromecast/media/cma/backend/stream_mixer.cc index e41b092b..f49a8c3 100644 --- a/chromecast/media/cma/backend/stream_mixer.cc +++ b/chromecast/media/cma/backend/stream_mixer.cc
@@ -933,11 +933,12 @@ if (fixed_num_output_channels_ != kInvalidNumChannels && fixed_num_output_channels_ != mixer_pipeline_->GetOutputChannelCount()) { - LOG(WARNING) << "PostProcessor configuration channel count does not match " - << "command line flag: " + // Just log a warning, but this is still fine because we will remap the + // channels prior to output (so don't return false). + LOG(WARNING) << "PostProcessor configuration output channel count does not " + << "match command line flag: " << mixer_pipeline_->GetOutputChannelCount() << " vs " - << fixed_num_output_channels_; - return false; + << fixed_num_output_channels_ << ". Channels will be remapped"; } if (mixer_pipeline_->GetLoopbackChannelCount() > 2) {
diff --git a/chromecast/media/cma/backend/stream_mixer_unittest.cc b/chromecast/media/cma/backend/stream_mixer_unittest.cc index 7cad5135..8d070492 100644 --- a/chromecast/media/cma/backend/stream_mixer_unittest.cc +++ b/chromecast/media/cma/backend/stream_mixer_unittest.cc
@@ -1577,26 +1577,6 @@ DeathRegex("Invalid JSON")); } -TEST_F(StreamMixerDeathTest, CrashesIfChannelCountDoesNotMatchFlags) { - const int kNumOutputChannels = 2; - const std::string config = R"Json({ -"postprocessors": { - "linearize": { - "processors": [{ - "processor": "delay.so", - "config": { "output_channels": 4, - "delay": 0 } - }] - } -}})Json"; - - ::testing::FLAGS_gtest_death_test_style = "threadsafe"; - mixer_->SetNumOutputChannelsForTest(kNumOutputChannels); - ASSERT_DEATH(mixer_->ResetPostProcessorsForTest( - std::make_unique<MockPostProcessorFactory>(), config), - DeathRegex("PostProcessorsHaveCorrectNumOutputs")); -} - TEST_F(StreamMixerDeathTest, CrashesIfMoreThan2LoopbackChannels) { const int kNumOutputChannels = 2; const std::string config = R"Json({
diff --git a/chromeos/components/power/dark_resume_controller.cc b/chromeos/components/power/dark_resume_controller.cc index 891a977..54ecbcc 100644 --- a/chromeos/components/power/dark_resume_controller.cc +++ b/chromeos/components/power/dark_resume_controller.cc
@@ -11,15 +11,25 @@ namespace chromeos { namespace system { +namespace { + +// The default value of |dark_resume_hard_timeout_| till +// |PowerManagerInitialized| is called. +constexpr base::TimeDelta kDefaultDarkResumeHardTimeout = + base::TimeDelta::FromSeconds(20); + +} // namespace + // static. constexpr base::TimeDelta DarkResumeController::kDarkResumeWakeLockCheckTimeout; -constexpr base::TimeDelta DarkResumeController::kDarkResumeHardTimeout; DarkResumeController::DarkResumeController( service_manager::Connector* connector) : connector_(connector), wake_lock_observer_binding_(this), + dark_resume_hard_timeout_(kDefaultDarkResumeHardTimeout), weak_ptr_factory_(this) { + DCHECK(!dark_resume_hard_timeout_.is_zero()); connector_->BindInterface(device::mojom::kServiceName, mojo::MakeRequest(&wake_lock_provider_)); PowerManagerClient::Get()->AddObserver(this); @@ -29,6 +39,11 @@ PowerManagerClient::Get()->RemoveObserver(this); } +void DarkResumeController::PowerManagerInitialized() { + dark_resume_hard_timeout_ = + PowerManagerClient::Get()->GetDarkSuspendDelayTimeout(); +} + void DarkResumeController::DarkSuspendImminent() { DVLOG(1) << __func__; block_suspend_token_ = base::UnguessableToken::Create(); @@ -70,6 +85,10 @@ return block_suspend_token_ && wake_lock_observer_binding_.is_bound(); } +base::TimeDelta DarkResumeController::GetHardTimeoutForTesting() const { + return dark_resume_hard_timeout_; +} + bool DarkResumeController::IsDarkResumeStateClearedForTesting() const { return !weak_ptr_factory_.HasWeakPtrs() && !wake_lock_check_timer_.IsRunning() && @@ -95,7 +114,7 @@ // the device doesn't stay up indefinitely in dark resume. DCHECK(!hard_timeout_timer_.IsRunning()); hard_timeout_timer_.Start( - FROM_HERE, kDarkResumeHardTimeout, + FROM_HERE, dark_resume_hard_timeout_, base::BindOnce(&DarkResumeController::HandleDarkResumeHardTimeout, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chromeos/components/power/dark_resume_controller.h b/chromeos/components/power/dark_resume_controller.h index 9853321..e34defd 100644 --- a/chromeos/components/power/dark_resume_controller.h +++ b/chromeos/components/power/dark_resume_controller.h
@@ -56,12 +56,8 @@ static constexpr base::TimeDelta kDarkResumeWakeLockCheckTimeout = base::TimeDelta::FromSeconds(3); - // Max time to wait for wake lock release after a wake lock check after a dark - // resume. After this time the system is asked to re-suspend. - static constexpr base::TimeDelta kDarkResumeHardTimeout = - base::TimeDelta::FromSeconds(10); - // chromeos::PowerManagerClient::Observer overrides. + void PowerManagerInitialized() override; void DarkSuspendImminent() override; void SuspendDone(const base::TimeDelta& sleep_duration) override; @@ -79,6 +75,9 @@ // either by re-suspending or transitioning to full resume. bool IsDarkResumeStateClearedForTesting() const; + // Returns |dark_resume_hard_timeout_|. + base::TimeDelta GetHardTimeoutForTesting() const; + private: // Called |kDarkResumeWakeLockCheckTimeout| after a dark resume. Checks if // app suspension wake locks are held. If no wake locks are held then @@ -112,6 +111,13 @@ // Timer used to schedule HandleDarkResumeHardTimeout. base::OneShotTimer hard_timeout_timer_; + // Max time to wait for wake lock release after a wake lock check after a dark + // resume. After this time the system is asked to re-suspend. This is + // initialized via PowerManagerClient when it's initialization is complete in + // |PowerManagerInitialized|. Till then there may be a very small window after + // booth when it takes a default value. + base::TimeDelta dark_resume_hard_timeout_; + // Used for checking if HandleDarkResumeWakeLockCheckTimeout and // HandleDarkResumeHardTimeout run on the same sequence. SEQUENCE_CHECKER(dark_resume_tasks_sequence_checker_);
diff --git a/chromeos/components/power/dark_resume_controller_unittest.cc b/chromeos/components/power/dark_resume_controller_unittest.cc index 252af6e..5c13ccb 100644 --- a/chromeos/components/power/dark_resume_controller_unittest.cc +++ b/chromeos/components/power/dark_resume_controller_unittest.cc
@@ -9,6 +9,7 @@ #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" +#include "base/time/time.h" #include "chromeos/dbus/power/fake_power_manager_client.h" #include "services/device/public/cpp/test/test_wake_lock_provider.h" #include "services/device/public/mojom/constants.mojom.h" @@ -127,10 +128,12 @@ run_loop.RunUntilIdle(); EXPECT_TRUE(dark_resume_controller_->IsDarkResumeStateSetForTesting()); - // Move time forward by < |kDarkResumeHardTimeout| and release the + // Move time forward by < |dark_resume_hard_timeout_| and release the // partial wake lock. This should instantaneously re-suspend the device. - task_environment_.FastForwardBy(DarkResumeController::kDarkResumeHardTimeout - - base::TimeDelta::FromSeconds(1)); + base::TimeDelta small_delay = base::TimeDelta::FromSeconds(1); + ASSERT_GT(dark_resume_controller_->GetHardTimeoutForTesting(), small_delay); + task_environment_.FastForwardBy( + dark_resume_controller_->GetHardTimeoutForTesting() - small_delay); wake_lock_->CancelWakeLock(); base::RunLoop run_loop2; run_loop2.RunUntilIdle(); @@ -153,9 +156,10 @@ run_loop.RunUntilIdle(); EXPECT_TRUE(dark_resume_controller_->IsDarkResumeStateSetForTesting()); - // Move time forward by |kDarkResumeHardTimeout|. At this point the + // Move time forward by |dark_resume_hard_timeout_|. At this point the // device should re-suspend even though the wake lock is acquired. - task_environment_.FastForwardBy(DarkResumeController::kDarkResumeHardTimeout); + task_environment_.FastForwardBy( + dark_resume_controller_->GetHardTimeoutForTesting()); EXPECT_EQ(1, GetActiveWakeLocks(WakeLockType::kPreventAppSuspension)); base::RunLoop run_loop2; run_loop2.RunUntilIdle();
diff --git a/chromeos/dbus/constants/dbus_switches.cc b/chromeos/dbus/constants/dbus_switches.cc index ac2d80e..dc0a7d7e 100644 --- a/chromeos/dbus/constants/dbus_switches.cc +++ b/chromeos/dbus/constants/dbus_switches.cc
@@ -42,5 +42,10 @@ // session manager. const char kSystemDevMode[] = "system-developer-mode"; +// Makes Chrome register the maximum dark suspend delay possible on Chrome OS +// i.e. give the device the maximum amount of time to do its work in dark +// resume as is allowed by the power manager. +const char kRegisterMaxDarkSuspendDelay[] = "register-max-dark-suspend-delay"; + } // namespace switches } // namespace chromeos
diff --git a/chromeos/dbus/constants/dbus_switches.h b/chromeos/dbus/constants/dbus_switches.h index 838e21c..cc668f6 100644 --- a/chromeos/dbus/constants/dbus_switches.h +++ b/chromeos/dbus/constants/dbus_switches.h
@@ -22,6 +22,8 @@ extern const char kSmsTestMessages[]; COMPONENT_EXPORT(CHROMEOS_DBUS_CONSTANTS) extern const char kSystemDevMode[]; +COMPONENT_EXPORT(CHROMEOS_DBUS_CONSTANTS) +extern const char kRegisterMaxDarkSuspendDelay[]; } // namespace switches } // namespace chromeos
diff --git a/chromeos/dbus/power/fake_power_manager_client.cc b/chromeos/dbus/power/fake_power_manager_client.cc index bb424c3..46f6f1a 100644 --- a/chromeos/dbus/power/fake_power_manager_client.cc +++ b/chromeos/dbus/power/fake_power_manager_client.cc
@@ -27,6 +27,10 @@ // Minimum power for a USB power source to be classified as AC. constexpr double kUsbMinAcWatts = 24; +// The time power manager will wait before resuspending from a dark resume. +constexpr base::TimeDelta kDarkSuspendDelayTimeout = + base::TimeDelta::FromSeconds(20); + // Callback fired when timer started through |StartArcTimer| expires. In // non-test environments this does a potentially blocking call on the UI // thread. However, the clients that exercise this code path don't run in @@ -97,6 +101,7 @@ void FakePowerManagerClient::AddObserver(Observer* observer) { observers_.AddObserver(observer); observer->PowerManagerBecameAvailable(true); + observer->PowerManagerInitialized(); } void FakePowerManagerClient::RemoveObserver(Observer* observer) { @@ -361,6 +366,10 @@ FROM_HERE, base::BindOnce(std::move(callback), true)); } +base::TimeDelta FakePowerManagerClient::GetDarkSuspendDelayTimeout() { + return kDarkSuspendDelayTimeout; +} + bool FakePowerManagerClient::PopVideoActivityReport() { CHECK(!video_activity_reports_.empty()); bool fullscreen = video_activity_reports_.front();
diff --git a/chromeos/dbus/power/fake_power_manager_client.h b/chromeos/dbus/power/fake_power_manager_client.h index 4095117..41954f9 100644 --- a/chromeos/dbus/power/fake_power_manager_client.h +++ b/chromeos/dbus/power/fake_power_manager_client.h
@@ -127,6 +127,7 @@ VoidDBusMethodCallback callback) override; void DeleteArcTimers(const std::string& tag, VoidDBusMethodCallback callback) override; + base::TimeDelta GetDarkSuspendDelayTimeout() override; // Pops the first report from |video_activity_reports_|, returning whether the // activity was fullscreen or not. There must be at least one report.
diff --git a/chromeos/dbus/power/power_manager_client.cc b/chromeos/dbus/power/power_manager_client.cc index 06ab167d..fa24ab71 100644 --- a/chromeos/dbus/power/power_manager_client.cc +++ b/chromeos/dbus/power/power_manager_client.cc
@@ -8,10 +8,12 @@ #include <algorithm> #include <memory> +#include <unordered_map> #include <utility> #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/format_macros.h" #include "base/logging.h" @@ -22,8 +24,10 @@ #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/threading/platform_thread.h" +#include "base/time/time.h" #include "base/timer/timer.h" #include "base/unguessable_token.h" +#include "chromeos/dbus/constants/dbus_switches.h" #include "chromeos/dbus/power/fake_power_manager_client.h" #include "chromeos/dbus/power_manager/backlight.pb.h" #include "chromeos/dbus/power_manager/idle.pb.h" @@ -537,6 +541,10 @@ base::BindOnce(&OnVoidDBusMethod, std::move(callback))); } + base::TimeDelta GetDarkSuspendDelayTimeout() override { + return max_dark_suspend_delay_timeout_; + } + private: // Returns true if the current thread is the origin thread. bool OnOriginThread() { @@ -584,6 +592,11 @@ } } + void NotifiyIntiailization() { + for (auto& observer : observers_) + observer.PowerManagerInitialized(); + } + void ScreenBrightnessChangedReceived(dbus::Signal* signal) { dbus::MessageReader reader(signal); power_manager::BacklightBrightnessChange proto; @@ -674,6 +687,12 @@ } void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) { + // This is the last callback to run after all the initialization in |Init|. + // Notify all observers that the initialization is complete. + base::ScopedClosureRunner( + base::BindOnce(&PowerManagerClientImpl::NotifiyIntiailization, + base::Unretained(this))); + if (!response) { POWER_LOG(ERROR) << "Error calling " << power_manager::kGetPowerSupplyPropertiesMethod; @@ -800,6 +819,12 @@ if (dark_suspend) { dark_suspend_delay_id_ = protobuf.delay_id(); has_dark_suspend_delay_id_ = true; + + // Set |max_dark_suspend_delay_timeout_| to the minimum time power manager + // guarantees before resuspending. + max_dark_suspend_delay_timeout_ = + base::TimeDelta::FromMilliseconds(protobuf.min_delay_timeout_ms()); + POWER_LOG(EVENT) << "Registered dark suspend delay " << dark_suspend_delay_id_; } else { @@ -1027,6 +1052,12 @@ base::BindOnce(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply, weak_ptr_factory_.GetWeakPtr(), false, power_manager::kRegisterSuspendDelayMethod)); + + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kRegisterMaxDarkSuspendDelay)) { + // Negative timeout means request maximum delay. + protobuf_request.set_timeout(-1); + } RegisterSuspendDelayImpl( power_manager::kRegisterDarkSuspendDelayMethod, protobuf_request, base::BindOnce(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply, @@ -1098,6 +1129,10 @@ int32_t dark_suspend_delay_id_ = -1; bool has_dark_suspend_delay_id_ = false; + // The maximum time power manager will wait before resuspending from a dark + // resume. + base::TimeDelta max_dark_suspend_delay_timeout_; + // powerd-supplied ID corresponding to an imminent (either regular or dark) // suspend attempt that is currently being delayed. int32_t pending_suspend_id_ = -1;
diff --git a/chromeos/dbus/power/power_manager_client.h b/chromeos/dbus/power/power_manager_client.h index 9bd84f5d..cfbb078 100644 --- a/chromeos/dbus/power/power_manager_client.h +++ b/chromeos/dbus/power/power_manager_client.h
@@ -72,6 +72,9 @@ // PowerManagerClient if the service's availability is already known. virtual void PowerManagerBecameAvailable(bool available) {} + // Called when the power manager is completely initialized. + virtual void PowerManagerInitialized() {} + // Called if the power manager process restarts. virtual void PowerManagerRestarted() {} @@ -318,6 +321,9 @@ virtual void DeleteArcTimers(const std::string& tag, VoidDBusMethodCallback callback) = 0; + // The time power manager will wait before resuspending from a dark resume. + virtual base::TimeDelta GetDarkSuspendDelayTimeout() = 0; + PowerManagerClient(); virtual ~PowerManagerClient();
diff --git a/chromeos/hugepage_text/OWNERS b/chromeos/hugepage_text/OWNERS index 6f2d98e8..a71a7f42 100644 --- a/chromeos/hugepage_text/OWNERS +++ b/chromeos/hugepage_text/OWNERS
@@ -3,3 +3,4 @@ gbiv@chromium.org manojgupta@chromium.org tcwang@chromium.org +# COMPONENT: Tools>ChromeOS-Toolchain
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 3ec082a..679168b 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -415,6 +415,7 @@ "payments/test_credit_card_save_manager.h", "payments/test_credit_card_save_strike_database.cc", "payments/test_credit_card_save_strike_database.h", + "payments/test_legal_message_line.h", "payments/test_local_card_migration_manager.cc", "payments/test_local_card_migration_manager.h", "payments/test_payments_client.cc",
diff --git a/components/autofill/core/browser/payments/legal_message_line_unittest.cc b/components/autofill/core/browser/payments/legal_message_line_unittest.cc index d5a10a1..b126d82d 100644 --- a/components/autofill/core/browser/payments/legal_message_line_unittest.cc +++ b/components/autofill/core/browser/payments/legal_message_line_unittest.cc
@@ -11,6 +11,7 @@ #include "base/json/json_reader.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "components/autofill/core/browser/payments/test_legal_message_line.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,31 +19,6 @@ using Link = LegalMessageLine::Link; -// A legal message line that allows for modifications. -class TestLegalMessageLine : public LegalMessageLine { - public: - TestLegalMessageLine() {} - - TestLegalMessageLine(const std::string& ascii_text) { set_text(ascii_text); } - - TestLegalMessageLine(const std::string& ascii_text, - const std::vector<Link>& links) { - set_text(ascii_text); - set_links(links); - } - - ~TestLegalMessageLine() override {} - - void set_text(const std::string& ascii_text) { - text_ = base::ASCIIToUTF16(ascii_text); - } - - void set_links(const std::vector<Link>& links) { links_ = links; } - - private: - DISALLOW_COPY_AND_ASSIGN(TestLegalMessageLine); -}; - // A test case. struct TestCase { std::string message_json;
diff --git a/components/autofill/core/browser/payments/test_legal_message_line.h b/components/autofill/core/browser/payments/test_legal_message_line.h new file mode 100644 index 0000000..1fdfcd66 --- /dev/null +++ b/components/autofill/core/browser/payments/test_legal_message_line.h
@@ -0,0 +1,44 @@ +// 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 COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_LEGAL_MESSAGE_LINE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_LEGAL_MESSAGE_LINE_H_ + +#include <string> + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/payments/legal_message_line.h" + +namespace autofill { + +using Link = LegalMessageLine::Link; + +// A legal message line that allows for modifications. +class TestLegalMessageLine : public LegalMessageLine { + public: + TestLegalMessageLine() {} + + TestLegalMessageLine(const std::string& ascii_text) { set_text(ascii_text); } + + TestLegalMessageLine(const std::string& ascii_text, + const std::vector<Link>& links) { + set_text(ascii_text); + set_links(links); + } + + ~TestLegalMessageLine() override {} + + void set_text(const std::string& ascii_text) { + text_ = base::ASCIIToUTF16(ascii_text); + } + + void set_links(const std::vector<Link>& links) { links_ = links; } + + private: + DISALLOW_COPY_AND_ASSIGN(TestLegalMessageLine); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_LEGAL_MESSAGE_LINE_H_
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp index 11764da8..b180566 100644 --- a/components/autofill_payments_strings.grdp +++ b/components/autofill_payments_strings.grdp
@@ -428,6 +428,41 @@ CVC </message> + <!-- WebAuthn fingerprint opt-in dialog --> + <!-- Desktop only --> + <if expr="not is_ios and not is_android"> + <if expr="is_macosx"> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE" desc="Headline asking the user if they want to use their device's platform authenticator to confirm their cards in the future instead of CVC."> + Use Touch ID instead of CVC? + </message> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL" desc="Button that allows the user to use their device's platform authenticator to confirm card use in the future."> + Use Touch ID + </message> + </if> + <if expr="is_win"> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE" desc="Headline asking the user if they want to use their device's platform authenticator to confirm their cards in the future instead of CVC."> + Use Windows Hello instead of CVC? + </message> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL" desc="Button that allows the user to use their device's platform authenticator to confirm card use in the future."> + Use Windows Hello + </message> + </if> + <if expr="not is_win and not is_macosx"> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_TITLE" desc="Headline asking the user if they want to use their device's platform authenticator to confirm their cards in the future instead of CVC."> + Use WebAuthn instead of CVC? + </message> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_OK_BUTTON_LABEL" desc="Button that allows the user to use their device's platform authenticator to confirm card use in the future."> + Use WebAuthn + </message> + </if> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_INSTRUCTION" desc="Subheading that appears below the headline explaining to the user that they won't have to enter their card's security code if they decide to use their device's platform authenticator in the future."> + You won't need to enter a card security code from now on + </message> + <message name="IDS_AUTOFILL_WEBAUTHN_OPT_IN_DIALOG_CANCEL_BUTTON_LABEL" desc="Button that allows the user to decline the option of using their device's platform authenticator for card confirmation."> + Not now + </message> + </if> + <message name="IDS_AUTOFILL_WALLET_MANAGEMENT_LINK_TEXT" desc="Text for link that allows users to see and edit their Wallet information." formatter_data="android_java"> Edit </message>
diff --git a/components/browser_sync/OWNERS b/components/browser_sync/OWNERS index 261ab18..2fe6dcc 100644 --- a/components/browser_sync/OWNERS +++ b/components/browser_sync/OWNERS
@@ -1 +1,3 @@ file://components/sync/OWNERS +# COMPONENT: Services>Sync +# TEAM: chromium-reviews@chromium.org
diff --git a/components/chrome_cleaner/public/proto/BUILD.gn b/components/chrome_cleaner/public/proto/BUILD.gn index d24d95e5..0f556a43 100644 --- a/components/chrome_cleaner/public/proto/BUILD.gn +++ b/components/chrome_cleaner/public/proto/BUILD.gn
@@ -9,3 +9,11 @@ "chrome_prompt.proto", ] } + +proto_library("test_only_proto") { + testonly = true + generate_python = false + sources = [ + "chrome_prompt_for_tests.proto", + ] +}
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_for_tests.proto b/components/chrome_cleaner/public/proto/chrome_prompt_for_tests.proto similarity index 93% rename from chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_for_tests.proto rename to components/chrome_cleaner/public/proto/chrome_prompt_for_tests.proto index 875e552..e368a22a 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_for_tests.proto +++ b/components/chrome_cleaner/public/proto/chrome_prompt_for_tests.proto
@@ -6,7 +6,7 @@ // contains added fields to validate that they do not break the parsing. This is // to simulate an outdated Chrome handling messages from an updated cleaner. -// This file contains minimal comments for descriptions of non-test +// This file contains minimal comments. For descriptions of non-test // fields/messages please refer to the original file. syntax = "proto2"; @@ -35,6 +35,7 @@ ACCEPTED_WITH_LOGS = 1; ACCEPTED_WITHOUT_LOGS = 2; DENIED = 3; + FOR_TESTS_ONLY = 255; }; optional PromptAcceptance prompt_acceptance = 1 [default = UNSPECIFIED];
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc index 907f77e2..03b54070 100644 --- a/components/exo/wayland/clients/client_base.cc +++ b/components/exo/wayland/clients/client_base.cc
@@ -322,6 +322,8 @@ ClientBase::InitParams::~InitParams() {} +ClientBase::InitParams::InitParams(const InitParams& params) = default; + bool ClientBase::InitParams::FromCommandLine( const base::CommandLine& command_line) { if (command_line.HasSwitch(switches::kSize)) {
diff --git a/components/exo/wayland/clients/client_base.h b/components/exo/wayland/clients/client_base.h index 678281731..fca06483 100644 --- a/components/exo/wayland/clients/client_base.h +++ b/components/exo/wayland/clients/client_base.h
@@ -38,6 +38,7 @@ struct InitParams { InitParams(); ~InitParams(); + InitParams(const InitParams& params); bool FromCommandLine(const base::CommandLine& command_line);
diff --git a/components/exo/wayland/clients/vulkan.cc b/components/exo/wayland/clients/vulkan.cc index 021d8cf..9e91e965 100644 --- a/components/exo/wayland/clients/vulkan.cc +++ b/components/exo/wayland/clients/vulkan.cc
@@ -120,7 +120,6 @@ }; void VulkanClient::Run(const ClientBase::InitParams& params) { - params.use_vulkan = true; if (!ClientBase::Init(params)) return; @@ -177,6 +176,7 @@ if (!params.FromCommandLine(*command_line)) return 1; + params.use_vulkan = true; base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI); exo::wayland::clients::VulkanClient client; client.Run(params);
diff --git a/components/gwp_asan/OWNERS b/components/gwp_asan/OWNERS index 57999e8..26e52daa 100644 --- a/components/gwp_asan/OWNERS +++ b/components/gwp_asan/OWNERS
@@ -1,2 +1,3 @@ vitalybuka@chromium.org vtsyrklevich@chromium.org +# COMPONENT: Internals>Instrumentation
diff --git a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java index b5083a5..1dcaafd0 100644 --- a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java +++ b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInstaller.java
@@ -4,7 +4,7 @@ package org.chromium.components.module_installer; -import android.content.Context; +import android.app.Activity; import org.chromium.base.VisibleForTesting; @@ -32,8 +32,9 @@ * * For details, see: * https://developer.android.com/reference/com/google/android/play/core/splitcompat/SplitCompat.html#install(android.content.Context) + * @param activity The Activity for which SplitCompat will be run. */ - default void initActivity(Context context) {} + default void initActivity(Activity activity) {} /** * Records via UMA all modules that have been requested and are currently installed. The intent
diff --git a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java index b26e1623..1fc6fd55 100644 --- a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java +++ b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/ModuleInterface.java
@@ -17,7 +17,7 @@ @Retention(RetentionPolicy.SOURCE) public @interface ModuleInterface { /** The name of the module. */ - public String module(); + String module(); /** The fully qualified name of the module's interface implementation. */ - public String impl(); + String impl(); }
diff --git a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategy.java b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategy.java index 9bd9af49..f50ef963 100644 --- a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategy.java +++ b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategy.java
@@ -11,8 +11,8 @@ import java.util.List; /** Interface outlining the necessary strategy to load activities and install modules. */ -interface ObserverStrategy { - public ModuleInstaller getModuleInstaller(); - public List<Activity> getRunningActivities(); - public int getStateForActivity(Activity activity); +/* package */ interface ObserverStrategy { + ModuleInstaller getModuleInstaller(); + List<Activity> getRunningActivities(); + int getStateForActivity(Activity activity); } \ No newline at end of file
diff --git a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java index db46dba..414d9cc 100644 --- a/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java +++ b/components/module_installer/android/java/src-common/org/chromium/components/module_installer/observers/ObserverStrategyImpl.java
@@ -12,7 +12,7 @@ import java.util.List; /** Strategy utilizing ModuleInstaller and ApplicationStatus. */ -class ObserverStrategyImpl implements ObserverStrategy { +/* package */ class ObserverStrategyImpl implements ObserverStrategy { @Override public ModuleInstaller getModuleInstaller() { return ModuleInstaller.getInstance();
diff --git a/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java b/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java index 74b6fa4..e560d0a 100644 --- a/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java +++ b/components/module_installer/android/java/src-impl/org/chromium/components/module_installer/ModuleInstallerImpl.java
@@ -4,6 +4,7 @@ package org.chromium.components.module_installer; +import android.app.Activity; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; @@ -33,7 +34,7 @@ /** Installs dynamic feature modules (DFMs). */ @MainDex -public class ModuleInstallerImpl implements ModuleInstaller { +/* package */ class ModuleInstallerImpl implements ModuleInstaller { /** Command line switch for activating the fake backend. */ private static final String FAKE_FEATURE_MODULE_INSTALL = "fake-feature-module-install"; private static ModuleInstaller sInstance = new ModuleInstallerImpl(); @@ -65,8 +66,11 @@ } @Override - public void initActivity(Context context) { - SplitCompat.install(context); + public void initActivity(Activity activity) { + // SplitCompat#install should always be run for the application first before it is run for + // any activities. + init(); + SplitCompat.install(activity); } @Override
diff --git a/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java b/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java index 25654c30..c5b064d2 100644 --- a/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java +++ b/components/module_installer/android/java/src-stub/org/chromium/components/module_installer/ModuleInstallerImpl.java
@@ -8,7 +8,7 @@ /** Dummy fallback of ModuleInstaller for APK builds. */ @MainDex -public class ModuleInstallerImpl implements ModuleInstaller { +/* package */ class ModuleInstallerImpl implements ModuleInstaller { /** A valid singleton instance is necessary for tests to swap it out. */ private static ModuleInstaller sInstance = new ModuleInstallerImpl();
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index 64a7778..8cfa00f5 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -176,10 +176,10 @@ MaybeCullTailSuggestions(&matches_); } #endif - DeduplicateMatches(input.current_page_classification(), &matches_); - DemoteOnDeviceSearchSuggestions(); + DeduplicateMatches(input.current_page_classification(), &matches_); + // Sort and trim to the most relevant GetMaxMatches() matches. CompareWithDemoteByType<AutocompleteMatch> comparing_object( input.current_page_classification());
diff --git a/components/optimization_guide/hints_fetcher.cc b/components/optimization_guide/hints_fetcher.cc index b8a0205..3e5e5d83 100644 --- a/components/optimization_guide/hints_fetcher.cc +++ b/components/optimization_guide/hints_fetcher.cc
@@ -10,8 +10,13 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/time/default_clock.h" +#include "components/optimization_guide/hints_processing_util.h" #include "components/optimization_guide/optimization_guide_features.h" +#include "components/optimization_guide/optimization_guide_prefs.h" #include "components/optimization_guide/proto/hints.pb.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/network_service_instance.h" #include "net/base/load_flags.h" #include "net/base/url_util.h" @@ -24,13 +29,25 @@ namespace optimization_guide { +namespace { + +// The duration that hosts placed in the HintsFetcherHostsSuccessfullyFetched +// dictionary pref are considered valid. +constexpr base::TimeDelta kHintsFetcherHostFetchedValidDuration = + base::TimeDelta::FromDays(7); + +} // namespace + HintsFetcher::HintsFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - GURL optimization_guide_service_url) + GURL optimization_guide_service_url, + PrefService* pref_service) : optimization_guide_service_url_(net::AppendOrReplaceQueryParameter( optimization_guide_service_url, "key", - features::GetOptimizationGuideServiceAPIKey())) { + features::GetOptimizationGuideServiceAPIKey())), + pref_service_(pref_service), + time_clock_(base::DefaultClock::GetInstance()) { url_loader_factory_ = std::move(url_loader_factory); CHECK(optimization_guide_service_url_.SchemeIs(url::kHttpsScheme)); CHECK(features::IsHintsFetchingEnabled()); @@ -38,6 +55,17 @@ HintsFetcher::~HintsFetcher() {} +// static +void HintsFetcher::ClearHostsSuccessfullyFetched(PrefService* pref_service) { + DictionaryPrefUpdate hosts_fetched_list( + pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched); + hosts_fetched_list->Clear(); +} + +void HintsFetcher::SetTimeClockForTesting(const base::Clock* time_clock) { + time_clock_ = time_clock; +} + bool HintsFetcher::FetchOptimizationGuideServiceHints( const std::vector<std::string>& hosts, HintsFetchedCallback hints_fetched_callback) { @@ -123,6 +151,7 @@ base::BindOnce(&HintsFetcher::OnURLLoadComplete, base::Unretained(this))); hints_fetched_callback_ = std::move(hints_fetched_callback); + hosts_fetched_ = hosts; return true; } @@ -146,12 +175,28 @@ UMA_HISTOGRAM_COUNTS_100( "OptimizationGuide.HintsFetcher.GetHintsRequest.HintCount", get_hints_response->hints_size()); + UpdateHostsSuccessfullyFetched(); std::move(hints_fetched_callback_).Run(std::move(get_hints_response)); } else { std::move(hints_fetched_callback_).Run(base::nullopt); } } +void HintsFetcher::UpdateHostsSuccessfullyFetched() { + if (hosts_fetched_.size() == 0) + return; + DictionaryPrefUpdate hosts_fetched_list( + pref_service_, prefs::kHintsFetcherHostsSuccessfullyFetched); + base::Time host_invalid_time = + time_clock_->Now() + kHintsFetcherHostFetchedValidDuration; + for (const std::string& host : hosts_fetched_) { + hosts_fetched_list->SetDoubleKey( + HashHostForDictionary(host), + host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF()); + } + hosts_fetched_.clear(); +} + void HintsFetcher::OnURLLoadComplete( std::unique_ptr<std::string> response_body) { int response_code = -1;
diff --git a/components/optimization_guide/hints_fetcher.h b/components/optimization_guide/hints_fetcher.h index e7a05f5f..3e85a5dc 100644 --- a/components/optimization_guide/hints_fetcher.h +++ b/components/optimization_guide/hints_fetcher.h
@@ -14,9 +14,12 @@ #include "base/memory/scoped_refptr.h" #include "base/optional.h" #include "base/sequence_checker.h" +#include "base/time/clock.h" #include "components/optimization_guide/proto/hints.pb.h" #include "url/gurl.h" +class PrefService; + namespace network { class SharedURLLoaderFactory; class SimpleURLLoader; @@ -40,7 +43,8 @@ public: HintsFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - GURL optimization_guide_service_url); + GURL optimization_guide_service_url, + PrefService* pref_service); virtual ~HintsFetcher(); // Requests hints from the Optimization Guide Service if a request for them is @@ -52,6 +56,13 @@ const std::vector<std::string>& hosts, HintsFetchedCallback hints_fetched_callback); + // Set |time_clock_| for testing. + void SetTimeClockForTesting(const base::Clock* time_clock); + + // Clear all the hosts and expiration times from the + // HintsFetcherHostsSuccessfullyFetched dictionary pref. + static void ClearHostsSuccessfullyFetched(PrefService* pref_service); + private: // URL loader completion callback. void OnURLLoadComplete(std::unique_ptr<std::string> response_body); @@ -64,6 +75,13 @@ int status, int response_code); + // Stores the hosts in |hosts_in_fetch_| in the + // HintsFetcherHostsSuccessfullyFetched dictionary pref. The value stored for + // each host is the time that the hints fetched for each host will expire. + // |hosts_in_fetch_| is cleared once the hosts are stored + // in the pref. + void UpdateHostsSuccessfullyFetched(); + // Used to hold the GetHintsRequest being constructed and sent as a remote // request. std::unique_ptr<proto::GetHintsRequest> get_hints_request_; @@ -78,6 +96,15 @@ // Holds the |URLLoader| for an active hints request. std::unique_ptr<network::SimpleURLLoader> url_loader_; + // A reference to the PrefService for this profile. Not owned. + PrefService* pref_service_ = nullptr; + + // Holds the hosts being requested by the hints fetcher. + std::vector<std::string> hosts_fetched_; + + // Clock used for recording time that the hints fetch occurred. + const base::Clock* time_clock_; + // Used for creating a |url_loader_| when needed for request hints. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
diff --git a/components/optimization_guide/hints_fetcher_unittest.cc b/components/optimization_guide/hints_fetcher_unittest.cc index 5210f2c..51cb279 100644 --- a/components/optimization_guide/hints_fetcher_unittest.cc +++ b/components/optimization_guide/hints_fetcher_unittest.cc
@@ -13,8 +13,13 @@ #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" +#include "base/test/simple_test_clock.h" #include "components/optimization_guide/hint_cache.h" +#include "components/optimization_guide/hints_processing_util.h" #include "components/optimization_guide/optimization_guide_features.h" +#include "components/optimization_guide/optimization_guide_prefs.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" #include "net/base/url_util.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -28,16 +33,23 @@ class HintsFetcherTest : public testing::Test { public: - explicit HintsFetcherTest() - : shared_url_loader_factory_( + HintsFetcherTest() + : task_environment_(base::test::TaskEnvironment::MainThreadType::UI, + base::test::TaskEnvironment::TimeSource::MOCK_TIME), + shared_url_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)) { base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeatureWithParameters( features::kOptimizationHintsFetching, {}); + pref_service_ = std::make_unique<TestingPrefServiceSimple>(); + prefs::RegisterProfilePrefs(pref_service_->registry()); + hints_fetcher_ = std::make_unique<HintsFetcher>( - shared_url_loader_factory_, GURL(optimization_guide_service_url)); + shared_url_loader_factory_, GURL(optimization_guide_service_url), + pref_service_.get()); + hints_fetcher_->SetTimeClockForTesting(task_environment_.GetMockClock()); } ~HintsFetcherTest() override {} @@ -62,6 +74,12 @@ network::mojom::ConnectionType::CONNECTION_4G); } + PrefService* pref_service() { return pref_service_.get(); } + + const base::Clock* GetMockClock() const { + return task_environment_.GetMockClock(); + } + protected: bool FetchHints(const std::vector<std::string>& hosts) { bool status = hints_fetcher_->FetchOptimizationGuideServiceHints( @@ -101,6 +119,7 @@ std::unique_ptr<HintsFetcher> hints_fetcher_; + std::unique_ptr<TestingPrefServiceSimple> pref_service_; scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; network::TestURLLoaderFactory test_url_loader_factory_; network::TestNetworkConnectionTracker* network_tracker_; @@ -162,4 +181,63 @@ EXPECT_TRUE(hints_fetched()); } +TEST_F(HintsFetcherTest, HintsFetchSuccessfulHostsRecorded) { + std::vector<std::string> hosts{"host1.com", "host2.com"}; + std::string response_content; + + EXPECT_TRUE(FetchHints(hosts)); + VerifyHasPendingFetchRequests(); + EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK)); + EXPECT_TRUE(hints_fetched()); + + const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary( + prefs::kHintsFetcherHostsSuccessfullyFetched); + base::Optional<double> value; + for (const std::string& host : hosts) { + value = hosts_fetched->FindDoubleKey(HashHostForDictionary(host)); + EXPECT_EQ(base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromSecondsD(*value)), + GetMockClock()->Now() + base::TimeDelta::FromDays(7)); + } +} + +TEST_F(HintsFetcherTest, HintsFetchFailsHostNotRecorded) { + std::vector<std::string> hosts{"host1.com", "host2.com"}; + std::string response_content; + + EXPECT_TRUE(FetchHints(hosts)); + VerifyHasPendingFetchRequests(); + EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_NOT_FOUND)); + EXPECT_FALSE(hints_fetched()); + + const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary( + prefs::kHintsFetcherHostsSuccessfullyFetched); + for (const std::string& host : hosts) { + EXPECT_FALSE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host))); + } +} + +TEST_F(HintsFetcherTest, HintsFetchClearHostsSuccessfullyFetched) { + std::vector<std::string> hosts{"host1.com", "host2.com"}; + std::string response_content; + + EXPECT_TRUE(FetchHints(hosts)); + VerifyHasPendingFetchRequests(); + EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK)); + EXPECT_TRUE(hints_fetched()); + + const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary( + prefs::kHintsFetcherHostsSuccessfullyFetched); + for (const std::string& host : hosts) { + EXPECT_TRUE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host))); + } + + HintsFetcher::ClearHostsSuccessfullyFetched(pref_service()); + hosts_fetched = pref_service()->GetDictionary( + prefs::kHintsFetcherHostsSuccessfullyFetched); + for (const std::string& host : hosts) { + EXPECT_FALSE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host))); + } +} + } // namespace optimization_guide
diff --git a/components/optimization_guide/optimization_guide_prefs.cc b/components/optimization_guide/optimization_guide_prefs.cc index 05f11264..aa2246e 100644 --- a/components/optimization_guide/optimization_guide_prefs.cc +++ b/components/optimization_guide/optimization_guide_prefs.cc
@@ -33,6 +33,13 @@ const char kHintsFetcherDataSaverTopHostBlacklistState[] = "optimization_guide.hintsfetcher.top_host_blacklist_state"; +// A dictionary pref that stores hosts that have had hints successfully fetched +// from the remote Optimization Guide Server. The entry for each host contains +// the time that the fetch that covered this host expires, i.e., any hints +// from the fetch would be considered stale. +const char kHintsFetcherHostsSuccessfullyFetched[] = + "optimization_guide.hintsfetcher.hosts_successfully_fetched"; + // A string pref that stores the version of the Optimization Hints component // that is currently being processed. This pref is cleared once processing // completes. It is used for detecting a potential crash loop on processing a @@ -48,6 +55,8 @@ PrefRegistry::LOSSY_PREF); registry->RegisterDictionaryPref(kHintsFetcherDataSaverTopHostBlacklist, PrefRegistry::LOSSY_PREF); + registry->RegisterDictionaryPref(kHintsFetcherHostsSuccessfullyFetched, + PrefRegistry::LOSSY_PREF); registry->RegisterIntegerPref( kHintsFetcherDataSaverTopHostBlacklistState, static_cast<int>(HintsFetcherTopHostBlacklistState::kNotInitialized),
diff --git a/components/optimization_guide/optimization_guide_prefs.h b/components/optimization_guide/optimization_guide_prefs.h index ca14ac9..f866e2f 100644 --- a/components/optimization_guide/optimization_guide_prefs.h +++ b/components/optimization_guide/optimization_guide_prefs.h
@@ -16,6 +16,7 @@ extern const char kHintsFetcherLastFetchAttempt[]; extern const char kHintsFetcherDataSaverTopHostBlacklist[]; extern const char kHintsFetcherDataSaverTopHostBlacklistState[]; +extern const char kHintsFetcherHostsSuccessfullyFetched[]; extern const char kPendingHintsProcessingVersion[]; // State of |HintsFetcherTopHostsBlacklist|. The blacklist begins in
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc index 7878ec2..88779df8 100644 --- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc +++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc
@@ -171,18 +171,19 @@ } void AuthenticatedLeakCheck::Start(const GURL& url, - base::StringPiece16 username, - base::StringPiece16 password) { + base::string16 username, + base::string16 password) { DCHECK(payload_helper_); DCHECK(!request_); url_ = url; - username_ = base::UTF16ToUTF8(username); + username_ = std::move(username); + password_ = std::move(password); payload_helper_->RequestAccessToken( base::BindOnce(&AuthenticatedLeakCheck::OnAccessTokenRequestCompleted, weak_ptr_factory_.GetWeakPtr())); payload_helper_->PreparePayload( - username_, base::UTF16ToUTF8(password), + base::UTF16ToUTF8(username_), base::UTF16ToUTF8(password_), base::BindOnce(&AuthenticatedLeakCheck::OnRequestDataReady, weak_ptr_factory_.GetWeakPtr())); } @@ -237,14 +238,14 @@ AnalyzeResponseResult( std::move(response), encryption_key_, - base::BindOnce(&AuthenticatedLeakCheck::OnAnalazeSingleLeakResponse, + base::BindOnce(&AuthenticatedLeakCheck::OnAnalyzeSingleLeakResponse, weak_ptr_factory_.GetWeakPtr())); } -void AuthenticatedLeakCheck::OnAnalazeSingleLeakResponse(bool is_leaked) { +void AuthenticatedLeakCheck::OnAnalyzeSingleLeakResponse(bool is_leaked) { DVLOG(0) << "Leak check result=" << is_leaked; delegate_->OnLeakDetectionDone(is_leaked, std::move(url_), - base::UTF8ToUTF16(username_)); + std::move(username_), std::move(password_)); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h index da7fa85..cebf377d 100644 --- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h +++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h
@@ -47,8 +47,8 @@ // LeakDetectionCheck: void Start(const GURL& url, - base::StringPiece16 username, - base::StringPiece16 password) override; + base::string16 username, + base::string16 password) override; #if defined(UNIT_TEST) void set_network_factory( @@ -81,7 +81,7 @@ // Called when the network response is analazyed on the background thread. The // method is called on the main thread. - void OnAnalazeSingleLeakResponse(bool is_leaked); + void OnAnalyzeSingleLeakResponse(bool is_leaked); // Delegate for the instance. Should outlive |this|. LeakDetectionDelegateInterface* const delegate_; @@ -95,7 +95,9 @@ // |url| passed to Start(). GURL url_; // |username| passed to Start(). - std::string username_; + base::string16 username_; + // |password| passed to Start(). + base::string16 password_; // Encryption key used during the request. std::string encryption_key_; // Weak pointers for different callbacks.
diff --git a/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc b/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc index 8212bda..09674c9 100644 --- a/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc +++ b/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc
@@ -227,7 +227,8 @@ key_server))); EXPECT_CALL(delegate(), OnLeakDetectionDone(false, GURL(kExampleCom), - base::ASCIIToUTF16(kUsername))); + base::ASCIIToUTF16(kUsername), + base::ASCIIToUTF16(kPassword))); std::move(payload_and_callback.callback).Run(std::move(response)); task_env().RunUntilIdle(); } @@ -247,7 +248,8 @@ ScryptHashUsernameAndPassword(kUsername, kPassword), key_server))); EXPECT_CALL(delegate(), OnLeakDetectionDone(true, GURL(kExampleCom), - base::ASCIIToUTF16(kUsername))); + base::ASCIIToUTF16(kUsername), + base::ASCIIToUTF16(kPassword))); std::move(payload_and_callback.callback).Run(std::move(response)); task_env().RunUntilIdle(); }
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_check.h b/components/password_manager/core/browser/leak_detection/leak_detection_check.h index 80ebccf..6a3a3cd1 100644 --- a/components/password_manager/core/browser/leak_detection/leak_detection_check.h +++ b/components/password_manager/core/browser/leak_detection/leak_detection_check.h
@@ -5,7 +5,7 @@ #ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_H_ #define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LEAK_DETECTION_LEAK_DETECTION_CHECK_H_ -#include "base/strings/string_piece_forward.h" +#include "base/strings/string16.h" #include "url/gurl.h" namespace password_manager { @@ -27,8 +27,8 @@ // |url| is used later for presentation in the UI but not for actual business // logic. The method should be called only once per lifetime of the object. virtual void Start(const GURL& url, - base::StringPiece16 username, - base::StringPiece16 password) = 0; + base::string16 username, + base::string16 password) = 0; }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h b/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h index ec4c1eb..6176099 100644 --- a/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h +++ b/components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h
@@ -41,9 +41,10 @@ // |leak| is true iff the checked credential was leaked. // |url| and |username| are taken from Start() for presentation in the UI. // Pass parameters by value because the caller can be destroyed here. - virtual void OnLeakDetectionDone(bool leaked, + virtual void OnLeakDetectionDone(bool is_leaked, GURL url, - base::string16 username) = 0; + base::string16 username, + base::string16 password) = 0; virtual void OnError(LeakDetectionError error) = 0; };
diff --git a/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h b/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h index e8b8d65..3bd76b8 100644 --- a/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h +++ b/components/password_manager/core/browser/leak_detection/mock_leak_detection_delegate.h
@@ -17,7 +17,8 @@ ~MockLeakDetectionDelegateInterface() override; // LeakDetectionDelegateInterface: - MOCK_METHOD3(OnLeakDetectionDone, void(bool, GURL, base::string16)); + MOCK_METHOD4(OnLeakDetectionDone, + void(bool, GURL, base::string16, base::string16)); MOCK_METHOD1(OnError, void(LeakDetectionError)); };
diff --git a/components/password_manager/core/browser/leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection_delegate.cc index f9ff1354..62e0148 100644 --- a/components/password_manager/core/browser/leak_detection_delegate.cc +++ b/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -38,14 +38,17 @@ leak_check_->Start(form.origin, form.username_value, form.password_value); } -void LeakDetectionDelegate::OnLeakDetectionDone(bool leaked, +void LeakDetectionDelegate::OnLeakDetectionDone(bool is_leaked, GURL url, - base::string16 username) { + base::string16 username, + base::string16 password) { leak_check_.reset(); if (password_manager_util::IsLoggingActive(client_)) { BrowserSavePasswordProgressLogger logger(client_->GetLogManager()); - logger.LogBoolean(Logger::STRING_LEAK_DETECTION_FINISHED, leaked); + logger.LogBoolean(Logger::STRING_LEAK_DETECTION_FINISHED, is_leaked); } + if (is_leaked) + client_->NotifyUserCredentialsWereLeaked(url); } void LeakDetectionDelegate::OnError(LeakDetectionError error) {
diff --git a/components/password_manager/core/browser/leak_detection_delegate.h b/components/password_manager/core/browser/leak_detection_delegate.h index a079309..37da214 100644 --- a/components/password_manager/core/browser/leak_detection_delegate.h +++ b/components/password_manager/core/browser/leak_detection_delegate.h
@@ -43,9 +43,10 @@ private: // LeakDetectionDelegateInterface: - void OnLeakDetectionDone(bool leaked, + void OnLeakDetectionDone(bool is_leaked, GURL url, - base::string16 username) override; + base::string16 username, + base::string16 password) override; void OnError(LeakDetectionError error) override; PasswordManagerClient* client_;
diff --git a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc index f8e2e272..ea5b486 100644 --- a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc +++ b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
@@ -21,6 +21,7 @@ namespace { using base::ASCIIToUTF16; +using testing::_; using testing::ByMove; using testing::Eq; using testing::Return; @@ -41,12 +42,12 @@ MOCK_CONST_METHOD0(IsIncognito, bool()); MOCK_CONST_METHOD0(GetPrefs, PrefService*()); + MOCK_METHOD1(NotifyUserCredentialsWereLeaked, void(const GURL&)); }; class MockLeakDetectionCheck : public LeakDetectionCheck { public: - MOCK_METHOD3(Start, - void(const GURL&, base::StringPiece16, base::StringPiece16)); + MOCK_METHOD3(Start, void(const GURL&, base::string16, base::string16)); }; class MockLeakDetectionCheckFactory : public LeakDetectionCheckFactory { @@ -82,7 +83,7 @@ std::unique_ptr<TestingPrefServiceSimple> prefs_; private: - MockPasswordManagerClient client_; + testing::NiceMock<MockPasswordManagerClient> client_; MockLeakDetectionCheckFactory* mock_factory_ = nullptr; LeakDetectionDelegate delegate_; }; @@ -111,13 +112,26 @@ const autofill::PasswordForm form = CreateTestForm(); EXPECT_CALL(client(), IsIncognito).WillOnce(Return(false)); auto check_instance = std::make_unique<MockLeakDetectionCheck>(); - EXPECT_CALL(*check_instance, Start(form.origin, Eq(form.username_value), - Eq(form.password_value))); - EXPECT_CALL(factory(), TryCreateLeakCheck) + EXPECT_CALL(*check_instance, + Start(form.origin, form.username_value, form.password_value)); + EXPECT_CALL(factory(), TryCreateLeakCheck(&delegate(), _, _)) .WillOnce(Return(ByMove(std::move(check_instance)))); delegate().StartLeakCheck(form); EXPECT_TRUE(delegate().leak_check()); } +TEST_F(LeakDetectionDelegateTest, LeakDetectionDone) { + LeakDetectionDelegateInterface* delegate_interface = &delegate(); + const autofill::PasswordForm form = CreateTestForm(); + + EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked).Times(0); + delegate_interface->OnLeakDetectionDone( + false, form.origin, form.username_value, form.password_value); + + EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked(form.origin)); + delegate_interface->OnLeakDetectionDone( + true, form.origin, form.username_value, form.password_value); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 4429e60..d395e07 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -91,8 +91,7 @@ class MockLeakDetectionCheck : public LeakDetectionCheck { public: - MOCK_METHOD3(Start, - void(const GURL&, base::StringPiece16, base::StringPiece16)); + MOCK_METHOD3(Start, void(const GURL&, base::string16, base::string16)); }; class MockLeakDetectionCheckFactory : public LeakDetectionCheckFactory { @@ -3874,8 +3873,7 @@ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); auto check_instance = std::make_unique<MockLeakDetectionCheck>(); EXPECT_CALL(*check_instance, - Start(form.origin, base::StringPiece16(form.username_value), - base::StringPiece16(form.password_value))); + Start(form.origin, form.username_value, form.password_value)); EXPECT_CALL(*weak_factory, TryCreateLeakCheck) .WillOnce(Return(ByMove(std::move(check_instance))));
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc index 4e08ed7..7f54f5dc 100644 --- a/components/previews/content/previews_decider_impl_unittest.cc +++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -39,6 +39,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/optimization_guide/hint_cache_store.h" #include "components/optimization_guide/optimization_guide_features.h" +#include "components/optimization_guide/optimization_guide_prefs.h" #include "components/optimization_guide/optimization_guide_service.h" #include "components/optimization_guide/proto_database_provider_test_base.h" #include "components/optimization_guide/top_host_provider.h" @@ -434,6 +435,7 @@ std::make_unique<TestPreviewsDeciderImpl>(&clock_); previews_decider_impl_ = previews_decider_impl.get(); pref_service_ = std::make_unique<TestingPrefServiceSimple>(); + optimization_guide::prefs::RegisterProfilePrefs(pref_service_->registry()); ui_service_.reset(new TestPreviewsUIService( std::move(previews_decider_impl), std::make_unique<TestOptOutStore>(), std::make_unique<TestPreviewsOptimizationGuide>(
diff --git a/components/previews/content/previews_optimization_guide.cc b/components/previews/content/previews_optimization_guide.cc index 411e659..3174502 100644 --- a/components/previews/content/previews_optimization_guide.cc +++ b/components/previews/content/previews_optimization_guide.cc
@@ -264,7 +264,8 @@ if (!hints_fetcher_) { hints_fetcher_ = std::make_unique<optimization_guide::HintsFetcher>( url_loader_factory_, - optimization_guide::features::GetOptimizationGuideServiceURL()); + optimization_guide::features::GetOptimizationGuideServiceURL(), + pref_service_); } if (top_hosts->size() > 0) { @@ -322,6 +323,8 @@ void PreviewsOptimizationGuide::ClearFetchedHints() { DCHECK(hint_cache_); hint_cache_->ClearFetchedHints(); + optimization_guide::HintsFetcher::ClearHostsSuccessfullyFetched( + pref_service_); } void PreviewsOptimizationGuide::OnHintsUpdated(
diff --git a/components/previews/content/previews_optimization_guide_unittest.cc b/components/previews/content/previews_optimization_guide_unittest.cc index 8c74784..9f18402 100644 --- a/components/previews/content/previews_optimization_guide_unittest.cc +++ b/components/previews/content/previews_optimization_guide_unittest.cc
@@ -125,8 +125,11 @@ TestHintsFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GURL optimization_guide_service_url, - HintsFetcherEndState fetch_state) - : HintsFetcher(url_loader_factory, optimization_guide_service_url), + HintsFetcherEndState fetch_state, + PrefService* pref_service) + : HintsFetcher(url_loader_factory, + optimization_guide_service_url, + pref_service), fetch_state_(fetch_state) {} bool FetchOptimizationGuideServiceHints( @@ -320,8 +323,9 @@ std::unique_ptr<TestHintsFetcher> BuildTestHintsFetcher( HintsFetcherEndState end_state) { std::unique_ptr<TestHintsFetcher> hints_fetcher = - std::make_unique<TestHintsFetcher>( - url_loader_factory_, GURL("https://hintsserver.com"), end_state); + std::make_unique<TestHintsFetcher>(url_loader_factory_, + GURL("https://hintsserver.com"), + end_state, pref_service()); return hints_fetcher; }
diff --git a/components/sync_bookmarks/OWNERS b/components/sync_bookmarks/OWNERS index ef97383..2453e93 100644 --- a/components/sync_bookmarks/OWNERS +++ b/components/sync_bookmarks/OWNERS
@@ -1,3 +1,4 @@ file://components/sync/OWNERS # COMPONENT: Services>Sync +# TEAM: chromium-reviews@chromium.org
diff --git a/components/sync_bookmarks/bookmark_model_type_processor.cc b/components/sync_bookmarks/bookmark_model_type_processor.cc index 6816537a..75fd611 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor.cc +++ b/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -338,6 +338,7 @@ bookmark_model_ = model; schedule_save_closure_ = schedule_save_closure; + base::TimeTicks start_time = base::TimeTicks::Now(); sync_pb::BookmarkModelMetadata model_metadata; model_metadata.ParseFromString(metadata_str); @@ -363,6 +364,8 @@ StartTrackingMetadata(std::move(nodes_metadata), std::move(model_type_state)); bookmark_tracker_->CheckAllNodesTracked(bookmark_model_); + UMA_HISTOGRAM_TIMES("Sync.BookmarksModelReadyToSyncTime", + base::TimeTicks::Now() - start_time); } else if (!model_metadata.model_type_state().initial_sync_done() && !model_metadata.bookmarks_metadata().empty()) { DLOG(ERROR)
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc index 2218df1..a6782e59a 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc +++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind_helpers.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/scoped_task_environment.h" #include "components/bookmarks/browser/bookmark_model.h" @@ -344,8 +345,11 @@ std::string metadata_str; model_metadata.SerializeToString(&metadata_str); + base::HistogramTester histogram_tester; new_processor.ModelReadyToSync(metadata_str, base::DoNothing(), bookmark_model()); + histogram_tester.ExpectTotalCount("Sync.BookmarksModelReadyToSyncTime", + /*count=*/1); AssertState(&new_processor, bookmarks); }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 24cd1b19..5309c35 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1033,6 +1033,7 @@ "indexed_db/indexed_db_reporting.h", "indexed_db/indexed_db_return_value.cc", "indexed_db/indexed_db_return_value.h", + "indexed_db/indexed_db_task_helper.h", "indexed_db/indexed_db_tombstone_sweeper.cc", "indexed_db/indexed_db_tombstone_sweeper.h", "indexed_db/indexed_db_tracing.h", @@ -1243,6 +1244,8 @@ "native_file_system/fixed_native_file_system_permission_grant.h", "native_file_system/native_file_system_directory_handle_impl.cc", "native_file_system/native_file_system_directory_handle_impl.h", + "native_file_system/native_file_system_error.cc", + "native_file_system/native_file_system_error.h", "native_file_system/native_file_system_file_handle_impl.cc", "native_file_system/native_file_system_file_handle_impl.h", "native_file_system/native_file_system_file_writer_impl.cc",
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 532706b..d45da88 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -1877,6 +1877,9 @@ case ax::mojom::Role::kDetails: return content_client->GetLocalizedString(IDS_AX_ROLE_DETAILS); + case ax::mojom::Role::kFigure: + return content_client->GetLocalizedString(IDS_AX_ROLE_FIGURE); + case ax::mojom::Role::kMeter: return content_client->GetLocalizedString(IDS_AX_ROLE_METER);
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc index 15160b96..29da868 100644 --- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc +++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -708,6 +708,7 @@ "data:text/html," "<audio controls></audio>" "<details></details>" + "<figure></figure>" "<input>" "<input type='color'>" "<input type='date'>" @@ -724,7 +725,7 @@ BrowserAccessibility* root = GetManager()->GetRoot(); ASSERT_NE(nullptr, root); - ASSERT_EQ(12u, root->PlatformChildCount()); + ASSERT_EQ(13u, root->PlatformChildCount()); auto TestLocalizedRoleDescription = [root](int child_index, @@ -739,17 +740,18 @@ // For testing purposes, assume we get en-US localized strings. TestLocalizedRoleDescription(0, base::ASCIIToUTF16("audio")); TestLocalizedRoleDescription(1, base::ASCIIToUTF16("details")); - TestLocalizedRoleDescription(2, base::ASCIIToUTF16("")); - TestLocalizedRoleDescription(3, base::ASCIIToUTF16("color picker")); - TestLocalizedRoleDescription(4, base::ASCIIToUTF16("date picker")); + TestLocalizedRoleDescription(2, base::ASCIIToUTF16("figure")); + TestLocalizedRoleDescription(3, base::ASCIIToUTF16("")); + TestLocalizedRoleDescription(4, base::ASCIIToUTF16("color picker")); + TestLocalizedRoleDescription(5, base::ASCIIToUTF16("date picker")); TestLocalizedRoleDescription( - 5, base::ASCIIToUTF16("local date and time picker")); - TestLocalizedRoleDescription(6, base::ASCIIToUTF16("email")); - TestLocalizedRoleDescription(7, base::ASCIIToUTF16("telephone")); - TestLocalizedRoleDescription(8, base::ASCIIToUTF16("url")); - TestLocalizedRoleDescription(9, base::ASCIIToUTF16("week picker")); - TestLocalizedRoleDescription(10, base::ASCIIToUTF16("meter")); - TestLocalizedRoleDescription(11, base::ASCIIToUTF16("output")); + 6, base::ASCIIToUTF16("local date and time picker")); + TestLocalizedRoleDescription(7, base::ASCIIToUTF16("email")); + TestLocalizedRoleDescription(8, base::ASCIIToUTF16("telephone")); + TestLocalizedRoleDescription(9, base::ASCIIToUTF16("url")); + TestLocalizedRoleDescription(10, base::ASCIIToUTF16("week picker")); + TestLocalizedRoleDescription(11, base::ASCIIToUTF16("meter")); + TestLocalizedRoleDescription(12, base::ASCIIToUTF16("output")); } IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index d01404c..b7445d3 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2057,6 +2057,10 @@ RunHtmlTest(FILE_PATH_LITERAL("button-with-listbox-popup.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, DeleteSelectionCrash) { + RunHtmlTest(FILE_PATH_LITERAL("delete-selection-crash.html")); +} + // // Regression tests. These don't test a specific web platform feature, // they test a specific web page that crashed or had some bad behavior
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 5acff0fb..39edaaf 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -47,6 +47,7 @@ #include "base/timer/hi_res_timer_manager.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" +#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "cc/base/histograms.h" @@ -184,7 +185,6 @@ #include <commctrl.h> #include <shellapi.h> -#include "base/memory/memory_pressure_monitor_win.h" #include "content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h" #include "net/base/winsock_init.h" #include "services/service_manager/sandbox/win/sandbox_win.h" @@ -384,7 +384,7 @@ #elif defined(OS_MACOSX) return std::make_unique<base::mac::MemoryPressureMonitor>(); #elif defined(OS_WIN) - return std::make_unique<base::win::MemoryPressureMonitor>(); + return std::make_unique<util::MultiSourceMemoryPressureMonitor>(); #else // No memory monitor on other platforms... return nullptr;
diff --git a/content/browser/devtools/protocol/OWNERS b/content/browser/devtools/protocol/OWNERS new file mode 100644 index 0000000..187afe1f --- /dev/null +++ b/content/browser/devtools/protocol/OWNERS
@@ -0,0 +1,3 @@ +per-file system_info_handler.*=kbr@chromium.org + +# COMPONENT: Platform>DevTools
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index c257ed7..4bd0d65c 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -19,6 +19,7 @@ #include "base/rand_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/system/sys_info.h" #include "base/task/post_task.h" #include "build/build_config.h" #include "content/browser/appcache/appcache_navigation_handle.h" @@ -3104,11 +3105,26 @@ // TODO(http://crbug.com/934317): Remove this once done debugging renderer // hangs. if (base::RandDouble() < 0.1) { - static base::debug::CrashKeyString* url = + static base::debug::CrashKeyString* url_key = base::debug::AllocateCrashKeyString("commit_timeout_url", base::debug::CrashKeySize::Size256); - base::debug::ScopedCrashKeyString( - url, common_params_->url.possibly_invalid_spec()); + base::debug::ScopedCrashKeyString scoped_url( + url_key, common_params_->url.possibly_invalid_spec()); + + static base::debug::CrashKeyString* last_crash_key = + base::debug::AllocateCrashKeyString("ns_last_crash_ms", + base::debug::CrashKeySize::Size32); + base::debug::ScopedCrashKeyString scoped_last_crash( + last_crash_key, + base::NumberToString( + GetTimeSinceLastNetworkServiceCrash().InMilliseconds())); + + static base::debug::CrashKeyString* memory_key = + base::debug::AllocateCrashKeyString("physical_memory_mb", + base::debug::CrashKeySize::Size32); + base::debug::ScopedCrashKeyString scoped_memory( + memory_key, + base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB())); base::debug::DumpWithoutCrashing(); if (IsOutOfProcessNetworkService())
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 6e5edaf..c6381fe 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -101,6 +101,7 @@ #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" #include "content/browser/renderer_interface_binders.h" #include "content/browser/scoped_active_url.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/sms/sms_service.h" #include "content/browser/speech/speech_recognition_dispatcher_host.h" #include "content/browser/storage_partition_impl.h" @@ -5311,8 +5312,8 @@ // it until its request endpoint is sent. Now that the request endpoint was // sent, it can be used, so add it to ServiceWorkerObjectHost. if (remote_object.is_valid()) { - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), base::BindOnce( &ServiceWorkerObjectHost::AddRemoteObjectPtrAndUpdateState, subresource_loader_params->controller_service_worker_object_host,
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc index 3bab9b2..910fb1ce 100644 --- a/content/browser/indexed_db/database_impl.cc +++ b/content/browser/indexed_db/database_impl.cc
@@ -17,6 +17,7 @@ #include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" +#include "content/browser/indexed_db/indexed_db_factory_impl.h" #include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/browser/indexed_db/transaction_impl.h" #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h" @@ -57,7 +58,7 @@ DatabaseImpl::~DatabaseImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (connection_->IsConnected()) - connection_->Close(); + connection_->AbortTransactionsAndClose(); indexed_db_context_->ConnectionClosed(origin_, connection_.get()); } @@ -86,8 +87,8 @@ leveldb::Status status = connection_->database()->RenameObjectStoreOperation( object_store_id, new_name, transaction); if (!status.ok()) { - connection_->database()->error_callback().Run( - status, "Internal error renaming object store."); + indexed_db_context_->GetIDBFactory()->OnDatabaseError( + origin_, status, "Internal error renaming object store."); } } @@ -127,7 +128,7 @@ if (!connection_->IsConnected()) return; - connection_->Close(); + connection_->AbortTransactionsAndClose(); } void DatabaseImpl::VersionChangeIgnored() { @@ -290,8 +291,8 @@ object_store_id, std::make_unique<IndexedDBKey>(primary_key), index_keys, transaction); if (!status.ok()) { - connection_->database()->error_callback().Run( - status, "Internal error setting index keys."); + indexed_db_context_->GetIDBFactory()->OnDatabaseError( + origin_, status, "Internal error setting index keys."); } } @@ -516,8 +517,8 @@ object_store_id, index_id, name, key_path, unique, multi_entry, transaction); if (!status.ok()) { - connection_->database()->error_callback().Run( - status, "Internal error creating an index."); + indexed_db_context_->GetIDBFactory()->OnDatabaseError( + origin_, status, "Internal error creating an index."); } }
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index a86ed277..1385a758 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -830,6 +830,11 @@ return V2SchemaCorruptionStatus::kYes; } +std::unique_ptr<IndexedDBBackingStore::Transaction> +IndexedDBBackingStore::CreateTransaction() { + return std::make_unique<IndexedDBBackingStore::Transaction>(this); +} + leveldb::Status IndexedDBBackingStore::GetCompleteMetadata( std::vector<IndexedDBDatabaseMetadata>* output) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); @@ -1386,7 +1391,7 @@ ++iter_; WriteNextFile(); } else { - std::move(callback_).Run(BlobWriteResult::FAILURE_ASYNC); + std::move(callback_).Run(BlobWriteResult::kFailure); } } @@ -1416,12 +1421,12 @@ } if (iter_ == blobs_.end()) { DCHECK(!self_ref_.get()); - std::move(callback_).Run(BlobWriteResult::SUCCESS_ASYNC); + std::move(callback_).Run(BlobWriteResult::kRunPhaseTwoAsync); return; } else { if (!backing_store_ || !backing_store_->WriteBlobFile(database_id_, *iter_, this)) { - std::move(callback_).Run(BlobWriteResult::FAILURE_ASYNC); + std::move(callback_).Run(BlobWriteResult::kFailure); return; } waiting_for_callback_ = true; @@ -3001,7 +3006,8 @@ return WriteNewBlobs(&new_blob_entries, &new_files_to_write, std::move(callback)); } else { - return std::move(callback).Run(BlobWriteResult::SUCCESS_SYNC); + return std::move(callback).Run( + BlobWriteResult::kRunPhaseTwoAndReturnResult); } } @@ -3133,21 +3139,21 @@ [](base::WeakPtr<IndexedDBBackingStore::Transaction> transaction, void* tracing_end_ptr, BlobWriteCallback final_callback, BlobWriteResult result) { - DCHECK_NE(result, BlobWriteResult::SUCCESS_SYNC); + DCHECK_NE(result, BlobWriteResult::kRunPhaseTwoAndReturnResult); IDB_ASYNC_TRACE_END( "IndexedDBBackingStore::Transaction::WriteNewBlobs", tracing_end_ptr); - Status leveldb_result = std::move(final_callback).Run(result); + leveldb::Status s = std::move(final_callback).Run(result); switch (result) { - case BlobWriteResult::FAILURE_ASYNC: + case BlobWriteResult::kFailure: break; - case BlobWriteResult::SUCCESS_ASYNC: - case BlobWriteResult::SUCCESS_SYNC: + case BlobWriteResult::kRunPhaseTwoAsync: + case BlobWriteResult::kRunPhaseTwoAndReturnResult: if (transaction) transaction->chained_blob_writer_ = nullptr; break; } - return leveldb_result; + return s; }, ptr_factory_.GetWeakPtr(), this, std::move(callback))); return leveldb::Status::OK();
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 6b35e905..138cbc1 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -20,7 +20,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -97,10 +96,21 @@ DISALLOW_COPY_AND_ASSIGN(RecordIdentifier); }; - enum class BlobWriteResult { FAILURE_ASYNC, SUCCESS_ASYNC, SUCCESS_SYNC }; + enum class BlobWriteResult { + // There was an error writing the blobs. + kFailure, + // The blobs were written, and phase two should be scheduled asynchronously. + // The returned status will be ignored. + kRunPhaseTwoAsync, + // The blobs were written, and phase two should be run now. The returned + // status will be correctly propagated. + kRunPhaseTwoAndReturnResult, + }; + // The returned status is only used when the result is + // |kRunPhaseTwoAndReturnResult|. using BlobWriteCallback = base::OnceCallback<leveldb::Status( - IndexedDBBackingStore::BlobWriteResult result)>; + IndexedDBBackingStore::BlobWriteResult)>; class BlobChangeRecord { public: @@ -563,6 +573,8 @@ bool is_incognito() const { return backing_store_mode_ == Mode::kInMemory; } + virtual std::unique_ptr<Transaction> CreateTransaction(); + base::WeakPtr<IndexedDBBackingStore> AsWeakPtr() { return weak_factory_.GetWeakPtr(); }
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index d07766b3..2af6d6a 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -438,12 +438,13 @@ [this](IndexedDBBackingStore::BlobWriteResult result) { this->called = true; switch (result) { - case IndexedDBBackingStore::BlobWriteResult::FAILURE_ASYNC: + case IndexedDBBackingStore::BlobWriteResult::kFailure: // Not tested. this->succeeded = false; break; - case IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC: - case IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC: + case IndexedDBBackingStore::BlobWriteResult::kRunPhaseTwoAsync: + case IndexedDBBackingStore::BlobWriteResult:: + kRunPhaseTwoAndReturnResult: this->succeeded = true; break; }
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index 730f778..b8d18b6 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -279,10 +279,10 @@ handle.origin_state()->backing_store()->db(); s = db->Put(key, &value); CHECK(s.ok()) << s.ToString(); - - // Force close to ensure a cold start on the next database open. - handle.origin_state()->ForceClose(); handle.Release(); + + context->GetIDBFactory()->ForceClose(origin, true); + CHECK(!context->GetIDBFactory()->IsBackingStoreOpen(origin)); context.reset(); } @@ -436,20 +436,6 @@ DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTestWithGCExposed); }; -class IndexedDBBrowserTestWithExperimentalWebFeatures - : public IndexedDBBrowserTest { - public: - IndexedDBBrowserTestWithExperimentalWebFeatures() = default; - - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch( - switches::kEnableExperimentalWebPlatformFeatures); - } - - private: - DISALLOW_COPY_AND_ASSIGN(IndexedDBBrowserTestWithExperimentalWebFeatures); -}; - IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DatabaseCallbacksTest) { SimpleTest(GetTestUrl("indexeddb", "database_callbacks_first.html")); @@ -1048,35 +1034,6 @@ EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); } -// Testing abort ordering for commit. Verifies that an explicitly committed -// transaction blocked by another pending transaction will be committed rather -// than aborted in the event that the page crashes before its committed. -IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithExperimentalWebFeatures, - CommitContinuesOnAbort) { - // Sets up a database, opens four transactions against it such that two end - // up indefinitely blocked, one of which is explicitly committed. - NavigateAndWaitForTitle(shell(), "blocked_explicit_commit.html", "#tab1", - "transactions registered"); - - // Crashes the tab to cause the database set up above to force close with the - // blocked transactions still open. - ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell()); - shell()->web_contents()->GetMainFrame()->GetProcess()->Shutdown(0); - - // Reopens the same page that was just crashed and inspects the database to - // see the results of the transactions that were open at time of crash. - Shell* new_shell = CreateBrowser(); - GURL url = GetTestUrl("indexeddb", "blocked_explicit_commit.html"); - url = GURL(url.spec() + "#tab2"); - base::string16 expected_title16( - ASCIIToUTF16("transactions aborted and committed as expected")); - TitleWatcher title_watcher(new_shell->web_contents(), expected_title16); - title_watcher.AlsoWaitForTitle( - ASCIIToUTF16("fail - transactions did not abort and commit as expected")); - NavigateToURL(new_shell, url); - EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); -} - // Verify that a "close" event is fired at database connections when // the backing store is deleted. IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) {
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h index b48692c..831495f9 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.h +++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -119,6 +119,8 @@ void OnConnectionError(); + bool is_complete() const { return complete_; } + protected: virtual ~IndexedDBCallbacks();
diff --git a/content/browser/indexed_db/indexed_db_class_factory.cc b/content/browser/indexed_db/indexed_db_class_factory.cc index cc79985..40e6e8c 100644 --- a/content/browser/indexed_db/indexed_db_class_factory.cc +++ b/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -35,8 +35,7 @@ const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, - IndexedDBDatabase::ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const IndexedDBDatabase::Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager) { @@ -44,9 +43,9 @@ DCHECK(factory); std::unique_ptr<IndexedDBDatabase> database = base::WrapUnique(new IndexedDBDatabase( - name, backing_store, factory, this, std::move(error_callback), - std::move(destroy_me), std::move(metadata_coding), unique_identifier, - transaction_lock_manager)); + name, backing_store, factory, this, + std::move(tasks_available_callback), std::move(metadata_coding), + unique_identifier, transaction_lock_manager)); leveldb::Status s = database->OpenInternal(); if (!s.ok()) database = nullptr; @@ -57,13 +56,13 @@ IndexedDBClassFactory::CreateIndexedDBTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& scope, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction) { - return base::WrapUnique( - new IndexedDBTransaction(id, connection, std::move(error_callback), scope, - mode, backing_store_transaction)); + return base::WrapUnique(new IndexedDBTransaction( + id, connection, scope, mode, std::move(tasks_available_callback), + backing_store_transaction)); } } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_class_factory.h b/content/browser/indexed_db/indexed_db_class_factory.h index fd675f6b..36189114 100644 --- a/content/browser/indexed_db/indexed_db_class_factory.h +++ b/content/browser/indexed_db/indexed_db_class_factory.h
@@ -17,6 +17,8 @@ #include "base/strings/string16.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_database.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" +#include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/browser/indexed_db/scopes/scopes_lock_manager.h" #include "content/common/content_export.h" #include "third_party/blink/public/common/indexeddb/web_idb_types.h" @@ -46,28 +48,25 @@ static void SetIndexedDBClassFactoryGetter(GetterCallback* cb); // Returns a constructed database, or a leveldb::Status error if there was a - // problem initializing the database. |error_callback| is called when a - // backing store operation has failed. The database will be closed - // (IndexedDBFactory::ForceClose) when the callback is called. |destroy_me| - // will destroy the IndexedDBDatabase object. + // problem initializing the database. |run_tasks_callback| is called when the + // database has tasks to run. virtual std::pair<std::unique_ptr<IndexedDBDatabase>, leveldb::Status> CreateIndexedDBDatabase( const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, - IndexedDBDatabase::ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const IndexedDBDatabase::Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager); - // |error_callback| is used to report unrecoverable errors. + // |tasks_available_callback| is called when the transaction has tasks to run. virtual std::unique_ptr<IndexedDBTransaction> CreateIndexedDBTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& scope, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction); protected:
diff --git a/content/browser/indexed_db/indexed_db_connection.cc b/content/browser/indexed_db/indexed_db_connection.cc index c8b9f71..565161c 100644 --- a/content/browser/indexed_db/indexed_db_connection.cc +++ b/content/browser/indexed_db/indexed_db_connection.cc
@@ -32,7 +32,6 @@ base::WeakPtr<IndexedDBDatabase> database, base::RepeatingClosure on_version_change_ignored, base::OnceCallback<void(IndexedDBConnection*)> on_close, - ErrorCallback error_callback, scoped_refptr<IndexedDBDatabaseCallbacks> callbacks) : id_(g_next_indexed_db_connection_id++), child_process_id_(child_process_id), @@ -41,40 +40,41 @@ database_(std::move(database)), on_version_change_ignored_(std::move(on_version_change_ignored)), on_close_(std::move(on_close)), - error_callback_(std::move(error_callback)), callbacks_(callbacks) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } IndexedDBConnection::~IndexedDBConnection() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (on_close_) - std::move(on_close_).Run(this); + if (IsConnected()) + AbortTransactionsAndClose(); } -void IndexedDBConnection::Close() { +void IndexedDBConnection::AbortTransactionsAndClose() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!callbacks_.get()) + if (!IsConnected()) return; + DCHECK(database_); + active_observers_.clear(); + callbacks_ = nullptr; + // Finish up any transaction, in case there were any running. FinishAllTransactions(IndexedDBDatabaseError( blink::kWebIDBDatabaseExceptionUnknownError, "Connection is closing.")); - // Calling |on_close_| can destroy this object. - base::WeakPtr<IndexedDBConnection> this_obj = weak_factory_.GetWeakPtr(); std::move(on_close_).Run(this); - if (this_obj) - ClearStateAfterClose(); + origin_state_handle_.Release(); + active_observers_.clear(); } void IndexedDBConnection::CloseAndReportForceClose() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!callbacks_.get()) + if (!IsConnected()) return; scoped_refptr<IndexedDBDatabaseCallbacks> callbacks(callbacks_); - Close(); + AbortTransactionsAndClose(); callbacks->OnForcedClose(); } @@ -84,6 +84,7 @@ } bool IndexedDBConnection::IsConnected() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return callbacks_.get(); } @@ -129,7 +130,8 @@ CHECK_EQ(GetTransaction(id), nullptr) << "Duplicate transaction id." << id; std::unique_ptr<IndexedDBTransaction> transaction = indexed_db_class_factory_->CreateIndexedDBTransaction( - id, this, error_callback_, scope, mode, backing_store_transaction); + id, this, scope, mode, database()->tasks_available_callback(), + backing_store_transaction); IndexedDBTransaction* transaction_ptr = transaction.get(); transactions_[id] = std::move(transaction); return transaction_ptr; @@ -146,21 +148,17 @@ void IndexedDBConnection::FinishAllTransactions( const IndexedDBDatabaseError& error) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::unordered_map<int64_t, std::unique_ptr<IndexedDBTransaction>> temp_map; - std::swap(temp_map, transactions_); - for (const auto& pair : temp_map) { + base::WeakPtr<IndexedDBConnection> weak_ptr = weak_factory_.GetWeakPtr(); + for (const auto& pair : transactions_) { auto& transaction = pair.second; - if (transaction->is_commit_pending()) { - IDB_TRACE1("IndexedDBDatabase::Commit", "transaction.id", - transaction->id()); - transaction->ForcePendingCommit(); - } - // If a transaction has blobs, then it can still pending after the call to - // ForcePendingCommit while it waits on blobs to be written or deleted. if (transaction->state() != IndexedDBTransaction::FINISHED) { IDB_TRACE1("IndexedDBDatabase::Abort(error)", "transaction.id", transaction->id()); transaction->Abort(error); + // Calling Abort on a transaction can destroy the IndexedDBOriginState if + // the revert fails when scopes is in single-sequence mode. + if (!weak_ptr) + return; } } }
diff --git a/content/browser/indexed_db/indexed_db_connection.h b/content/browser/indexed_db/indexed_db_connection.h index 7f8d1b5..2a96a9c 100644 --- a/content/browser/indexed_db/indexed_db_connection.h +++ b/content/browser/indexed_db/indexed_db_connection.h
@@ -7,9 +7,9 @@ #include <memory> #include <set> -#include <unordered_map> #include <vector> +#include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" @@ -26,22 +26,16 @@ class CONTENT_EXPORT IndexedDBConnection { public: - // Used to report irrecoverable backend errors. The second argument can be - // null. - using ErrorCallback = - base::RepeatingCallback<void(leveldb::Status, const char*)>; - IndexedDBConnection(int child_process_id, IndexedDBOriginStateHandle origin_state_handle, IndexedDBClassFactory* indexed_db_class_factory, base::WeakPtr<IndexedDBDatabase> database, base::RepeatingClosure on_version_change_ignored, base::OnceCallback<void(IndexedDBConnection*)> on_close, - ErrorCallback error_callback, scoped_refptr<IndexedDBDatabaseCallbacks> callbacks); virtual ~IndexedDBConnection(); - void Close(); + void AbortTransactionsAndClose(); void CloseAndReportForceClose(); bool IsConnected(); @@ -92,7 +86,7 @@ // TODO(dmurph): Change that so this doesn't need to ignore unknown ids. void RemoveTransaction(int64_t id); - const std::unordered_map<int64_t, std::unique_ptr<IndexedDBTransaction>>& + const base::flat_map<int64_t, std::unique_ptr<IndexedDBTransaction>>& transactions() const { return transactions_; } @@ -112,13 +106,12 @@ base::WeakPtr<IndexedDBDatabase> database_; base::RepeatingClosure on_version_change_ignored_; - // Note: Calling |on_close_| can destroy this object. base::OnceCallback<void(IndexedDBConnection*)> on_close_; - ErrorCallback error_callback_; // The connection owns transactions created on this connection. - std::unordered_map<int64_t, std::unique_ptr<IndexedDBTransaction>> - transactions_; + // This is |flat_map| to preserve ordering, and because the vast majority of + // users have less than 200 transactions. + base::flat_map<int64_t, std::unique_ptr<IndexedDBTransaction>> transactions_; // The callbacks_ member is cleared when the connection is closed. // May be NULL in unit tests.
diff --git a/content/browser/indexed_db/indexed_db_connection_coordinator.cc b/content/browser/indexed_db/indexed_db_connection_coordinator.cc index 2630db7..6ebca10 100644 --- a/content/browser/indexed_db/indexed_db_connection_coordinator.cc +++ b/content/browser/indexed_db/indexed_db_connection_coordinator.cc
@@ -31,6 +31,17 @@ using leveldb::Status; namespace content { +namespace { +enum class RequestState { + kNotStarted, + kPendingNoConnections, + kPendingLocks, + kPendingTransactionComplete, + kError, + kDone, +}; +} // namespace + // This represents what script calls an 'IDBOpenDBRequest' - either a database // open or delete call. These may be blocked on other connections. After every // callback, the request must call @@ -40,25 +51,32 @@ public: ConnectionRequest(IndexedDBOriginStateHandle origin_state_handle, IndexedDBDatabase* db, - IndexedDBConnectionCoordinator* connection_coordinator) + IndexedDBConnectionCoordinator* connection_coordinator, + TasksAvailableCallback tasks_available_callback) : origin_state_handle_(std::move(origin_state_handle)), db_(db), - connection_coordinator_(connection_coordinator) {} + connection_coordinator_(connection_coordinator), + tasks_available_callback_(std::move(tasks_available_callback)) {} virtual ~ConnectionRequest() {} - // Called when the request makes it to the front of the queue. - virtual void Perform() = 0; + // Called when the request makes it to the front of the queue. The state() + // will be checked after this call, so there is no need to run the + // |tasks_available_callback_|. + virtual void Perform(bool has_connections) = 0; // Called if a front-end signals that it is ignoring a "versionchange" // event. This should result in firing a "blocked" event at the request. virtual void OnVersionChangeIgnored() const = 0; // Called when a connection is closed; if it corresponds to this connection, - // need to do cleanup. Otherwise, it may unblock further steps. - // |connection| can be null if all connections were closed (see ForceClose). + // need to do cleanup. + // Not called during a force close. virtual void OnConnectionClosed(IndexedDBConnection* connection) = 0; + // Called when there are no connections to the database. + virtual void OnNoConnections() = 0; + // Called when the transaction should be bound. virtual void CreateAndBindTransaction() = 0; @@ -68,13 +86,18 @@ // Called when the upgrade transaction has finished. virtual void UpgradeTransactionFinished(bool committed) = 0; - // Called for pending tasks that we need to clear for a force close. Returns - // if the request should still execute after all the connections are - // removed. This is not called for the active request - instead, - // OnConnectionClosed is called with a nullptr |connection|. - virtual bool OnForceClose() = 0; + // Called on all pending tasks during a force close. Returns if the task + // should be pruned (removed) from the task queue during the force close. + virtual bool ShouldPruneForForceClose() = 0; + + RequestState state() const { return state_; } + + // Relevant if state() is kError. + leveldb::Status status() const { return saved_leveldb_status_; } protected: + RequestState state_ = RequestState::kNotStarted; + IndexedDBOriginStateHandle origin_state_handle_; // This is safe because IndexedDBDatabase owns this object. IndexedDBDatabase* db_; @@ -82,6 +105,10 @@ // Rawptr safe because IndexedDBConnectionCoordinator owns this object. IndexedDBConnectionCoordinator* connection_coordinator_; + TasksAvailableCallback tasks_available_callback_; + + leveldb::Status saved_leveldb_status_; + private: DISALLOW_COPY_AND_ASSIGN(ConnectionRequest); }; @@ -92,19 +119,26 @@ OpenRequest(IndexedDBOriginStateHandle origin_state_handle, IndexedDBDatabase* db, std::unique_ptr<IndexedDBPendingConnection> pending_connection, - IndexedDBConnectionCoordinator* connection_coordinator) + IndexedDBConnectionCoordinator* connection_coordinator, + + TasksAvailableCallback tasks_available_callback) : ConnectionRequest(std::move(origin_state_handle), db, - connection_coordinator), + connection_coordinator, + + std::move(tasks_available_callback)), pending_(std::move(pending_connection)) { db_->metadata_.was_cold_open = pending_->was_cold_open; } - void Perform() override { - if (db_->metadata_.id == kInvalidId) { - // The database was deleted then immediately re-opened; OpenInternal() + // Note: the |tasks_available_callback_| is NOT called here because the state + // is checked after this method. + void Perform(bool has_connections) override { + if (db_->metadata().id == kInvalidDatabaseId) { + // The database was deleted then immediately re-opened; Open() // recreates it in the backing store. - if (!db_->OpenInternal().ok()) { + saved_leveldb_status_ = db_->OpenInternal(); + if (!saved_leveldb_status_.ok()) { // TODO(jsbell): Consider including sanitized leveldb status message. base::string16 message; if (pending_->version == IndexedDBDatabaseMetadata::NO_VERSION) { @@ -117,14 +151,14 @@ } pending_->callbacks->OnError(IndexedDBDatabaseError( blink::kWebIDBDatabaseExceptionUnknownError, message)); - connection_coordinator_->RequestComplete(this); + state_ = RequestState::kError; return; } - DCHECK_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata_.version); + DCHECK_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version); } - const int64_t old_version = db_->metadata_.version; + const int64_t old_version = db_->metadata().version; int64_t& new_version = pending_->version; bool is_new_database = old_version == IndexedDBDatabaseMetadata::NO_VERSION; @@ -138,7 +172,7 @@ pending_->database_callbacks, pending_->child_process_id), db_->metadata_); - connection_coordinator_->RequestComplete(this); + state_ = RequestState::kDone; return; } @@ -150,7 +184,7 @@ pending_->database_callbacks, pending_->child_process_id), db_->metadata_); - connection_coordinator_->RequestComplete(this); + state_ = RequestState::kDone; return; } @@ -168,17 +202,18 @@ NumberToString16(pending_->version) + ASCIIToUTF16(") is less than the existing version (") + NumberToString16(db_->metadata_.version) + ASCIIToUTF16(")."))); - connection_coordinator_->RequestComplete(this); + state_ = RequestState::kDone; return; } // Requested version is higher than current version - upgrade needed. DCHECK_GT(new_version, old_version); - if (db_->HasNoConnections()) { + if (!has_connections) { std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = { {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id), ScopesLockManager::LockType::kExclusive}}; + state_ = RequestState::kPendingLocks; db_->lock_manager_->AcquireLocks( std::move(lock_requests), lock_receiver_.weak_factory.GetWeakPtr(), base::BindOnce( @@ -194,38 +229,38 @@ // "versionchange" event was ignored. DCHECK_NE(pending_->data_loss_info.status, blink::mojom::IDBDataLoss::Total); + state_ = RequestState::kPendingNoConnections; db_->SendVersionChangeToAllConnections(old_version, new_version); // When all connections have closed the upgrade can proceed. } void OnVersionChangeIgnored() const override { + DCHECK(state_ == RequestState::kPendingNoConnections); pending_->callbacks->OnBlocked(db_->metadata_.version); } void OnConnectionClosed(IndexedDBConnection* connection) override { - if (!connection) { - pending_->callbacks->OnError( - IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionAbortError, - "All connections were closed.")); - connection_coordinator_->RequestComplete(this); - return; - } // This connection closed prematurely; signal an error and complete. - if (connection && connection->callbacks() == pending_->database_callbacks) { - pending_->callbacks->OnError( - IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionAbortError, - "The connection was closed.")); - connection_coordinator_->RequestComplete(this); + if (connection == connection_ptr_for_close_comparision_) { + connection_ptr_for_close_comparision_ = nullptr; + if (!pending_->callbacks->is_complete()) { + pending_->callbacks->OnError( + IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionAbortError, + "The connection was closed.")); + } + state_ = RequestState::kDone; + tasks_available_callback_.Run(); return; } + } - if (!db_->HasNoConnections()) - return; - + void OnNoConnections() override { + DCHECK(state_ == RequestState::kPendingNoConnections); std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = { - {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id), + {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata().id), ScopesLockManager::LockType::kExclusive}}; + state_ = RequestState::kPendingLocks; db_->lock_manager_->AcquireLocks( std::move(lock_requests), lock_receiver_.weak_factory.GetWeakPtr(), base::BindOnce( @@ -237,20 +272,24 @@ // IndexedDBConnectionCoordinator::VersionChangeOperation in order to kick the // transaction into the correct state. void StartUpgrade() { + DCHECK(state_ == RequestState::kPendingLocks); + DCHECK(!lock_receiver_.locks.empty()); connection_ = db_->CreateConnection(std::move(origin_state_handle_), pending_->database_callbacks, pending_->child_process_id); - DCHECK_EQ(connection_coordinator_->connections_.count(connection_.get()), - 1UL); + DCHECK(!connection_ptr_for_close_comparision_); + connection_ptr_for_close_comparision_ = connection_.get(); + DCHECK_EQ(db_->connections().count(connection_.get()), 1UL); std::vector<int64_t> object_store_ids; + state_ = RequestState::kPendingTransactionComplete; IndexedDBTransaction* transaction = connection_->CreateTransaction( pending_->transaction_id, std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), blink::mojom::IDBTransactionMode::VersionChange, - new IndexedDBBackingStore::Transaction(db_->backing_store())); + db_->backing_store()->CreateTransaction().release()); // Save a WeakPtr<IndexedDBTransaction> for the CreateAndBindTransaction // function to use later. @@ -259,7 +298,8 @@ transaction->ScheduleTask(BindWeakOperation( &IndexedDBDatabase::VersionChangeOperation, db_->AsWeakPtr(), pending_->version, pending_->callbacks)); - transaction->locks_receiver()->locks = std::move(lock_receiver_.locks); + transaction->mutable_locks_receiver()->locks = + std::move(lock_receiver_.locks); transaction->Start(); } @@ -272,6 +312,7 @@ // Called when the upgrade transaction has started executing. void UpgradeTransactionStarted(int64_t old_version) override { + DCHECK(state_ == RequestState::kPendingTransactionComplete); DCHECK(connection_); pending_->callbacks->OnUpgradeNeeded(old_version, std::move(connection_), db_->metadata_, @@ -279,6 +320,7 @@ } void UpgradeTransactionFinished(bool committed) override { + DCHECK(state_ == RequestState::kPendingTransactionComplete); // Ownership of connection was already passed along in OnUpgradeNeeded. if (committed) { DCHECK_EQ(pending_->version, db_->metadata_.version); @@ -290,14 +332,22 @@ "Version change transaction was aborted in " "upgradeneeded event handler.")); } - connection_coordinator_->RequestComplete(this); + state_ = RequestState::kDone; + tasks_available_callback_.Run(); } - bool OnForceClose() override { - DCHECK(!connection_); + bool ShouldPruneForForceClose() override { + if (!pending_->callbacks->is_complete()) { + pending_->callbacks->OnError( + IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionAbortError, + "The connection was closed.")); + } pending_->database_callbacks->OnForcedClose(); pending_.reset(); - return false; + state_ = RequestState::kDone; + // The tasks_available_callback_ is NOT run here, because we are assuming + // the caller is doing their own cleanup & execution for ForceClose. + return true; } private: @@ -309,6 +359,10 @@ // transferred to the IndexedDBDispatcherHost via OnUpgradeNeeded. std::unique_ptr<IndexedDBConnection> connection_; + // This raw pointer is stored solely for comparison to the connection in + // OnConnectionClosed. It is not guaranteed to be pointing to a live object. + IndexedDBConnection* connection_ptr_for_close_comparision_ = nullptr; + base::WeakPtrFactory<OpenRequest> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(OpenRequest); }; @@ -320,19 +374,22 @@ IndexedDBDatabase* db, scoped_refptr<IndexedDBCallbacks> callbacks, base::OnceClosure on_database_deleted, - IndexedDBConnectionCoordinator* connection_coordinator) + IndexedDBConnectionCoordinator* connection_coordinator, + TasksAvailableCallback tasks_available_callback) : ConnectionRequest(std::move(origin_state_handle), db, - connection_coordinator), + connection_coordinator, + std::move(tasks_available_callback)), callbacks_(callbacks), on_database_deleted_(std::move(on_database_deleted)) {} - void Perform() override { - if (db_->HasNoConnections()) { + void Perform(bool has_connections) override { + if (!has_connections) { // No connections, so delete immediately. std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = { - {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id), + {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata().id), ScopesLockManager::LockType::kExclusive}}; + state_ = RequestState::kPendingLocks; db_->lock_manager_->AcquireLocks( std::move(lock_requests), lock_receiver_.AsWeakPtr(), base::BindOnce( @@ -343,22 +400,25 @@ // Front end ensures the event is not fired at connections that have // close_pending set. - const int64_t old_version = db_->metadata_.version; + const int64_t old_version = db_->metadata().version; const int64_t new_version = IndexedDBDatabaseMetadata::NO_VERSION; db_->SendVersionChangeToAllConnections(old_version, new_version); + state_ = RequestState::kPendingNoConnections; } void OnVersionChangeIgnored() const override { + DCHECK(state_ == RequestState::kPendingNoConnections); callbacks_->OnBlocked(db_->metadata_.version); } - void OnConnectionClosed(IndexedDBConnection* connection) override { - if (!db_->HasNoConnections()) - return; + void OnConnectionClosed(IndexedDBConnection* connection) override {} + void OnNoConnections() override { + DCHECK(state_ == RequestState::kPendingNoConnections); std::vector<ScopesLockManager::ScopeLockRequest> lock_requests = { - {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata_.id), + {kDatabaseRangeLockLevel, GetDatabaseLockRange(db_->metadata().id), ScopesLockManager::LockType::kExclusive}}; + state_ = RequestState::kPendingLocks; db_->lock_manager_->AcquireLocks( std::move(lock_requests), lock_receiver_.AsWeakPtr(), base::BindOnce(&IndexedDBConnectionCoordinator::DeleteRequest::DoDelete, @@ -366,7 +426,8 @@ } void DoDelete() { - Status s; + DCHECK(state_ == RequestState::kPendingLocks); + state_ = RequestState::kPendingTransactionComplete; // This is used to check if this class is still alive after the destruction // of the TransactionalLevelDBTransaction, which can synchronously cause the // system to be shut down if the disk is really bad. @@ -380,31 +441,27 @@ txn->set_commit_cleanup_complete_callback( std::move(on_database_deleted_)); } - s = db_->backing_store_->DeleteDatabase(db_->metadata_.name, txn.get()); + saved_leveldb_status_ = + db_->backing_store_->DeleteDatabase(db_->metadata_.name, txn.get()); } if (!weak_ptr) return; - if (!s.ok()) { + if (!saved_leveldb_status_.ok()) { // TODO(jsbell): Consider including sanitized leveldb status message. IndexedDBDatabaseError error(blink::kWebIDBDatabaseExceptionUnknownError, "Internal error deleting database."); callbacks_->OnError(error); - - // Calling |error_callback_| can destroy the database and connection - // coordinator, so keep a WeakPtr to avoid a UAF. - base::WeakPtr<IndexedDBConnectionCoordinator> connection_coordinator = - connection_coordinator_->AsWeakPtr(); - db_->error_callback_.Run(s, "Internal error deleting database."); - if (connection_coordinator) - connection_coordinator->RequestComplete(this); + state_ = RequestState::kError; + tasks_available_callback_.Run(); return; } int64_t old_version = db_->metadata_.version; - db_->metadata_.id = kInvalidId; + db_->metadata_.id = kInvalidDatabaseId; db_->metadata_.version = IndexedDBDatabaseMetadata::NO_VERSION; - db_->metadata_.max_object_store_id = kInvalidId; + db_->metadata_.max_object_store_id = + blink::IndexedDBObjectStoreMetadata::kInvalidId; db_->metadata_.object_stores.clear(); // Unittests (specifically the IndexedDBDatabase unittests) can have the // backing store be a nullptr, so report deleted here. @@ -412,7 +469,8 @@ std::move(on_database_deleted_).Run(); callbacks_->OnSuccess(old_version); - connection_coordinator_->RequestComplete(this); + state_ = RequestState::kDone; + tasks_available_callback_.Run(); } void CreateAndBindTransaction() override { NOTREACHED(); } @@ -422,7 +480,7 @@ void UpgradeTransactionFinished(bool committed) override { NOTREACHED(); } // The delete requests should always be run during force close. - bool OnForceClose() override { return true; } + bool ShouldPruneForForceClose() override { return false; } private: ScopesLocksHolder lock_receiver_; @@ -434,152 +492,141 @@ }; IndexedDBConnectionCoordinator::IndexedDBConnectionCoordinator( - IndexedDBDatabase* db) - : db_(db) {} + IndexedDBDatabase* db, + TasksAvailableCallback tasks_available_callback) + : db_(db), tasks_available_callback_(std::move(tasks_available_callback)) {} IndexedDBConnectionCoordinator::~IndexedDBConnectionCoordinator() = default; void IndexedDBConnectionCoordinator::ScheduleOpenConnection( IndexedDBOriginStateHandle origin_state_handle, std::unique_ptr<IndexedDBPendingConnection> connection) { - AppendRequest(std::make_unique<OpenRequest>( - std::move(origin_state_handle), db_, std::move(connection), this)); + request_queue_.push(std::make_unique<OpenRequest>( + std::move(origin_state_handle), db_, std::move(connection), this, + tasks_available_callback_)); + tasks_available_callback_.Run(); } void IndexedDBConnectionCoordinator::ScheduleDeleteDatabase( IndexedDBOriginStateHandle origin_state_handle, scoped_refptr<IndexedDBCallbacks> callbacks, base::OnceClosure on_deletion_complete) { - AppendRequest(std::make_unique<DeleteRequest>( + request_queue_.push(std::make_unique<DeleteRequest>( std::move(origin_state_handle), db_, callbacks, - std::move(on_deletion_complete), this)); + std::move(on_deletion_complete), this, tasks_available_callback_)); + tasks_available_callback_.Run(); } -void IndexedDBConnectionCoordinator::ForceClose() { - force_closing_ = true; +void IndexedDBConnectionCoordinator::PruneTasksForForceClose() { // Remove all pending requests that don't want to execute during force close // (open requests). base::queue<std::unique_ptr<ConnectionRequest>> requests_to_still_run; - while (!pending_requests_.empty()) { + while (!request_queue_.empty()) { std::unique_ptr<ConnectionRequest> request = - std::move(pending_requests_.front()); - pending_requests_.pop(); - if (request->OnForceClose()) + std::move(request_queue_.front()); + request_queue_.pop(); + if (!request->ShouldPruneForForceClose()) requests_to_still_run.push(std::move(request)); } - if (!requests_to_still_run.empty()) - pending_requests_ = std::move(requests_to_still_run); - - // Since |force_closing_| is true, there are no re-entry modifications to - // this list by ConnectionClosed(). - while (!connections_.empty()) { - IndexedDBConnection* connection = *connections_.begin(); - connection->CloseAndReportForceClose(); - connections_.erase(connection); - } - force_closing_ = false; - - // OnConnectionClosed usually synchronously calls RequestComplete. - if (active_request_) - active_request_->OnConnectionClosed(nullptr); - else - db_->ProcessRequestQueueAndMaybeRelease(); + request_queue_ = std::move(requests_to_still_run); } void IndexedDBConnectionCoordinator::OnConnectionClosed( IndexedDBConnection* connection) { - if (force_closing_) - return; - DCHECK(connections().count(connection)); - DCHECK(connection->IsConnected()); - DCHECK(connection->transactions().empty()); DCHECK(connection->database().get() == db_); - // Abort transactions before removing the connection; aborting may complete - // an upgrade, and thus allow the next open/delete requests to proceed. The - // new active_request_ should see the old connection count until explicitly - // notified below. - connections_.erase(connection); + if (!request_queue_.empty()) + request_queue_.front()->OnConnectionClosed(connection); +} - base::WeakPtr<IndexedDBDatabase> database = db_->AsWeakPtr(); - // Notify the active request, which may need to do cleanup or proceed with - // the operation. This may trigger other work, such as more connections or - // deletions, so |active_request_| itself may change. - if (active_request_) - active_request_->OnConnectionClosed(connection); - - if (database) - database->ProcessRequestQueueAndMaybeRelease(); +void IndexedDBConnectionCoordinator::OnNoConnections() { + if (request_queue_.empty() || + request_queue_.front()->state() != RequestState::kPendingNoConnections) { + return; + } + request_queue_.front()->OnNoConnections(); } // TODO(dmurph): Attach an ID to the connection change events to prevent // mis-propogation to the wrong connection request. void IndexedDBConnectionCoordinator::OnVersionChangeIgnored() { - if (active_request_) - active_request_->OnVersionChangeIgnored(); + if (request_queue_.empty() || + request_queue_.front()->state() != RequestState::kPendingNoConnections) { + return; + } + request_queue_.front()->OnVersionChangeIgnored(); } void IndexedDBConnectionCoordinator::OnUpgradeTransactionStarted( int64_t old_version) { - DCHECK(active_request_); - active_request_->UpgradeTransactionStarted(old_version); + if (request_queue_.empty() || request_queue_.front()->state() != + RequestState::kPendingTransactionComplete) { + return; + } + request_queue_.front()->UpgradeTransactionStarted(old_version); } void IndexedDBConnectionCoordinator::CreateAndBindUpgradeTransaction() { - DCHECK(active_request_); - active_request_->CreateAndBindTransaction(); + if (request_queue_.empty() || request_queue_.front()->state() != + RequestState::kPendingTransactionComplete) { + return; + } + request_queue_.front()->CreateAndBindTransaction(); } void IndexedDBConnectionCoordinator::OnUpgradeTransactionFinished( bool committed) { - if (active_request_ && !force_closing_) - active_request_->UpgradeTransactionFinished(committed); -} - -void IndexedDBConnectionCoordinator::ProcessRequestQueue() { - // Don't run re-entrantly to avoid exploding call stacks for requests that - // complete synchronously. The loop below will process requests until one is - // blocked. - if (processing_pending_requests_) + if (request_queue_.empty() || request_queue_.front()->state() != + RequestState::kPendingTransactionComplete) { return; - processing_pending_requests_ = true; - // If the active request completed synchronously, keep going. - while (!active_request_ && !pending_requests_.empty()) { - active_request_ = std::move(pending_requests_.front()); - pending_requests_.pop(); - active_request_->Perform(); } - processing_pending_requests_ = false; + request_queue_.front()->UpgradeTransactionFinished(committed); } -void IndexedDBConnectionCoordinator::AddConnection( - IndexedDBConnection* connection) { - connections_.insert(connection); +std::tuple<IndexedDBConnectionCoordinator::ExecuteTaskResult, leveldb::Status> +IndexedDBConnectionCoordinator::ExecuteTask(bool has_connections) { + if (request_queue_.empty()) + return {ExecuteTaskResult::kDone, leveldb::Status()}; + + auto& request = request_queue_.front(); + if (request->state() == RequestState::kNotStarted) { + request->Perform(has_connections); + DCHECK(request->state() != RequestState::kNotStarted); + } + + switch (request->state()) { + case RequestState::kNotStarted: + NOTREACHED(); + return {ExecuteTaskResult::kError, leveldb::Status::OK()}; + case RequestState::kPendingNoConnections: + case RequestState::kPendingLocks: + case RequestState::kPendingTransactionComplete: + return {ExecuteTaskResult::kPendingAsyncWork, leveldb::Status()}; + case RequestState::kDone: + request_queue_.pop(); + return {request_queue_.empty() ? ExecuteTaskResult::kDone + : ExecuteTaskResult::kMoreTasks, + leveldb::Status::OK()}; + case RequestState::kError: { + leveldb::Status status = request->status(); + request_queue_.pop(); + return {ExecuteTaskResult::kError, status}; + } + } + NOTREACHED(); } -void IndexedDBConnectionCoordinator::AppendRequest( - std::unique_ptr<ConnectionRequest> request) { - pending_requests_.push(std::move(request)); - - // This may be an unrelated transaction finishing while waiting for - // connections to close, or the actual upgrade transaction from an active - // request. Notify the active request if it's the latter. - if (!active_request_) - db_->ProcessRequestQueueAndMaybeRelease(); +size_t IndexedDBConnectionCoordinator::ActiveOpenDeleteCount() const { + return request_queue_.empty() ? 0 : 1; } -void IndexedDBConnectionCoordinator::RequestComplete( - ConnectionRequest* request) { - DCHECK_EQ(request, active_request_.get()); - // Destroying a request can cause this instance to be destroyed (through - // ConnectionClosed), so hold a WeakPtr. - base::WeakPtr<IndexedDBDatabase> weak_ptr = db_->AsWeakPtr(); - active_request_.reset(); - - if (!weak_ptr) - return; - - db_->ProcessRequestQueueAndMaybeRelease(); +// Number of open/delete calls that are waiting their turn. +size_t IndexedDBConnectionCoordinator::PendingOpenDeleteCount() const { + if (request_queue_.empty()) + return 0; + if (request_queue_.front()->state() == RequestState::kNotStarted) + return request_queue_.size(); + return request_queue_.size() - 1; } } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_connection_coordinator.h b/content/browser/indexed_db/indexed_db_connection_coordinator.h index 91e7445..3a54799 100644 --- a/content/browser/indexed_db/indexed_db_connection_coordinator.h +++ b/content/browser/indexed_db/indexed_db_connection_coordinator.h
@@ -6,13 +6,16 @@ #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CONNECTION_COORDINATOR_H_ #include <memory> +#include <tuple> #include "base/callback.h" #include "base/containers/queue.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/list_set.h" +#include "content/common/content_export.h" #include "third_party/leveldatabase/src/include/leveldb/status.h" namespace content { @@ -21,12 +24,14 @@ class IndexedDBDatabase; struct IndexedDBPendingConnection; -class IndexedDBConnectionCoordinator { +class CONTENT_EXPORT IndexedDBConnectionCoordinator { public: - static const int64_t kInvalidId = 0; + static const int64_t kInvalidDatabaseId = 0; static const int64_t kMinimumIndexId = 30; - explicit IndexedDBConnectionCoordinator(IndexedDBDatabase* db); + IndexedDBConnectionCoordinator( + IndexedDBDatabase* db, + TasksAvailableCallback tasks_available_callback); ~IndexedDBConnectionCoordinator(); void ScheduleOpenConnection( @@ -37,11 +42,14 @@ scoped_refptr<IndexedDBCallbacks> callbacks, base::OnceClosure on_deletion_complete); - // Returns if the caller should process the request queue. - void ForceClose(); + // Call this method to prune any tasks that don't want to be run during + // force close. + void PruneTasksForForceClose(); void OnConnectionClosed(IndexedDBConnection* connection); + void OnNoConnections(); + // Ack that one of the connections notified with a "versionchange" event did // not promptly close. Therefore a "blocked" event should be fired at the // pending connection. @@ -53,36 +61,30 @@ void OnUpgradeTransactionFinished(bool committed); - // If there is no active request, grab a new one from the pending queue and - // start it. Afterwards, possibly release the database by calling - // MaybeReleaseDatabase(). - void ProcessRequestQueue(); + enum class ExecuteTaskResult { + // There are more tasks to run, so ExecuteTask() should be called again. + kMoreTasks, + // There are tasks but they are waiting on async work to complete. No more + // calls to ExecuteTask() are necessary. + kPendingAsyncWork, + // There was an error executing a task - see the status. The offending task + // was removed, and the caller can choose to continue executing tasks if + // they want. + kError, + // There are no more tasks to run. + kDone, + }; + std::tuple<ExecuteTaskResult, leveldb::Status> ExecuteTask( + bool has_connections); - bool processing_pending_requests() const { - return processing_pending_requests_; - } - - bool force_closing() const { return force_closing_; } - - const list_set<IndexedDBConnection*>& connections() const { - return connections_; - } - - void AddConnection(IndexedDBConnection* connection); + bool HasTasks() const { return !request_queue_.empty(); } // Number of active open/delete calls (running or blocked on other // connections). - size_t ActiveOpenDeleteCount() const { return active_request_ ? 1 : 0; } + size_t ActiveOpenDeleteCount() const; // Number of open/delete calls that are waiting their turn. - size_t PendingOpenDeleteCount() const { return pending_requests_.size(); } - - // Number of connections that have progressed passed initial open call. - size_t ConnectionCount() const { return connections_.size(); } - - bool HasActiveRequest() { return !!active_request_; } - - bool HasPendingRequests() { return !pending_requests_.empty(); } + size_t PendingOpenDeleteCount() const; base::WeakPtr<IndexedDBConnectionCoordinator> AsWeakPtr() { return weak_factory_.GetWeakPtr(); @@ -94,39 +96,11 @@ class OpenRequest; class DeleteRequest; - // Called internally when an open or delete request comes in. Processes - // the queue immediately if there are no other requests. - void AppendRequest(std::unique_ptr<ConnectionRequest> request); - - // Called by requests when complete. The request will be freed, so the - // request must do no other work after calling this. If there are pending - // requests, the queue will be synchronously processed. - void RequestComplete(ConnectionRequest* request); - IndexedDBDatabase* db_; - list_set<IndexedDBConnection*> connections_; + TasksAvailableCallback tasks_available_callback_; - // During ForceClose(), the internal state can be inconsistent during cleanup, - // specifically for ConnectionClosed() and MaybeReleaseDatabase(). Keeping - // track of whether the code is currently in the ForceClose() method helps - // ensure that the state stays consistent. - bool force_closing_ = false; - - // This holds the first open or delete request that is currently being - // processed. The request has already broadcast OnVersionChange if - // necessary. - std::unique_ptr<ConnectionRequest> active_request_; - - // This holds open or delete requests that are waiting for the active - // request to be completed. The requests have not yet broadcast - // OnVersionChange (if necessary). - base::queue<std::unique_ptr<ConnectionRequest>> pending_requests_; - - // The |processing_pending_requests_| flag is set while ProcessRequestQueue() - // is executing. It prevents rentrant calls if the active request completes - // synchronously. - bool processing_pending_requests_ = false; + base::queue<std::unique_ptr<ConnectionRequest>> request_queue_; // |weak_factory_| is used for all callback uses. base::WeakPtrFactory<IndexedDBConnectionCoordinator> weak_factory_{this};
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index b5b39fca..89f857cd 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -139,8 +139,7 @@ IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, IndexedDBClassFactory* class_factory, - ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager) @@ -154,10 +153,8 @@ class_factory_(class_factory), metadata_coding_(std::move(metadata_coding)), lock_manager_(transaction_lock_manager), - error_callback_(std::move(error_callback)), - destroy_me_(std::move(destroy_me)), - connection_coordinator_(this) { - DCHECK(destroy_me_); + tasks_available_callback_(tasks_available_callback), + connection_coordinator_(this, tasks_available_callback) { DCHECK(factory != nullptr); } @@ -185,12 +182,117 @@ } lock_manager_->AcquireLocks( std::move(lock_requests), - transaction->locks_receiver()->weak_factory.GetWeakPtr(), + transaction->mutable_locks_receiver()->weak_factory.GetWeakPtr(), base::BindOnce(&IndexedDBTransaction::Start, transaction->AsWeakPtr())); } -void IndexedDBDatabase::ForceClose() { - connection_coordinator_.ForceClose(); +std::tuple<IndexedDBDatabase::RunTasksResult, leveldb::Status> +IndexedDBDatabase::RunTasks() { + // First execute any pending tasks in the connection coordinator. + IndexedDBConnectionCoordinator::ExecuteTaskResult task_state; + leveldb::Status status; + do { + std::tie(task_state, status) = + connection_coordinator_.ExecuteTask(!connections_.empty()); + } while (task_state == + IndexedDBConnectionCoordinator::ExecuteTaskResult::kMoreTasks); + + if (task_state == IndexedDBConnectionCoordinator::ExecuteTaskResult::kError) + return {RunTasksResult::kError, status}; + + bool transactions_removed = true; + + // Finally, execute transactions that have tasks & remove those that are + // complete. + while (transactions_removed) { + transactions_removed = false; + IndexedDBTransaction* finished_upgrade_transaction = nullptr; + bool upgrade_transaction_commmitted = false; + for (IndexedDBConnection* connection : connections_) { + std::vector<int64_t> txns_to_remove; + for (const auto& id_txn_pair : connection->transactions()) { + IndexedDBTransaction* txn = id_txn_pair.second.get(); + // Determine if the transaction's task queue should be processed. + switch (txn->state()) { + case IndexedDBTransaction::FINISHED: + if (txn->mode() == + blink::mojom::IDBTransactionMode::VersionChange) { + finished_upgrade_transaction = txn; + upgrade_transaction_commmitted = !txn->aborted(); + } + txns_to_remove.push_back(id_txn_pair.first); + continue; + case IndexedDBTransaction::CREATED: + continue; + case IndexedDBTransaction::STARTED: + case IndexedDBTransaction::COMMITTING: + break; + } + + // Process the queue for transactions that are STARTED or COMMITTING. + // Add transactions that can be removed to a queue. + IndexedDBTransaction::RunTasksResult task_result; + leveldb::Status transaction_status; + std::tie(task_result, transaction_status) = txn->RunTasks(); + switch (task_result) { + case IndexedDBTransaction::RunTasksResult::kError: + return {RunTasksResult::kError, transaction_status}; + case IndexedDBTransaction::RunTasksResult::kCommitted: + case IndexedDBTransaction::RunTasksResult::kAborted: + if (txn->mode() == + blink::mojom::IDBTransactionMode::VersionChange) { + DCHECK(!finished_upgrade_transaction); + finished_upgrade_transaction = txn; + upgrade_transaction_commmitted = !txn->aborted(); + } + txns_to_remove.push_back(txn->id()); + break; + case IndexedDBTransaction::RunTasksResult::kNotFinished: + continue; + } + } + // Do the removals. + for (int64_t id : txns_to_remove) { + connection->RemoveTransaction(id); + transactions_removed = true; + } + if (finished_upgrade_transaction) { + connection_coordinator_.OnUpgradeTransactionFinished( + upgrade_transaction_commmitted); + } + } + } + if (CanBeDestroyed()) + return {RunTasksResult::kCanBeDestroyed, leveldb::Status::OK()}; + return {RunTasksResult::kDone, leveldb::Status::OK()}; +} + +leveldb::Status IndexedDBDatabase::ForceCloseAndRunTasks() { + leveldb::Status status; + force_closing_ = true; + for (IndexedDBConnection* connection : connections_) { + connection->CloseAndReportForceClose(); + } + connections_.clear(); + connection_coordinator_.PruneTasksForForceClose(); + connection_coordinator_.OnNoConnections(); + + // Execute any pending tasks in the connection coordinator. + IndexedDBConnectionCoordinator::ExecuteTaskResult task_state; + do { + std::tie(task_state, status) = connection_coordinator_.ExecuteTask(false); + DCHECK(task_state != + IndexedDBConnectionCoordinator::ExecuteTaskResult::kPendingAsyncWork) + << "There are no more connections, so all tasks should be able to " + "complete synchronously."; + } while ( + task_state != IndexedDBConnectionCoordinator::ExecuteTaskResult::kDone && + task_state != IndexedDBConnectionCoordinator::ExecuteTaskResult::kError); + DCHECK(connections_.empty()); + force_closing_ = false; + if (CanBeDestroyed()) + tasks_available_callback_.Run(); + return status; } void IndexedDBDatabase::Commit(IndexedDBTransaction* transaction) { @@ -199,12 +301,7 @@ // been dispatched to the frontend, so it will find out about that // asynchronously. if (transaction) { - // The database can be destroyed in the call to Commit(), so save a copy of - // the error callback in case of an error. - auto error_callback_copy = error_callback_; - Status result = transaction->Commit(); - if (!result.ok()) - error_callback_copy.Run(result, nullptr); + transaction->SetCommitFlag(); } } @@ -1573,23 +1670,6 @@ metadata_.version, &metadata_); } -void IndexedDBDatabase::ProcessRequestQueueAndMaybeRelease() { - // Don't run re-entrantly to avoid exploding call stacks for requests that - // complete synchronously. The loop below will process requests until one is - // blocked. - if (connection_coordinator_.processing_pending_requests()) - return; - connection_coordinator_.ProcessRequestQueue(); - MaybeReleaseDatabase(); -} - -void IndexedDBDatabase::MaybeReleaseDatabase() { - if (!connection_coordinator_.HasActiveRequest() && - !connection_coordinator_.HasPendingRequests() && connections().empty() && - !connection_coordinator_.force_closing()) - std::move(destroy_me_).Run(); -} - std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection( IndexedDBOriginStateHandle origin_state_handle, scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, @@ -1602,8 +1682,8 @@ weak_factory_.GetWeakPtr()), base::BindOnce(&IndexedDBDatabase::ConnectionClosed, weak_factory_.GetWeakPtr()), - error_callback_, database_callbacks); - connection_coordinator_.AddConnection(connection.get()); + database_callbacks); + connections_.insert(connection.get()); backing_store_->GrantChildProcessPermissions(child_process_id); return connection; } @@ -1613,20 +1693,32 @@ } bool IndexedDBDatabase::HasNoConnections() const { - return connection_coordinator_.force_closing() || connections().empty(); + return force_closing_ || connections().empty(); } void IndexedDBDatabase::SendVersionChangeToAllConnections(int64_t old_version, int64_t new_version) { - if (connection_coordinator_.force_closing()) + if (force_closing_) return; for (const auto* connection : connections()) connection->callbacks()->OnVersionChange(old_version, new_version); } void IndexedDBDatabase::ConnectionClosed(IndexedDBConnection* connection) { - IDB_TRACE("IndexedDBDatabase::Close"); + IDB_TRACE("IndexedDBDatabase::ConnectionClosed"); + // Ignore connection closes during force close to prevent re-entry. + if (force_closing_) + return; + connections_.erase(connection); connection_coordinator_.OnConnectionClosed(connection); + if (connections_.empty()) + connection_coordinator_.OnNoConnections(); + if (CanBeDestroyed()) + tasks_available_callback_.Run(); +} + +bool IndexedDBDatabase::CanBeDestroyed() { + return !connection_coordinator_.HasTasks() && connections_.empty(); } } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h index 02a5ce4..7f65d75f 100644 --- a/content/browser/indexed_db/indexed_db_database.h +++ b/content/browser/indexed_db/indexed_db_database.h
@@ -30,6 +30,7 @@ #include "content/browser/indexed_db/indexed_db_observer.h" #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" #include "content/browser/indexed_db/indexed_db_pending_connection.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/indexed_db_value.h" #include "content/browser/indexed_db/list_set.h" #include "content/browser/indexed_db/scopes/scopes_lock_manager.h" @@ -88,21 +89,23 @@ } const list_set<IndexedDBConnection*>& connections() const { - return connection_coordinator_.connections(); + return connections_; } - - base::WeakPtr<IndexedDBDatabase> AsWeakPtr() { - return weak_factory_.GetWeakPtr(); + TasksAvailableCallback tasks_available_callback() { + return tasks_available_callback_; } // TODO(dmurph): Remove this method and have transactions be directly // scheduled using the lock manager. + + enum class RunTasksResult { kDone, kError, kCanBeDestroyed }; + std::tuple<RunTasksResult, leveldb::Status> RunTasks(); void RegisterAndScheduleTransaction(IndexedDBTransaction* transaction); // The database object (this object) must be kept alive for the duration of // this call. This means the caller should own an IndexedDBOriginStateHandle // while caling this methods. - void ForceClose(); + leveldb::Status ForceCloseAndRunTasks(); void Commit(IndexedDBTransaction* transaction); @@ -146,9 +149,7 @@ // database: // Number of connections that have progressed passed initial open call. - size_t ConnectionCount() const { - return connection_coordinator_.ConnectionCount(); - } + size_t ConnectionCount() const { return connections_.size(); } // Number of active open/delete calls (running or blocked on other // connections). @@ -306,7 +307,13 @@ bool IsObjectStoreIdInMetadataAndIndexNotInMetadata(int64_t object_store_id, int64_t index_id) const; - ErrorCallback error_callback() { return error_callback_; } + base::WeakPtr<IndexedDBDatabase> AsWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + + void AddConnectionForTesting(IndexedDBConnection* connection) { + connections_.insert(connection); + } protected: friend class IndexedDBTransaction; @@ -319,8 +326,7 @@ IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, IndexedDBClassFactory* class_factory, - ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager); @@ -370,6 +376,8 @@ // has any transaction objects. void ConnectionClosed(IndexedDBConnection* connection); + bool CanBeDestroyed(); + // Safe because the IndexedDBBackingStore is owned by the same object which // owns us, the IndexedDBPerOriginFactory. IndexedDBBackingStore* backing_store_; @@ -384,13 +392,11 @@ ScopesLockManager* lock_manager_; int64_t transaction_count_ = 0; - // Called when a backing store operation has failed. The database will be - // closed (IndexedDBFactory::ForceClose) during this call. This should NOT - // be used in an method scheduled as a transaction operation. - ErrorCallback error_callback_; + list_set<IndexedDBConnection*> connections_; - // Calling this closure will destroy this object. - base::OnceClosure destroy_me_; + TasksAvailableCallback tasks_available_callback_; + + bool force_closing_ = false; IndexedDBConnectionCoordinator connection_coordinator_;
diff --git a/content/browser/indexed_db/indexed_db_database_callbacks.cc b/content/browser/indexed_db/indexed_db_database_callbacks.cc index 9e97a891..5acaefb 100644 --- a/content/browser/indexed_db/indexed_db_database_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_database_callbacks.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/task/post_task.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_database_error.h" #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" @@ -37,6 +38,10 @@ IndexedDBDatabaseCallbacks::~IndexedDBDatabaseCallbacks() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Transfer |context_| ownership to a new task to prevent re-entrancy through + // IndexedDBFactory::ContextDestroyed. + base::SequencedTaskRunnerHandle::Get()->ReleaseSoon( + FROM_HERE, std::move(indexed_db_context_)); } void IndexedDBDatabaseCallbacks::OnForcedClose() {
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc index 6787660..68a5dc5e1 100644 --- a/content/browser/indexed_db/indexed_db_database_unittest.cc +++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -69,20 +69,40 @@ std::tie(db_, s) = IndexedDBClassFactory::Get()->CreateIndexedDBDatabase( ASCIIToUTF16("db"), backing_store_.get(), factory_.get(), - GetErrorCallback(), base::BindLambdaForTesting([&]() { - db_.reset(); - metadata_coding_ = nullptr; - }), + base::BindRepeating(&IndexedDBDatabaseTest::RunTasksForDatabase, + weak_factory_.GetWeakPtr(), true), std::move(metadata_coding), IndexedDBDatabase::Identifier(), &lock_manager_); ASSERT_TRUE(s.ok()); } - IndexedDBTransaction::ErrorCallback GetErrorCallback() { - return base::BindLambdaForTesting( - [&](leveldb::Status, const char*) { error_called_ = true; }); + void RunTasksForDatabase(bool async) { + if (!db_) + return; + if (async) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&IndexedDBDatabaseTest::RunTasksForDatabase, + weak_factory_.GetWeakPtr(), false)); + return; + } + IndexedDBDatabase::RunTasksResult result; + leveldb::Status status; + std::tie(result, status) = db_->RunTasks(); + switch (result) { + case IndexedDBDatabase::RunTasksResult::kDone: + return; + case IndexedDBDatabase::RunTasksResult::kError: + error_called_ = true; + return; + case IndexedDBDatabase::RunTasksResult::kCanBeDestroyed: + db_.reset(); + metadata_coding_ = nullptr; + return; + } } + void RunPostedTasks() { base::RunLoop().RunUntilIdle(); } + protected: std::unique_ptr<IndexedDBFakeBackingStore> backing_store_; std::unique_ptr<MockIndexedDBFactory> factory_; @@ -93,6 +113,8 @@ private: TestBrowserThreadBundle thread_bundle_; DisjointRangeLockManager lock_manager_; + + base::WeakPtrFactory<IndexedDBDatabaseTest> weak_factory_{this}; }; TEST_F(IndexedDBDatabaseTest, ConnectionLifecycle) { @@ -109,6 +131,7 @@ std::move(create_transaction_callback1))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection1)); + RunPostedTasks(); scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks()); scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2( @@ -123,13 +146,18 @@ std::move(create_transaction_callback2))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection2)); + RunPostedTasks(); + EXPECT_TRUE(request1->connection()); request1->connection()->CloseAndReportForceClose(); EXPECT_FALSE(request1->connection()->IsConnected()); + EXPECT_TRUE(request2->connection()); request2->connection()->CloseAndReportForceClose(); EXPECT_FALSE(request2->connection()->IsConnected()); + RunPostedTasks(); + EXPECT_FALSE(db_); } @@ -147,6 +175,8 @@ std::move(create_transaction_callback))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection)); + RunPostedTasks(); + EXPECT_EQ(db_.get(), request->connection()->database().get()); const int64_t transaction_id = 123; @@ -204,6 +234,7 @@ std::move(create_transaction_callback1))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL); @@ -214,6 +245,7 @@ db_->ScheduleDeleteDatabase( IndexedDBOriginStateHandle(), request2, base::BindLambdaForTesting([&]() { deleted = true; })); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL); @@ -225,7 +257,9 @@ EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL); - db_->ForceClose(); + db_->ForceCloseAndRunTasks(); + + RunPostedTasks(); EXPECT_FALSE(db_); EXPECT_TRUE(deleted); @@ -248,6 +282,7 @@ kDatabaseVersion, std::move(create_transaction_callback1))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection1)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); @@ -266,6 +301,7 @@ kDatabaseVersion, std::move(create_transaction_callback2))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection2)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); @@ -284,27 +320,24 @@ kDatabaseVersion, std::move(create_transaction_callback3))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection3)); + RunPostedTasks(); - // This causes the active request to call OnUpgradeNeeded on its callbacks. - // The Abort() triggered by ForceClose() assumes that the transaction was - // started and passed the connection along to the front end. - db_->CallUpgradeTransactionStartedForTesting( - IndexedDBDatabaseMetadata::DEFAULT_VERSION); EXPECT_TRUE(request1->upgrade_called()); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); EXPECT_EQ(db_->PendingOpenDeleteCount(), 2UL); - db_->ForceClose(); + db_->ForceCloseAndRunTasks(); + RunPostedTasks(); EXPECT_FALSE(db_); EXPECT_TRUE(callbacks1->forced_close_called()); EXPECT_TRUE(request1->error_called()); EXPECT_TRUE(callbacks2->forced_close_called()); - EXPECT_FALSE(request2->error_called()); + EXPECT_TRUE(request2->error_called()); EXPECT_TRUE(callbacks3->forced_close_called()); - EXPECT_FALSE(request3->error_called()); + EXPECT_TRUE(request3->error_called()); } TEST_F(IndexedDBDatabaseTest, ForceDelete) { @@ -321,6 +354,7 @@ std::move(create_transaction_callback1))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL); @@ -331,8 +365,10 @@ db_->ScheduleDeleteDatabase( IndexedDBOriginStateHandle(), request2, base::BindLambdaForTesting([&]() { deleted = true; })); + RunPostedTasks(); EXPECT_FALSE(deleted); - db_->ForceClose(); + db_->ForceCloseAndRunTasks(); + RunPostedTasks(); EXPECT_FALSE(db_); EXPECT_TRUE(deleted); EXPECT_FALSE(request2->blocked_called()); @@ -355,6 +391,7 @@ std::move(create_transaction_callback1))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL); @@ -373,12 +410,14 @@ std::move(create_transaction_callback2))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection2)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL); - db_->ForceClose(); + db_->ForceCloseAndRunTasks(); + RunPostedTasks(); EXPECT_FALSE(db_); } @@ -397,6 +436,7 @@ std::move(create_transaction_callback1)); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection)); + RunPostedTasks(); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL); @@ -413,20 +453,22 @@ std::move(create_transaction_callback2))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection2)); + RunPostedTasks(); bool deleted = false; auto request3 = base::MakeRefCounted<MockCallbacks>(); db_->ScheduleDeleteDatabase( IndexedDBOriginStateHandle(), request3, base::BindLambdaForTesting([&]() { deleted = true; })); + RunPostedTasks(); EXPECT_FALSE(deleted); EXPECT_EQ(db_->ConnectionCount(), 1UL); EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL); EXPECT_EQ(db_->PendingOpenDeleteCount(), 1UL); - db_->ForceClose(); - + db_->ForceCloseAndRunTasks(); + RunPostedTasks(); EXPECT_TRUE(deleted); EXPECT_FALSE(db_); } @@ -450,10 +492,9 @@ leveldb::Status s; std::tie(db_, s) = IndexedDBClassFactory::Get()->CreateIndexedDBDatabase( ASCIIToUTF16("db"), backing_store_.get(), factory_.get(), - GetErrorCallback(), base::BindLambdaForTesting([&]() { - db_.reset(); - metadata_coding_ = nullptr; - }), + base::BindRepeating( + &IndexedDBDatabaseOperationTest::RunTasksForDatabase, + base::Unretained(this), true), std::move(metadata_coding), IndexedDBDatabase::Identifier(), &lock_manager_); ASSERT_TRUE(s.ok()); @@ -470,8 +511,10 @@ std::move(create_transaction_callback1))); db_->ScheduleOpenConnection(IndexedDBOriginStateHandle(), std::move(connection)); + RunPostedTasks(); EXPECT_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version); + EXPECT_TRUE(request_->connection()); transaction_ = request_->connection()->CreateTransaction( transaction_id, std::set<int64_t>() /*scope*/, blink::mojom::IDBTransactionMode::VersionChange, @@ -487,13 +530,34 @@ RunPostedTasks(); } - void RunPostedTasks() { base::RunLoop().RunUntilIdle(); } - - IndexedDBTransaction::ErrorCallback GetErrorCallback() { - return base::BindLambdaForTesting( - [&](leveldb::Status, const char*) { error_called_ = true; }); + void RunTasksForDatabase(bool async) { + if (!db_) + return; + if (async) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&IndexedDBDatabaseOperationTest::RunTasksForDatabase, + base::Unretained(this), false)); + return; + } + IndexedDBDatabase::RunTasksResult result; + leveldb::Status status; + std::tie(result, status) = db_->RunTasks(); + switch (result) { + case IndexedDBDatabase::RunTasksResult::kDone: + return; + case IndexedDBDatabase::RunTasksResult::kError: + error_called_ = true; + return; + case IndexedDBDatabase::RunTasksResult::kCanBeDestroyed: + db_.reset(); + metadata_coding_ = nullptr; + return; + } } + void RunPostedTasks() { base::RunLoop().RunUntilIdle(); } + private: // Needs to outlive |db_|. content::TestBrowserThreadBundle thread_bundle_; @@ -523,8 +587,9 @@ store_id, ASCIIToUTF16("store"), IndexedDBKeyPath(), false /*auto_increment*/, transaction_); EXPECT_TRUE(s.ok()); - s = transaction_->Commit(); - EXPECT_TRUE(s.ok()); + transaction_->SetCommitFlag(); + RunPostedTasks(); + EXPECT_FALSE(error_called_); EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); } @@ -544,8 +609,9 @@ EXPECT_EQ( 1ULL, db_->metadata().object_stores.find(store_id)->second.indexes.size()); - s = transaction_->Commit(); - EXPECT_TRUE(s.ok()); + transaction_->SetCommitFlag(); + RunPostedTasks(); + EXPECT_FALSE(error_called_); EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); EXPECT_EQ( 1ULL, @@ -571,8 +637,8 @@ false /*auto_increment*/, transaction_); EXPECT_TRUE(s.ok()); EXPECT_EQ(1ULL, db_->metadata().object_stores.size()); - s = transaction_->Commit(); - EXPECT_FALSE(s.ok()); + transaction_->SetCommitFlag(); + RunPostedTasks(); EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); } @@ -592,8 +658,9 @@ EXPECT_EQ( 1ULL, db_->metadata().object_stores.find(store_id)->second.indexes.size()); - s = transaction_->Commit(); - EXPECT_FALSE(s.ok()); + transaction_->SetCommitFlag(); + RunPostedTasks(); + EXPECT_TRUE(error_called_); EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); } @@ -627,7 +694,9 @@ EXPECT_EQ(0ULL, db_->metadata().object_stores.size()); - s = transaction_->Commit(); // Cleans up the object hierarchy. + transaction_->SetCommitFlag(); + RunPostedTasks(); + EXPECT_FALSE(error_called_); EXPECT_TRUE(s.ok()); }
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc index c4dd860a..1eb52da5 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -199,6 +199,12 @@ base::OnTaskRunnerDeleter(context_impl_->TaskRunner())) {} void TearDown() override { + // Cycle the IndexedDBTaskQueue to remove all IDB tasks. + { + base::RunLoop loop; + context_impl_->TaskRunner()->PostTask(FROM_HERE, loop.QuitClosure()); + loop.Run(); + } base::RunLoop loop; context_impl_->TaskRunner()->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc index 55c4592..42ed4480 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -36,6 +36,7 @@ #include "content/browser/indexed_db/indexed_db_origin_state.h" #include "content/browser/indexed_db/indexed_db_pre_close_task_queue.h" #include "content/browser/indexed_db/indexed_db_reporting.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/indexed_db_tombstone_sweeper.h" #include "content/browser/indexed_db/indexed_db_tracing.h" #include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" @@ -276,9 +277,9 @@ std::unique_ptr<IndexedDBDatabase> database; std::tie(database, s) = indexed_db_class_factory_->CreateIndexedDBDatabase( name, factory->backing_store(), this, - base::BindRepeating(&IndexedDBFactoryImpl::OnDatabaseError, - weak_factory_.GetWeakPtr(), origin), - factory->CreateDatabaseDeleteClosure(name), + base::BindRepeating(&IndexedDBFactoryImpl::MaybeRunTasksForOrigin, + origin_state_destruction_weak_factory_.GetWeakPtr(), + origin), std::make_unique<IndexedDBMetadataCoding>(), std::move(unique_identifier), factory->lock_manager()); if (!database.get()) { @@ -331,8 +332,8 @@ std::move(origin_state_handle), callbacks, base::BindOnce(&IndexedDBFactoryImpl::OnDatabaseDeleted, weak_factory_.GetWeakPtr(), origin)); - if (force_close && database) - database->ForceClose(); + if (force_close) + database->ForceCloseAndRunTasks(); return; } @@ -362,9 +363,9 @@ std::unique_ptr<IndexedDBDatabase> database; std::tie(database, s) = indexed_db_class_factory_->CreateIndexedDBDatabase( name, factory->backing_store(), this, - base::BindRepeating(&IndexedDBFactoryImpl::OnDatabaseError, - weak_factory_.GetWeakPtr(), origin), - factory->CreateDatabaseDeleteClosure(name), + base::BindRepeating(&IndexedDBFactoryImpl::MaybeRunTasksForOrigin, + origin_state_destruction_weak_factory_.GetWeakPtr(), + origin), std::make_unique<IndexedDBMetadataCoding>(), unique_identifier, factory->lock_manager()); if (!database.get()) { @@ -384,8 +385,8 @@ std::move(origin_state_handle), std::move(callbacks), base::BindOnce(&IndexedDBFactoryImpl::OnDatabaseDeleted, weak_factory_.GetWeakPtr(), origin)); - if (force_close && database_ptr) - database_ptr->ForceClose(); + if (force_close) + database_ptr->ForceCloseAndRunTasks(); } void IndexedDBFactoryImpl::AbortTransactionsAndCompactDatabase( @@ -399,6 +400,7 @@ return; } it->second->AbortAllTransactions(true); + RunTasksForOrigin(it->second->AsWeakPtr()); std::move(callback).Run(leveldb::Status::OK()); } @@ -413,6 +415,7 @@ return; } it->second->AbortAllTransactions(false); + RunTasksForOrigin(it->second->AsWeakPtr()); std::move(callback).Run(leveldb::Status::OK()); } @@ -477,11 +480,17 @@ if (it == factories_per_origin_.end()) return; - IndexedDBOriginStateHandle origin_state_handle = it->second->CreateHandle(); + base::WeakPtr<IndexedDBOriginState> weak_ptr; + { + IndexedDBOriginStateHandle origin_state_handle = it->second->CreateHandle(); - if (delete_in_memory_store) - origin_state_handle.origin_state()->StopPersistingForIncognito(); - origin_state_handle.origin_state()->ForceClose(); + if (delete_in_memory_store) + origin_state_handle.origin_state()->StopPersistingForIncognito(); + origin_state_handle.origin_state()->ForceClose(); + weak_ptr = origin_state_handle.origin_state()->AsWeakPtr(); + } + // Run tasks so the origin state is deleted. + RunTasksForOrigin(std::move(weak_ptr)); } void IndexedDBFactoryImpl::ForceSchemaDowngrade(const Origin& origin) { @@ -714,10 +723,11 @@ .emplace( origin, std::make_unique<IndexedDBOriginState>( + origin, /*persist_for_incognito=*/is_incognito_and_in_memory, clock_, leveldb_factory_, &earliest_sweep_, std::move(lock_manager), - base::BindOnce( - &IndexedDBFactoryImpl::RemoveOriginState, + base::BindRepeating( + &IndexedDBFactoryImpl::MaybeRunTasksForOrigin, origin_state_destruction_weak_factory_.GetWeakPtr(), origin), std::move(backing_store))) @@ -886,6 +896,44 @@ context_->DatabaseDeleted(origin); } +void IndexedDBFactoryImpl::MaybeRunTasksForOrigin(const url::Origin& origin) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + auto it = factories_per_origin_.find(origin); + if (it == factories_per_origin_.end()) + return; + + IndexedDBOriginState* origin_state = it->second.get(); + if (origin_state->is_task_run_scheduled()) + return; + + origin_state->set_task_run_scheduled(); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&IndexedDBFactoryImpl::RunTasksForOrigin, + origin_state_destruction_weak_factory_.GetWeakPtr(), + origin_state->AsWeakPtr())); +} + +void IndexedDBFactoryImpl::RunTasksForOrigin( + base::WeakPtr<IndexedDBOriginState> origin_state) { + if (!origin_state) + return; + IndexedDBOriginState::RunTasksResult result; + leveldb::Status status; + std::tie(result, status) = origin_state->RunTasks(); + switch (result) { + case IndexedDBOriginState::RunTasksResult::kDone: + return; + case IndexedDBOriginState::RunTasksResult::kError: + OnDatabaseError(origin_state->origin(), status, nullptr); + return; + case IndexedDBOriginState::RunTasksResult::kCanBeDestroyed: + factories_per_origin_.erase(origin_state->origin()); + return; + } +} + bool IndexedDBFactoryImpl::IsDatabaseOpen(const Origin& origin, const base::string16& name) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h index a10b8ce..87de21c 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.h +++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -27,6 +27,7 @@ #include "content/browser/indexed_db/indexed_db_database_error.h" #include "content/browser/indexed_db/indexed_db_factory.h" #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/scopes/leveldb_scopes_factory.h" #include "third_party/leveldatabase/src/include/leveldb/status.h" @@ -133,6 +134,10 @@ GetOrOpenOriginFactory(const url::Origin& origin, const base::FilePath& data_directory); + void OnDatabaseError(const url::Origin& origin, + leveldb::Status s, + const char* message); + protected: // Used by unittests to allow subclassing of IndexedDBBackingStore. virtual std::unique_ptr<IndexedDBBackingStore> CreateBackingStore( @@ -185,13 +190,12 @@ void RemoveOriginState(const url::Origin& origin); - void OnDatabaseError(const url::Origin& origin, - leveldb::Status s, - const char* message); - // Called when the database has been deleted on disk. void OnDatabaseDeleted(const url::Origin& origin); + void MaybeRunTasksForOrigin(const url::Origin& origin); + void RunTasksForOrigin(base::WeakPtr<IndexedDBOriginState> origin_state); + // Testing helpers, so unit tests don't need to grovel through internal // state. bool IsDatabaseOpen(const url::Origin& origin,
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc index f55b06c..387d365 100644 --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -174,12 +174,19 @@ callbacks->connection() ->transactions() .find(transaction_id) - ->second->Commit(); + ->second->SetCommitFlag(); loop.Run(); } return {callbacks->TakeConnection(), db_callbacks}; } + void RunPostedTasks() { + base::RunLoop loop; + base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, + loop.QuitClosure()); + loop.Run(); + } + protected: IndexedDBContextImpl* context() const { return context_.get(); } @@ -188,6 +195,7 @@ TestBrowserThreadBundle* thread_bundle() const { return thread_bundle_.get(); } + IndexedDBOriginState* OriginStateFromHandle( IndexedDBOriginStateHandle& handle) { return handle.origin_state(); @@ -255,6 +263,7 @@ EXPECT_TRUE(factory()->GetOriginFactory(origin)->IsClosing()); factory()->ForceClose(origin, false); + RunPostedTasks(); EXPECT_FALSE(factory()->GetOriginFactory(origin)); } @@ -273,6 +282,8 @@ EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString(); origin_state_handle.Release(); + EXPECT_TRUE(factory()->GetOriginFactory(origin)); + RunPostedTasks(); EXPECT_FALSE(factory()->GetOriginFactory(origin)); EXPECT_EQ(0ul, factory()->GetOpenOrigins().size()); } @@ -348,7 +359,8 @@ // Manually execute the timer so that the PreCloseTaskList task doesn't also // run. factory()->GetOriginFactory(origin)->close_timer()->FireNow(); - + EXPECT_TRUE(factory()->GetOriginFactory(origin)); + RunPostedTasks(); EXPECT_FALSE(factory()->GetOriginFactory(origin)); // Finally, move the clock forward so the origin should allow a sweep. @@ -429,6 +441,7 @@ std::move(create_transaction_callback)); factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin, context()->data_path()); + RunPostedTasks(); // Now simulate shutdown, which should clear all factories. factory()->ContextDestroyed(); @@ -466,6 +479,8 @@ OriginStateFromHandle(origin_state_handle)->ForceClose(); origin_state_handle.Release(); + EXPECT_TRUE(factory()->GetOriginFactory(origin)); + RunPostedTasks(); EXPECT_FALSE(factory()->GetOriginFactory(origin)); } @@ -485,7 +500,8 @@ std::move(create_transaction_callback)); factory()->Open(ASCIIToUTF16("db"), std::move(connection), origin, context()->data_path()); - + EXPECT_FALSE(callbacks->connection()); + RunPostedTasks(); EXPECT_TRUE(callbacks->connection()); EXPECT_TRUE(factory()->GetOriginFactory(origin)); @@ -528,7 +544,7 @@ ASSERT_TRUE(callbacks->connection()); ASSERT_TRUE(callbacks->connection()->database()); - callbacks->connection()->database()->ForceClose(); + callbacks->connection()->database()->ForceCloseAndRunTasks(); EXPECT_TRUE(db_callbacks->forced_close_called()); // Since there are no more references the factory should be closing. @@ -565,7 +581,7 @@ ASSERT_TRUE(callbacks->connection()); // Close the connection. - callbacks->connection()->Close(); + callbacks->connection()->AbortTransactionsAndClose(); // Since there are no more references the factory should be closing. EXPECT_TRUE(factory()->GetOriginFactory(origin)); @@ -582,7 +598,7 @@ CreateConnectionForDatatabase(origin, ASCIIToUTF16("db")); // Force close the database. - connection->database()->ForceClose(); + connection->database()->ForceCloseAndRunTasks(); EXPECT_TRUE(db_callbacks->forced_close_called()); // Since there are no more references the factory should be closing. @@ -748,7 +764,8 @@ callbacks->connection()->database()->Commit( callbacks->connection()->GetTransaction(transaction_id)); loop.Run(); - callbacks->connection()->Close(); + callbacks->connection()->AbortTransactionsAndClose(); + RunPostedTasks(); EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name)); } @@ -763,6 +780,8 @@ std::move(create_transaction_callback)); factory()->Open(db_name, std::move(connection), origin, context()->data_path()); + EXPECT_TRUE(factory()->IsDatabaseOpen(origin, db_name)); + RunPostedTasks(); EXPECT_TRUE(failed_open_callbacks->saw_error()); EXPECT_FALSE(factory()->IsDatabaseOpen(origin, db_name)); } @@ -841,8 +860,9 @@ } } } - + RunPostedTasks(); factory()->ForceClose(origin, false); + RunPostedTasks(); return callbacks->data_loss(); }; @@ -851,44 +871,10 @@ IndexedDBDataFormatVersion open_version_1; IndexedDBDataFormatVersion open_version_2; blink::mojom::IDBDataLoss expected_data_loss; - } kTestCases[] = { - {"http://same-version.com/", - {3, 4}, - {3, 4}, - blink::mojom::IDBDataLoss::None}, - {"http://blink-upgrade.com/", - {3, 4}, - {3, 5}, - blink::mojom::IDBDataLoss::None}, - {"http://v8-upgrade.com/", - {3, 4}, - {4, 4}, - blink::mojom::IDBDataLoss::None}, - {"http://both-upgrade.com/", - {3, 4}, - {4, 5}, - blink::mojom::IDBDataLoss::None}, - {"http://blink-downgrade.com/", - {3, 4}, - {3, 3}, - blink::mojom::IDBDataLoss::Total}, - {"http://v8-downgrade.com/", - {3, 4}, - {2, 4}, - blink::mojom::IDBDataLoss::Total}, - {"http://both-downgrade.com/", - {3, 4}, - {2, 3}, - blink::mojom::IDBDataLoss::Total}, - {"http://v8-up-blink-down.com/", - {3, 4}, - {4, 2}, - blink::mojom::IDBDataLoss::Total}, - {"http://v8-down-blink-up.com/", - {3, 4}, - {2, 5}, - blink::mojom::IDBDataLoss::Total}, - }; + } kTestCases[] = {{"http://blink-downgrade.com/", + {3, 4}, + {3, 3}, + blink::mojom::IDBDataLoss::Total}}; for (const auto& test : kTestCases) { SCOPED_TRACE(test.origin); const Origin origin = Origin::Create(GURL(test.origin)); @@ -899,5 +885,4 @@ } } // namespace - } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc index 2555357..18e0031e 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -164,7 +164,7 @@ leveldb::Status IndexedDBFakeBackingStore::FakeTransaction::CommitPhaseOne( BlobWriteCallback callback) { return std::move(callback).Run( - IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC); + IndexedDBBackingStore::BlobWriteResult::kRunPhaseTwoAndReturnResult); } leveldb::Status IndexedDBFakeBackingStore::FakeTransaction::CommitPhaseTwo() { return result_; @@ -174,4 +174,9 @@ } void IndexedDBFakeBackingStore::FakeTransaction::RollbackAndMaybeTearDown() {} +std::unique_ptr<IndexedDBBackingStore::Transaction> +IndexedDBFakeBackingStore::CreateTransaction() { + return std::make_unique<FakeTransaction>(leveldb::Status::OK()); +} + } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.h b/content/browser/indexed_db/indexed_db_fake_backing_store.h index bf7a471..e855376 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.h +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -127,6 +127,10 @@ DISALLOW_COPY_AND_ASSIGN(FakeTransaction); }; + std::unique_ptr<IndexedDBBackingStore::Transaction> CreateTransaction() + override; + + protected: private: DISALLOW_COPY_AND_ASSIGN(IndexedDBFakeBackingStore); };
diff --git a/content/browser/indexed_db/indexed_db_origin_state.cc b/content/browser/indexed_db/indexed_db_origin_state.cc index 4ffc982..abb6a4c3 100644 --- a/content/browser/indexed_db/indexed_db_origin_state.cc +++ b/content/browser/indexed_db/indexed_db_origin_state.cc
@@ -76,20 +76,22 @@ IndexedDBOriginState::kMaxEarliestOriginSweepFromNow; IndexedDBOriginState::IndexedDBOriginState( + url::Origin origin, bool persist_for_incognito, base::Clock* clock, indexed_db::LevelDBFactory* leveldb_factory, base::Time* earliest_global_sweep_time, std::unique_ptr<DisjointRangeLockManager> lock_manager, - base::OnceClosure destruct_myself, + TasksAvailableCallback notify_tasks_callback, std::unique_ptr<IndexedDBBackingStore> backing_store) - : persist_for_incognito_(persist_for_incognito), + : origin_(std::move(origin)), + persist_for_incognito_(persist_for_incognito), clock_(clock), leveldb_factory_(leveldb_factory), earliest_global_sweep_time_(earliest_global_sweep_time), lock_manager_(std::move(lock_manager)), backing_store_(std::move(backing_store)), - destruct_myself_(std::move(destruct_myself)) { + notify_tasks_callback_(std::move(notify_tasks_callback)) { DCHECK(clock_); DCHECK(earliest_global_sweep_time_); if (*earliest_global_sweep_time_ == base::Time()) @@ -98,6 +100,8 @@ IndexedDBOriginState::~IndexedDBOriginState() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (backing_store_ && backing_store_->IsBlobCleanupPending()) + backing_store_->ForceRunBlobCleanup(); } void IndexedDBOriginState::AbortAllTransactions(bool compact) { @@ -112,6 +116,7 @@ origins.push_back(pair.first); } + base::WeakPtr<IndexedDBOriginState> weak_ptr = AsWeakPtr(); for (const base::string16& origin : origins) { auto it = databases_.find(origin); if (it == databases_.end()) @@ -133,6 +138,11 @@ } } } + + // FinishAllTransactions on a connection can destroy the IndexedDBOriginState + // if the revert fails when scopes is in single-sequence mode. + if (!weak_ptr) + return; if (compact) backing_store_->Compact(); } @@ -144,9 +154,8 @@ // no-op. This allows force closing all of the databases without having the // map mutate. Afterwards the map is manually deleted. IndexedDBOriginStateHandle handle = CreateHandle(); - db_destruction_weak_factory_.InvalidateWeakPtrs(); for (const auto& pair : databases_) { - pair.second->ForceClose(); + pair.second->ForceCloseAndRunTasks(); } databases_.clear(); if (has_blobs_outstanding_) { @@ -168,6 +177,34 @@ MaybeStartClosing(); } +std::tuple<IndexedDBOriginState::RunTasksResult, leveldb::Status> +IndexedDBOriginState::RunTasks() { + task_run_scheduled_ = false; + running_tasks_ = true; + leveldb::Status status; + for (auto db_it = databases_.begin(); db_it != databases_.end();) { + IndexedDBDatabase& db = *db_it->second; + + IndexedDBDatabase::RunTasksResult tasks_result; + std::tie(tasks_result, status) = db.RunTasks(); + switch (tasks_result) { + case IndexedDBDatabase::RunTasksResult::kDone: + ++db_it; + continue; + case IndexedDBDatabase::RunTasksResult::kError: + running_tasks_ = false; + return {RunTasksResult::kError, status}; + case IndexedDBDatabase::RunTasksResult::kCanBeDestroyed: + db_it = databases_.erase(db_it); + break; + } + } + running_tasks_ = false; + if (CanCloseFactory() && closing_stage_ == ClosingState::kClosed) + return {RunTasksResult::kCanBeDestroyed, leveldb::Status::OK()}; + return {RunTasksResult::kDone, leveldb::Status::OK()}; +} + IndexedDBDatabase* IndexedDBOriginState::AddDatabase( const base::string16& name, std::unique_ptr<IndexedDBDatabase> database) { @@ -176,21 +213,6 @@ return databases_.emplace(name, std::move(database)).first->second.get(); } -base::OnceClosure IndexedDBOriginState::CreateDatabaseDeleteClosure( - const base::string16& name) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return base::BindOnce( - [](base::WeakPtr<IndexedDBOriginState> factory, - const base::string16& name) { - if (!factory) - return; - DCHECK_CALLED_ON_VALID_SEQUENCE(factory->sequence_checker_); - size_t delete_size = factory->databases_.erase(name); - DCHECK(delete_size) << "Database " << name << " did not exist."; - }, - db_destruction_weak_factory_.GetWeakPtr(), name); -} - IndexedDBOriginStateHandle IndexedDBOriginState::CreateHandle() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++open_handles_; @@ -234,7 +256,9 @@ base::CommandLine::ForCurrentProcess()->HasSwitch( kIDBCloseImmediatelySwitch)) { closing_stage_ = ClosingState::kClosed; - CloseAndDestruct(); + close_timer_.AbandonAndStop(); + pre_close_task_queue_.reset(); + notify_tasks_callback_.Run(); return; } @@ -267,7 +291,8 @@ return; factory->closing_stage_ = ClosingState::kClosed; factory->pre_close_task_queue_.reset(); - factory->CloseAndDestruct(); + factory->close_timer_.AbandonAndStop(); + factory->notify_tasks_callback_.Run(); }, weak_factory_.GetWeakPtr())); @@ -319,17 +344,4 @@ base::Unretained(backing_store_.get()))); } -void IndexedDBOriginState::CloseAndDestruct() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(CanCloseFactory()); - DCHECK(closing_stage_ == ClosingState::kClosed); - close_timer_.AbandonAndStop(); - pre_close_task_queue_.reset(); - - if (backing_store_ && backing_store_->IsBlobCleanupPending()) - backing_store_->ForceRunBlobCleanup(); - - std::move(destruct_myself_).Run(); -} - } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_origin_state.h b/content/browser/indexed_db/indexed_db_origin_state.h index 516c4c6..c839d9e 100644 --- a/content/browser/indexed_db/indexed_db_origin_state.h +++ b/content/browser/indexed_db/indexed_db_origin_state.h
@@ -15,8 +15,11 @@ #include "base/time/clock.h" #include "base/timer/timer.h" #include "content/browser/indexed_db/indexed_db_origin_state_handle.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/scopes/disjoint_range_lock_manager.h" #include "content/common/content_export.h" +#include "third_party/leveldatabase/src/include/leveldb/status.h" +#include "url/origin.h" namespace content { class IndexedDBBackingStore; @@ -73,12 +76,13 @@ // Calling |destruct_myself| should destruct this object. // |earliest_global_sweep_time| is expected to outlive this object. - IndexedDBOriginState(bool persist_for_incognito, + IndexedDBOriginState(url::Origin origin, + bool persist_for_incognito, base::Clock* clock, indexed_db::LevelDBFactory* leveldb_factory, base::Time* earliest_global_sweep_time, std::unique_ptr<DisjointRangeLockManager> lock_manager, - base::OnceClosure destruct_myself, + TasksAvailableCallback notify_tasks_callback, std::unique_ptr<IndexedDBBackingStore> backing_store); ~IndexedDBOriginState(); @@ -100,6 +104,7 @@ void StopPersistingForIncognito(); + const url::Origin& origin() { return origin_; } IndexedDBBackingStore* backing_store() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return backing_store_.get(); @@ -116,12 +121,27 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return pre_close_task_queue_.get(); } + TasksAvailableCallback notify_tasks_callback() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return notify_tasks_callback_; + } + + bool is_running_tasks() const { return running_tasks_; } + bool is_task_run_scheduled() const { return task_run_scheduled_; } + void set_task_run_scheduled() { task_run_scheduled_ = true; } base::OneShotTimer* close_timer() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return &close_timer_; } + enum class RunTasksResult { kDone, kError, kCanBeDestroyed }; + std::tuple<RunTasksResult, leveldb::Status> RunTasks(); + + base::WeakPtr<IndexedDBOriginState> AsWeakPtr() { + return weak_factory_.GetWeakPtr(); + } + private: friend IndexedDBFactoryImpl; friend IndexedDBOriginStateHandle; @@ -129,9 +149,6 @@ IndexedDBDatabase* AddDatabase(const base::string16& name, std::unique_ptr<IndexedDBDatabase> database); - // Returns a closure that deletes the database object. - base::OnceClosure CreateDatabaseDeleteClosure(const base::string16& name); - // Returns a new handle to this factory. If this object was in its closing // sequence, then that sequence will be halted by this call. IndexedDBOriginStateHandle CreateHandle() WARN_UNUSED_RESULT; @@ -150,6 +167,8 @@ SEQUENCE_CHECKER(sequence_checker_); + url::Origin origin_; + // True if this factory should be remain alive due to the storage partition // being for incognito mode, and our backing store being in-memory. This is // used as closing criteria for this object, see CanCloseFactory. @@ -161,6 +180,10 @@ bool skip_closing_sequence_ = false; base::Clock* const clock_; indexed_db::LevelDBFactory* const leveldb_factory_; + + bool running_tasks_ = false; + bool task_run_scheduled_ = false; + // This is safe because it is owned by IndexedDBFactoryImpl, which owns this // object. base::Time* earliest_global_sweep_time_; @@ -177,13 +200,10 @@ std::unique_ptr<IndexedDBPreCloseTaskQueue> pre_close_task_queue_; - base::OnceClosure destruct_myself_; + TasksAvailableCallback notify_tasks_callback_; - // Weak pointers from this factory are used to bind database deletion in the - // ReleaseDatabaseClosure function. This allows those weak pointers to be - // invalidated during force close & shutdown to prevent re-entry. - base::WeakPtrFactory<IndexedDBOriginState> db_destruction_weak_factory_{this}; base::WeakPtrFactory<IndexedDBOriginState> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(IndexedDBOriginState); };
diff --git a/content/browser/indexed_db/indexed_db_task_helper.h b/content/browser/indexed_db/indexed_db_task_helper.h new file mode 100644 index 0000000..f7551a4 --- /dev/null +++ b/content/browser/indexed_db/indexed_db_task_helper.h
@@ -0,0 +1,16 @@ +// 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 CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TASK_HELPER_H_ +#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TASK_HELPER_H_ + +#include "base/callback_forward.h" + +namespace content { + +using TasksAvailableCallback = base::RepeatingClosure; + +} // namespace content + +#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TASK_HELPER_H_
diff --git a/content/browser/indexed_db/indexed_db_transaction.cc b/content/browser/indexed_db/indexed_db_transaction.cc index 2fcbede..ff23759 100644 --- a/content/browser/indexed_db/indexed_db_transaction.cc +++ b/content/browser/indexed_db/indexed_db_transaction.cc
@@ -28,15 +28,6 @@ const int64_t kInactivityTimeoutPeriodSeconds = 60; -// Helper for posting a task to call IndexedDBTransaction::Commit when we know -// the transaction had no requests and therefore the commit must succeed. -void CommitUnused(base::WeakPtr<IndexedDBTransaction> transaction) { - if (!transaction) - return; - leveldb::Status status = transaction->Commit(); - DCHECK(status.ok()); -} - // Used for UMA metrics - do not change values. enum UmaIDBException { UmaIDBExceptionUnknownError = 0, @@ -74,8 +65,8 @@ } // namespace -IndexedDBTransaction::TaskQueue::TaskQueue() {} -IndexedDBTransaction::TaskQueue::~TaskQueue() { clear(); } +IndexedDBTransaction::TaskQueue::TaskQueue() = default; +IndexedDBTransaction::TaskQueue::~TaskQueue() = default; void IndexedDBTransaction::TaskQueue::clear() { while (!queue_.empty()) @@ -89,8 +80,8 @@ return task; } -IndexedDBTransaction::TaskStack::TaskStack() {} -IndexedDBTransaction::TaskStack::~TaskStack() { clear(); } +IndexedDBTransaction::TaskStack::TaskStack() = default; +IndexedDBTransaction::TaskStack::~TaskStack() = default; void IndexedDBTransaction::TaskStack::clear() { while (!stack_.empty()) @@ -107,15 +98,15 @@ IndexedDBTransaction::IndexedDBTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& object_store_ids, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction) : id_(id), object_store_ids_(object_store_ids), mode_(mode), connection_(connection->GetWeakPtr()), - error_callback_(std::move(error_callback)), + run_tasks_callback_(std::move(tasks_available_callback)), transaction_(backing_store_transaction) { IDB_ASYNC_TRACE_BEGIN("IndexedDBTransaction::lifetime", this); callbacks_ = connection_->callbacks(); @@ -140,9 +131,13 @@ DCHECK(!processing_event_queue_); } +void IndexedDBTransaction::SetCommitFlag() { + is_commit_pending_ = true; + run_tasks_callback_.Run(); +} + void IndexedDBTransaction::ScheduleTask(blink::mojom::IDBTaskType type, Operation task) { - DCHECK_NE(state_, COMMITTING); if (state_ == FINISHED) return; @@ -154,7 +149,8 @@ } else { preemptive_task_queue_.push(std::move(task)); } - RunTasksIfStarted(); + if (state() == STARTED) + run_tasks_callback_.Run(); } void IndexedDBTransaction::ScheduleAbortTask(AbortOperation abort_task) { @@ -163,62 +159,25 @@ abort_task_stack_.push(std::move(abort_task)); } -void IndexedDBTransaction::RunTasksIfStarted() { - DCHECK(used_); - - // Not started by the coordinator yet. - if (state_ != STARTED) - return; - - // A task is already posted. - if (should_process_queue_) - return; - - should_process_queue_ = true; - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&IndexedDBTransaction::ProcessTaskQueue, - ptr_factory_.GetWeakPtr())); -} - -void IndexedDBTransaction::ForcePendingCommit() { - IDB_TRACE1("IndexedDBTransaction::ForceCommit", "txn.id", id()); - DCHECK(is_commit_pending_); +bool IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) { if (state_ == FINISHED) - return; - - should_process_queue_ = true; - state_ = STARTED; - if (!task_queue_.empty()) { - // Commits when completed. - ProcessTaskQueue(); - } else { - leveldb::Status result = Commit(); - if (!result.ok()) - error_callback_.Run(result, "Error force committing."); - } -} - -void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) { - DCHECK(!processing_event_queue_); - - if (state_ == FINISHED) - return; + return false; UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.TransactionAbortReason", ExceptionCodeToUmaEnum(error.code()), UmaIDBExceptionExclusiveMaxValue); + aborted_ = true; timeout_timer_.Stop(); state_ = FINISHED; - should_process_queue_ = false; // Save a WeakPtr in case the RollbackAndMaybeTearDown tears the system down. base::WeakPtr<IndexedDBTransaction> weak_ptr = ptr_factory_.GetWeakPtr(); if (backing_store_transaction_begun_) transaction_->RollbackAndMaybeTearDown(); if (!weak_ptr) - return; + return true; // Run the abort tasks, if any. while (!abort_task_stack_.empty()) @@ -252,19 +211,16 @@ if (callbacks_.get()) callbacks_->OnAbort(*this, error); - // |TransactionFinished| can delete the database, which owns the connection, - // which owns this transaction. Grab a weak pointer to the connection so we - // can test it later. - base::WeakPtr<IndexedDBConnection> connection = connection_; - if (database_) database_->TransactionFinished(mode_, false); + run_tasks_callback_.Run(); + return true; +} - // RemoveTransaction will delete |this|. - // Note: During force-close situations, the connection can be destroyed during - // the |IndexedDBDatabase::TransactionFinished| call - if (connection) - connection->RemoveTransaction(id_); +// static +leveldb::Status IndexedDBTransaction::CommitPhaseTwoProxy( + IndexedDBTransaction* transaction) { + return transaction->CommitPhaseTwo(); } bool IndexedDBTransaction::IsTaskQueueEmpty() const { @@ -288,19 +244,7 @@ state_ = STARTED; DCHECK(!locks_receiver_.locks.empty()); diagnostics_.start_time = base::Time::Now(); - - if (!used_) { - if (is_commit_pending_) { - // The transaction has never had requests issued against it, but the - // front-end previously requested a commit; do the commit now, but not - // re-entrantly as that may renter the coordinator. - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&CommitUnused, ptr_factory_.GetWeakPtr())); - } - return; - } - - RunTasksIfStarted(); + run_tasks_callback_.Run(); } void IndexedDBTransaction::EnsureBackingStoreTransactionBegun() { @@ -317,24 +261,17 @@ return leveldb::Status::OK(); DCHECK_EQ(state_, COMMITTING); - leveldb::Status s = leveldb::Status::OK(); - // Switch statement to protect against adding new enum values. switch (result) { - case IndexedDBBackingStore::BlobWriteResult::FAILURE_ASYNC: + case IndexedDBBackingStore::BlobWriteResult::kFailure: Abort(IndexedDBDatabaseError(blink::kWebIDBDatabaseExceptionDataError, "Failed to write blobs.")); return leveldb::Status::OK(); - case IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC: - case IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC: { - // Save the callback as|this| can be destroyed in the next line. - auto callback_copy = error_callback_; - s = CommitPhaseTwo(); - if (!s.ok() && - result == IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC) { - callback_copy.Run( - s, "Unable to finish transaction commit after writing blobs."); - } - return s; + case IndexedDBBackingStore::BlobWriteResult::kRunPhaseTwoAsync: + ScheduleTask(base::BindOnce(&CommitPhaseTwoProxy)); + run_tasks_callback_.Run(); + return leveldb::Status::OK(); + case IndexedDBBackingStore::BlobWriteResult::kRunPhaseTwoAndReturnResult: { + return CommitPhaseTwo(); } } NOTREACHED(); @@ -458,8 +395,8 @@ if (committed) { abort_task_stack_.clear(); - // SendObservations must be called before OnComplete to ensure consistency - // of callbacks at renderer. + // |observations_callback_| must be called before OnComplete to ensure + // consistency of callbacks at renderer. if (!connection_changes_map_.empty()) { if (database_) database_->SendObservations(std::move(connection_changes_map_)); @@ -473,11 +410,8 @@ } if (!pending_observers_.empty() && connection_) connection_->ActivatePendingObservers(std::move(pending_observers_)); - if (database_) database_->TransactionFinished(mode_, true); - // RemoveTransaction will delete |this|. - connection_->RemoveTransaction(id_); return s; } else { while (!abort_task_stack_.empty()) @@ -496,77 +430,85 @@ callbacks_->OnAbort(*this, error); if (database_) database_->TransactionFinished(mode_, false); - // RemoveTransaction will delete |this|. - connection_->RemoveTransaction(id_); } return s; } -void IndexedDBTransaction::ProcessTaskQueue() { - IDB_TRACE1("IndexedDBTransaction::ProcessTaskQueue", "txn.id", id()); +std::tuple<IndexedDBTransaction::RunTasksResult, leveldb::Status> +IndexedDBTransaction::RunTasks() { + IDB_TRACE1("IndexedDBTransaction::RunTasks", "txn.id", id()); DCHECK(!processing_event_queue_); // May have been aborted. - if (!should_process_queue_) - return; + if (aborted_) + return {RunTasksResult::kAborted, leveldb::Status::OK()}; + if (IsTaskQueueEmpty() && !is_commit_pending_) + return {RunTasksResult::kNotFinished, leveldb::Status::OK()}; processing_event_queue_ = true; - DCHECK(!IsTaskQueueEmpty()); - should_process_queue_ = false; + if (!backing_store_transaction_begun_) { + transaction_->Begin(std::move(locks_receiver_.locks)); + backing_store_transaction_begun_ = true; + } - EnsureBackingStoreTransactionBegun(); - + bool run_preemptive_queue = + !preemptive_task_queue_.empty() || pending_preemptive_events_ != 0; TaskQueue* task_queue = - pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; + run_preemptive_queue ? &preemptive_task_queue_ : &task_queue_; while (!task_queue->empty() && state_ != FINISHED) { - DCHECK_EQ(state_, STARTED); + DCHECK(state_ == STARTED || state_ == COMMITTING) << state_; Operation task(task_queue->pop()); leveldb::Status result = std::move(task).Run(this); - if (!pending_preemptive_events_) { + if (!run_preemptive_queue) { DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled); ++diagnostics_.tasks_completed; } if (!result.ok()) { processing_event_queue_ = false; - error_callback_.Run(result, "Error executing transaction tasks."); - return; + return { + RunTasksResult::kError, + result, + }; } + run_preemptive_queue = + !preemptive_task_queue_.empty() || pending_preemptive_events_ != 0; // Event itself may change which queue should be processed next. - task_queue = - pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; + task_queue = run_preemptive_queue ? &preemptive_task_queue_ : &task_queue_; } // If there are no pending tasks, we haven't already committed/aborted, // and the front-end requested a commit, it is now safe to do so. - if (!HasPendingTasks() && state_ != FINISHED && is_commit_pending_) { + if (!HasPendingTasks() && state_ == STARTED && is_commit_pending_) { processing_event_queue_ = false; // This can delete |this|. leveldb::Status result = Commit(); if (!result.ok()) - error_callback_.Run(result, "Error committing the transaction."); - return; + return {RunTasksResult::kError, result}; } // The transaction may have been aborted while processing tasks. if (state_ == FINISHED) { processing_event_queue_ = false; - return; + return {aborted_ ? RunTasksResult::kAborted : RunTasksResult::kCommitted, + leveldb::Status::OK()}; } - DCHECK(state_ == STARTED); + DCHECK(state_ == STARTED || state_ == COMMITTING) << state_; // Otherwise, start a timer in case the front-end gets wedged and // never requests further activity. Read-only transactions don't // block other transactions, so don't time those out. - if (mode_ != blink::mojom::IDBTransactionMode::ReadOnly) { + if (mode_ != blink::mojom::IDBTransactionMode::ReadOnly && + state_ == STARTED) { timeout_timer_.Start(FROM_HERE, GetInactivityTimeout(), base::BindOnce(&IndexedDBTransaction::Timeout, ptr_factory_.GetWeakPtr())); } processing_event_queue_ = false; + return {RunTasksResult::kNotFinished, leveldb::Status::OK()}; } base::TimeDelta IndexedDBTransaction::GetInactivityTimeout() const {
diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h index bef846c..acd1dde2 100644 --- a/content/browser/indexed_db/indexed_db_transaction.h +++ b/content/browser/indexed_db/indexed_db_transaction.h
@@ -10,9 +10,9 @@ #include <map> #include <memory> #include <set> -#include <utility> -#include <vector> +#include <tuple> +#include "base/callback.h" #include "base/containers/queue.h" #include "base/containers/stack.h" #include "base/gtest_prod_util.h" @@ -23,9 +23,9 @@ #include "base/timer/timer.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_connection.h" -#include "content/browser/indexed_db/indexed_db_database.h" #include "content/browser/indexed_db/indexed_db_database_error.h" #include "content/browser/indexed_db/indexed_db_observer.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/scopes/scope_lock.h" #include "third_party/blink/public/common/indexeddb/web_idb_types.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h" @@ -52,10 +52,6 @@ public: using Operation = base::OnceCallback<leveldb::Status(IndexedDBTransaction*)>; using AbortOperation = base::OnceClosure; - // Used to report irrecoverable backend errors. The second argument is - // optional. - using ErrorCallback = - base::RepeatingCallback<void(leveldb::Status, const char*)>; enum State { CREATED, // Created, but not yet started by coordinator. @@ -67,15 +63,12 @@ virtual ~IndexedDBTransaction(); - leveldb::Status Commit(); + // Signals the transaction for commit. + void SetCommitFlag(); - // If is_commit_pending_ is true this method does the necessary state - // manipulation to prepare the transaction to be committed, processes its - // task_queue_, and commits the transaction. - void ForcePendingCommit(); - - // This object is destroyed by this method. - void Abort(const IndexedDBDatabaseError& error); + // Returns true if the transaction was aborted, or false if it was already + // finished. + bool Abort(const IndexedDBDatabaseError& error); // Called by the scopes lock manager when this transaction is unblocked. void Start(); @@ -83,7 +76,6 @@ blink::mojom::IDBTransactionMode mode() const { return mode_; } const std::set<int64_t>& scope() const { return object_store_ids_; } - // Tasks cannot call Commit. void ScheduleTask(Operation task) { ScheduleTask(blink::mojom::IDBTaskType::Normal, std::move(task)); } @@ -96,6 +88,7 @@ pending_preemptive_events_--; DCHECK_GE(pending_preemptive_events_, 0); } + void AddPendingObserver(int32_t observer_id, const IndexedDBObserver::Options& options); // Delete pending observers with ID's listed in |pending_observer_ids|. @@ -110,6 +103,9 @@ blink::mojom::IDBObserverChangesPtr* GetPendingChangesForConnection( int32_t connection_id); + enum class RunTasksResult { kError, kNotFinished, kCommitted, kAborted }; + std::tuple<RunTasksResult, leveldb::Status> RunTasks(); + IndexedDBBackingStore::Transaction* BackingStoreTransaction() { return transaction_.get(); } @@ -127,6 +123,7 @@ } State state() const { return state_; } + bool aborted() const { return aborted_; } bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); } struct Diagnostics { @@ -145,7 +142,7 @@ return ptr_factory_.GetWeakPtr(); } - ScopesLocksHolder* locks_receiver() { return &locks_receiver_; } + ScopesLocksHolder* mutable_locks_receiver() { return &locks_receiver_; } protected: // Test classes may derive, but most creation should be done via @@ -153,9 +150,9 @@ IndexedDBTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& object_store_ids, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction); // May be overridden in tests. @@ -191,14 +188,18 @@ indexed_db_transaction_unittest::IndexedDBTransactionTest, IndexedDBObserver); - void RunTasksIfStarted(); + leveldb::Status Commit(); + + // Helper for posting a task to call IndexedDBTransaction::CommitPhaseTwo when + // we know the transaction had no requests and therefore the commit must + // succeed. + static leveldb::Status CommitPhaseTwoProxy(IndexedDBTransaction* transaction); bool IsTaskQueueEmpty() const; bool HasPendingTasks() const; leveldb::Status BlobWriteComplete( IndexedDBBackingStore::BlobWriteResult result); - void ProcessTaskQueue(); void CloseOpenCursorBindings(); void CloseOpenCursors(); leveldb::Status CommitPhaseTwo(); @@ -212,12 +213,13 @@ State state_ = CREATED; ScopesLocksHolder locks_receiver_; bool is_commit_pending_ = false; + // We are owned by the connection object, but during force closes sometimes // there are issues if there is a pending OpenRequest. So use a WeakPtr. base::WeakPtr<IndexedDBConnection> connection_; scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_; base::WeakPtr<IndexedDBDatabase> database_; - ErrorCallback error_callback_; + TasksAvailableCallback run_tasks_callback_; // Observers in pending queue do not listen to changes until activated. std::vector<std::unique_ptr<IndexedDBObserver>> pending_observers_; @@ -264,9 +266,9 @@ std::unique_ptr<IndexedDBBackingStore::Transaction> transaction_; bool backing_store_transaction_begun_ = false; - bool should_process_queue_ = false; int pending_preemptive_events_ = 0; bool processing_event_queue_ = false; + bool aborted_ = false; int64_t num_errors_sent_ = 0; int64_t num_errors_handled_ = 0;
diff --git a/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/content/browser/indexed_db/indexed_db_transaction_unittest.cc index c08d75b8..b7da376 100644 --- a/content/browser/indexed_db/indexed_db_transaction_unittest.cc +++ b/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -8,6 +8,7 @@ #include <memory> #include "base/bind.h" +#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/macros.h" #include "base/run_loop.h" @@ -62,18 +63,44 @@ leveldb::Status s; std::tie(db_, s) = IndexedDBClassFactory::Get()->CreateIndexedDBDatabase( base::ASCIIToUTF16("db"), backing_store_.get(), factory_.get(), - GetErrorCallback(), base::BindLambdaForTesting([&]() { db_.reset(); }), + CreateRunTasksCallback(), std::make_unique<FakeIndexedDBMetadataCoding>(), IndexedDBDatabase::Identifier(), &lock_manager_); ASSERT_TRUE(s.ok()); } - IndexedDBTransaction::ErrorCallback GetErrorCallback() { - return base::BindLambdaForTesting( - [&](leveldb::Status, const char*) { error_called_ = true; }); + TasksAvailableCallback CreateRunTasksCallback() { + return base::BindRepeating(&IndexedDBTransactionTest::RunTasksForDatabase, + base::Unretained(this), true); + } + + void RunTasksForDatabase(bool async) { + if (!db_) + return; + if (async) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&IndexedDBTransactionTest::RunTasksForDatabase, + base::Unretained(this), false)); + return; + } + IndexedDBDatabase::RunTasksResult result; + leveldb::Status status; + std::tie(result, status) = db_->RunTasks(); + switch (result) { + case IndexedDBDatabase::RunTasksResult::kDone: + return; + case IndexedDBDatabase::RunTasksResult::kError: + error_called_ = true; + return; + case IndexedDBDatabase::RunTasksResult::kCanBeDestroyed: + db_.reset(); + return; + } } void RunPostedTasks() { base::RunLoop().RunUntilIdle(); } + leveldb::Status DummyOperation(leveldb::Status result, IndexedDBTransaction* transaction) { return result; @@ -85,13 +112,14 @@ return leveldb::Status::OK(); } - std::unique_ptr<IndexedDBConnection> CreateConnection(int process_id) { - return std::unique_ptr<IndexedDBConnection>( + std::unique_ptr<IndexedDBConnection> CreateConnection() { + auto connection = std::unique_ptr<IndexedDBConnection>( std::make_unique<IndexedDBConnection>( kFakeProcessId, IndexedDBOriginStateHandle(), IndexedDBClassFactory::Get(), db_->AsWeakPtr(), base::DoNothing(), - base::DoNothing(), GetErrorCallback(), - new MockIndexedDBDatabaseCallbacks())); + base::DoNothing(), new MockIndexedDBDatabaseCallbacks())); + db_->AddConnectionForTesting(connection.get()); + return connection; } protected: @@ -122,14 +150,11 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, - blink::mojom::IDBTransactionMode::ReadWrite, - new IndexedDBFakeBackingStore::FakeTransaction(commit_success))); - db_->RegisterAndScheduleTransaction(transaction.get()); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, blink::mojom::IDBTransactionMode::ReadWrite, + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); + db_->RegisterAndScheduleTransaction(transaction); // No conflicting transactions, so coordinator will start it immediately: EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state()); @@ -168,14 +193,11 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, - blink::mojom::IDBTransactionMode::ReadOnly, - new IndexedDBFakeBackingStore::FakeTransaction(commit_success))); - db_->RegisterAndScheduleTransaction(transaction.get()); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, blink::mojom::IDBTransactionMode::ReadOnly, + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); + db_->RegisterAndScheduleTransaction(transaction); // No conflicting transactions, so coordinator will start it immediately: EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state()); @@ -203,12 +225,10 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, GetParam(), - new IndexedDBFakeBackingStore::FakeTransaction(commit_success))); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, GetParam(), + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -217,7 +237,7 @@ EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled); EXPECT_EQ(0, transaction->diagnostics().tasks_completed); - db_->RegisterAndScheduleTransaction(transaction.get()); + db_->RegisterAndScheduleTransaction(transaction); EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -248,28 +268,19 @@ EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled); EXPECT_EQ(1, transaction->diagnostics().tasks_completed); - transaction->Commit(); - - EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); - EXPECT_FALSE(transaction->HasPendingTasks()); - EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); - EXPECT_TRUE(transaction->IsTaskQueueEmpty()); - EXPECT_TRUE(transaction->task_queue_.empty()); - EXPECT_TRUE(transaction->preemptive_task_queue_.empty()); - EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled); - EXPECT_EQ(1, transaction->diagnostics().tasks_completed); + transaction->SetCommitFlag(); + RunPostedTasks(); + EXPECT_EQ(0UL, connection->transactions().size()); } TEST_P(IndexedDBTransactionTestMode, TaskFails) { const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, GetParam(), - new IndexedDBFakeBackingStore::FakeTransaction(commit_success))); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, GetParam(), + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -278,7 +289,7 @@ EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled); EXPECT_EQ(0, transaction->diagnostics().tasks_completed); - db_->RegisterAndScheduleTransaction(transaction.get()); + db_->RegisterAndScheduleTransaction(transaction); EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -312,29 +323,19 @@ EXPECT_TRUE(error_called_); - transaction->Commit(); - - EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); - EXPECT_FALSE(transaction->HasPendingTasks()); - EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); - EXPECT_TRUE(transaction->IsTaskQueueEmpty()); - EXPECT_TRUE(transaction->task_queue_.empty()); - EXPECT_TRUE(transaction->preemptive_task_queue_.empty()); - EXPECT_EQ(1, transaction->diagnostics().tasks_scheduled); - EXPECT_EQ(1, transaction->diagnostics().tasks_completed); + transaction->SetCommitFlag(); + RunPostedTasks(); + EXPECT_EQ(0UL, connection->transactions().size()); } TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) { const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_failure = leveldb::Status::Corruption("Ouch."); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, - blink::mojom::IDBTransactionMode::VersionChange, - new IndexedDBFakeBackingStore::FakeTransaction(commit_failure))); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, blink::mojom::IDBTransactionMode::VersionChange, + new IndexedDBFakeBackingStore::FakeTransaction(commit_failure)); EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -343,7 +344,7 @@ EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled); EXPECT_EQ(0, transaction->diagnostics().tasks_completed); - db_->RegisterAndScheduleTransaction(transaction.get()); + db_->RegisterAndScheduleTransaction(transaction); EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_TRUE(transaction->IsTaskQueueEmpty()); @@ -373,29 +374,20 @@ EXPECT_EQ(0, transaction->diagnostics().tasks_completed); transaction->DidCompletePreemptiveEvent(); - transaction->Commit(); - - EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); - EXPECT_FALSE(transaction->HasPendingTasks()); - EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); - EXPECT_TRUE(transaction->IsTaskQueueEmpty()); - EXPECT_TRUE(transaction->task_queue_.empty()); - EXPECT_TRUE(transaction->preemptive_task_queue_.empty()); - EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled); - EXPECT_EQ(0, transaction->diagnostics().tasks_completed); + transaction->SetCommitFlag(); + RunPostedTasks(); + EXPECT_TRUE(error_called_); } TEST_P(IndexedDBTransactionTestMode, AbortTasks) { const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_failure = leveldb::Status::Corruption("Ouch."); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, GetParam(), - new IndexedDBFakeBackingStore::FakeTransaction(commit_failure))); - db_->RegisterAndScheduleTransaction(transaction.get()); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, GetParam(), + new IndexedDBFakeBackingStore::FakeTransaction(commit_failure)); + db_->RegisterAndScheduleTransaction(transaction); AbortObserver observer; transaction->ScheduleTask( @@ -407,23 +399,21 @@ base::RunLoop().RunUntilIdle(); EXPECT_FALSE(observer.abort_task_called()); - transaction->Commit(); + transaction->SetCommitFlag(); + RunPostedTasks(); EXPECT_TRUE(observer.abort_task_called()); - EXPECT_EQ(IndexedDBTransaction::FINISHED, transaction->state()); - EXPECT_FALSE(transaction->IsTimeoutTimerRunning()); + EXPECT_TRUE(error_called_); } TEST_P(IndexedDBTransactionTestMode, AbortPreemptive) { const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - std::unique_ptr<IndexedDBTransaction> transaction = - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, GetParam(), - new IndexedDBFakeBackingStore::FakeTransaction(commit_success))); - db_->RegisterAndScheduleTransaction(transaction.get()); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, GetParam(), + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); + db_->RegisterAndScheduleTransaction(transaction); // No conflicting transactions, so coordinator will start it immediately: EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state()); @@ -450,7 +440,6 @@ EXPECT_FALSE(transaction->HasPendingTasks()); EXPECT_EQ(transaction->diagnostics().tasks_completed, transaction->diagnostics().tasks_scheduled); - EXPECT_FALSE(transaction->should_process_queue_); EXPECT_TRUE(transaction->backing_store_transaction_begun_); EXPECT_TRUE(transaction->used_); EXPECT_FALSE(transaction->is_commit_pending_); @@ -470,17 +459,12 @@ const int64_t id = 0; const std::set<int64_t> scope; const leveldb::Status commit_success = leveldb::Status::OK(); - std::unique_ptr<IndexedDBConnection> connection = - CreateConnection(kFakeProcessId); - - base::WeakPtr<IndexedDBTransaction> transaction = - connection->AddTransactionForTesting( - std::unique_ptr<IndexedDBTransaction>(new IndexedDBTransaction( - id, connection.get(), GetErrorCallback(), scope, - blink::mojom::IDBTransactionMode::ReadWrite, - new IndexedDBFakeBackingStore::FakeTransaction(commit_success)))); + std::unique_ptr<IndexedDBConnection> connection = CreateConnection(); + IndexedDBTransaction* transaction = connection->CreateTransaction( + id, scope, blink::mojom::IDBTransactionMode::ReadWrite, + new IndexedDBFakeBackingStore::FakeTransaction(commit_success)); ASSERT_TRUE(transaction); - db_->RegisterAndScheduleTransaction(transaction.get()); + db_->RegisterAndScheduleTransaction(transaction); EXPECT_EQ(0UL, transaction->pending_observers_.size()); EXPECT_EQ(0UL, connection->active_observers().size()); @@ -500,8 +484,9 @@ EXPECT_EQ(0UL, connection->active_observers().size()); // After commit, observer moved to connection's active observer. - transaction->Commit(); - EXPECT_FALSE(transaction); + transaction->SetCommitFlag(); + RunPostedTasks(); + EXPECT_EQ(0UL, connection->transactions().size()); EXPECT_EQ(1UL, connection->active_observers().size()); // Observer does not exist, so no change to active_observers.
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc index f90ccc9..f7c0cc5 100644 --- a/content/browser/indexed_db/indexed_db_unittest.cc +++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -5,6 +5,7 @@ #include <stdint.h> #include <utility> +#include "base/barrier_closure.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/macros.h" @@ -15,7 +16,9 @@ #include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_factory_impl.h" +#include "content/browser/indexed_db/indexed_db_origin_state.h" #include "content/browser/indexed_db/leveldb/leveldb_env.h" +#include "content/browser/indexed_db/leveldb/transactional_leveldb_database.h" #include "content/browser/indexed_db/mock_indexed_db_callbacks.h" #include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h" #include "content/public/browser/storage_partition.h" @@ -98,6 +101,46 @@ quota_manager_proxy_->SimulateQuotaManagerDestroyed(); } + void RunPostedTasks() { + base::RunLoop loop; + context_->TaskRunner()->PostTask(FROM_HERE, loop.QuitClosure()); + loop.Run(); + } + + void TearDown() override { + if (context_ && !context_->IsInMemoryContext()) { + IndexedDBFactoryImpl* factory = context_->GetIDBFactory(); + + // Loop through all open origins, and force close them, and request the + // deletion of the leveldb state. Once the states are no longer around, + // delete all of the databases on disk. + auto open_factory_origins = factory->GetOpenOrigins(); + base::RunLoop loop; + auto callback = base::BarrierClosure( + open_factory_origins.size(), base::BindLambdaForTesting([&]() { + // All leveldb databases are closed, and they can be deleted. + for (auto origin : context_->GetAllOrigins()) { + context_->DeleteForOrigin(origin); + } + loop.Quit(); + })); + for (auto origin : open_factory_origins) { + IndexedDBOriginState* per_origin_factory = + factory->GetOriginFactory(origin); + per_origin_factory->backing_store() + ->db() + ->leveldb_state() + ->RequestDestruction(callback, + base::SequencedTaskRunnerHandle::Get()); + context_->ForceClose(origin, + IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN); + } + loop.Run(); + } + if (temp_dir_.IsValid()) + ASSERT_TRUE(temp_dir_.Delete()); + } + protected: IndexedDBContextImpl* context() const { return context_.get(); } scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_; @@ -186,56 +229,55 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) { const Origin kTestOrigin = Origin::Create(GURL("http://test/")); - base::RunLoop loop; - context()->TaskRunner()->PostTask( - FROM_HERE, base::BindLambdaForTesting([&]() { - const int child_process_id = 0; - const int64_t host_transaction_id = 0; - const int64_t version = 0; + auto open_db_callbacks = + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(); + auto closed_db_callbacks = + base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(); + auto open_callbacks = + base::MakeRefCounted<ForceCloseDBCallbacks>(context(), kTestOrigin); + auto closed_callbacks = + base::MakeRefCounted<ForceCloseDBCallbacks>(context(), kTestOrigin); + base::FilePath test_path = context()->GetFilePathForTesting(kTestOrigin); - IndexedDBFactory* factory = context()->GetIDBFactory(); + const int child_process_id = 0; + const int64_t host_transaction_id = 0; + const int64_t version = 0; - base::FilePath test_path = - context()->GetFilePathForTesting(kTestOrigin); + IndexedDBFactory* factory = context()->GetIDBFactory(); - auto open_db_callbacks = - base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(); - auto closed_db_callbacks = - base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(); - auto open_callbacks = - base::MakeRefCounted<ForceCloseDBCallbacks>(context(), kTestOrigin); - auto closed_callbacks = - base::MakeRefCounted<ForceCloseDBCallbacks>(context(), kTestOrigin); + auto create_transaction_callback1 = + base::BindOnce(&CreateAndBindTransactionPlaceholder); + factory->Open(base::ASCIIToUTF16("opendb"), + std::make_unique<IndexedDBPendingConnection>( + open_callbacks, open_db_callbacks, child_process_id, + host_transaction_id, version, + std::move(create_transaction_callback1)), + kTestOrigin, context()->data_path()); + EXPECT_TRUE(base::DirectoryExists(test_path)); - auto create_transaction_callback1 = - base::BindOnce(&CreateAndBindTransactionPlaceholder); - factory->Open(base::ASCIIToUTF16("opendb"), - std::make_unique<IndexedDBPendingConnection>( - open_callbacks, open_db_callbacks, child_process_id, - host_transaction_id, version, - std::move(create_transaction_callback1)), - kTestOrigin, context()->data_path()); - EXPECT_TRUE(base::DirectoryExists(test_path)); + auto create_transaction_callback2 = + base::BindOnce(&CreateAndBindTransactionPlaceholder); + factory->Open(base::ASCIIToUTF16("closeddb"), + std::make_unique<IndexedDBPendingConnection>( + closed_callbacks, closed_db_callbacks, child_process_id, + host_transaction_id, version, + std::move(create_transaction_callback2)), + kTestOrigin, context()->data_path()); + RunPostedTasks(); + ASSERT_TRUE(closed_callbacks->connection()); + closed_callbacks->connection()->AbortTransactionsAndClose(); + RunPostedTasks(); - auto create_transaction_callback2 = - base::BindOnce(&CreateAndBindTransactionPlaceholder); - factory->Open(base::ASCIIToUTF16("closeddb"), - std::make_unique<IndexedDBPendingConnection>( - closed_callbacks, closed_db_callbacks, - child_process_id, host_transaction_id, version, - std::move(create_transaction_callback2)), - kTestOrigin, context()->data_path()); + context()->ForceClose(kTestOrigin, + IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN); + EXPECT_TRUE(open_db_callbacks->forced_close_called()); + EXPECT_FALSE(closed_db_callbacks->forced_close_called()); - closed_callbacks->connection()->Close(); + RunPostedTasks(); - context()->DeleteForOrigin(kTestOrigin); + context()->DeleteForOrigin(kTestOrigin); - EXPECT_TRUE(open_db_callbacks->forced_close_called()); - EXPECT_FALSE(closed_db_callbacks->forced_close_called()); - EXPECT_FALSE(base::DirectoryExists(test_path)); - loop.Quit(); - })); - loop.Run(); + EXPECT_FALSE(base::DirectoryExists(test_path)); } TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) { @@ -259,46 +301,39 @@ } TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) { - base::RunLoop loop; - context()->TaskRunner()->PostTask( - FROM_HERE, base::BindLambdaForTesting([&]() { - const Origin kTestOrigin = Origin::Create(GURL("http://test/")); + const Origin kTestOrigin = Origin::Create(GURL("http://test/")); - auto* factory = - static_cast<IndexedDBFactoryImpl*>(context()->GetIDBFactory()); + auto* factory = + static_cast<IndexedDBFactoryImpl*>(context()->GetIDBFactory()); - const int child_process_id = 0; - const int64_t transaction_id = 1; + const int child_process_id = 0; + const int64_t transaction_id = 1; - auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(); - auto db_callbacks = - base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(); - auto create_transaction_callback1 = - base::BindOnce(&CreateAndBindTransactionPlaceholder); - auto connection = std::make_unique<IndexedDBPendingConnection>( - callbacks, db_callbacks, child_process_id, transaction_id, - IndexedDBDatabaseMetadata::DEFAULT_VERSION, - std::move(create_transaction_callback1)); - factory->Open(base::ASCIIToUTF16("db"), std::move(connection), - Origin(kTestOrigin), context()->data_path()); + auto callbacks = base::MakeRefCounted<MockIndexedDBCallbacks>(); + auto db_callbacks = base::MakeRefCounted<MockIndexedDBDatabaseCallbacks>(); + auto create_transaction_callback1 = + base::BindOnce(&CreateAndBindTransactionPlaceholder); + auto connection = std::make_unique<IndexedDBPendingConnection>( + callbacks, db_callbacks, child_process_id, transaction_id, + IndexedDBDatabaseMetadata::DEFAULT_VERSION, + std::move(create_transaction_callback1)); + factory->Open(base::ASCIIToUTF16("db"), std::move(connection), + Origin(kTestOrigin), context()->data_path()); + RunPostedTasks(); - EXPECT_TRUE(callbacks->connection()); + ASSERT_TRUE(callbacks->connection()); - // ConnectionOpened() is usually called by the dispatcher. - context()->ConnectionOpened(kTestOrigin, callbacks->connection()); + // ConnectionOpened() is usually called by the dispatcher. + context()->ConnectionOpened(kTestOrigin, callbacks->connection()); - EXPECT_TRUE(factory->IsBackingStoreOpen(kTestOrigin)); + EXPECT_TRUE(factory->IsBackingStoreOpen(kTestOrigin)); - // Simulate the write failure. - leveldb::Status status = leveldb::Status::IOError("Simulated failure"); - factory->HandleBackingStoreFailure(kTestOrigin); + // Simulate the write failure. + leveldb::Status status = leveldb::Status::IOError("Simulated failure"); + factory->HandleBackingStoreFailure(kTestOrigin); - EXPECT_TRUE(db_callbacks->forced_close_called()); - EXPECT_FALSE(factory->IsBackingStoreOpen(kTestOrigin)); - - loop.Quit(); - })); - loop.Run(); + EXPECT_TRUE(db_callbacks->forced_close_called()); + EXPECT_FALSE(factory->IsBackingStoreOpen(kTestOrigin)); } } // namespace content
diff --git a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc index 08b1eaac..d3e2f77 100644 --- a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc +++ b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
@@ -57,8 +57,7 @@ IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, IndexedDBClassFactory* class_factory, - ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager) @@ -66,8 +65,7 @@ backing_store, factory, class_factory, - std::move(error_callback), - std::move(destroy_me), + std::move(tasks_available_callback), std::move(metadata_coding), unique_identifier, transaction_lock_manager) {} @@ -84,15 +82,15 @@ IndexedDBTestTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& scope, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction) : IndexedDBTransaction(id, connection, - std::move(error_callback), scope, mode, + std::move(tasks_available_callback), backing_store_transaction) {} ~IndexedDBTestTransaction() override {} @@ -368,16 +366,15 @@ const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, - IndexedDBDatabase::ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const IndexedDBDatabase::Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager) { std::unique_ptr<IndexedDBTestDatabase> database = std::make_unique<IndexedDBTestDatabase>( - name, backing_store, factory, this, std::move(error_callback), - std::move(destroy_me), std::move(metadata_coding), unique_identifier, - transaction_lock_manager); + name, backing_store, factory, this, + std::move(tasks_available_callback), std::move(metadata_coding), + unique_identifier, transaction_lock_manager); leveldb::Status s = database->OpenInternal(); if (!s.ok()) database.reset(); @@ -388,12 +385,12 @@ MockBrowserTestIndexedDBClassFactory::CreateIndexedDBTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& scope, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction) { return std::make_unique<IndexedDBTestTransaction>( - id, connection, std::move(error_callback), scope, mode, + id, connection, scope, mode, std::move(tasks_available_callback), backing_store_transaction); }
diff --git a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h index 9e0a9215..7877bcb7 100644 --- a/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h +++ b/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
@@ -14,6 +14,7 @@ #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_class_factory.h" #include "content/browser/indexed_db/indexed_db_database.h" +#include "content/browser/indexed_db/indexed_db_task_helper.h" #include "content/browser/indexed_db/leveldb/leveldb_env.h" #include "content/browser/indexed_db/scopes/scopes_lock_manager.h" #include "third_party/blink/public/common/indexeddb/web_idb_types.h" @@ -55,17 +56,16 @@ const base::string16& name, IndexedDBBackingStore* backing_store, IndexedDBFactory* factory, - IndexedDBDatabase::ErrorCallback error_callback, - base::OnceClosure destroy_me, + TasksAvailableCallback tasks_available_callback, std::unique_ptr<IndexedDBMetadataCoding> metadata_coding, const IndexedDBDatabase::Identifier& unique_identifier, ScopesLockManager* transaction_lock_manager) override; std::unique_ptr<IndexedDBTransaction> CreateIndexedDBTransaction( int64_t id, IndexedDBConnection* connection, - ErrorCallback error_callback, const std::set<int64_t>& scope, blink::mojom::IDBTransactionMode mode, + TasksAvailableCallback tasks_available_callback, IndexedDBBackingStore::Transaction* backing_store_transaction) override; std::unique_ptr<TransactionalLevelDBDatabase> CreateLevelDBDatabase(
diff --git a/content/browser/indexed_db/transaction_impl.cc b/content/browser/indexed_db/transaction_impl.cc index a303949..9d53560cc 100644 --- a/content/browser/indexed_db/transaction_impl.cc +++ b/content/browser/indexed_db/transaction_impl.cc
@@ -15,6 +15,7 @@ #include "content/browser/indexed_db/indexed_db_connection.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" +#include "content/browser/indexed_db/indexed_db_factory_impl.h" #include "content/browser/indexed_db/indexed_db_transaction.h" #include "content/browser/indexed_db/indexed_db_value.h" #include "content/public/browser/browser_task_traits.h" @@ -125,8 +126,8 @@ leveldb::Status status = connection->database()->CreateObjectStoreOperation( object_store_id, name, key_path, auto_increment, transaction_.get()); if (!status.ok()) { - connection->database()->error_callback().Run( - status, "Internal error creating object store."); + indexed_db_context_->GetIDBFactory()->OnDatabaseError( + origin_, status, "Internal error creating object store."); } }
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index 91e0ca1..2bd57a6 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -1029,8 +1029,8 @@ // TODO(crbug/898733): Support SignedExchange loading and Service // Worker integration. if (service_worker_navigation_handle_) { - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), base::BindOnce( [](ServiceWorkerNavigationHandleCore* core) { base::WeakPtr<ServiceWorkerProviderHost> host = @@ -1042,7 +1042,7 @@ } }, // Unretained() is safe because the handle owns the core, - // and core gets deleted on the IO thread in a task that + // and core gets deleted on the core thread in a task that // must occur after this task. base::Unretained( service_worker_navigation_handle_->core())));
diff --git a/content/browser/native_file_system/file_system_chooser.cc b/content/browser/native_file_system/file_system_chooser.cc index 55ca206..98687a1 100644 --- a/content/browser/native_file_system/file_system_chooser.cc +++ b/content/browser/native_file_system/file_system_chooser.cc
@@ -10,6 +10,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "build/build_config.h" +#include "content/browser/native_file_system/native_file_system_error.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/content_browser_client.h" @@ -175,37 +176,38 @@ callback_runner->PostTask( FROM_HERE, base::BindOnce(std::move(callback), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_ERROR_FAILED), + native_file_system_error::FromStatus( + blink::mojom::NativeFileSystemStatus:: + kOperationFailed, + "Failed to create file"), std::vector<base::FilePath>())); return; } } callback_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_OK), - std::move(files))); + FROM_HERE, base::BindOnce(std::move(callback), + native_file_system_error::Ok(), + std::move(files))); }, files, callback_runner_, std::move(callback_))); delete this; return; } callback_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_OK), - std::move(files))); + FROM_HERE, + base::BindOnce(std::move(callback_), native_file_system_error::Ok(), + std::move(files))); delete this; } void FileSystemChooser::FileSelectionCanceled(void* params) { callback_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_ERROR_ABORT), - std::vector<base::FilePath>())); + FROM_HERE, + base::BindOnce( + std::move(callback_), + native_file_system_error::FromStatus( + blink::mojom::NativeFileSystemStatus::kOperationAborted), + std::vector<base::FilePath>())); delete this; }
diff --git a/content/browser/native_file_system/file_system_chooser_browsertest.cc b/content/browser/native_file_system/file_system_chooser_browsertest.cc index 33fa3eb..1fb9a64 100644 --- a/content/browser/native_file_system/file_system_chooser_browsertest.cc +++ b/content/browser/native_file_system/file_system_chooser_browsertest.cc
@@ -85,7 +85,7 @@ ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); auto result = EvalJs(shell(), "self.chooseFileSystemEntries()"); - EXPECT_TRUE(result.error.find("AbortError") != std::string::npos) + EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; } @@ -241,7 +241,7 @@ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); auto result = EvalJs(shell(), "self.chooseFileSystemEntries({type: 'openDirectory'})"); - EXPECT_TRUE(result.error.find("AbortError") != std::string::npos) + EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; } @@ -257,7 +257,7 @@ " {description: 'foo', extensions: ['txt', 'Js']}," " {mimeTypes: ['image/jpeg']}" "]})"); - EXPECT_TRUE(result.error.find("AbortError") != std::string::npos) + EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; ASSERT_TRUE(dialog_params.file_types);
diff --git a/content/browser/native_file_system/native_file_system_directory_handle_impl.cc b/content/browser/native_file_system/native_file_system_directory_handle_impl.cc index 4967789..1e1ef73c 100644 --- a/content/browser/native_file_system/native_file_system_directory_handle_impl.cc +++ b/content/browser/native_file_system/native_file_system_directory_handle_impl.cc
@@ -8,6 +8,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "content/browser/native_file_system/native_file_system_error.h" #include "content/browser/native_file_system/native_file_system_transfer_token_impl.h" #include "net/base/escape.h" #include "storage/browser/fileapi/file_system_context.h" @@ -19,8 +20,8 @@ using blink::mojom::NativeFileSystemEntry; using blink::mojom::NativeFileSystemEntryPtr; -using blink::mojom::NativeFileSystemError; using blink::mojom::NativeFileSystemHandle; +using blink::mojom::NativeFileSystemStatus; using blink::mojom::NativeFileSystemTransferTokenPtr; using blink::mojom::NativeFileSystemTransferTokenRequest; @@ -84,16 +85,17 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); storage::FileSystemURL child_url; - const base::File::Error file_error = GetChildURL(basename, &child_url); - if (file_error != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(file_error), nullptr); + blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + GetChildURL(basename, &child_url); + if (get_child_url_result->status != NativeFileSystemStatus::kOk) { + std::move(callback).Run(std::move(get_child_url_result), nullptr); return; } if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - nullptr); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + nullptr); return; } @@ -107,7 +109,8 @@ weak_factory_.GetWeakPtr(), child_url), base::BindOnce([](GetFileCallback callback) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), nullptr); }), std::move(callback)); @@ -127,16 +130,17 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); storage::FileSystemURL child_url; - const base::File::Error file_error = GetChildURL(basename, &child_url); - if (file_error != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(file_error), nullptr); + blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + GetChildURL(basename, &child_url); + if (get_child_url_result->status != NativeFileSystemStatus::kOk) { + std::move(callback).Run(std::move(get_child_url_result), nullptr); return; } if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - nullptr); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + nullptr); return; } @@ -150,7 +154,8 @@ weak_factory_.GetWeakPtr(), child_url), base::BindOnce([](GetDirectoryCallback callback) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), nullptr); }), std::move(callback)); @@ -181,9 +186,10 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); storage::FileSystemURL child_url; - const base::File::Error file_error = GetChildURL(basename, &child_url); - if (file_error != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(file_error)); + blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + GetChildURL(basename, &child_url); + if (get_child_url_result->status != NativeFileSystemStatus::kOk) { + std::move(callback).Run(std::move(get_child_url_result)); return; } @@ -191,8 +197,8 @@ base::BindOnce(&NativeFileSystemDirectoryHandleImpl::RemoveEntryImpl, weak_factory_.GetWeakPtr(), child_url, recurse), base::BindOnce([](RemoveEntryCallback callback) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED)); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied)); }), std::move(callback)); } @@ -225,12 +231,13 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (result != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(result), nullptr); + std::move(callback).Run(native_file_system_error::FromFileError(result), + nullptr); return; } std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_OK), + native_file_system_error::Ok(), manager()->CreateFileHandle(context(), url, handle_state())); } @@ -255,12 +262,13 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (result != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(result), nullptr); + std::move(callback).Run(native_file_system_error::FromFileError(result), + nullptr); return; } std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_OK), + native_file_system_error::Ok(), manager()->CreateDirectoryHandle(context(), url, handle_state())); } @@ -273,7 +281,8 @@ if (result != base::File::FILE_OK) { DCHECK(!has_more); - std::move(state->callback).Run(NativeFileSystemError::New(result), {}); + std::move(state->callback) + .Run(native_file_system_error::FromFileError(result), {}); return; } @@ -281,11 +290,12 @@ std::string basename = storage::FilePathToString(entry.name); storage::FileSystemURL child_url; - const base::File::Error file_error = GetChildURL(basename, &child_url); + blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + GetChildURL(basename, &child_url); // All entries must exist in this directory as a direct child with a valid // |basename|. - CHECK_EQ(file_error, base::File::FILE_OK); + CHECK_EQ(get_child_url_result->status, NativeFileSystemStatus::kOk); state->entries.push_back( CreateEntry(basename, child_url, @@ -296,8 +306,7 @@ // than waiting till we have retrieved them all. if (!has_more) { std::move(state->callback) - .Run(NativeFileSystemError::New(base::File::FILE_OK), - std::move(state->entries)); + .Run(native_file_system_error::Ok(), std::move(state->entries)); } } @@ -313,25 +322,31 @@ url, recurse, base::BindOnce( [](RemoveEntryCallback callback, base::File::Error result) { - std::move(callback).Run(NativeFileSystemError::New(result)); + std::move(callback).Run( + native_file_system_error::FromFileError(result)); }, std::move(callback))); } -base::File::Error NativeFileSystemDirectoryHandleImpl::GetChildURL( +blink::mojom::NativeFileSystemErrorPtr +NativeFileSystemDirectoryHandleImpl::GetChildURL( const std::string& basename, storage::FileSystemURL* result) { // TODO(mek): Rather than doing URL serialization and parsing we should just // have a way to get a child FileSystemURL directly from its parent. if (basename.empty()) { - return base::File::FILE_ERROR_NOT_FOUND; + return native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidArgument, + "Name can't be an empty string."); } if (ContainsPathSeparator(basename) || IsCurrentOrParentDirectory(basename)) { // |basename| must refer to a entry that exists in this directory as a // direct child. - return base::File::FILE_ERROR_SECURITY; + return native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidArgument, + "Name contains invalid characters."); } std::string escaped_name = @@ -344,7 +359,7 @@ GURL child_url = parent_url.ReplaceComponents(replacements); *result = file_system_context()->CrackURL(child_url); - return base::File::FILE_OK; + return native_file_system_error::Ok(); } NativeFileSystemEntryPtr NativeFileSystemDirectoryHandleImpl::CreateEntry(
diff --git a/content/browser/native_file_system/native_file_system_directory_handle_impl.h b/content/browser/native_file_system/native_file_system_directory_handle_impl.h index 20ea065d..e1e0885 100644 --- a/content/browser/native_file_system/native_file_system_directory_handle_impl.h +++ b/content/browser/native_file_system/native_file_system_directory_handle_impl.h
@@ -80,9 +80,9 @@ // Calculates a FileSystemURL for a (direct) child of this directory with the // given basename. Returns an error when |basename| includes invalid input // like "/". - base::File::Error GetChildURL(const std::string& basename, - storage::FileSystemURL* result) - WARN_UNUSED_RESULT; + blink::mojom::NativeFileSystemErrorPtr GetChildURL( + const std::string& basename, + storage::FileSystemURL* result) WARN_UNUSED_RESULT; // Helper to create a blink::mojom::NativeFileSystemEntry struct. blink::mojom::NativeFileSystemEntryPtr CreateEntry(
diff --git a/content/browser/native_file_system/native_file_system_error.cc b/content/browser/native_file_system/native_file_system_error.cc new file mode 100644 index 0000000..59247c6 --- /dev/null +++ b/content/browser/native_file_system/native_file_system_error.cc
@@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/native_file_system/native_file_system_error.h" + +namespace content { + +using blink::mojom::NativeFileSystemError; +using blink::mojom::NativeFileSystemErrorPtr; +using blink::mojom::NativeFileSystemStatus; + +namespace native_file_system_error { + +NativeFileSystemErrorPtr Ok() { + return NativeFileSystemError::New(NativeFileSystemStatus::kOk, + base::File::FILE_OK, ""); +} + +NativeFileSystemErrorPtr FromFileError(base::File::Error result, + base::StringPiece message) { + if (result == base::File::FILE_OK) + return Ok(); + return NativeFileSystemError::New(NativeFileSystemStatus::kFileError, result, + std::string(message)); +} + +blink::mojom::NativeFileSystemErrorPtr FromStatus( + blink::mojom::NativeFileSystemStatus status, + base::StringPiece message) { + return NativeFileSystemError::New(status, base::File::FILE_OK, + std::string(message)); +} + +} // namespace native_file_system_error +} // namespace content
diff --git a/content/browser/native_file_system/native_file_system_error.h b/content/browser/native_file_system/native_file_system_error.h new file mode 100644 index 0000000..e578c130 --- /dev/null +++ b/content/browser/native_file_system/native_file_system_error.h
@@ -0,0 +1,36 @@ +// 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 CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_ +#define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_ + +#include <string> + +#include "base/files/file.h" +#include "base/strings/string_piece.h" +#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom.h" + +namespace content { +namespace native_file_system_error { + +// Returns a NativeFileSystemError representing a successful result of an +// operation. +blink::mojom::NativeFileSystemErrorPtr Ok(); + +// Wraps a base::File::Error in a NativeFileSystemError, optionally with a +// custom error message. +blink::mojom::NativeFileSystemErrorPtr FromFileError( + base::File::Error result, + base::StringPiece message = ""); + +// Wraps a NativeFileSystemStatus in a NativeFileSystemError, optionally with a +// custom error message. +blink::mojom::NativeFileSystemErrorPtr FromStatus( + blink::mojom::NativeFileSystemStatus status, + base::StringPiece message = ""); + +} // namespace native_file_system_error +} // namespace content + +#endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_
diff --git a/content/browser/native_file_system/native_file_system_file_handle_impl.cc b/content/browser/native_file_system/native_file_system_file_handle_impl.cc index 8d71b72..9d7b5dc 100644 --- a/content/browser/native_file_system/native_file_system_file_handle_impl.cc +++ b/content/browser/native_file_system/native_file_system_file_handle_impl.cc
@@ -7,6 +7,7 @@ #include "base/guid.h" #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "content/browser/native_file_system/native_file_system_error.h" #include "net/base/mime_util.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_impl.h" @@ -17,7 +18,7 @@ #include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom.h" #include "third_party/blink/public/mojom/native_file_system/native_file_system_transfer_token.mojom.h" -using blink::mojom::NativeFileSystemError; +using blink::mojom::NativeFileSystemStatus; using storage::BlobDataHandle; using storage::BlobImpl; using storage::FileSystemOperation; @@ -52,9 +53,9 @@ void NativeFileSystemFileHandleImpl::AsBlob(AsBlobCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - nullptr); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + nullptr); return; } @@ -78,9 +79,9 @@ base::BindOnce(&NativeFileSystemFileHandleImpl::CreateFileWriterImpl, weak_factory_.GetWeakPtr(), keep_existing_data), base::BindOnce([](CreateFileWriterCallback callback) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - nullptr); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + nullptr); }), std::move(callback)); } @@ -99,7 +100,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (result != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(result), nullptr); + std::move(callback).Run(native_file_system_error::FromFileError(result), + nullptr); return; } @@ -126,7 +128,9 @@ blob_context()->AddFinishedBlob(std::move(blob_builder)); if (blob_handle->IsBroken()) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_FAILED), nullptr); + native_file_system_error::FromStatus( + NativeFileSystemStatus::kOperationFailed, "Failed to create blob."), + nullptr); return; } @@ -135,7 +139,7 @@ BlobImpl::Create(std::move(blob_handle), mojo::MakeRequest(&blob_ptr)); std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_OK), + native_file_system_error::Ok(), blink::mojom::SerializedBlob::New(uuid, content_type, info.size, blob_ptr.PassInterface())); } @@ -169,9 +173,9 @@ DCHECK(max_swap_files_ >= 0); if (GetWritePermissionStatus() != blink::mojom::PermissionStatus::GRANTED) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - nullptr); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + nullptr); return; } @@ -179,8 +183,10 @@ DLOG(ERROR) << "Error Creating Swap File, count: " << count << " exceeds max unique files of: " << max_swap_files_ << " base path: " << base_swap_path; - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_MAX), nullptr); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kOperationFailed, + "Failed to create swap file."), + nullptr); return; } @@ -221,12 +227,14 @@ DLOG(ERROR) << "Error Creating Swap File, status: " << base::File::ErrorToString(result) << " path: " << swap_url.path(); - std::move(callback).Run(NativeFileSystemError::New(result), nullptr); + std::move(callback).Run(native_file_system_error::FromFileError( + result, "Error creating swap file."), + nullptr); return; } if (!keep_existing_data) { - std::move(callback).Run(NativeFileSystemError::New(base::File::FILE_OK), + std::move(callback).Run(native_file_system_error::Ok(), manager()->CreateFileWriter( context(), url(), swap_url, handle_state())); return; @@ -251,11 +259,13 @@ DLOG(ERROR) << "Error Creating Swap File, status: " << base::File::ErrorToString(result) << " path: " << swap_url.path(); - std::move(callback).Run(NativeFileSystemError::New(result), nullptr); + std::move(callback).Run(native_file_system_error::FromFileError( + result, "Error copying to swap file."), + nullptr); return; } std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_OK), + native_file_system_error::Ok(), manager()->CreateFileWriter(context(), url(), swap_url, handle_state())); }
diff --git a/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc b/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc index be51d67..50ed230 100644 --- a/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc +++ b/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc
@@ -138,7 +138,8 @@ base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result, blink::mojom::NativeFileSystemFileWriterPtr writer_ptr) { - EXPECT_EQ(base::File::FILE_OK, result->error_code); + EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, + result->status); EXPECT_EQ("", ReadFile(swap_url)); writers.push_back(std::move(writer_ptr)); loop.Quit(); @@ -152,7 +153,8 @@ base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result, blink::mojom::NativeFileSystemFileWriterPtr writer_ptr) { - EXPECT_EQ(base::File::FILE_ERROR_MAX, result->error_code); + EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOperationFailed, + result->status); loop.Quit(); })); loop.Run();
diff --git a/content/browser/native_file_system/native_file_system_file_writer_impl.cc b/content/browser/native_file_system/native_file_system_file_writer_impl.cc index 50218af6..d77a79a 100644 --- a/content/browser/native_file_system/native_file_system_file_writer_impl.cc +++ b/content/browser/native_file_system/native_file_system_file_writer_impl.cc
@@ -4,13 +4,14 @@ #include "content/browser/native_file_system/native_file_system_file_writer_impl.h" #include "base/logging.h" +#include "content/browser/native_file_system/native_file_system_error.h" #include "content/browser/native_file_system/native_file_system_manager_impl.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" #include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom.h" -using blink::mojom::NativeFileSystemError; +using blink::mojom::NativeFileSystemStatus; using storage::BlobDataHandle; using storage::FileSystemOperation; @@ -59,9 +60,9 @@ base::BindOnce(&NativeFileSystemFileWriterImpl::WriteImpl, weak_factory_.GetWeakPtr(), offset, std::move(data)), base::BindOnce([](WriteCallback callback) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - /*bytes_written=*/0); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + /*bytes_written=*/0); }), std::move(callback)); } @@ -76,9 +77,9 @@ base::BindOnce(&NativeFileSystemFileWriterImpl::WriteStreamImpl, weak_factory_.GetWeakPtr(), offset, std::move(stream)), base::BindOnce([](WriteStreamCallback callback) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED), - /*bytes_written=*/0); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + /*bytes_written=*/0); }), std::move(callback)); } @@ -91,8 +92,8 @@ base::BindOnce(&NativeFileSystemFileWriterImpl::TruncateImpl, weak_factory_.GetWeakPtr(), length), base::BindOnce([](TruncateCallback callback) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED)); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied)); }), std::move(callback)); } @@ -104,8 +105,8 @@ base::BindOnce(&NativeFileSystemFileWriterImpl::CloseImpl, weak_factory_.GetWeakPtr()), base::BindOnce([](CloseCallback callback) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ACCESS_DENIED)); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied)); }), std::move(callback)); } @@ -119,7 +120,9 @@ if (is_closed()) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_INVALID_OPERATION), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidState, + "An attempt was made to write to a closed writer."), /*bytes_written=*/0); return; } @@ -138,7 +141,8 @@ if (!blob) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_FAILED), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidArgument, "Blob does not exist"), /*bytes_written=*/0); return; } @@ -160,7 +164,9 @@ if (is_closed()) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_INVALID_OPERATION), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidState, + "An attempt was made to write to a closed writer."), /*bytes_written=*/0); return; } @@ -182,7 +188,8 @@ state->bytes_written += bytes; if (complete) { std::move(state->callback) - .Run(NativeFileSystemError::New(result), state->bytes_written); + .Run(native_file_system_error::FromFileError(result), + state->bytes_written); } } @@ -193,8 +200,9 @@ blink::mojom::PermissionStatus::GRANTED); if (is_closed()) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_INVALID_OPERATION)); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidState, + "An attempt was made to write to a closed writer.")); return; } @@ -202,7 +210,8 @@ swap_url(), length, base::BindOnce( [](TruncateCallback callback, base::File::Error result) { - std::move(callback).Run(NativeFileSystemError::New(result)); + std::move(callback).Run( + native_file_system_error::FromFileError(result)); }, std::move(callback))); } @@ -212,8 +221,9 @@ DCHECK_EQ(GetWritePermissionStatus(), blink::mojom::PermissionStatus::GRANTED); if (is_closed()) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_INVALID_OPERATION)); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kInvalidState, + "An attempt was made to close an already closed writer.")); return; } @@ -245,7 +255,7 @@ state_ = State::kClosed; } - std::move(callback).Run(NativeFileSystemError::New(result)); + std::move(callback).Run(native_file_system_error::FromFileError(result)); } base::WeakPtr<NativeFileSystemHandleBase>
diff --git a/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc b/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc index 2a96d80..70033dd 100644 --- a/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc +++ b/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc
@@ -28,6 +28,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" +using blink::mojom::NativeFileSystemStatus; using storage::FileSystemURL; namespace content { @@ -135,16 +136,16 @@ } } - base::File::Error WriteBlobSync(uint64_t position, - blink::mojom::BlobPtr blob, - uint64_t* bytes_written_out) { + NativeFileSystemStatus WriteBlobSync(uint64_t position, + blink::mojom::BlobPtr blob, + uint64_t* bytes_written_out) { base::RunLoop loop; - base::File::Error result_out; + NativeFileSystemStatus result_out; handle_->Write(position, std::move(blob), base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result, uint64_t bytes_written) { - result_out = result->error_code; + result_out = result->status; *bytes_written_out = bytes_written; loop.Quit(); })); @@ -152,17 +153,17 @@ return result_out; } - base::File::Error WriteStreamSync( + NativeFileSystemStatus WriteStreamSync( uint64_t position, mojo::ScopedDataPipeConsumerHandle data_pipe, uint64_t* bytes_written_out) { base::RunLoop loop; - base::File::Error result_out; + NativeFileSystemStatus result_out; handle_->WriteStream(position, std::move(data_pipe), base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result, uint64_t bytes_written) { - result_out = result->error_code; + result_out = result->status; *bytes_written_out = bytes_written; loop.Quit(); })); @@ -170,25 +171,25 @@ return result_out; } - base::File::Error TruncateSync(uint64_t length) { + NativeFileSystemStatus TruncateSync(uint64_t length) { base::RunLoop loop; - base::File::Error result_out; + NativeFileSystemStatus result_out; handle_->Truncate(length, base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result) { - result_out = result->error_code; + result_out = result->status; loop.Quit(); })); loop.Run(); return result_out; } - base::File::Error CloseSync() { + NativeFileSystemStatus CloseSync() { base::RunLoop loop; - base::File::Error result_out; + NativeFileSystemStatus result_out; handle_->Close(base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result) { - result_out = result->error_code; + result_out = result->status; loop.Quit(); })); loop.Run(); @@ -197,9 +198,9 @@ virtual bool WriteUsingBlobs() { return true; } - base::File::Error WriteSync(uint64_t position, - const std::string& contents, - uint64_t* bytes_written_out) { + NativeFileSystemStatus WriteSync(uint64_t position, + const std::string& contents, + uint64_t* bytes_written_out) { if (WriteUsingBlobs()) return WriteBlobSync(position, CreateBlob(contents), bytes_written_out); return WriteStreamSync(position, CreateStream(contents), bytes_written_out); @@ -242,24 +243,25 @@ MakeRequest(&blob); uint64_t bytes_written; - base::File::Error result = WriteBlobSync(0, std::move(blob), &bytes_written); - EXPECT_EQ(result, base::File::FILE_ERROR_FAILED); + NativeFileSystemStatus result = + WriteBlobSync(0, std::move(blob), &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kInvalidArgument); EXPECT_EQ(bytes_written, 0u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ("", ReadFile(test_file_url_)); } TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteValidEmptyString) { uint64_t bytes_written; - base::File::Error result = WriteSync(0, "", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + NativeFileSystemStatus result = WriteSync(0, "", &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 0u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ("", ReadFile(test_file_url_)); } @@ -267,116 +269,116 @@ TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteValidNonEmpty) { std::string test_data("abcdefghijklmnopqrstuvwxyz"); uint64_t bytes_written; - base::File::Error result = WriteSync(0, test_data, &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + NativeFileSystemStatus result = WriteSync(0, test_data, &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, test_data.size()); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(test_data, ReadFile(test_file_url_)); } TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteWithOffsetInFile) { uint64_t bytes_written; - base::File::Error result; + NativeFileSystemStatus result; result = WriteSync(0, "1234567890", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 10u); result = WriteSync(4, "abc", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ("1234abc890", ReadFile(test_file_url_)); } TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteWithOffsetPastFile) { uint64_t bytes_written; - base::File::Error result = WriteSync(4, "abc", &bytes_written); - EXPECT_EQ(result, base::File::FILE_ERROR_FAILED); + NativeFileSystemStatus result = WriteSync(4, "abc", &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kFileError); EXPECT_EQ(bytes_written, 0u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ("", ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, TruncateShrink) { uint64_t bytes_written; - base::File::Error result; + NativeFileSystemStatus result; result = WriteSync(0, "1234567890", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 10u); result = TruncateSync(5); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ("12345", ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, TruncateGrow) { uint64_t bytes_written; - base::File::Error result; + NativeFileSystemStatus result; result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = TruncateSync(5); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(std::string("abc\0\0", 5), ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, CloseAfterCloseNotOK) { uint64_t bytes_written; - base::File::Error result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_ERROR_INVALID_OPERATION); + EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); } TEST_F(NativeFileSystemFileWriterImplTest, TruncateAfterCloseNotOK) { uint64_t bytes_written; - base::File::Error result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); result = TruncateSync(0); - EXPECT_EQ(result, base::File::FILE_ERROR_INVALID_OPERATION); + EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); } TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteAfterCloseNotOK) { uint64_t bytes_written; - base::File::Error result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, base::File::FILE_OK); + NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(result, NativeFileSystemStatus::kOk); result = WriteSync(0, "bcd", &bytes_written); - EXPECT_EQ(result, base::File::FILE_ERROR_INVALID_OPERATION); + EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); } // TODO(mek): More tests, particularly for error conditions.
diff --git a/content/browser/native_file_system/native_file_system_manager_impl.cc b/content/browser/native_file_system/native_file_system_manager_impl.cc index b98b802..f4ad0b7 100644 --- a/content/browser/native_file_system/native_file_system_manager_impl.cc +++ b/content/browser/native_file_system/native_file_system_manager_impl.cc
@@ -10,6 +10,7 @@ #include "content/browser/native_file_system/file_system_chooser.h" #include "content/browser/native_file_system/fixed_native_file_system_permission_grant.h" #include "content/browser/native_file_system/native_file_system_directory_handle_impl.h" +#include "content/browser/native_file_system/native_file_system_error.h" #include "content/browser/native_file_system/native_file_system_file_handle_impl.h" #include "content/browser/native_file_system/native_file_system_file_writer_impl.h" #include "content/browser/native_file_system/native_file_system_transfer_token_impl.h" @@ -31,7 +32,7 @@ namespace content { -using blink::mojom::NativeFileSystemError; +using blink::mojom::NativeFileSystemStatus; using PermissionStatus = NativeFileSystemPermissionGrant::PermissionStatus; using SensitiveDirectoryResult = NativeFileSystemPermissionContext::SensitiveDirectoryResult; @@ -50,10 +51,11 @@ if (!web_contents) { callback_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_ERROR_ABORT), - std::vector<base::FilePath>())); + FROM_HERE, + base::BindOnce(std::move(callback), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kOperationAborted), + std::vector<base::FilePath>())); return; } @@ -62,10 +64,13 @@ if (embedding_origin != requesting_origin) { // Third party iframes are not allowed to show a file picker. callback_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_ERROR_ACCESS_DENIED), - std::vector<base::FilePath>())); + FROM_HERE, + base::BindOnce( + std::move(callback), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied, + "Third party iframes are not allowed to show a file picker."), + std::vector<base::FilePath>())); return; } @@ -75,10 +80,13 @@ // to expire between the renderer side check and this check. if (!rfh->HasTransientUserActivation()) { callback_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - blink::mojom::NativeFileSystemError::New( - base::File::FILE_ERROR_ACCESS_DENIED), - std::vector<base::FilePath>())); + FROM_HERE, + base::BindOnce( + std::move(callback), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied, + "User activation is required to show a file picker."), + std::vector<base::FilePath>())); return; } @@ -347,7 +355,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (result != base::File::FILE_OK) { - std::move(callback).Run(NativeFileSystemError::New(result), nullptr); + std::move(callback).Run(native_file_system_error::FromFileError(result), + nullptr); return; } @@ -356,7 +365,7 @@ PermissionStatus::GRANTED); std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_OK), + native_file_system_error::Ok(), CreateDirectoryHandle( binding_context, context()->CrackURL(root), SharedHandleState(permission_grant, permission_grant, @@ -369,7 +378,7 @@ ChooseEntriesCallback callback, blink::mojom::NativeFileSystemErrorPtr result, std::vector<base::FilePath> entries) { - if (result->error_code != base::File::FILE_OK) { + if (result->status != NativeFileSystemStatus::kOk) { std::move(callback).Run( std::move(result), std::vector<blink::mojom::NativeFileSystemEntryPtr>()); @@ -400,7 +409,8 @@ SensitiveDirectoryResult result) { if (result == SensitiveDirectoryResult::kAbort) { std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ABORT), + native_file_system_error::FromStatus( + NativeFileSystemStatus::kOperationAborted), std::vector<blink::mojom::NativeFileSystemEntryPtr>()); return; } @@ -445,7 +455,7 @@ } } - std::move(callback).Run(NativeFileSystemError::New(base::File::FILE_OK), + std::move(callback).Run(native_file_system_error::Ok(), std::move(result_entries)); } @@ -456,14 +466,14 @@ NativeFileSystemPermissionContext::PermissionStatus permission) { std::vector<blink::mojom::NativeFileSystemEntryPtr> result_entries; if (permission != PermissionStatus::GRANTED) { - std::move(callback).Run( - NativeFileSystemError::New(base::File::FILE_ERROR_ABORT), - std::move(result_entries)); + std::move(callback).Run(native_file_system_error::FromStatus( + NativeFileSystemStatus::kOperationAborted), + std::move(result_entries)); return; } result_entries.push_back(CreateDirectoryEntryFromPath(binding_context, path)); - std::move(callback).Run(NativeFileSystemError::New(base::File::FILE_OK), + std::move(callback).Run(native_file_system_error::Ok(), std::move(result_entries)); }
diff --git a/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc b/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc index 1a4a244..d252959 100644 --- a/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc +++ b/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc
@@ -95,7 +95,7 @@ manager_ptr_->GetSandboxedFileSystem(base::BindLambdaForTesting( [&](blink::mojom::NativeFileSystemErrorPtr result, blink::mojom::NativeFileSystemDirectoryHandlePtr handle) { - EXPECT_EQ(base::File::FILE_OK, result->error_code); + EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, result->status); root = std::move(handle); loop.Quit(); }));
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc index 7a52f40..4981362 100644 --- a/content/browser/network_service_client.cc +++ b/content/browser/network_service_client.cc
@@ -17,6 +17,7 @@ #include "content/browser/devtools/devtools_url_loader_interceptor.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/loader/webrtc_connections_observer.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/ssl/ssl_client_auth_handler.h" #include "content/browser/ssl/ssl_error_handler.h" #include "content/browser/ssl/ssl_manager.h" @@ -364,12 +365,21 @@ std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt); return; } - base::PostTaskAndReplyWithResult( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&GetWebContentsFromRegistry, window_id), - base::BindOnce(&OnAuthRequiredContinuation, process_id, routing_id, - request_id, url, *is_main_frame_opt, first_auth_attempt, - auth_info, head, std::move(auth_challenge_responder))); + + if (ServiceWorkerContextWrapper::IsServiceWorkerOnUIEnabled()) { + OnAuthRequiredContinuation(process_id, routing_id, request_id, url, + *is_main_frame_opt, first_auth_attempt, + auth_info, head, + std::move(auth_challenge_responder), + GetWebContentsFromRegistry(window_id)); + } else { + base::PostTaskAndReplyWithResult( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&GetWebContentsFromRegistry, window_id), + base::BindOnce(&OnAuthRequiredContinuation, process_id, routing_id, + request_id, url, *is_main_frame_opt, first_auth_attempt, + auth_info, head, std::move(auth_challenge_responder))); + } } void CreateSSLClientAuthDelegateOnIO( @@ -488,13 +498,21 @@ const base::Optional<network::ResourceResponseHead>& head, network::mojom::AuthChallengeResponderPtr auth_challenge_responder) { if (window_id) { - base::PostTaskAndReplyWithResult( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&GetIsMainFrameFromRegistry, *window_id), - base::BindOnce(&OnAuthRequiredContinuationForWindowId, *window_id, - process_id, routing_id, request_id, url, - first_auth_attempt, auth_info, head, - std::move(auth_challenge_responder))); + if (ServiceWorkerContextWrapper::IsServiceWorkerOnUIEnabled()) { + OnAuthRequiredContinuationForWindowId( + *window_id, process_id, routing_id, request_id, url, + first_auth_attempt, auth_info, head, + std::move(auth_challenge_responder), + GetIsMainFrameFromRegistry(*window_id)); + } else { + base::PostTaskAndReplyWithResult( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&GetIsMainFrameFromRegistry, *window_id), + base::BindOnce(&OnAuthRequiredContinuationForWindowId, *window_id, + process_id, routing_id, request_id, url, + first_auth_attempt, auth_info, head, + std::move(auth_challenge_responder))); + } return; } OnAuthRequiredContinuation(process_id, routing_id, request_id, url, @@ -512,12 +530,19 @@ network::mojom::ClientCertificateResponderPtr cert_responder) { // Use |window_id| if it's provided. if (window_id) { - base::PostTaskAndReplyWithResult( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&GetWebContentsFromRegistry, *window_id), - base::BindOnce(&OnCertificateRequestedContinuation, process_id, - routing_id, request_id, cert_info, - cert_responder.PassInterface())); + if (ServiceWorkerContextWrapper::IsServiceWorkerOnUIEnabled()) { + OnCertificateRequestedContinuation( + process_id, routing_id, request_id, cert_info, + cert_responder.PassInterface(), + GetWebContentsFromRegistry(*window_id)); + } else { + base::PostTaskAndReplyWithResult( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&GetWebContentsFromRegistry, *window_id), + base::BindOnce(&OnCertificateRequestedContinuation, process_id, + routing_id, request_id, cert_info, + cert_responder.PassInterface())); + } return; }
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index df0df3f3..04b8fc3 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -118,38 +118,41 @@ std::unique_ptr<storage::BlobDataHandle> blob_data_handle; }; -void RunAndQuit(base::OnceClosure closure, - base::OnceClosure quit, - base::SingleThreadTaskRunner* original_message_loop) { - std::move(closure).Run(); - original_message_loop->PostTask(FROM_HERE, std::move(quit)); -} - -void RunOnIOThreadWithDelay(base::OnceClosure closure, base::TimeDelta delay) { +void RunOnCoreThreadWithDelay(base::OnceClosure closure, + base::TimeDelta delay) { base::RunLoop run_loop; - base::PostDelayedTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&RunAndQuit, std::move(closure), run_loop.QuitClosure(), - base::RetainedRef(base::ThreadTaskRunnerHandle::Get())), - delay); + base::PostDelayedTask(FROM_HERE, + {ServiceWorkerContextWrapper::GetCoreThreadId()}, + base::BindLambdaForTesting([&]() { + std::move(closure).Run(); + run_loop.Quit(); + }), + delay); run_loop.Run(); } -void RunOnIOThread(base::OnceClosure closure) { - RunOnIOThreadWithDelay(std::move(closure), base::TimeDelta()); +void RunOnCoreThread(base::OnceClosure closure) { + base::RunLoop run_loop; + RunOrPostTaskOnThread(FROM_HERE, + ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindLambdaForTesting([&]() { + std::move(closure).Run(); + run_loop.Quit(); + })); + run_loop.Run(); } -void RunOnIOThread( +// Runs the given |callback|, which itself takes a callback, on the core thread. +// Returns when |callback| invokes its callback. +void RunOnCoreThread( base::OnceCallback<void(base::OnceClosure continuation)> callback) { base::RunLoop run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce( - std::move(callback), - base::BindOnce( - base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask), - base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, - run_loop.QuitClosure()))); + base::OnceClosure continuation = + base::BindOnce([](base::OnceClosure quit) { std::move(quit).Run(); }, + run_loop.QuitClosure()); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(std::move(callback), std::move(continuation))); run_loop.Run(); } @@ -169,7 +172,7 @@ scoped_refptr<ServiceWorkerRegistration> registration) { *out_status = status; if (!quit.is_null()) - base::PostTask(FROM_HERE, {run_quit_thread}, std::move(quit)); + RunOrPostTaskOnThread(FROM_HERE, run_quit_thread, std::move(quit)); } ServiceWorkerStorage::FindRegistrationCallback CreateFindRegistrationReceiver( @@ -204,21 +207,23 @@ explicit WorkerActivatedObserver(ServiceWorkerContextWrapper* context) : context_(context) {} void Init() { - RunOnIOThread( - base::BindOnce(&WorkerActivatedObserver::InitOnIOThread, this)); + RunOnCoreThread( + base::BindOnce(&WorkerActivatedObserver::InitOnCoreThread, this)); } // ServiceWorkerContextCoreObserver overrides. void OnVersionStateChanged(int64_t version_id, const GURL& scope, ServiceWorkerVersion::Status) override { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); const ServiceWorkerVersion* version = context_->GetLiveVersion(version_id); if (version->status() == ServiceWorkerVersion::ACTIVATED) { context_->RemoveObserver(this); version_id_ = version_id; registration_id_ = version->registration_id(); - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&WorkerActivatedObserver::Quit, this)); + RunOrPostTaskOnThread( + FROM_HERE, BrowserThread::UI, + base::BindOnce(&WorkerActivatedObserver::Quit, this)); } } void Wait() { run_loop_.Run(); } @@ -229,7 +234,7 @@ private: friend class base::RefCountedThreadSafe<WorkerActivatedObserver>; ~WorkerActivatedObserver() override {} - void InitOnIOThread() { context_->AddObserver(this); } + void InitOnCoreThread() { context_->AddObserver(this); } void Quit() { run_loop_.Quit(); } int64_t registration_id_ = blink::mojom::kInvalidServiceWorkerRegistrationId; @@ -470,13 +475,13 @@ wrapper_ = static_cast<ServiceWorkerContextWrapper*>( partition->GetServiceWorkerContext()); - RunOnIOThread( - base::BindOnce(&self::SetUpOnIOThread, base::Unretained(this))); + RunOnCoreThread( + base::BindOnce(&self::SetUpOnCoreThread, base::Unretained(this))); } void TearDownOnMainThread() override { - RunOnIOThread( - base::BindOnce(&self::TearDownOnIOThread, base::Unretained(this))); + RunOnCoreThread( + base::BindOnce(&self::TearDownOnCoreThread, base::Unretained(this))); wrapper_ = nullptr; } @@ -494,8 +499,8 @@ 1); } - virtual void SetUpOnIOThread() {} - virtual void TearDownOnIOThread() {} + virtual void SetUpOnCoreThread() {} + virtual void TearDownOnCoreThread() {} ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); } ServiceWorkerContext* public_context() { return wrapper(); } @@ -511,10 +516,11 @@ const base::string16& message, int line_number, const GURL& source_url) override { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&ConsoleListener::OnReportConsoleMessageOnUI, - base::Unretained(this), message)); + DCHECK_CURRENTLY_ON(ServiceWorkerContextWrapper::GetCoreThreadId()); + RunOrPostTaskOnThread( + FROM_HERE, BrowserThread::UI, + base::BindOnce(&ConsoleListener::OnReportConsoleMessageOnUI, + base::Unretained(this), message)); } void WaitForConsoleMessages(size_t expected_message_count) { @@ -598,8 +604,8 @@ ~ServiceWorkerVersionBrowserTest() override {} - void TearDownOnIOThread() override { - // Ensure that these resources are released while the IO thread still + void TearDownOnCoreThread() override { + // Ensure that these resources are released while the core thread still // exists. registration_ = nullptr; version_ = nullptr; @@ -611,34 +617,35 @@ blink::ServiceWorkerStatusCode expected_status, blink::mojom::ScriptType script_type = blink::mojom::ScriptType::kClassic) { - RunOnIOThread( - base::BindOnce(&self::SetUpRegistrationWithScriptTypeOnIOThread, + RunOnCoreThread( + base::BindOnce(&self::SetUpRegistrationWithScriptTypeOnCoreThread, base::Unretained(this), worker_url, script_type)); // Dispatch install on a worker. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop install_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::InstallOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::InstallOnCoreThread, base::Unretained(this), install_run_loop.QuitClosure(), &status)); install_run_loop.Run(); ASSERT_EQ(expected_status, status.value()); // Stop the worker. base::RunLoop stop_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StopOnIOThread, base::Unretained(this), - stop_run_loop.QuitClosure())); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StopOnCoreThread, base::Unretained(this), + stop_run_loop.QuitClosure())); stop_run_loop.Run(); } void ActivateTestHelper(blink::ServiceWorkerStatusCode expected_status) { base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::ActivateOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::ActivateOnCoreThread, base::Unretained(this), run_loop.QuitClosure(), &status)); run_loop.Run(); ASSERT_EQ(expected_status, status.value()); @@ -655,9 +662,9 @@ FetchResult fetch_result; fetch_result.status = blink::ServiceWorkerStatusCode::kErrorFailed; base::RunLoop fetch_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::FetchOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::FetchOnCoreThread, base::Unretained(this), fetch_run_loop.QuitClosure(), path, &prepare_result, &fetch_result)); fetch_run_loop.Run(); @@ -668,15 +675,16 @@ ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, fetch_result.status); } - void SetUpRegistrationOnIOThread(const std::string& worker_url) { - SetUpRegistrationWithScriptTypeOnIOThread( + void SetUpRegistrationOnCoreThread(const std::string& worker_url) { + SetUpRegistrationWithScriptTypeOnCoreThread( worker_url, blink::mojom::ScriptType::kClassic); } - void SetUpRegistrationWithScriptTypeOnIOThread( + void SetUpRegistrationWithScriptTypeOnCoreThread( const std::string& worker_url, blink::mojom::ScriptType script_type) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); const GURL scope = embedded_test_server()->GetURL("/service_worker/"); blink::mojom::ServiceWorkerRegistrationOptions options; options.scope = scope; @@ -697,14 +705,16 @@ registration_.get()); } - void TimeoutWorkerOnIOThread() { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void TimeoutWorkerOnCoreThread() { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); EXPECT_TRUE(version_->timeout_timer_.IsRunning()); version_->SimulatePingTimeoutForTesting(); } - void AddControlleeOnIOThread() { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void AddControlleeOnCoreThread() { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); remote_endpoints_.emplace_back(); base::WeakPtr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow( 33 /* dummy render process id */, true /* is_parent_frame_secure */, @@ -715,8 +725,9 @@ false /* notify_controllerchange */); } - void AddWaitingWorkerOnIOThread(const std::string& worker_url) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void AddWaitingWorkerOnCoreThread(const std::string& worker_url) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); scoped_refptr<ServiceWorkerVersion> waiting_version( new ServiceWorkerVersion( registration_.get(), embedded_test_server()->GetURL(worker_url), @@ -734,9 +745,9 @@ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop start_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StartOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StartOnCoreThread, base::Unretained(this), start_run_loop.QuitClosure(), &status)); start_run_loop.Run(); ASSERT_EQ(expected_status, status.value()); @@ -745,9 +756,10 @@ void StopWorker() { ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); base::RunLoop stop_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StopOnIOThread, base::Unretained(this), - stop_run_loop.QuitClosure())); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StopOnCoreThread, base::Unretained(this), + stop_run_loop.QuitClosure())); stop_run_loop.Run(); } @@ -756,15 +768,15 @@ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop store_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StoreOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StoreOnCoreThread, base::Unretained(this), store_run_loop.QuitClosure(), &status, version_id)); store_run_loop.Run(); ASSERT_EQ(expected_status, status.value()); - RunOnIOThread( - base::BindOnce(&self::NotifyDoneInstallingRegistrationOnIOThread, + RunOnCoreThread( + base::BindOnce(&self::NotifyDoneInstallingRegistrationOnCoreThread, base::Unretained(this), status.value())); } @@ -772,12 +784,12 @@ blink::ServiceWorkerStatusCode* out_status, bool* out_update_found) { base::RunLoop update_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), base::BindOnce( - &self::UpdateOnIOThread, base::Unretained(this), registration_id, + &self::UpdateOnCoreThread, base::Unretained(this), registration_id, base::BindOnce( - &self::ReceiveUpdateResultOnIOThread, base::Unretained(this), + &self::ReceiveUpdateResultOnCoreThread, base::Unretained(this), update_run_loop.QuitClosure(), out_status, out_update_found))); update_run_loop.Run(); } @@ -789,56 +801,63 @@ blink::ServiceWorkerStatusCode status = blink::ServiceWorkerStatusCode::kErrorFailed; base::RunLoop run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::FindRegistrationForIdOnIOThread, - base::Unretained(this), - run_loop.QuitClosure(), &status, id, origin)); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::FindRegistrationForIdOnCoreThread, + base::Unretained(this), run_loop.QuitClosure(), &status, + id, origin)); run_loop.Run(); ASSERT_EQ(expected_status, status); } - void FindRegistrationForIdOnIOThread(base::OnceClosure done, - blink::ServiceWorkerStatusCode* result, - int64_t id, - const GURL& origin) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void FindRegistrationForIdOnCoreThread(base::OnceClosure done, + blink::ServiceWorkerStatusCode* result, + int64_t id, + const GURL& origin) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); wrapper()->context()->storage()->FindRegistrationForId( id, origin, CreateFindRegistrationReceiver(BrowserThread::UI, std::move(done), result)); } - void NotifyDoneInstallingRegistrationOnIOThread( + void NotifyDoneInstallingRegistrationOnCoreThread( blink::ServiceWorkerStatusCode status) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); wrapper()->context()->storage()->NotifyDoneInstallingRegistration( registration_.get(), version_.get(), status); } - void StartOnIOThread(base::OnceClosure done, - base::Optional<blink::ServiceWorkerStatusCode>* result) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void StartOnCoreThread( + base::OnceClosure done, + base::Optional<blink::ServiceWorkerStatusCode>* result) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); version_->SetMainScriptHttpResponseInfo(CreateHttpResponseInfo()); version_->StartWorker( ServiceWorkerMetrics::EventType::UNKNOWN, CreateReceiver(BrowserThread::UI, std::move(done), result)); } - void InstallOnIOThread( + void InstallOnCoreThread( const base::RepeatingClosure& done, base::Optional<blink::ServiceWorkerStatusCode>* result) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); version_->RunAfterStartWorker( ServiceWorkerMetrics::EventType::INSTALL, - base::BindOnce(&self::DispatchInstallEventOnIOThread, + base::BindOnce(&self::DispatchInstallEventOnCoreThread, base::Unretained(this), done, result)); } - void DispatchInstallEventOnIOThread( + void DispatchInstallEventOnCoreThread( base::OnceClosure done, base::Optional<blink::ServiceWorkerStatusCode>* result, blink::ServiceWorkerStatusCode start_worker_status) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, start_worker_status); version_->SetStatus(ServiceWorkerVersion::INSTALLING); @@ -847,11 +866,11 @@ ServiceWorkerMetrics::EventType::INSTALL, CreateReceiver(BrowserThread::UI, repeating_done, result)); version_->endpoint()->DispatchInstallEvent(base::BindOnce( - &self::ReceiveInstallEventOnIOThread, base::Unretained(this), + &self::ReceiveInstallEventOnCoreThread, base::Unretained(this), repeating_done, result, request_id)); } - void ReceiveInstallEventOnIOThread( + void ReceiveInstallEventOnCoreThread( base::OnceClosure done, base::Optional<blink::ServiceWorkerStatusCode>* out_result, int request_id, @@ -867,13 +886,14 @@ *out_result = mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status); if (!done.is_null()) - base::PostTask(FROM_HERE, {BrowserThread::UI}, std::move(done)); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, std::move(done)); } - void StoreOnIOThread(base::OnceClosure done, - base::Optional<blink::ServiceWorkerStatusCode>* result, - int64_t version_id) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void StoreOnCoreThread(base::OnceClosure done, + base::Optional<blink::ServiceWorkerStatusCode>* result, + int64_t version_id) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ServiceWorkerVersion* version = wrapper()->context()->GetLiveVersion(version_id); wrapper()->context()->storage()->StoreRegistration( @@ -881,21 +901,23 @@ CreateReceiver(BrowserThread::UI, std::move(done), result)); } - void ActivateOnIOThread( + void ActivateOnCoreThread( base::OnceClosure done, base::Optional<blink::ServiceWorkerStatusCode>* result) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); version_->RunAfterStartWorker( ServiceWorkerMetrics::EventType::ACTIVATE, - base::BindOnce(&self::DispatchActivateEventOnIOThread, + base::BindOnce(&self::DispatchActivateEventOnCoreThread, base::Unretained(this), std::move(done), result)); } - void DispatchActivateEventOnIOThread( + void DispatchActivateEventOnCoreThread( base::OnceClosure done, base::Optional<blink::ServiceWorkerStatusCode>* result, blink::ServiceWorkerStatusCode start_worker_status) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, start_worker_status); version_->SetStatus(ServiceWorkerVersion::ACTIVATING); registration_->SetActiveVersion(version_.get()); @@ -906,9 +928,10 @@ version_->CreateSimpleEventCallback(request_id)); } - void UpdateOnIOThread(int registration_id, - ServiceWorkerContextCore::UpdateCallback callback) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void UpdateOnCoreThread(int registration_id, + ServiceWorkerContextCore::UpdateCallback callback) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ServiceWorkerRegistration* registration = wrapper()->context()->GetLiveRegistration(registration_id); ASSERT_TRUE(registration); @@ -917,26 +940,28 @@ false /* skip_script_comparison */, std::move(callback)); } - void ReceiveUpdateResultOnIOThread(const base::RepeatingClosure& done_on_ui, - blink::ServiceWorkerStatusCode* out_status, - bool* out_update_found, - blink::ServiceWorkerStatusCode status, - const std::string& status_message, - int64_t registration_id) { + void ReceiveUpdateResultOnCoreThread( + const base::RepeatingClosure& done_on_ui, + blink::ServiceWorkerStatusCode* out_status, + bool* out_update_found, + blink::ServiceWorkerStatusCode status, + const std::string& status_message, + int64_t registration_id) { ServiceWorkerRegistration* registration = wrapper()->context()->GetLiveRegistration(registration_id); DCHECK(registration); *out_status = status; *out_update_found = !!registration->installing_version(); - base::PostTask(FROM_HERE, {BrowserThread::UI}, done_on_ui); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, done_on_ui); } - void FetchOnIOThread(base::OnceClosure done, - const std::string& path, - bool* prepare_result, - FetchResult* result) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void FetchOnCoreThread(base::OnceClosure done, + const std::string& path, + bool* prepare_result, + FetchResult* result) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); version_->SetStatus(ServiceWorkerVersion::ACTIVATED); GURL url = embedded_test_server()->GetURL(path); ResourceType resource_type = ResourceType::kMainFrame; @@ -955,41 +980,45 @@ base::Time GetLastUpdateCheck(int64_t registration_id) { base::Time last_update_time; base::RunLoop time_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::GetLastUpdateCheckOnIOThread, + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::GetLastUpdateCheckOnCoreThread, base::Unretained(this), registration_id, &last_update_time, time_run_loop.QuitClosure())); time_run_loop.Run(); return last_update_time; } - void GetLastUpdateCheckOnIOThread(int64_t registration_id, - base::Time* out_time, - const base::RepeatingClosure& done_on_ui) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void GetLastUpdateCheckOnCoreThread( + int64_t registration_id, + base::Time* out_time, + const base::RepeatingClosure& done_on_ui) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ServiceWorkerRegistration* registration = wrapper()->context()->GetLiveRegistration(registration_id); ASSERT_TRUE(registration); *out_time = registration->last_update_check(); - base::PostTask(FROM_HERE, {BrowserThread::UI}, done_on_ui); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, done_on_ui); } - void SetLastUpdateCheckOnIOThread(int64_t registration_id, - base::Time last_update_time, - const base::RepeatingClosure& done_on_ui) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + void SetLastUpdateCheckOnCoreThread( + int64_t registration_id, + base::Time last_update_time, + const base::RepeatingClosure& done_on_ui) { + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ServiceWorkerRegistration* registration = wrapper()->context()->GetLiveRegistration(registration_id); ASSERT_TRUE(registration); registration->set_last_update_check(last_update_time); - base::PostTask(FROM_HERE, {BrowserThread::UI}, done_on_ui); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, done_on_ui); } // Contrary to the style guide, the output parameter of this function comes // before input parameters so Bind can be used on it to create a FetchCallback // to pass to DispatchFetchEvent. - void ReceiveFetchResultOnIOThread( + void ReceiveFetchResultOnCoreThread( base::OnceClosure quit, ChromeBlobStorageContext* blob_context, FetchResult* out_result, @@ -999,7 +1028,8 @@ blink::mojom::ServiceWorkerStreamHandlePtr /* stream */, blink::mojom::ServiceWorkerFetchEventTimingPtr /* timing */, scoped_refptr<ServiceWorkerVersion> worker) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); ASSERT_TRUE(fetch_dispatcher_); fetch_dispatcher_.reset(); out_result->status = actual_status; @@ -1012,32 +1042,32 @@ out_result->response->blob->uuid); } if (!quit.is_null()) - base::PostTask(FROM_HERE, {BrowserThread::UI}, std::move(quit)); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, std::move(quit)); } ServiceWorkerFetchDispatcher::FetchCallback CreateResponseReceiver( base::OnceClosure quit, ChromeBlobStorageContext* blob_context, FetchResult* result) { - return base::BindOnce(&self::ReceiveFetchResultOnIOThread, + return base::BindOnce(&self::ReceiveFetchResultOnCoreThread, base::Unretained(this), std::move(quit), base::RetainedRef(blob_context), result); } - void StopOnIOThread(base::OnceClosure done) { + void StopOnCoreThread(base::OnceClosure done) { ASSERT_TRUE(version_.get()); version_->StopWorker(std::move(done)); } - void SetActiveVersionOnIOThread(ServiceWorkerRegistration* registration, - ServiceWorkerVersion* version) { + void SetActiveVersionOnCoreThread(ServiceWorkerRegistration* registration, + ServiceWorkerVersion* version) { version->set_fetch_handler_existence( ServiceWorkerVersion::FetchHandlerExistence::EXISTS); version->SetStatus(ServiceWorkerVersion::ACTIVATED); registration->SetActiveVersion(version); } - void SetResourcesOnIOThread( + void SetResourcesOnCoreThread( ServiceWorkerVersion* version, const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources) { version->script_cache_map()->resource_map_.clear(); @@ -1054,24 +1084,26 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) { StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread, - base::Unretained(this), - "/service_worker/worker.js")); + RunOnCoreThread(base::BindOnce(&self::SetUpRegistrationOnCoreThread, + base::Unretained(this), + "/service_worker/worker.js")); // Start a worker. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop start_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StartOnIOThread, base::Unretained(this), - start_run_loop.QuitClosure(), &status)); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StartOnCoreThread, base::Unretained(this), + start_run_loop.QuitClosure(), &status)); start_run_loop.Run(); ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value()); // Stop the worker. base::RunLoop stop_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StopOnIOThread, base::Unretained(this), - stop_run_loop.QuitClosure())); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StopOnCoreThread, base::Unretained(this), + stop_run_loop.QuitClosure())); stop_run_loop.Run(); } @@ -1080,15 +1112,16 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, DropCountsOnBlinkUseCounter) { StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread, - base::Unretained(this), - "/service_worker/worker.js")); + RunOnCoreThread(base::BindOnce(&self::SetUpRegistrationOnCoreThread, + base::Unretained(this), + "/service_worker/worker.js")); // Start a worker. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop start_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StartOnIOThread, base::Unretained(this), - start_run_loop.QuitClosure(), &status)); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StartOnCoreThread, base::Unretained(this), + start_run_loop.QuitClosure(), &status)); start_run_loop.Run(); ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value()); @@ -1098,9 +1131,10 @@ // Stop the worker. base::RunLoop stop_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StopOnIOThread, base::Unretained(this), - stop_run_loop.QuitClosure())); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StopOnCoreThread, base::Unretained(this), + stop_run_loop.QuitClosure())); stop_run_loop.Run(); // Expect no PageVisits count. EXPECT_EQ(nullptr, base::StatisticsRecorder::FindHistogram( @@ -1109,9 +1143,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) { StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread, - base::Unretained(this), - "/service_worker/nonexistent.js")); + RunOnCoreThread(base::BindOnce(&self::SetUpRegistrationOnCoreThread, + base::Unretained(this), + "/service_worker/nonexistent.js")); // Start a worker for nonexistent URL. StartWorker(blink::ServiceWorkerStatusCode::kErrorNetwork); @@ -1121,19 +1155,19 @@ StartServerAndNavigateToSetup(); // Create a registration with an active version. - RunOnIOThread(base::BindOnce( - &ServiceWorkerVersionBrowserTest::SetUpRegistrationOnIOThread, + RunOnCoreThread(base::BindOnce( + &ServiceWorkerVersionBrowserTest::SetUpRegistrationOnCoreThread, base::Unretained(this), "/service_worker/worker.js")); - RunOnIOThread(base::BindOnce( - &ServiceWorkerVersionBrowserTest::SetActiveVersionOnIOThread, + RunOnCoreThread(base::BindOnce( + &ServiceWorkerVersionBrowserTest::SetActiveVersionOnCoreThread, base::Unretained(this), base::Unretained(registration_.get()), base::Unretained(version_.get()))); // Add a non-existent resource to the version. std::vector<ServiceWorkerDatabase::ResourceRecord> records = { ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100)}; - RunOnIOThread(base::BindOnce( - &ServiceWorkerVersionBrowserTest::SetResourcesOnIOThread, + RunOnCoreThread(base::BindOnce( + &ServiceWorkerVersionBrowserTest::SetResourcesOnCoreThread, base::Unretained(this), base::Unretained(version_.get()), records)); // Store the registration. @@ -1160,24 +1194,24 @@ ASSERT_TRUE(registration_->active_version()); // Give the version a controllee. - RunOnIOThread( - base::BindOnce(&self::AddControlleeOnIOThread, base::Unretained(this))); + RunOnCoreThread( + base::BindOnce(&self::AddControlleeOnCoreThread, base::Unretained(this))); // Set a non-existent resource to the version. std::vector<ServiceWorkerDatabase::ResourceRecord> records = { ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100)}; - RunOnIOThread(base::BindOnce( - &ServiceWorkerVersionBrowserTest::SetResourcesOnIOThread, + RunOnCoreThread(base::BindOnce( + &ServiceWorkerVersionBrowserTest::SetResourcesOnCoreThread, base::Unretained(this), base::Unretained(version_.get()), records)); // Make a waiting version and store it. - RunOnIOThread(base::BindOnce(&self::AddWaitingWorkerOnIOThread, - base::Unretained(this), - "/service_worker/worker.js")); + RunOnCoreThread(base::BindOnce(&self::AddWaitingWorkerOnCoreThread, + base::Unretained(this), + "/service_worker/worker.js")); records = { ServiceWorkerDatabase::ResourceRecord(31, version_->script_url(), 100)}; - RunOnIOThread(base::BindOnce( - &ServiceWorkerVersionBrowserTest::SetResourcesOnIOThread, + RunOnCoreThread(base::BindOnce( + &ServiceWorkerVersionBrowserTest::SetResourcesOnCoreThread, base::Unretained(this), base::Unretained(registration_->waiting_version()), records)); StoreRegistration(registration_->waiting_version()->version_id(), @@ -1266,21 +1300,21 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, InstallWithWaitUntil_RejectConsoleMessage) { StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread, - base::Unretained(this), - "/service_worker/worker_install_rejected.js")); + RunOnCoreThread(base::BindOnce(&self::SetUpRegistrationOnCoreThread, + base::Unretained(this), + "/service_worker/worker_install_rejected.js")); ConsoleListener console_listener; - RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver, - base::Unretained(version_->embedded_worker()), - &console_listener)); + RunOnCoreThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver, + base::Unretained(version_->embedded_worker()), + &console_listener)); // Dispatch install on a worker. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop install_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::InstallOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::InstallOnCoreThread, base::Unretained(this), install_run_loop.QuitClosure(), &status)); install_run_loop.Run(); ASSERT_EQ(blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected, @@ -1291,9 +1325,9 @@ console_listener.WaitForConsoleMessages(1); ASSERT_NE(base::string16::npos, console_listener.messages()[0].find(expected)); - RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver, - base::Unretained(version_->embedded_worker()), - &console_listener)); + RunOnCoreThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver, + base::Unretained(version_->embedded_worker()), + &console_listener)); } // Tests starting an installed classic service worker while offline. @@ -1339,9 +1373,9 @@ explicit WaitForLoaded(base::OnceClosure quit) : quit_(std::move(quit)) {} void OnScriptEvaluationStart() override { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK_CURRENTLY_ON(ServiceWorkerContextWrapper::GetCoreThreadId()); DCHECK(quit_); - base::PostTask(FROM_HERE, {BrowserThread::UI}, std::move(quit_)); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, std::move(quit_)); } private: @@ -1350,25 +1384,26 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) { StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread, - base::Unretained(this), - "/service_worker/while_true_worker.js")); + RunOnCoreThread(base::BindOnce(&self::SetUpRegistrationOnCoreThread, + base::Unretained(this), + "/service_worker/while_true_worker.js")); // Start a worker, waiting until the script is loaded. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop start_run_loop; base::RunLoop load_run_loop; WaitForLoaded wait_for_load(load_run_loop.QuitClosure()); - RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver, - base::Unretained(version_->embedded_worker()), - &wait_for_load)); - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StartOnIOThread, base::Unretained(this), - start_run_loop.QuitClosure(), &status)); + RunOnCoreThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver, + base::Unretained(version_->embedded_worker()), + &wait_for_load)); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StartOnCoreThread, base::Unretained(this), + start_run_loop.QuitClosure(), &status)); load_run_loop.Run(); - RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver, - base::Unretained(version_->embedded_worker()), - &wait_for_load)); + RunOnCoreThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver, + base::Unretained(version_->embedded_worker()), + &wait_for_load)); // The script has loaded but start has not completed yet. ASSERT_FALSE(status); @@ -1376,8 +1411,8 @@ // Simulate execution timeout. Use a delay to prevent killing the worker // before it's started execution. - RunOnIOThreadWithDelay( - base::BindOnce(&self::TimeoutWorkerOnIOThread, base::Unretained(this)), + RunOnCoreThreadWithDelay( + base::BindOnce(&self::TimeoutWorkerOnCoreThread, base::Unretained(this)), base::TimeDelta::FromMilliseconds(100)); start_run_loop.Run(); @@ -1386,30 +1421,31 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) { StartServerAndNavigateToSetup(); - RunOnIOThread( - base::BindOnce(&self::SetUpRegistrationOnIOThread, base::Unretained(this), - "/service_worker/while_true_in_install_worker.js")); + RunOnCoreThread(base::BindOnce( + &self::SetUpRegistrationOnCoreThread, base::Unretained(this), + "/service_worker/while_true_in_install_worker.js")); // Start a worker. base::Optional<blink::ServiceWorkerStatusCode> status; base::RunLoop start_run_loop; - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::StartOnIOThread, base::Unretained(this), - start_run_loop.QuitClosure(), &status)); + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::StartOnCoreThread, base::Unretained(this), + start_run_loop.QuitClosure(), &status)); start_run_loop.Run(); ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value()); // Dispatch an event. base::RunLoop install_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::InstallOnIOThread, base::Unretained(this), + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::InstallOnCoreThread, base::Unretained(this), install_run_loop.QuitClosure(), &status)); // Simulate execution timeout. Use a delay to prevent killing the worker // before it's started execution. - RunOnIOThreadWithDelay( - base::BindOnce(&self::TimeoutWorkerOnIOThread, base::Unretained(this)), + RunOnCoreThreadWithDelay( + base::BindOnce(&self::TimeoutWorkerOnCoreThread, base::Unretained(this)), base::TimeDelta::FromMilliseconds(100)); install_run_loop.Run(); @@ -1444,8 +1480,8 @@ EXPECT_EQ(expected_headers, response->headers); std::string body; - RunOnIOThread(base::BindOnce(&ReadResponseBody, &body, - base::Owned(blob_data_handle.release()))); + RunOnCoreThread(base::BindOnce(&ReadResponseBody, &body, + base::Owned(blob_data_handle.release()))); EXPECT_EQ("This resource is gone. Gone, gone, gone.", body); } @@ -1525,9 +1561,9 @@ ActivateTestHelper(blink::ServiceWorkerStatusCode::kOk); ConsoleListener console_listener; - RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver, - base::Unretained(version_->embedded_worker()), - &console_listener)); + RunOnCoreThread(base::BindOnce(&EmbeddedWorkerInstance::AddObserver, + base::Unretained(version_->embedded_worker()), + &console_listener)); FetchOnRegisteredWorker("/service_worker/empty.html", &result, &response, &blob_data_handle); @@ -1539,9 +1575,9 @@ ASSERT_NE(base::string16::npos, console_listener.messages()[0].find(expected1)); ASSERT_EQ(0u, console_listener.messages()[1].find(expected2)); - RunOnIOThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver, - base::Unretained(version_->embedded_worker()), - &console_listener)); + RunOnCoreThread(base::BindOnce(&EmbeddedWorkerInstance::RemoveObserver, + base::Unretained(version_->embedded_worker()), + &console_listener)); ASSERT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse, result); @@ -1605,9 +1641,9 @@ { last_update_time = base::Time::Now() - base::TimeDelta::FromHours(24); base::RunLoop time_run_loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&self::SetLastUpdateCheckOnIOThread, + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), + base::BindOnce(&self::SetLastUpdateCheckOnCoreThread, base::Unretained(this), registration_id, last_update_time, time_run_loop.QuitClosure())); time_run_loop.Run(); @@ -1950,12 +1986,13 @@ // Simulate to attach DevTools. base::RunLoop loop; - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + RunOrPostTaskOnThread( + FROM_HERE, ServiceWorkerContextWrapper::GetCoreThreadId(), base::BindOnce( [](base::OnceClosure done, ServiceWorkerContextWrapper* wrapper, int64_t version_id) { - ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + ASSERT_TRUE(BrowserThread::CurrentlyOn( + ServiceWorkerContextWrapper::GetCoreThreadId())); scoped_refptr<ServiceWorkerVersion> version = wrapper->GetLiveVersion(version_id); version->SetDevToolsAttached(true); @@ -2884,7 +2921,7 @@ // Verify the number of resources in the implicit script cache is correct. const int kExpectedNumResources = 2; int num_resources = 0; - RunOnIOThread(base::BindOnce( + RunOnCoreThread(base::BindOnce( &CountScriptResources, base::Unretained(wrapper()), embedded_test_server()->GetURL(kScopeUrl), &num_resources)); EXPECT_EQ(kExpectedNumResources, num_resources); @@ -2980,7 +3017,8 @@ void OnRunningStateChanged(ServiceWorkerVersion* version) override { if (version->running_status() == EmbeddedWorkerStatus::STOPPED) { DCHECK(quit_closure_); - base::PostTask(FROM_HERE, {BrowserThread::UI}, std::move(quit_closure_)); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, + std::move(quit_closure_)); } } @@ -2991,9 +3029,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, RendererCrash) { // Start a worker. StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationOnIOThread, - base::Unretained(this), - "/service_worker/worker.js")); + RunOnCoreThread(base::BindOnce(&self::SetUpRegistrationOnCoreThread, + base::Unretained(this), + "/service_worker/worker.js")); StartWorker(blink::ServiceWorkerStatusCode::kOk); // Crash the renderer process. The version should stop. @@ -3003,32 +3041,32 @@ process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); base::RunLoop run_loop; StopObserver observer(run_loop.QuitClosure()); - RunOnIOThread(base::BindOnce(&ServiceWorkerVersion::AddObserver, - base::Unretained(version_.get()), &observer)); + RunOnCoreThread(base::BindOnce(&ServiceWorkerVersion::AddObserver, + base::Unretained(version_.get()), &observer)); process->Shutdown(content::RESULT_CODE_KILLED); run_loop.Run(); process_watcher.Wait(); EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status()); - RunOnIOThread(base::BindOnce(&ServiceWorkerVersion::RemoveObserver, - base::Unretained(version_.get()), &observer)); + RunOnCoreThread(base::BindOnce(&ServiceWorkerVersion::RemoveObserver, + base::Unretained(version_.get()), &observer)); } class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest { public: using self = ServiceWorkerBlackBoxBrowserTest; - void FindRegistrationOnIO(const GURL& document_url, - blink::ServiceWorkerStatusCode* status, - base::OnceClosure continuation) { + void FindRegistrationOnCoreThread(const GURL& document_url, + blink::ServiceWorkerStatusCode* status, + base::OnceClosure continuation) { wrapper()->FindReadyRegistrationForDocument( document_url, base::BindOnce( - &ServiceWorkerBlackBoxBrowserTest::DidFindRegistrationOnIO, + &ServiceWorkerBlackBoxBrowserTest::DidFindRegistrationOnCoreThread, base::Unretained(this), status, std::move(continuation))); } - void DidFindRegistrationOnIO( + void DidFindRegistrationOnCoreThread( blink::ServiceWorkerStatusCode* out_status, base::OnceClosure continuation, blink::ServiceWorkerStatusCode status, @@ -3124,8 +3162,8 @@ { blink::ServiceWorkerStatusCode status = blink::ServiceWorkerStatusCode::kErrorFailed; - RunOnIOThread(base::BindOnce( - &ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO, + RunOnCoreThread(base::BindOnce( + &ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnCoreThread, base::Unretained(this), embedded_test_server()->GetURL("/service_worker/empty.html"), &status)); EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound, status); @@ -3142,8 +3180,8 @@ if (version_) version_->RemoveObserver(this); } - void SetUpRegistrationAndListenerOnIOThread(const std::string& worker_url) { - SetUpRegistrationOnIOThread(worker_url); + void SetUpRegistrationAndListenerOnCoreThread(const std::string& worker_url) { + SetUpRegistrationOnCoreThread(worker_url); version_->AddObserver(this); } void StartWorkerAndWaitUntilCachedMetadataUpdated( @@ -3168,8 +3206,8 @@ size_t size) override { DCHECK(cache_updated_closure_); metadata_size_ = size; - base::PostTask(FROM_HERE, {BrowserThread::UI}, - std::move(cache_updated_closure_)); + RunOrPostTaskOnThread(FROM_HERE, BrowserThread::UI, + std::move(cache_updated_closure_)); } private: @@ -3180,9 +3218,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8FullCodeCacheTest, FullCode) { StartServerAndNavigateToSetup(); - RunOnIOThread(base::BindOnce(&self::SetUpRegistrationAndListenerOnIOThread, - base::Unretained(this), - "/service_worker/worker.js")); + RunOnCoreThread( + base::BindOnce(&self::SetUpRegistrationAndListenerOnCoreThread, + base::Unretained(this), "/service_worker/worker.js")); StartWorkerAndWaitUntilCachedMetadataUpdated( blink::ServiceWorkerStatusCode::kOk); @@ -3226,11 +3264,12 @@ int GetSizeImpl() { int result = 0; - RunOnIOThread(base::BindOnce(&self::OpenCacheOnIOThread, this, &result)); + RunOnCoreThread( + base::BindOnce(&self::OpenCacheOnCoreThread, this, &result)); return result; } - void OpenCacheOnIOThread(int* result, base::OnceClosure continuation) { + void OpenCacheOnCoreThread(int* result, base::OnceClosure continuation) { CacheStorageHandle cache_storage = cache_storage_context_->CacheManager()->OpenCacheStorage( url::Origin::Create(origin_), CacheStorageOwner::kCacheAPI);
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 7d848dd..5a23b61 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -2042,12 +2042,20 @@ // was previously allowed and installed, but later content settings changed to // disallow this scope. Since this worker might not be used for a specific // tab, pass a null callback as WebContents getter. - // resource_context() can return null in unit tests. - if ((context_->wrapper()->resource_context() && - !GetContentClient()->browser()->AllowServiceWorkerOnIO( - scope_, scope_, script_url_, context_->wrapper()->resource_context(), - base::NullCallback()))) { - return false; + if (ServiceWorkerContextWrapper::IsServiceWorkerOnUIEnabled()) { + if (!GetContentClient()->browser()->AllowServiceWorkerOnUI( + scope_, scope_, script_url_, context_->wrapper()->browser_context(), + base::NullCallback())) { + return false; + } + } else { + // resource_context() can return null in unit tests. + if ((context_->wrapper()->resource_context() && + !GetContentClient()->browser()->AllowServiceWorkerOnIO( + scope_, scope_, script_url_, + context_->wrapper()->resource_context(), base::NullCallback()))) { + return false; + } } return true;
diff --git a/content/browser/sms/README.md b/content/browser/sms/README.md index aebf884..80488cc 100644 --- a/content/browser/sms/README.md +++ b/content/browser/sms/README.md
@@ -35,8 +35,10 @@ ## Related Documentation -[design doc](https://docs.google.com/document/d/1dB5UM9x8Ap2-bs6Xn0KnbC_B1KNLIUv4W05MunuXYh0) +[Design Doc](https://docs.google.com/document/d/1dB5UM9x8Ap2-bs6Xn0KnbC_B1KNLIUv4W05MunuXYh0) [SMS Receiver API explainer](https://github.com/samuelgoto/sms-receiver) -[launch bug](https://bugs.chromium.org/p/chromium/issues/detail?id=670299) +[How to use the SMS Receiver API](https://github.com/samuelgoto/sms-receiver/blob/master/HOWTO.md) + +[Launch Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=670299)
diff --git a/content/browser/web_contents/frame_tree_node_id_registry.h b/content/browser/web_contents/frame_tree_node_id_registry.h index b96c2a1..3dbd5be2 100644 --- a/content/browser/web_contents/frame_tree_node_id_registry.h +++ b/content/browser/web_contents/frame_tree_node_id_registry.h
@@ -17,10 +17,14 @@ class WebContents; -// A global map of UnguessableToken to FrameTreeNode id. This registry lives -// and is used only on the IO thread, as it's convenient for the current user -// of the class (ServiceWorkerProviderHost, which should move to the UI thread -// eventually). This is currently used to map a network request to a frame so +// A global map of UnguessableToken to FrameTreeNode id. This registry lives and +// is used only on the thread identified by +// ServiceWorkerContextWrapper::GetCoreThreadId(), as that's the thread the +// class that adds/removes from this registry is on (ServiceWorkerProviderHost). +// TODO(crbug.com/824858): Make this live on the UI thread once the service +// worker core thread moves to the UI thread. +// +// This is currently used to map a network request to a frame so // that the network service can tell the browser to display tab-level UI // required for the request in certain cases, including client certificates and // basic HTTP authentication.
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 18204bb4..9304dc1e 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -351,63 +351,6 @@ return -1; } -WebData loadAudioSpatializationResource(const char* name) { -#ifdef IDR_AUDIO_SPATIALIZATION_COMPOSITE - if (!strcmp(name, "Composite")) { - base::StringPiece resource = GetContentClient()->GetDataResource( - IDR_AUDIO_SPATIALIZATION_COMPOSITE, ui::SCALE_FACTOR_NONE); - return WebData(resource.data(), resource.size()); - } -#endif - -#ifdef IDR_AUDIO_SPATIALIZATION_T000_P000 - const size_t kExpectedSpatializationNameLength = 31; - if (strlen(name) != kExpectedSpatializationNameLength) { - return WebData(); - } - - // Extract the azimuth and elevation from the resource name. - int azimuth = 0; - int elevation = 0; - int values_parsed = - sscanf(name, "IRC_Composite_C_R0195_T%3d_P%3d", &azimuth, &elevation); - if (values_parsed != 2) { - return WebData(); - } - - // The resource index values go through the elevations first, then azimuths. - const int kAngleSpacing = 15; - - // 0 <= elevation <= 90 (or 315 <= elevation <= 345) - // in increments of 15 degrees. - int elevation_index = - elevation <= 90 ? elevation / kAngleSpacing : - 7 + (elevation - 315) / kAngleSpacing; - bool is_elevation_index_good = 0 <= elevation_index && elevation_index < 10; - - // 0 <= azimuth < 360 in increments of 15 degrees. - int azimuth_index = azimuth / kAngleSpacing; - bool is_azimuth_index_good = 0 <= azimuth_index && azimuth_index < 24; - - const int kNumberOfElevations = 10; - const int kNumberOfAudioResources = 240; - int resource_index = kNumberOfElevations * azimuth_index + elevation_index; - bool is_resource_index_good = 0 <= resource_index && - resource_index < kNumberOfAudioResources; - - if (is_azimuth_index_good && is_elevation_index_good && - is_resource_index_good) { - const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000; - base::StringPiece resource = GetContentClient()->GetDataResource( - kFirstAudioResourceIndex + resource_index, ui::SCALE_FACTOR_NONE); - return WebData(resource.data(), resource.size()); - } -#endif // IDR_AUDIO_SPATIALIZATION_T000_P000 - - NOTREACHED(); - return WebData(); -} - // This must match third_party/WebKit/public/blink_resources.grd. // In particular, |is_gzipped| corresponds to compress="gzip". struct DataResource { @@ -434,6 +377,8 @@ {"placeholderIcon", IDR_PLACEHOLDER_ICON, ui::SCALE_FACTOR_100P, false}, {"brokenCanvas", IDR_BROKENCANVAS, ui::SCALE_FACTOR_100P, false}, {"brokenCanvas@2x", IDR_BROKENCANVAS, ui::SCALE_FACTOR_200P, false}, + {"Composite", IDR_AUDIO_SPATIALIZATION_COMPOSITE, ui::SCALE_FACTOR_NONE, + false}, }; class NestedMessageLoopRunnerImpl @@ -497,11 +442,6 @@ if (!strlen(name)) return WebData(); - // Check the name prefix to see if it's an audio resource. - if (base::StartsWith(name, "IRC_Composite", base::CompareCase::SENSITIVE) || - base::StartsWith(name, "Composite", base::CompareCase::SENSITIVE)) - return loadAudioSpatializationResource(name); - // TODO(flackr): We should use a better than linear search here, a trie would // be ideal. for (size_t i = 0; i < base::size(kDataResources); ++i) {
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 1a87ac0f..a7a59da 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -361,6 +361,7 @@ "//content/browser/android/select_popup.cc", "//content/public/browser/android/child_process_importance.h", "//content/public/browser/android/motion_event_action.h", + "//content/public/browser/bluetooth_scanning_prompt.h", "//content/public/browser/browser_task_traits.h", "//content/public/browser/browsing_data_remover.h", "//content/public/browser/invalidate_type.h",
diff --git a/content/public/browser/bluetooth_scanning_prompt.h b/content/public/browser/bluetooth_scanning_prompt.h index 6f8b339..933625f 100644 --- a/content/public/browser/bluetooth_scanning_prompt.h +++ b/content/public/browser/bluetooth_scanning_prompt.h
@@ -17,6 +17,9 @@ // Bluetooth advertisement packets from Bluetooth devices. class CONTENT_EXPORT BluetoothScanningPrompt { public: + // A Java counterpart will be generated for this enum. + // GENERATED_JAVA_ENUM_PACKAGE: ( + // org.chromium.content_public.browser.bluetooth_scanning) enum class Event { kAllow, kBlock,
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 78f0053..a1f9989 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -232,7 +232,7 @@ // API font fallback calls to retrieve a fallback font family name as opposed to // using a hard-coded font lookup table. const base::Feature kLegacyWindowsDWriteFontFallback{ - "LegacyWindowsDWriteFontFallback", base::FEATURE_DISABLED_BY_DEFAULT}; + "LegacyWindowsDWriteFontFallback", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kLogJsConsoleMessages{"LogJsConsoleMessages", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 9bcd88b3..c07fd1e 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -92,6 +92,10 @@ // a local frame for this view, then it also manages a RenderWidget for the // main frame. // +// The main distinction between RenderView and RenderWidget is that the +// RenderView holds synchronized state across all processes participating in the +// frame tree, whereas the RenderWidget holds per-root-frame state. +// // TODO(419087): Currently even though the RenderViewImpl "manages" the // RenderWidget, the RenderWidget owns the RenderViewImpl. This is due to // RenderViewImpl historically being a subclass of RenderWidget. Breaking
diff --git a/content/shell/browser/DEPS b/content/shell/browser/DEPS index 2d807b6..d6588ee 100644 --- a/content/shell/browser/DEPS +++ b/content/shell/browser/DEPS
@@ -13,6 +13,9 @@ "shell\.cc": [ "+content/shell/browser/layout_test", ], + "shell_browser_main_parts_mac\.mm": [ + "+content/browser/sandbox_parameters_mac.h", + ], "shell_devtools_manager_delegate\.cc": [ "+content/shell/browser/layout_test", ],
diff --git a/content/shell/browser/shell_browser_main_parts_mac.mm b/content/shell/browser/shell_browser_main_parts_mac.mm index 311f2a9..0109eac 100644 --- a/content/shell/browser/shell_browser_main_parts_mac.mm +++ b/content/shell/browser/shell_browser_main_parts_mac.mm
@@ -9,6 +9,8 @@ #include "base/mac/bundle_locations.h" #include "base/mac/scoped_nsobject.h" #include "base/mac/sdk_forward_declarations.h" +#include "content/browser/sandbox_parameters_mac.h" // nogncheck +#include "net/test/test_data_directory.h" namespace { @@ -132,6 +134,10 @@ void ShellBrowserMainParts::PreMainMessageLoopStart() { base::scoped_nsobject<NSMenu> main_menu = BuildMainMenu(); [[NSApplication sharedApplication] setMainMenu:main_menu]; + + // Expand the network service sandbox to allow reading the test TLS + // certificates. + SetNetworkTestCertsDirectoryForTesting(net::GetTestCertsDirectory()); } } // namespace content
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 6fbe4b3..80214e5 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -523,6 +523,11 @@ return network_context; } +std::vector<base::FilePath> +ShellContentBrowserClient::GetNetworkContextsParentDirectory() { + return {browser_context()->GetPath()}; +} + ShellBrowserContext* ShellContentBrowserClient::browser_context() { return shell_browser_main_parts_->browser_context(); }
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index 075ec5e..e07c9a0 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -103,6 +103,7 @@ BrowserContext* context, bool in_memory, const base::FilePath& relative_partition_path) override; + std::vector<base::FilePath> GetNetworkContextsParentDirectory() override; ShellBrowserContext* browser_context(); ShellBrowserContext* off_the_record_browser_context();
diff --git a/content/test/content_browser_test_test.cc b/content/test/content_browser_test_test.cc index c87d7bc0..5a7340e7 100644 --- a/content/test/content_browser_test_test.cc +++ b/content/test/content_browser_test_test.cc
@@ -14,6 +14,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" #include "base/test/launcher/test_launcher.h" +#include "base/test/launcher/test_launcher_test_utils.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_restrictions.h" @@ -143,6 +144,78 @@ } } +// The following 3 tests are disabled as they are meant to only run from +// |RunMockTests| to validate tests launcher output for known results. +using MockContentBrowserTest = ContentBrowserTest; + +// Basic Test to pass +IN_PROC_BROWSER_TEST_F(MockContentBrowserTest, DISABLED_PassTest) { + ASSERT_TRUE(true); +} +// Basic Test to fail +IN_PROC_BROWSER_TEST_F(MockContentBrowserTest, DISABLED_FailTest) { + ASSERT_TRUE(false); +} +// Basic Test to crash +IN_PROC_BROWSER_TEST_F(MockContentBrowserTest, DISABLED_CrashTest) { + IMMEDIATE_CRASH(); +} + +// Using TestLauncher to launch 3 simple browser tests +// and validate the resulting json file. +IN_PROC_BROWSER_TEST_F(ContentBrowserTest, RunMockTests) { + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_dir; + + base::CommandLine command_line( + base::CommandLine::ForCurrentProcess()->GetProgram()); + command_line.AppendSwitchASCII("gtest_filter", + "MockContentBrowserTest.DISABLED_*"); + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath path = + temp_dir.GetPath().AppendASCII("SaveSummaryResult.json"); + command_line.AppendSwitchPath("test-launcher-summary-output", path); + command_line.AppendSwitch("gtest_also_run_disabled_tests"); + command_line.AppendSwitch("--test-launcher-retry-limit=0"); + + std::string output; + base::GetAppOutputAndError(command_line, &output); + + // Validate the resulting JSON file is the expected output. + base::Optional<base::Value> root = + base::test_launcher_utils::ReadSummary(path); + ASSERT_TRUE(root); + + base::Value* val = root->FindDictKey("test_locations"); + ASSERT_TRUE(val); + EXPECT_EQ(3u, val->DictSize()); + // If path or test location changes, the following expectation + // will need to change accordingly. + std::string file_name = "../../content/test/content_browser_test_test.cc"; + EXPECT_TRUE(base::test_launcher_utils::ValidateTestLocation( + val, "MockContentBrowserTest.DISABLED_PassTest", file_name, 152)); + EXPECT_TRUE(base::test_launcher_utils::ValidateTestLocation( + val, "MockContentBrowserTest.DISABLED_FailTest", file_name, 156)); + EXPECT_TRUE(base::test_launcher_utils::ValidateTestLocation( + val, "MockContentBrowserTest.DISABLED_CrashTest", file_name, 160)); + + val = root->FindListKey("per_iteration_data"); + ASSERT_TRUE(val); + ASSERT_EQ(1u, val->GetList().size()); + + base::Value* iteration_val = &(val->GetList().at(0)); + ASSERT_TRUE(iteration_val); + ASSERT_TRUE(iteration_val->is_dict()); + EXPECT_EQ(3u, iteration_val->DictSize()); + // We expect the result to be stripped of disabled prefix. + EXPECT_TRUE(base::test_launcher_utils::ValidateTestResult( + iteration_val, "MockContentBrowserTest.PassTest", "SUCCESS", 0u)); + EXPECT_TRUE(base::test_launcher_utils::ValidateTestResult( + iteration_val, "MockContentBrowserTest.FailTest", "FAILURE", 1u)); + EXPECT_TRUE(base::test_launcher_utils::ValidateTestResult( + iteration_val, "MockContentBrowserTest.CrashTest", "CRASH", 0u)); +} + #endif class ContentBrowserTestSanityTest : public ContentBrowserTest {
diff --git a/content/test/data/accessibility/html/article-expected-uia-win.txt b/content/test/data/accessibility/html/article-expected-uia-win.txt index efe01316..057c893 100644 --- a/content/test/data/accessibility/html/article-expected-uia-win.txt +++ b/content/test/data/accessibility/html/article-expected-uia-win.txt
@@ -1,3 +1,3 @@ document -++article +++article ControlType='UIA_GroupControlTypeId' LocalizedControlType='article' ++++description Name='This is an article element.'
diff --git a/content/test/data/accessibility/html/article.html b/content/test/data/accessibility/html/article.html index 10af48b..bf9ff949 100644 --- a/content/test/data/accessibility/html/article.html +++ b/content/test/data/accessibility/html/article.html
@@ -2,6 +2,8 @@ @MAC-ALLOW:AXRole* @MAC-ALLOW:AXSubrole=AXDocumentArticle @MAC-DENY:AXTitle* +@UIA-WIN-ALLOW:ControlType='UIA_GroupControlTypeId' +@UIA-WIN-ALLOW:LocalizedControlType='article' @WIN-ALLOW:xml-roles:article @AURALINUX-ALLOW:xml-roles:article -->
diff --git a/content/test/data/accessibility/html/delete-selection-crash-expected-blink.txt b/content/test/data/accessibility/html/delete-selection-crash-expected-blink.txt new file mode 100644 index 0000000..00f2a70 --- /dev/null +++ b/content/test/data/accessibility/html/delete-selection-crash-expected-blink.txt
@@ -0,0 +1,4 @@ +rootWebArea +++genericContainer +++++staticText name='Done' +++++++inlineTextBox name='Done'
diff --git a/content/test/data/accessibility/html/delete-selection-crash-expected-win.txt b/content/test/data/accessibility/html/delete-selection-crash-expected-win.txt new file mode 100644 index 0000000..e21f1c54 --- /dev/null +++ b/content/test/data/accessibility/html/delete-selection-crash-expected-win.txt
@@ -0,0 +1,3 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++IA2_ROLE_SECTION +++++ROLE_SYSTEM_STATICTEXT name='Done'
diff --git a/content/test/data/accessibility/html/delete-selection-crash.html b/content/test/data/accessibility/html/delete-selection-crash.html new file mode 100644 index 0000000..902410f --- /dev/null +++ b/content/test/data/accessibility/html/delete-selection-crash.html
@@ -0,0 +1,68 @@ +<!-- +@WAIT-FOR:Done + +This is a regression test for a bug that intermittently causes a crash due to a +combination of re-creating a node and setting its parent to an AXNode created +for a continuation LayoutObject. + +Since the crash is intermittent, give the (generated) reproduction code 10 +chances to reproduce the bug before terminating the test successfully. +--> +<html> +<head> +<style> +#fuzz1 { + -webkit-shape-outside: url(x); +} +</style> +<script> + +function boom() { + let iteration = Number.parseInt(document.location.hash.substring(1)); + if (isNaN(iteration)) + iteration = 0; + + if (iteration > 10) { + document.body.innerHTML = "Done"; + // remove hash + history.pushState("", document.title, window.location.pathname + + window.location.search); + return; + } + iteration = iteration + 1; + location.hash = iteration; + var fuzz11 = document.getElementById("fuzz11"); + var fuzz16 = document.getElementById("fuzz16"); + var fuzz18 = document.getElementById("fuzz18"); + + try { var i5 = document.execCommand("selectAll", false); } catch(e) { } + try { var i18 = document.getSelection(); } catch(e) { } + try { i18.extend(fuzz18); } catch(e) { } + try { var i78 = window.frames; } catch(e) { } + try { fuzz11.after(fuzz16); } catch(e) { } + try { var i167 = i78.pageYOffset; } catch(e) { } + try { i18.deleteFromDocument(); } catch(e) { } + location.reload(true); +} + +</script> +</head> +<body onload=boom()> +<marquee id="fuzz2"> +<hr id="fuzz4" > +</hr> +</marquee> +<data id="fuzz6" alt="AAAA" > +<time id="fuzz1" > +<label id="fuzz11" ></label> +<style id="fuzz12" ></style> +<hr id="fuzz16" > +<hr id="fuzz17" > +<dl id="fuzz18" > +</dl> +</hr> +<span id="fuzz24" style="columns: 0px"> +</span> +</hr> +</body> +</html>
diff --git a/content/test/data/accessibility/html/figure-expected-uia-win.txt b/content/test/data/accessibility/html/figure-expected-uia-win.txt index 0c4353e3..1eb4524 100644 --- a/content/test/data/accessibility/html/figure-expected-uia-win.txt +++ b/content/test/data/accessibility/html/figure-expected-uia-win.txt
@@ -1,3 +1,3 @@ document -++group +++group LocalizedControlType='figure' ++++img Name='Sunspots'
diff --git a/content/test/data/accessibility/html/figure-expected-win.txt b/content/test/data/accessibility/html/figure-expected-win.txt index 9359a64..325d0f9273 100644 --- a/content/test/data/accessibility/html/figure-expected-win.txt +++ b/content/test/data/accessibility/html/figure-expected-win.txt
@@ -1,3 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE -++ROLE_SYSTEM_GROUPING xml-roles:figure +++ROLE_SYSTEM_GROUPING xml-roles:figure localized_extended_role='figure' ++++ROLE_SYSTEM_GRAPHIC name='Sunspots' READONLY xml-roles:img
diff --git a/content/test/data/accessibility/html/figure.html b/content/test/data/accessibility/html/figure.html index 49dfa3550..12f6f72 100644 --- a/content/test/data/accessibility/html/figure.html +++ b/content/test/data/accessibility/html/figure.html
@@ -1,5 +1,7 @@ <!-- @MAC-ALLOW:AXRole* +@UIA-WIN-ALLOW:LocalizedControlType='figure' +@WIN-ALLOW:localized_extended_role='figure' @WIN-ALLOW:xml-roles* @AURALINUX-ALLOW:xml-roles* -->
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index f96b016..a162f02 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -305,6 +305,21 @@ libfuzzer_options = [ "max_len=2048" ] } +fuzzer_test("fido_cable_handshake_handler_v2_fuzzer") { + sources = [ + "cable/fido_cable_handshake_handler_v2_fuzzer.cc", + ] + deps = [ + ":fido", + "//base", + "//base/test:test_support", + "//device/bluetooth:mocks", + "//testing/gmock", + "//testing/gtest", + ] + libfuzzer_options = [ "max_len=2048" ] +} + is_linux_without_udev = is_linux && !use_udev source_set("test_support") {
diff --git a/device/fido/cable/fido_cable_discovery.cc b/device/fido/cable/fido_cable_discovery.cc index 76cafa8f..e4299b4 100644 --- a/device/fido/cable/fido_cable_discovery.cc +++ b/device/fido/cable/fido_cable_discovery.cc
@@ -23,6 +23,7 @@ #include "device/fido/ble/fido_ble_uuids.h" #include "device/fido/cable/fido_cable_device.h" #include "device/fido/cable/fido_cable_handshake_handler.h" +#include "device/fido/features.h" #include "device/fido/fido_parsing_utils.h" #include "third_party/boringssl/src/include/openssl/digest.h" #include "third_party/boringssl/src/include/openssl/hkdf.h" @@ -189,13 +190,39 @@ advertisement.second->Unregister(base::DoNothing(), base::DoNothing()); } -std::unique_ptr<FidoCableHandshakeHandler> +base::Optional<std::unique_ptr<FidoCableHandshakeHandler>> FidoCableDiscovery::CreateHandshakeHandler( FidoCableDevice* device, - base::span<const uint8_t, kCableSessionPreKeySize> session_pre_key, - base::span<const uint8_t, 8> nonce) { - return std::make_unique<FidoCableHandshakeHandler>(device, nonce, - session_pre_key); + const CableDiscoveryData* discovery_data) { + std::unique_ptr<FidoCableHandshakeHandler> handler; + switch (discovery_data->version) { + case 1: { + // Nonce is embedded as first 8 bytes of client EID. + std::array<uint8_t, 8> nonce; + const bool ok = fido_parsing_utils::ExtractArray( + discovery_data->client_eid, 0, &nonce); + DCHECK(ok); + + handler.reset(new FidoCableV1HandshakeHandler( + device, nonce, discovery_data->session_pre_key)); + break; + } + + case 2: + if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) { + return base::nullopt; + } + handler.reset(new FidoCableV2HandshakeHandler( + device, discovery_data->session_pre_key)); + break; + + default: + FIDO_LOG(DEBUG) << "Dropping caBLE handshake request for unknown version " + << discovery_data->version; + return base::nullopt; + } + + return handler; } void FidoCableDiscovery::DeviceAdded(BluetoothAdapter* adapter, @@ -353,17 +380,19 @@ StopAdvertisements( base::BindOnce(&FidoCableDiscovery::ConductEncryptionHandshake, weak_factory_.GetWeakPtr(), std::move(cable_device), - found_cable_device_data->session_pre_key, nonce)); + *found_cable_device_data)); } void FidoCableDiscovery::ConductEncryptionHandshake( std::unique_ptr<FidoCableDevice> cable_device, - base::span<const uint8_t, kCableSessionPreKeySize> session_pre_key, - base::span<const uint8_t, 8> nonce) { - auto handshake_handler = - CreateHandshakeHandler(cable_device.get(), session_pre_key, nonce); - auto* const handshake_handler_ptr = handshake_handler.get(); - cable_handshake_handlers_.emplace_back(std::move(handshake_handler)); + CableDiscoveryData discovery_data) { + base::Optional<std::unique_ptr<FidoCableHandshakeHandler>> handshake_handler = + CreateHandshakeHandler(cable_device.get(), &discovery_data); + if (!handshake_handler) { + return; + } + auto* const handshake_handler_ptr = handshake_handler->get(); + cable_handshake_handlers_.emplace_back(std::move(*handshake_handler)); handshake_handler_ptr->InitiateCableHandshake( base::BindOnce(&FidoCableDiscovery::ValidateAuthenticatorHandshakeMessage,
diff --git a/device/fido/cable/fido_cable_discovery.h b/device/fido/cable/fido_cable_discovery.h index 6dbec1d..867803f 100644 --- a/device/fido/cable/fido_cable_discovery.h +++ b/device/fido/cable/fido_cable_discovery.h
@@ -35,10 +35,9 @@ ~FidoCableDiscovery() override; protected: - virtual std::unique_ptr<FidoCableHandshakeHandler> CreateHandshakeHandler( - FidoCableDevice* device, - base::span<const uint8_t, kCableSessionPreKeySize> session_pre_key, - base::span<const uint8_t, 8> nonce); + virtual base::Optional<std::unique_ptr<FidoCableHandshakeHandler>> + CreateHandshakeHandler(FidoCableDevice* device, + const CableDiscoveryData* discovery_data); private: FRIEND_TEST_ALL_PREFIXES(FidoCableDiscoveryTest, @@ -76,10 +75,8 @@ // |callback|. void StopAdvertisements(base::OnceClosure callback); void CableDeviceFound(BluetoothAdapter* adapter, BluetoothDevice* device); - void ConductEncryptionHandshake( - std::unique_ptr<FidoCableDevice> device, - base::span<const uint8_t, kCableSessionPreKeySize> session_pre_key, - base::span<const uint8_t, 8> nonce); + void ConductEncryptionHandshake(std::unique_ptr<FidoCableDevice> cable_device, + CableDiscoveryData discovery_data); void ValidateAuthenticatorHandshakeMessage( std::unique_ptr<FidoCableDevice> cable_device, FidoCableHandshakeHandler* handshake_handler,
diff --git a/device/fido/cable/fido_cable_discovery_unittest.cc b/device/fido/cable/fido_cable_discovery_unittest.cc index e886ea4..ca66243 100644 --- a/device/fido/cable/fido_cable_discovery_unittest.cc +++ b/device/fido/cable/fido_cable_discovery_unittest.cc
@@ -266,12 +266,12 @@ ~CableMockAdapter() override = default; }; -class FakeHandshakeHandler : public FidoCableHandshakeHandler { +class FakeHandshakeHandler : public FidoCableV1HandshakeHandler { public: FakeHandshakeHandler(FidoCableDevice* device, base::span<const uint8_t, 8> nonce, base::span<const uint8_t, 32> session_pre_key) - : FidoCableHandshakeHandler(device, nonce, session_pre_key) {} + : FidoCableV1HandshakeHandler(device, nonce, session_pre_key) {} ~FakeHandshakeHandler() override = default; void InitiateCableHandshake(FidoDevice::DeviceCallback callback) override { @@ -295,12 +295,16 @@ ~FakeFidoCableDiscovery() override = default; private: - std::unique_ptr<FidoCableHandshakeHandler> CreateHandshakeHandler( - FidoCableDevice* device, - base::span<const uint8_t, kCableSessionPreKeySize> session_pre_key, - base::span<const uint8_t, 8> nonce) override { - return std::make_unique<FakeHandshakeHandler>(device, nonce, - session_pre_key); + base::Optional<std::unique_ptr<FidoCableHandshakeHandler>> + CreateHandshakeHandler(FidoCableDevice* device, + const CableDiscoveryData* discovery_data) override { + // Nonce is embedded as first 8 bytes of client EID. + std::array<uint8_t, 8> nonce; + const bool ok = + fido_parsing_utils::ExtractArray(discovery_data->client_eid, 0, &nonce); + DCHECK(ok); + return std::make_unique<FakeHandshakeHandler>( + device, nonce, discovery_data->session_pre_key); } };
diff --git a/device/fido/cable/fido_cable_handshake_handler.cc b/device/fido/cable/fido_cable_handshake_handler.cc index b41b2e0..c3e8fa3 100644 --- a/device/fido/cable/fido_cable_handshake_handler.cc +++ b/device/fido/cable/fido_cable_handshake_handler.cc
@@ -5,21 +5,30 @@ #include "device/fido/cable/fido_cable_handshake_handler.h" #include <algorithm> +#include <tuple> #include <utility> #include "base/bind.h" #include "base/containers/span.h" +#include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "components/cbor/reader.h" #include "components/cbor/values.h" #include "components/cbor/writer.h" #include "components/device_event_log/device_event_log.h" +#include "crypto/aead.h" #include "crypto/hkdf.h" #include "crypto/hmac.h" #include "crypto/random.h" #include "device/fido/cable/fido_cable_device.h" #include "device/fido/fido_constants.h" #include "device/fido/fido_parsing_utils.h" +#include "third_party/boringssl/src/include/openssl/digest.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/ecdh.h" +#include "third_party/boringssl/src/include/openssl/hkdf.h" +#include "third_party/boringssl/src/include/openssl/obj.h" +#include "third_party/boringssl/src/include/openssl/sha.h" namespace device { @@ -76,7 +85,9 @@ } // namespace -FidoCableHandshakeHandler::FidoCableHandshakeHandler( +FidoCableHandshakeHandler::~FidoCableHandshakeHandler() {} + +FidoCableV1HandshakeHandler::FidoCableV1HandshakeHandler( FidoCableDevice* cable_device, base::span<const uint8_t, 8> nonce, base::span<const uint8_t, 32> session_pre_key) @@ -91,9 +102,9 @@ client_session_random_.size()); } -FidoCableHandshakeHandler::~FidoCableHandshakeHandler() = default; +FidoCableV1HandshakeHandler::~FidoCableV1HandshakeHandler() = default; -void FidoCableHandshakeHandler::InitiateCableHandshake( +void FidoCableV1HandshakeHandler::InitiateCableHandshake( FidoDevice::DeviceCallback callback) { auto handshake_message = ConstructHandshakeMessage(handshake_key_, client_session_random_); @@ -108,7 +119,7 @@ fido_parsing_utils::Materialize(*handshake_message), std::move(callback)); } -bool FidoCableHandshakeHandler::ValidateAuthenticatorHandshakeMessage( +bool FidoCableV1HandshakeHandler::ValidateAuthenticatorHandshakeMessage( base::span<const uint8_t> response) { crypto::HMAC hmac(crypto::HMAC::SHA256); if (!hmac.Init(handshake_key_)) @@ -158,7 +169,8 @@ return true; } -std::string FidoCableHandshakeHandler::GetEncryptionKeyAfterSuccessfulHandshake( +std::string +FidoCableV1HandshakeHandler::GetEncryptionKeyAfterSuccessfulHandshake( base::span<const uint8_t, 16> authenticator_random_nonce) const { std::vector<uint8_t> nonce_message; fido_parsing_utils::Append(&nonce_message, nonce_); @@ -172,4 +184,206 @@ kCableDeviceEncryptionKeyInfo); } +FidoCableV2HandshakeHandler::FidoCableV2HandshakeHandler( + FidoCableDevice* cable_device, + base::span<const uint8_t, 32> session_pre_key) + : cable_device_(cable_device), + session_pre_key_(fido_parsing_utils::Materialize(session_pre_key)) {} + +FidoCableV2HandshakeHandler::~FidoCableV2HandshakeHandler() {} + +namespace { + +// P256PointSize is the number of bytes in an X9.62 encoding of a P-256 point. +constexpr size_t P256PointSize = 65; + +// HKDF2 implements the functions with the same name from Noise[1], specialized +// to the case where |num_outputs| is two. +// +// [1] https://www.noiseprotocol.org/noise.html#hash-functions +std::tuple<std::array<uint8_t, 32>, std::array<uint8_t, 32>> HKDF2( + base::span<const uint8_t, 32> ck, + base::span<const uint8_t> ikm) { + uint8_t output[32 * 2]; + HKDF(output, sizeof(output), EVP_sha256(), ikm.data(), ikm.size(), ck.data(), + ck.size(), /*salt=*/nullptr, 0); + + std::array<uint8_t, 32> a, b; + memcpy(a.data(), &output[0], 32); + memcpy(b.data(), &output[32], 32); + + return std::make_tuple(a, b); +} + +// HKDF3 implements the functions with the same name from Noise[1], specialized +// to the case where |num_outputs| is three. +// +// [1] https://www.noiseprotocol.org/noise.html#hash-functions +std::tuple<std::array<uint8_t, 32>, + std::array<uint8_t, 32>, + std::array<uint8_t, 32>> +HKDF3(base::span<const uint8_t, 32> ck, base::span<const uint8_t> ikm) { + uint8_t output[32 * 3]; + HKDF(output, sizeof(output), EVP_sha256(), ikm.data(), ikm.size(), ck.data(), + ck.size(), /*salt=*/nullptr, 0); + + std::array<uint8_t, 32> a, b, c; + memcpy(a.data(), &output[0], 32); + memcpy(b.data(), &output[32], 32); + memcpy(c.data(), &output[64], 32); + + return std::make_tuple(a, b, c); +} + +} // namespace + +void FidoCableV2HandshakeHandler::InitiateCableHandshake( + FidoDevice::DeviceCallback callback) { + // See https://www.noiseprotocol.org/noise.html#the-handshakestate-object + static const char kProtocolName[] = "Noise_NNpsk0_P256_AESGCM_SHA256"; + static_assert(sizeof(kProtocolName) == crypto::kSHA256Length, + "name may need padding if not HASHLEN bytes long"); + static_assert( + std::tuple_size<decltype(chaining_key_)>::value == crypto::kSHA256Length, + "chaining_key_ is wrong size"); + static_assert(std::tuple_size<decltype(h_)>::value == crypto::kSHA256Length, + "h_ is wrong size"); + memcpy(chaining_key_.data(), kProtocolName, sizeof(kProtocolName)); + h_ = chaining_key_; + + static const uint8_t kPrologue[] = "caBLE QR code handshake"; + MixHash(kPrologue); + + MixKeyAndHash(session_pre_key_); + ephemeral_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + CHECK(EC_KEY_generate_key(ephemeral_key_.get())); + uint8_t ephemeral_key_public_bytes[P256PointSize]; + CHECK_EQ(sizeof(ephemeral_key_public_bytes), + EC_POINT_point2oct( + EC_KEY_get0_group(ephemeral_key_.get()), + EC_KEY_get0_public_key(ephemeral_key_.get()), + POINT_CONVERSION_UNCOMPRESSED, ephemeral_key_public_bytes, + sizeof(ephemeral_key_public_bytes), /*ctx=*/nullptr)); + MixHash(ephemeral_key_public_bytes); + MixKey(ephemeral_key_public_bytes); + + std::vector<uint8_t> ciphertext = Encrypt(base::span<const uint8_t>()); + MixHash(ciphertext); + + std::vector<uint8_t> handshake_message; + handshake_message.reserve(sizeof(ephemeral_key_public_bytes) + + ciphertext.size()); + handshake_message.insert( + handshake_message.end(), ephemeral_key_public_bytes, + ephemeral_key_public_bytes + sizeof(ephemeral_key_public_bytes)); + handshake_message.insert(handshake_message.end(), ciphertext.begin(), + ciphertext.end()); + + cable_device_->SendHandshakeMessage(std::move(handshake_message), + std::move(callback)); +} + +bool FidoCableV2HandshakeHandler::ValidateAuthenticatorHandshakeMessage( + base::span<const uint8_t> response) { + if (response.size() < P256PointSize) { + return false; + } + auto peer_point_bytes = response.subspan(0, P256PointSize); + auto ciphertext = response.subspan(P256PointSize); + + bssl::UniquePtr<EC_POINT> peer_point( + EC_POINT_new(EC_KEY_get0_group(ephemeral_key_.get()))); + uint8_t shared_key[32]; + if (!EC_POINT_oct2point(EC_KEY_get0_group(ephemeral_key_.get()), + peer_point.get(), peer_point_bytes.data(), + peer_point_bytes.size(), /*ctx=*/nullptr) || + !ECDH_compute_key(shared_key, sizeof(shared_key), peer_point.get(), + ephemeral_key_.get(), /*kdf=*/nullptr)) { + return false; + } + + MixHash(peer_point_bytes); + MixKey(peer_point_bytes); + MixKey(shared_key); + + auto maybe_plaintext = Decrypt(ciphertext); + if (!maybe_plaintext || !maybe_plaintext->empty()) { + return false; + } + // Here the spec says to do MixHash(ciphertext), but there are no more + // handshake messages so that's moot. + // MixHash(ciphertext); + + std::array<uint8_t, 32> key1, unused_key2; + std::tie(key1, unused_key2) = + HKDF2(chaining_key_, base::span<const uint8_t>()); + + uint8_t zero_nonce[8] = {0}; + cable_device_->SetEncryptionData( + std::string(reinterpret_cast<const char*>(key1.data()), key1.size()), + zero_nonce); + + return true; +} + +void FidoCableV2HandshakeHandler::MixHash(base::span<const uint8_t> in) { + // See https://www.noiseprotocol.org/noise.html#the-symmetricstate-object + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, h_.data(), h_.size()); + SHA256_Update(&ctx, in.data(), in.size()); + SHA256_Final(h_.data(), &ctx); +} + +void FidoCableV2HandshakeHandler::MixKey(base::span<const uint8_t> ikm) { + // See https://www.noiseprotocol.org/noise.html#the-symmetricstate-object + std::array<uint8_t, 32> temp_k; + std::tie(chaining_key_, temp_k) = HKDF2(chaining_key_, ikm); + InitializeKey(temp_k); +} + +void FidoCableV2HandshakeHandler::MixKeyAndHash(base::span<const uint8_t> ikm) { + // See https://www.noiseprotocol.org/noise.html#the-symmetricstate-object + std::array<uint8_t, 32> temp_h, temp_k; + std::tie(chaining_key_, temp_h, temp_k) = HKDF3(chaining_key_, ikm); + MixHash(temp_h); + InitializeKey(temp_k); +} + +void FidoCableV2HandshakeHandler::InitializeKey( + base::span<const uint8_t, 32> key) { + // See https://www.noiseprotocol.org/noise.html#the-cipherstate-object + DCHECK_EQ(symmetric_key_.size(), key.size()); + memcpy(symmetric_key_.data(), key.data(), symmetric_key_.size()); + symmetric_nonce_ = 0; +} + +std::vector<uint8_t> FidoCableV2HandshakeHandler::Encrypt( + base::span<const uint8_t> plaintext) { + uint8_t nonce[12] = {0}; + nonce[8] = symmetric_nonce_ >> 24; + nonce[9] = symmetric_nonce_ >> 16; + nonce[10] = symmetric_nonce_ >> 8; + nonce[11] = symmetric_nonce_; + symmetric_nonce_++; + + crypto::Aead aead(crypto::Aead::AES_256_GCM); + aead.Init(symmetric_key_); + return aead.Seal(base::span<const uint8_t>(), nonce, h_); +} + +base::Optional<std::vector<uint8_t>> FidoCableV2HandshakeHandler::Decrypt( + base::span<const uint8_t> ciphertext) { + uint8_t nonce[12] = {0}; + nonce[8] = symmetric_nonce_ >> 24; + nonce[9] = symmetric_nonce_ >> 16; + nonce[10] = symmetric_nonce_ >> 8; + nonce[11] = symmetric_nonce_; + symmetric_nonce_++; + + crypto::Aead aead(crypto::Aead::AES_256_GCM); + aead.Init(symmetric_key_); + return aead.Open(ciphertext, nonce, h_); +} + } // namespace device
diff --git a/device/fido/cable/fido_cable_handshake_handler.h b/device/fido/cable/fido_cable_handshake_handler.h index 7cd3f291..bd137a7 100644 --- a/device/fido/cable/fido_cable_handshake_handler.h +++ b/device/fido/cable/fido_cable_handshake_handler.h
@@ -16,27 +16,41 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "device/fido/fido_device.h" +#include "third_party/boringssl/src/include/openssl/base.h" namespace device { class FidoCableDevice; +// FidoCableHandshakeHandler abstracts over the different versions of caBLE +// handshakes. +class FidoCableHandshakeHandler { + public: + virtual ~FidoCableHandshakeHandler() = 0; + virtual void InitiateCableHandshake(FidoDevice::DeviceCallback callback) = 0; + virtual bool ValidateAuthenticatorHandshakeMessage( + base::span<const uint8_t> response) = 0; +}; + // Handles exchanging handshake messages with external authenticator and // validating the handshake messages to derive a shared session key to be used // for message encryption. // See: fido-client-to-authenticator-protocol.html#cable-encryption-handshake of // the most up-to-date spec. -class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableHandshakeHandler { +class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableV1HandshakeHandler + : public FidoCableHandshakeHandler { public: - FidoCableHandshakeHandler(FidoCableDevice* device, - base::span<const uint8_t, 8> nonce, - base::span<const uint8_t, 32> session_pre_key); - virtual ~FidoCableHandshakeHandler(); + FidoCableV1HandshakeHandler(FidoCableDevice* device, + base::span<const uint8_t, 8> nonce, + base::span<const uint8_t, 32> session_pre_key); + ~FidoCableV1HandshakeHandler() override; - virtual void InitiateCableHandshake(FidoDevice::DeviceCallback callback); - virtual bool ValidateAuthenticatorHandshakeMessage( - base::span<const uint8_t> response); + // FidoCableHandshakeHandler: + void InitiateCableHandshake(FidoDevice::DeviceCallback callback) override; + bool ValidateAuthenticatorHandshakeMessage( + base::span<const uint8_t> response) override; private: FRIEND_TEST_ALL_PREFIXES(FidoCableHandshakeHandlerTest, HandShakeSuccess); @@ -52,9 +66,43 @@ std::array<uint8_t, 16> client_session_random_; std::string handshake_key_; - base::WeakPtrFactory<FidoCableHandshakeHandler> weak_factory_{this}; + base::WeakPtrFactory<FidoCableV1HandshakeHandler> weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(FidoCableHandshakeHandler); + DISALLOW_COPY_AND_ASSIGN(FidoCableV1HandshakeHandler); +}; + +// FidoCableV2HandshakeHandler implements an NNpsk0[1] handshake that provides +// forward secrecy. +// +// [1] https://noiseexplorer.com/patterns/NNpsk0/ +class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableV2HandshakeHandler + : public FidoCableHandshakeHandler { + public: + FidoCableV2HandshakeHandler(FidoCableDevice* device, + base::span<const uint8_t, 32> session_pre_key); + ~FidoCableV2HandshakeHandler() override; + + // FidoCableHandshakeHandler: + void InitiateCableHandshake(FidoDevice::DeviceCallback callback) override; + bool ValidateAuthenticatorHandshakeMessage( + base::span<const uint8_t> response) override; + + private: + void MixHash(base::span<const uint8_t> in); + void MixKey(base::span<const uint8_t> ikm); + void MixKeyAndHash(base::span<const uint8_t> ikm); + void InitializeKey(base::span<const uint8_t, 32> key); + std::vector<uint8_t> Encrypt(base::span<const uint8_t> plaintext); + base::Optional<std::vector<uint8_t>> Decrypt( + base::span<const uint8_t> ciphertext); + + FidoCableDevice* const cable_device_; + std::array<uint8_t, 32> session_pre_key_; + std::array<uint8_t, 32> chaining_key_; + std::array<uint8_t, 32> h_; + std::array<uint8_t, 32> symmetric_key_; + uint32_t symmetric_nonce_; + bssl::UniquePtr<EC_KEY> ephemeral_key_; }; } // namespace device
diff --git a/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc b/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc index 5b0432e..2e98b952 100644 --- a/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc +++ b/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc
@@ -37,8 +37,9 @@ auto adapter = base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>(); device::FidoCableDevice test_cable_device(adapter.get(), kTestDeviceAddress); - device::FidoCableHandshakeHandler handshake_handler( + + device::FidoCableV1HandshakeHandler handshake_handler_v1( &test_cable_device, kTestNonce, kTestSessionPreKey); - handshake_handler.ValidateAuthenticatorHandshakeMessage(data_span); + handshake_handler_v1.ValidateAuthenticatorHandshakeMessage(data_span); return 0; }
diff --git a/device/fido/cable/fido_cable_handshake_handler_unittest.cc b/device/fido/cable/fido_cable_handshake_handler_unittest.cc index bfe3243..4cea756 100644 --- a/device/fido/cable/fido_cable_handshake_handler_unittest.cc +++ b/device/fido/cable/fido_cable_handshake_handler_unittest.cc
@@ -264,11 +264,11 @@ connection_->read_callback() = device_->GetReadCallbackForTesting(); } - std::unique_ptr<FidoCableHandshakeHandler> CreateHandshakeHandler( + std::unique_ptr<FidoCableV1HandshakeHandler> CreateHandshakeHandler( std::array<uint8_t, 8> nonce, std::array<uint8_t, 32> session_pre_key) { - return std::make_unique<FidoCableHandshakeHandler>(device_.get(), nonce, - session_pre_key); + return std::make_unique<FidoCableV1HandshakeHandler>(device_.get(), nonce, + session_pre_key); } void ConnectWithLength(uint16_t length) {
diff --git a/device/fido/cable/fido_cable_handshake_handler_v2_fuzzer.cc b/device/fido/cable/fido_cable_handshake_handler_v2_fuzzer.cc new file mode 100644 index 0000000..279fd85 --- /dev/null +++ b/device/fido/cable/fido_cable_handshake_handler_v2_fuzzer.cc
@@ -0,0 +1,44 @@ +// 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. + +#include <stddef.h> +#include <stdint.h> + +#include <array> + +#include "base/containers/span.h" +#include "base/memory/ref_counted.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" +#include "device/fido/cable/fido_cable_device.h" +#include "device/fido/cable/fido_cable_handshake_handler.h" +#include "device/fido/fido_constants.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +constexpr std::array<uint8_t, 32> kTestSessionPreKey = {{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}}; + +constexpr char kTestDeviceAddress[] = "Fake_Address"; + +} // namespace + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* raw_data, size_t size) { + auto data_span = base::make_span(raw_data, size); + auto adapter = + base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>(); + device::FidoCableDevice test_cable_device(adapter.get(), kTestDeviceAddress); + test_cable_device.SetStateForTesting( + device::FidoCableDevice::State::kDeviceError); + + device::FidoCableV2HandshakeHandler handshake_handler_v2(&test_cable_device, + kTestSessionPreKey); + handshake_handler_v2.InitiateCableHandshake(base::DoNothing()); + handshake_handler_v2.ValidateAuthenticatorHandshakeMessage(data_span); + return 0; +}
diff --git a/device/fido/features.cc b/device/fido/features.cc index faf40ab..d80f894 100644 --- a/device/fido/features.cc +++ b/device/fido/features.cc
@@ -25,4 +25,7 @@ extern const base::Feature kWebAuthCredentialManagement{ "WebAuthenticationCredentialManagement", base::FEATURE_ENABLED_BY_DEFAULT}; +extern const base::Feature kWebAuthPhoneSupport{ + "WebAuthenticationPhoneSupport", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace device
diff --git a/device/fido/features.h b/device/fido/features.h index c65fb1f..24f04e1 100644 --- a/device/fido/features.h +++ b/device/fido/features.h
@@ -28,6 +28,10 @@ COMPONENT_EXPORT(DEVICE_FIDO) extern const base::Feature kWebAuthCredentialManagement; +// Enable using a phone as a generic security key. +COMPONENT_EXPORT(DEVICE_FIDO) +extern const base::Feature kWebAuthPhoneSupport; + } // namespace device #endif // DEVICE_FIDO_FEATURES_H_
diff --git a/device/fido/fido_device.h b/device/fido/fido_device.h index 9d61442..44ea4a84 100644 --- a/device/fido/fido_device.h +++ b/device/fido/fido_device.h
@@ -115,6 +115,7 @@ } State state_for_testing() const { return state_; } + void SetStateForTesting(State state) { state_ = state; } protected: void OnDeviceInfoReceived(base::OnceClosure done,
diff --git a/docs/gpu/gpu_testing_bot_details.md b/docs/gpu/gpu_testing_bot_details.md index 29a246b..4d9af081 100644 --- a/docs/gpu/gpu_testing_bot_details.md +++ b/docs/gpu/gpu_testing_bot_details.md
@@ -27,11 +27,11 @@ All of the physical hardware for the bots lives in the Swarming pool, and most of it in the Chrome-GPU Swarming pool. The waterfall bots are simply virtual machines which spawn Swarming tasks with the appropriate tags to get them to run -on the desired GPU and operating system type. So, for example, the [Win10 +on the desired GPU and operating system type. So, for example, the [Win10 x64 Release (NVIDIA)] bot is actually a virtual machine which spawns all of its jobs with the Swarming parameters: -[Win10 Release (NVIDIA)]: https://ci.chromium.org/p/chromium/builders/luci.chromium.ci/Win10%20Release%20%28NVIDIA%29 +[Win10 x64 Release (NVIDIA)]: https://ci.chromium.org/p/chromium/builders/ci/Win10%20x64%20Release%20%28NVIDIA%29 ```json {
diff --git a/docs/infra/cq_builders.md b/docs/infra/cq_builders.md index a37163a..34db85e3 100644 --- a/docs/infra/cq_builders.md +++ b/docs/infra/cq_builders.md
@@ -143,8 +143,8 @@ * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) * [`//testing/buildbot/chromium.dawn.json`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:testing/buildbot/chromium.dawn.json) * [`//third_party/blink/renderer/modules/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgpu/) - * [`//third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu) - * [`//third_party/blink/web_tests/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/webgpu/) + * [`//third_party/blink/web_tests/external/wpt/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/webgpu/) + * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) * [dawn-mac-x64-deps-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/dawn-mac-x64-deps-rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/dawn-mac-x64-deps-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+dawn-mac-x64-deps-rel)) @@ -153,8 +153,8 @@ * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) * [`//testing/buildbot/chromium.dawn.json`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:testing/buildbot/chromium.dawn.json) * [`//third_party/blink/renderer/modules/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgpu/) - * [`//third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu) - * [`//third_party/blink/web_tests/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/webgpu/) + * [`//third_party/blink/web_tests/external/wpt/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/webgpu/) + * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) * [dawn-win10-x64-deps-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/dawn-win10-x64-deps-rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/dawn-win10-x64-deps-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+dawn-win10-x64-deps-rel)) @@ -163,8 +163,8 @@ * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) * [`//testing/buildbot/chromium.dawn.json`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:testing/buildbot/chromium.dawn.json) * [`//third_party/blink/renderer/modules/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgpu/) - * [`//third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu) - * [`//third_party/blink/web_tests/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/webgpu/) + * [`//third_party/blink/web_tests/external/wpt/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/webgpu/) + * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) * [dawn-win10-x86-deps-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/dawn-win10-x86-deps-rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/dawn-win10-x86-deps-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+dawn-win10-x86-deps-rel)) @@ -173,8 +173,8 @@ * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) * [`//testing/buildbot/chromium.dawn.json`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:testing/buildbot/chromium.dawn.json) * [`//third_party/blink/renderer/modules/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgpu/) - * [`//third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu) - * [`//third_party/blink/web_tests/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/webgpu/) + * [`//third_party/blink/web_tests/external/wpt/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/webgpu/) + * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) * [fuchsia-arm64-cast](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/fuchsia-arm64-cast) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/fuchsia-arm64-cast)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+fuchsia-arm64-cast)) @@ -187,15 +187,6 @@ Path regular expressions: * [`//chromecast/.+`](https://cs.chromium.org/chromium/src/chromecast/) -* [gpu-fyi-try-android-p-pixel-2-skv-32](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/gpu-fyi-try-android-p-pixel-2-skv-32) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/gpu-fyi-try-android-p-pixel-2-skv-32)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+gpu-fyi-try-android-p-pixel-2-skv-32)) - - Path regular expressions: - * [`//components/viz/.+`](https://cs.chromium.org/chromium/src/components/viz/) - * [`//content/test/gpu/gpu_tests/.+py`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:content/test/gpu/gpu_tests/.+py) - * [`//content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt) - * [`//gpu/vulkan/.+`](https://cs.chromium.org/chromium/src/gpu/vulkan/) - * [`//services/viz/.+`](https://cs.chromium.org/chromium/src/services/viz/) - * [ios-simulator-cronet](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/ios-simulator-cronet) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/ios-simulator-cronet)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+ios-simulator-cronet)) Path regular expressions: @@ -232,7 +223,7 @@ * [`//third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint) * [`//third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/) -* [linux_layout_tests_layout_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_layout_ng) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/linux_layout_tests_layout_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_layout_ng)) +* [linux_layout_tests_layout_ng_disabled](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_layout_ng_disabled) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/linux_layout_tests_layout_ng_disabled)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_layout_ng_disabled)) Path regular expressions: * [`//third_party/blink/renderer/core/editing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/editing/)
diff --git a/docs/speed/OWNERS b/docs/speed/OWNERS index 495e268..aed0a96 100644 --- a/docs/speed/OWNERS +++ b/docs/speed/OWNERS
@@ -1,4 +1,4 @@ -sullivan@chromium.org benhenry@chromium.org ushesh@chromium.org per-file apk_size_regressions.md=agrieve@chromium.org +# COMPONENT: Speed
diff --git a/docs/speed/benchmark/OWNERS b/docs/speed/benchmark/OWNERS new file mode 100644 index 0000000..9a42e388 --- /dev/null +++ b/docs/speed/benchmark/OWNERS
@@ -0,0 +1 @@ +# COMPONENT: Speed>Telemetry
diff --git a/docs/speed/binary_size/OWNERS b/docs/speed/binary_size/OWNERS new file mode 100644 index 0000000..a35bb21b --- /dev/null +++ b/docs/speed/binary_size/OWNERS
@@ -0,0 +1 @@ +# COMPONENT: Speed>Release
diff --git a/docs/speed/images/OWNERS b/docs/speed/images/OWNERS new file mode 100644 index 0000000..48be081 --- /dev/null +++ b/docs/speed/images/OWNERS
@@ -0,0 +1 @@ +# COMPONENT: Speed>Benchmarks
diff --git a/extensions/common/csp_validator.cc b/extensions/common/csp_validator.cc index 525b058..4d0c184 100644 --- a/extensions/common/csp_validator.cc +++ b/extensions/common/csp_validator.cc
@@ -663,8 +663,9 @@ return seen_sandbox; } -bool IsSecureIsolatedWorldCSP(const std::string& isolated_world_csp, - base::string16* error) { +bool DoesCSPDisallowRemoteCode(const std::string& content_security_policy, + base::StringPiece manifest_key, + base::string16* error) { DCHECK(error); struct DirectiveMapping { @@ -687,7 +688,7 @@ }; // Populate |directive_mappings|. - CSPParser csp_parser(isolated_world_csp); + CSPParser csp_parser(content_security_policy); for (DirectiveMapping* mapping : directive_mappings) { // Find the first matching directive. As per // http://www.w3.org/TR/CSP/#parse-a-csp-policy, duplicate directive names @@ -723,12 +724,11 @@ // "default-src". fallback_if_necessary(&worker_src_mapping, script_src_mapping); - auto is_secure_directive = [](const DirectiveMapping& mapping, - base::string16* error) { + auto is_secure_directive = [manifest_key](const DirectiveMapping& mapping, + base::string16* error) { if (!mapping.directive) { *error = ErrorUtils::FormatErrorMessageUTF16( - manifest_errors::kInvalidCSPMissingSecureSrc, - manifest_keys::kContentSecurityPolicy_IsolatedWorldPath, + manifest_errors::kInvalidCSPMissingSecureSrc, manifest_key, mapping.status.name()); return false; } @@ -746,8 +746,7 @@ return true; *error = ErrorUtils::FormatErrorMessageUTF16( - manifest_errors::kInvalidCSPInsecureValueError, - manifest_keys::kContentSecurityPolicy_IsolatedWorldPath, *it, + manifest_errors::kInvalidCSPInsecureValueError, manifest_key, *it, mapping.status.name()); return false; };
diff --git a/extensions/common/csp_validator.h b/extensions/common/csp_validator.h index 98fe1c96..acc35e7 100644 --- a/extensions/common/csp_validator.h +++ b/extensions/common/csp_validator.h
@@ -132,10 +132,11 @@ bool ContentSecurityPolicyIsSandboxed( const std::string& policy, Manifest::Type type); -// Returns whether the given |isolated_world_csp| is secure. If not, populates -// |error|. -bool IsSecureIsolatedWorldCSP(const std::string& isolated_world_csp, - base::string16* error); +// Returns whether the given |content_security_policy| prevents remote scripts. +// If not, populates |error|. +bool DoesCSPDisallowRemoteCode(const std::string& content_security_policy, + base::StringPiece manifest_key, + base::string16* error); } // namespace csp_validator
diff --git a/extensions/common/csp_validator_unittest.cc b/extensions/common/csp_validator_unittest.cc index 95a96ed..f69d378 100644 --- a/extensions/common/csp_validator_unittest.cc +++ b/extensions/common/csp_validator_unittest.cc
@@ -616,19 +616,17 @@ } } -TEST(ExtensionCSPValidator, IsSecureIsolatedWorldCSP) { - auto insecure_value_error = [](const std::string& directive, - const std::string& value) { +TEST(ExtensionCSPValidator, DoesCSPDisallowRemoteCode) { + const char* kManifestKey = "dummy_key"; + auto insecure_value_error = [kManifestKey](const std::string& directive, + const std::string& value) { return ErrorUtils::FormatErrorMessage( extensions::manifest_errors::kInvalidCSPInsecureValueError, - extensions::manifest_keys::kContentSecurityPolicy_IsolatedWorldPath, - value, directive); + kManifestKey, value, directive); }; - auto missing_secure_src_error = [](const std::string& directive) { - return MissingSecureSrcWarning( - extensions::manifest_keys::kContentSecurityPolicy_IsolatedWorldPath, - directive); + auto missing_secure_src_error = [kManifestKey](const std::string& directive) { + return MissingSecureSrcWarning(kManifestKey, directive); }; struct { @@ -657,8 +655,8 @@ for (const auto& test_case : test_cases) { SCOPED_TRACE(test_case.policy); base::string16 error; - bool result = extensions::csp_validator::IsSecureIsolatedWorldCSP( - test_case.policy, &error); + bool result = extensions::csp_validator::DoesCSPDisallowRemoteCode( + test_case.policy, kManifestKey, &error); EXPECT_EQ(test_case.expected_error.empty(), result); EXPECT_EQ(base::ASCIIToUTF16(test_case.expected_error), error); }
diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc index af65064..2479523 100644 --- a/extensions/common/manifest_handlers/csp_info.cc +++ b/extensions/common/manifest_handlers/csp_info.cc
@@ -33,8 +33,9 @@ "object-src 'self' blob: filesystem:;"; const char kDefaultIsolatedWorldCSP_BypassMainWorld[] = ""; -const char kDefaultIsolatedWorldCSP_Secure[] = - "script-src 'self'; object-src 'self'; worker-src 'self'"; + +// The default secure CSP to be used in order to prevent remote scripts. +const char kDefaultSecureCSP[] = "script-src 'self'; object-src 'self';"; const char kDefaultSandboxedPageContentSecurityPolicy[] = "sandbox allow-scripts allow-forms allow-popups allow-modals; " @@ -96,6 +97,17 @@ return extension->manifest()->Get(path, &value) ? value : nullptr; } +const char* GetDefaultExtensionPagesCSP(Extension* extension, + bool secure_only) { + if (secure_only) + return kDefaultSecureCSP; + + if (extension->GetType() == Manifest::TYPE_PLATFORM_APP) + return kDefaultPlatformAppContentSecurityPolicy; + + return kDefaultContentSecurityPolicy; +} + } // namespace CSPInfo::CSPInfo(std::string extension_pages_csp) @@ -176,8 +188,10 @@ return ParseCSPDictionary(extension, error); } - if (!ParseExtensionPagesCSP(extension, error, key, csp)) + if (!ParseExtensionPagesCSP(extension, error, key, false /* secure_only */, + csp)) { return false; + } if (!ParseSandboxCSP(extension, error, keys::kSandboxedPagesCSP, GetManifestPath(extension, keys::kSandboxedPagesCSP))) { @@ -192,6 +206,7 @@ base::string16* error) { if (!ParseExtensionPagesCSP( extension, error, keys::kContentSecurityPolicy_ExtensionPagesPath, + true /* secure_only */, GetManifestPath(extension, keys::kContentSecurityPolicy_ExtensionPagesPath))) { return false; @@ -215,9 +230,13 @@ Extension* extension, base::string16* error, base::StringPiece manifest_key, + bool secure_only, const base::Value* content_security_policy) { - if (!content_security_policy) - return SetDefaultExtensionPagesCSP(extension, manifest_key); + if (!content_security_policy) { + return SetExtensionPagesCSP( + extension, manifest_key, secure_only, + GetDefaultExtensionPagesCSP(extension, secure_only)); + } if (!content_security_policy->is_string()) { *error = GetInvalidManifestKeyError(manifest_key); @@ -231,18 +250,24 @@ return false; } + if (secure_only) { + if (!csp_validator::DoesCSPDisallowRemoteCode(content_security_policy_str, + manifest_key, error)) { + return false; + } + SetExtensionPagesCSP(extension, manifest_key, secure_only, + content_security_policy_str); + return true; + } + std::vector<InstallWarning> warnings; - // TODO(crbug.com/914224): For manifest V3, instead of sanitizing the - // extension provided csp value and raising install warnings, see if we want - // to raise errors and prevent the extension from loading. std::string sanitized_content_security_policy = SanitizeContentSecurityPolicy( content_security_policy_str, manifest_key.as_string(), GetValidatorOptions(extension), &warnings); extension->AddInstallWarnings(std::move(warnings)); - extension->SetManifestData( - keys::kContentSecurityPolicy, - std::make_unique<CSPInfo>(std::move(sanitized_content_security_policy))); + SetExtensionPagesCSP(extension, manifest_key, secure_only, + std::move(sanitized_content_security_policy)); return true; } @@ -253,7 +278,7 @@ const base::Value* isolated_world_csp = GetManifestPath(extension, key); if (!isolated_world_csp) { - SetIsolatedWorldCSP(extension, kDefaultIsolatedWorldCSP_Secure); + SetIsolatedWorldCSP(extension, kDefaultSecureCSP); return true; } @@ -268,8 +293,11 @@ return false; } - if (!csp_validator::IsSecureIsolatedWorldCSP(isolated_world_csp_str, error)) + if (!csp_validator::DoesCSPDisallowRemoteCode( + isolated_world_csp_str, + manifest_keys::kContentSecurityPolicy_IsolatedWorldPath, error)) { return false; + } SetIsolatedWorldCSP(extension, isolated_world_csp_str); return true; @@ -306,22 +334,24 @@ return true; } -bool CSPHandler::SetDefaultExtensionPagesCSP(Extension* extension, - base::StringPiece manifest_key) { - // TODO(abarth): Should we continue to let extensions override the - // default Content-Security-Policy? - const char* content_security_policy = - extension->GetType() == Manifest::TYPE_PLATFORM_APP - ? kDefaultPlatformAppContentSecurityPolicy - : kDefaultContentSecurityPolicy; +bool CSPHandler::SetExtensionPagesCSP(Extension* extension, + base::StringPiece manifest_key, + bool secure_only, + std::string content_security_policy) { + if (secure_only) { + base::string16 error; + DCHECK(csp_validator::DoesCSPDisallowRemoteCode(content_security_policy, + manifest_key, &error)); + } else { + DCHECK_EQ(content_security_policy, + SanitizeContentSecurityPolicy( + content_security_policy, manifest_key.as_string(), + GetValidatorOptions(extension), nullptr)); + } - DCHECK_EQ(content_security_policy, - SanitizeContentSecurityPolicy( - content_security_policy, manifest_key.as_string(), - GetValidatorOptions(extension), nullptr)); extension->SetManifestData( keys::kContentSecurityPolicy, - std::make_unique<CSPInfo>(content_security_policy)); + std::make_unique<CSPInfo>(std::move(content_security_policy))); return true; }
diff --git a/extensions/common/manifest_handlers/csp_info.h b/extensions/common/manifest_handlers/csp_info.h index 18d6e13..ec7812c 100644 --- a/extensions/common/manifest_handlers/csp_info.h +++ b/extensions/common/manifest_handlers/csp_info.h
@@ -76,6 +76,7 @@ bool ParseExtensionPagesCSP(Extension* extension, base::string16* error, base::StringPiece manifest_key, + bool secure_only, const base::Value* content_security_policy); // Parses the content security policy specified in the manifest for isolated @@ -89,9 +90,11 @@ base::StringPiece manifest_key, const base::Value* sandbox_csp); - // Sets the default CSP value for the extension. - bool SetDefaultExtensionPagesCSP(Extension* extension, - base::StringPiece manifest_key); + // Helper to set the extension pages content security policy manifest data. + bool SetExtensionPagesCSP(Extension* extension, + base::StringPiece manifest_key, + bool secure_only, + std::string content_security_policy); // Helper to set the isolated world content security policy manifest data. void SetIsolatedWorldCSP(Extension* extension,
diff --git a/extensions/common/manifest_handlers/csp_info_unittest.cc b/extensions/common/manifest_handlers/csp_info_unittest.cc index dd8b8ac..94b8871 100644 --- a/extensions/common/manifest_handlers/csp_info_unittest.cc +++ b/extensions/common/manifest_handlers/csp_info_unittest.cc
@@ -29,8 +29,7 @@ "script-src 'self' blob: filesystem:; " "object-src 'self' blob: filesystem:;"; const char kDefaultIsolatedWorldCSP_BypassMainWorld[] = ""; -const char kDefaultIsolatedWorldCSP_Secure[] = - "script-src 'self'; object-src 'self'; worker-src 'self'"; +const char kDefaultSecureCSP[] = "script-src 'self'; object-src 'self';"; } // namespace @@ -122,10 +121,10 @@ struct { const char* file_name; const char* csp; - } cases[] = { - {"csp_dictionary_valid.json", "default-src 'none';"}, - {"csp_empty_valid.json", "script-src 'self'; object-src 'self';"}, - {"csp_empty_dictionary_valid.json", kDefaultExtensionPagesCSP}}; + } cases[] = {{"csp_dictionary_valid_1.json", "default-src 'none'"}, + {"csp_dictionary_valid_2.json", + "worker-src 'self'; script-src; default-src 'self'"}, + {"csp_empty_dictionary_valid.json", kDefaultSecureCSP}}; // Verify that keys::kContentSecurityPolicy key can be used as a dictionary on // trunk. @@ -162,7 +161,18 @@ keys::kContentSecurityPolicy_ExtensionPagesPath)), Testcase("csp_invalid_3.json", GetInvalidManifestKeyError( - keys::kContentSecurityPolicy_ExtensionPagesPath))}; + keys::kContentSecurityPolicy_ExtensionPagesPath)), + Testcase( + "csp_missing_src.json", + ErrorUtils::FormatErrorMessage( + errors::kInvalidCSPMissingSecureSrc, + keys::kContentSecurityPolicy_ExtensionPagesPath, "script-src")), + Testcase("csp_insecure_src.json", + ErrorUtils::FormatErrorMessage( + errors::kInvalidCSPInsecureValueError, + keys::kContentSecurityPolicy_ExtensionPagesPath, + "'unsafe-eval'", "worker-src")), + }; RunTestcases(testcases, base::size(testcases), EXPECT_TYPE_ERROR); } } @@ -180,7 +190,7 @@ const char* expected_csp; } success_cases[] = { {"sandbox_dictionary_1.json", "/test", kCustomSandboxedCSP}, - {"sandbox_dictionary_1.json", "/index", kDefaultExtensionPagesCSP}, + {"sandbox_dictionary_1.json", "/index", kDefaultSecureCSP}, {"sandbox_dictionary_2.json", "/test", kDefaultSandboxedPageCSP}, {"sandbox_dictionary_2.json", "/index", kCustomExtensionPagesCSP}, }; @@ -216,12 +226,11 @@ const char* file_name; const char* expected_csp; } success_cases[] = { - {"isolated_world_csp_dictionary_default_v2.json", - kDefaultIsolatedWorldCSP_Secure}, + {"isolated_world_csp_dictionary_default_v2.json", kDefaultSecureCSP}, {"isolated_world_csp_no_dictionary_default_v2.json", kDefaultIsolatedWorldCSP_BypassMainWorld}, - {"csp_dictionary_empty_v3.json", kDefaultIsolatedWorldCSP_Secure}, - {"csp_dictionary_missing_v3.json", kDefaultIsolatedWorldCSP_Secure}, + {"csp_dictionary_empty_v3.json", kDefaultSecureCSP}, + {"csp_dictionary_missing_v3.json", kDefaultSecureCSP}, {"isolated_world_csp_valid.json", "script-src 'self'; object-src http://localhost:80;"}}; @@ -273,10 +282,10 @@ const std::string* isolated_world_csp = CSPInfo::GetIsolatedWorldCSP(*extension); ASSERT_TRUE(isolated_world_csp); - EXPECT_EQ(kDefaultIsolatedWorldCSP_Secure, *isolated_world_csp); + EXPECT_EQ(kDefaultSecureCSP, *isolated_world_csp); EXPECT_EQ(kDefaultSandboxedPageCSP, CSPInfo::GetSandboxContentSecurityPolicy(extension.get())); - EXPECT_EQ(kDefaultExtensionPagesCSP, + EXPECT_EQ(kDefaultSecureCSP, CSPInfo::GetExtensionPagesCSP(extension.get())); } }
diff --git a/extensions/common/manifest_test.cc b/extensions/common/manifest_test.cc index 397016c..c435a83 100644 --- a/extensions/common/manifest_test.cc +++ b/extensions/common/manifest_test.cc
@@ -12,6 +12,7 @@ #include "base/path_service.h" #include "base/strings/pattern.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/values.h" #include "extensions/common/extension_l10n_util.h" #include "extensions/common/extension_paths.h" @@ -269,6 +270,9 @@ void ManifestTest::RunTestcase(const Testcase& testcase, ExpectType type) { + SCOPED_TRACE(base::StringPrintf("Testing file '%s'", + testcase.manifest_filename_.c_str())); + switch (type) { case EXPECT_TYPE_ERROR: LoadAndExpectError(testcase.manifest_filename_.c_str(),
diff --git a/extensions/common/url_pattern.cc b/extensions/common/url_pattern.cc index 91663db..1656c461 100644 --- a/extensions/common/url_pattern.cc +++ b/extensions/common/url_pattern.cc
@@ -297,21 +297,22 @@ // wasn't found. base::StringPiece host_piece = host_and_port.substr(0, port_separator_pos); - // The first component can optionally be '*' to match all subdomains. - std::vector<base::StringPiece> host_components = base::SplitStringPiece( - host_piece, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - // Could be empty if the host only consists of whitespace characters. - if (host_components.empty() || - (host_components.size() == 1 && host_components[0].empty())) + if (host_piece.empty()) return ParseResult::kEmptyHost; - if (host_components[0] == "*") { + if (host_piece == "*") { match_subdomains_ = true; - host_components.erase(host_components.begin()); + host_piece.clear(); + } else if (host_piece.starts_with("*.")) { + if (host_piece.length() == 2) { + // We don't allow just '*.' as a host. + return ParseResult::kEmptyHost; + } + match_subdomains_ = true; + host_piece = host_piece.substr(2); } - host_ = base::JoinString(host_components, "."); + host_ = host_piece.as_string(); path_start_pos = host_end_pos; }
diff --git a/extensions/common/url_pattern_unittest.cc b/extensions/common/url_pattern_unittest.cc index 88514f0..dda87a33 100644 --- a/extensions/common/url_pattern_unittest.cc +++ b/extensions/common/url_pattern_unittest.cc
@@ -38,8 +38,8 @@ {"about://", URLPattern::ParseResult::kWrongSchemeSeparator}, {"http://", URLPattern::ParseResult::kEmptyHost}, {"http:///", URLPattern::ParseResult::kEmptyHost}, - {"http:// /", URLPattern::ParseResult::kEmptyHost}, {"http://:1234/", URLPattern::ParseResult::kEmptyHost}, + {"http://*./", URLPattern::ParseResult::kEmptyHost}, {"http://*foo/bar", URLPattern::ParseResult::kInvalidHostWildcard}, {"http://foo.*.bar/baz", URLPattern::ParseResult::kInvalidHostWildcard}, {"http://fo.*.ba:123/baz", URLPattern::ParseResult::kInvalidHostWildcard}, @@ -1258,4 +1258,40 @@ "http://google.com/*"))); } +// Tests the handling of whitespace, along with various "."s. +TEST(ExtensionURLPatternTest, WhitespaceHostParsing) { + constexpr char const* kHosts[] = { + ".", " ", " .", ". ", ". .", ". . .", " . ", + }; + + for (const char* host : kHosts) { + SCOPED_TRACE(base::StringPrintf("Testing Host: '%s'", host)); + + std::string pattern_str = base::StringPrintf("https://%s/*", host); + URLPattern pattern(URLPattern::SCHEME_HTTPS); + EXPECT_EQ(URLPattern::ParseResult::kSuccess, pattern.Parse(pattern_str)); + + std::string match_subdomains_pattern_str = + base::StringPrintf("https://*.%s/*", host); + URLPattern match_subdomains_pattern(URLPattern::SCHEME_HTTPS); + EXPECT_EQ(URLPattern::ParseResult::kSuccess, + match_subdomains_pattern.Parse(match_subdomains_pattern_str)); + + GURL url(base::StringPrintf("https://%s/foo", host)); + EXPECT_TRUE(url.is_valid()); + GURL subdomain_url(base::StringPrintf("https://foo.%s/foo", host)); + EXPECT_TRUE(subdomain_url.is_valid()); + + // Both the root pattern and the subdomain-matching pattern should match + // the root URL. + EXPECT_TRUE(pattern.MatchesURL(url)) << url; + EXPECT_TRUE(match_subdomains_pattern.MatchesURL(url)) << url; + + // Only the subdomain-matching pattern should match the subdomain URL. + EXPECT_FALSE(pattern.MatchesURL(subdomain_url)) << subdomain_url; + EXPECT_TRUE(match_subdomains_pattern.MatchesURL(subdomain_url)) + << subdomain_url; + } +} + } // namespace
diff --git a/extensions/test/data/manifest_tests/csp_dictionary_valid.json b/extensions/test/data/manifest_tests/csp_dictionary_valid_1.json similarity index 100% rename from extensions/test/data/manifest_tests/csp_dictionary_valid.json rename to extensions/test/data/manifest_tests/csp_dictionary_valid_1.json
diff --git a/extensions/test/data/manifest_tests/csp_dictionary_valid_2.json b/extensions/test/data/manifest_tests/csp_dictionary_valid_2.json new file mode 100644 index 0000000..0176d232 --- /dev/null +++ b/extensions/test/data/manifest_tests/csp_dictionary_valid_2.json
@@ -0,0 +1,8 @@ +{ + "name": "test", + "version": "0.1", + "manifest_version": 2, + "content_security_policy": { + "extension_pages" : "worker-src 'self'; script-src; default-src 'self'" + } +}
diff --git a/extensions/test/data/manifest_tests/csp_insecure_src.json b/extensions/test/data/manifest_tests/csp_insecure_src.json new file mode 100644 index 0000000..7b1eb14 --- /dev/null +++ b/extensions/test/data/manifest_tests/csp_insecure_src.json
@@ -0,0 +1,8 @@ +{ + "name": "test", + "version": "0.1", + "manifest_version": 2, + "content_security_policy": { + "extension_pages" : "default-src 'none'; worker-src 'unsafe-eval';" + } +}
diff --git a/extensions/test/data/manifest_tests/csp_empty_valid.json b/extensions/test/data/manifest_tests/csp_missing_src.json similarity index 100% rename from extensions/test/data/manifest_tests/csp_empty_valid.json rename to extensions/test/data/manifest_tests/csp_missing_src.json
diff --git a/extensions/test/data/manifest_tests/sandbox_csp_with_dictionary.json b/extensions/test/data/manifest_tests/sandbox_csp_with_dictionary.json index ffceab8..03b5ef9 100644 --- a/extensions/test/data/manifest_tests/sandbox_csp_with_dictionary.json +++ b/extensions/test/data/manifest_tests/sandbox_csp_with_dictionary.json
@@ -7,6 +7,6 @@ "content_security_policy": "sandbox;" }, "content_security_policy" : { - "extension_pages" : "script-src google.com;" + "extension_pages" : "default-src;" } }
diff --git a/fuchsia/base/frame_test_util.cc b/fuchsia/base/frame_test_util.cc index 9bd182e72..50fedd6 100644 --- a/fuchsia/base/frame_test_util.cc +++ b/fuchsia/base/frame_test_util.cc
@@ -33,7 +33,7 @@ base::RunLoop run_loop; ResultReceiver<fuchsia::web::Frame_ExecuteJavaScript_Result> result( run_loop.QuitClosure()); - frame->ExecuteJavaScript({"*"}, MemBufferFromString(script), + frame->ExecuteJavaScript({"*"}, MemBufferFromString(script, "test"), CallbackToFitFunction(result.GetReceiveCallback())); run_loop.Run();
diff --git a/fuchsia/base/mem_buffer_util.cc b/fuchsia/base/mem_buffer_util.cc index c71f2180..4ae3ec9 100644 --- a/fuchsia/base/mem_buffer_util.cc +++ b/fuchsia/base/mem_buffer_util.cc
@@ -26,12 +26,16 @@ return base::UTF8ToUTF16(&output_utf8.front(), output_utf8.size(), output); } -fuchsia::mem::Buffer MemBufferFromString(const base::StringPiece& data) { +fuchsia::mem::Buffer MemBufferFromString(base::StringPiece data, + base::StringPiece name) { fuchsia::mem::Buffer buffer; zx_status_t status = zx::vmo::create(data.size(), 0, &buffer.vmo); ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create"; + status = buffer.vmo.set_property(ZX_PROP_NAME, name.data(), name.size()); + ZX_DCHECK(status == ZX_OK, status); + status = buffer.vmo.write(data.data(), 0, data.size()); ZX_CHECK(status == ZX_OK, status) << "zx_vmo_write"; @@ -39,10 +43,12 @@ return buffer; } -fuchsia::mem::Buffer MemBufferFromString16(const base::StringPiece16& data) { +fuchsia::mem::Buffer MemBufferFromString16(const base::StringPiece16& data, + base::StringPiece name) { return MemBufferFromString( base::StringPiece(reinterpret_cast<const char*>(data.data()), - data.size() * sizeof(base::char16))); + data.size() * sizeof(base::char16)), + name); } bool StringFromMemBuffer(const fuchsia::mem::Buffer& buffer, @@ -74,12 +80,17 @@ return output; } -fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer) { +fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer, + base::StringPiece name) { fuchsia::mem::Buffer output; output.size = buffer.size; zx_status_t status = buffer.vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE, 0, buffer.size, &output.vmo); ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create_child"; + + status = output.vmo.set_property(ZX_PROP_NAME, name.data(), name.size()); + ZX_DCHECK(status == ZX_OK, status); + return output; }
diff --git a/fuchsia/base/mem_buffer_util.h b/fuchsia/base/mem_buffer_util.h index cf20419..4eb39c84 100644 --- a/fuchsia/base/mem_buffer_util.h +++ b/fuchsia/base/mem_buffer_util.h
@@ -20,10 +20,12 @@ base::string16* output); // Creates a Fuchsia memory buffer from |data|. -fuchsia::mem::Buffer MemBufferFromString(const base::StringPiece& data); +fuchsia::mem::Buffer MemBufferFromString(base::StringPiece data, + base::StringPiece name); // Creates a Fuchsia memory buffer from the UTF-16 string |data|. -fuchsia::mem::Buffer MemBufferFromString16(const base::StringPiece16& data); +fuchsia::mem::Buffer MemBufferFromString16(const base::StringPiece16& data, + base::StringPiece name); // Reads the contents of |buffer| into |output|. // Returns true if the read operation succeeded. @@ -35,7 +37,8 @@ fuchsia::mem::Buffer MemBufferFromFile(base::File file); // Creates a non-resizeable, copy-on-write shared memory clone of |buffer|. -fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer); +fuchsia::mem::Buffer CloneBuffer(const fuchsia::mem::Buffer& buffer, + base::StringPiece name); } // namespace cr_fuchsia
diff --git a/fuchsia/base/message_port.cc b/fuchsia/base/message_port.cc index 9c1bba3..8485d74 100644 --- a/fuchsia/base/message_port.cc +++ b/fuchsia/base/message_port.cc
@@ -87,7 +87,8 @@ base::STLClearObject(&data_utf16); - fuchsia::mem::Buffer data = cr_fuchsia::MemBufferFromString(data_utf8); + fuchsia::mem::Buffer data = + cr_fuchsia::MemBufferFromString(data_utf8, "cr-web-message-from-mojo"); if (!data.vmo) return {};
diff --git a/fuchsia/engine/browser/context_impl.cc b/fuchsia/engine/browser/context_impl.cc index 170f65a2..b154c97 100644 --- a/fuchsia/engine/browser/context_impl.cc +++ b/fuchsia/engine/browser/context_impl.cc
@@ -25,6 +25,15 @@ ContextImpl::~ContextImpl() = default; +fidl::InterfaceHandle<fuchsia::web::Frame> +ContextImpl::CreateFrameForPopupWebContents( + std::unique_ptr<content::WebContents> web_contents) { + fidl::InterfaceHandle<fuchsia::web::Frame> frame_handle; + frames_.insert(std::make_unique<FrameImpl>(std::move(web_contents), this, + frame_handle.NewRequest())); + return frame_handle; +} + void ContextImpl::DestroyFrame(FrameImpl* frame) { DCHECK(frames_.find(frame) != frames_.end()); frames_.erase(frames_.find(frame));
diff --git a/fuchsia/engine/browser/context_impl.h b/fuchsia/engine/browser/context_impl.h index 2d5a817f..6a53ae1 100644 --- a/fuchsia/engine/browser/context_impl.h +++ b/fuchsia/engine/browser/context_impl.h
@@ -18,6 +18,7 @@ namespace content { class BrowserContext; +class WebContents; } // namespace content class FrameImpl; @@ -43,6 +44,10 @@ // Returns |true| if JS injection was enabled for this Context. bool IsJavaScriptInjectionAllowed(); + // Registers a Frame originating from web content (i.e. a popup). + fidl::InterfaceHandle<fuchsia::web::Frame> CreateFrameForPopupWebContents( + std::unique_ptr<content::WebContents> web_contents); + // Called by Frames to signal a document has been loaded and signal to the // debug listeners in |web_engine_remote_debugging_| that they can now // successfully connect ChromeDriver.
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc index 04a1590b..161957fc 100644 --- a/fuchsia/engine/browser/frame_impl.cc +++ b/fuchsia/engine/browser/frame_impl.cc
@@ -266,8 +266,8 @@ } fuchsia::web::Frame_ExecuteJavaScript_Response response; - response.result = - cr_fuchsia::MemBufferFromString(std::move(result_json)); + response.result = cr_fuchsia::MemBufferFromString( + std::move(result_json), "cr-execute-js-response"); result.set_response(std::move(response)); callback(std::move(result)); }, @@ -285,6 +285,117 @@ } } +FrameImpl::PendingPopup::PendingPopup() = default; +FrameImpl::PendingPopup::~PendingPopup() = default; + +bool FrameImpl::ShouldCreateWebContents( + content::WebContents* web_contents, + content::RenderFrameHost* opener, + content::SiteInstance* source_site_instance, + int32_t route_id, + int32_t main_frame_route_id, + int32_t main_frame_widget_route_id, + content::mojom::WindowContainerType window_container_type, + const GURL& opener_url, + const std::string& frame_name, + const GURL& target_url, + const std::string& partition_id, + content::SessionStorageNamespace* session_storage_namespace) { + // Specify a generous upper bound for unacknowledged popup windows, so that we + // can catch bad client behavior while not interfering with normal operation. + constexpr size_t kMaxPendingWebContentsCount = 10; + + DCHECK_EQ(web_contents, web_contents_.get()); + + if (!popup_listener_) + return false; + + if (pending_popups_.size() >= kMaxPendingWebContentsCount) { + // The content is producing popups faster than the embedder can process + // them. Drop the popups so as to prevent resource exhaustion. + LOG(WARNING) << "Too many pending popups, ignoring request."; + + // Don't produce a WebContents for this popup. + return false; + } + + return true; +} + +void FrameImpl::AddNewContents( + content::WebContents* source, + std::unique_ptr<content::WebContents> new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_rect, + bool user_gesture, + bool* was_blocked) { + DCHECK_EQ(source, web_contents_.get()); + DCHECK(!last_popup_url_.is_empty()); + + // TODO(crbug.com/995395): Add window disposition to the FIDL interface. + switch (disposition) { + case WindowOpenDisposition::NEW_FOREGROUND_TAB: + case WindowOpenDisposition::NEW_BACKGROUND_TAB: + case WindowOpenDisposition::NEW_POPUP: + case WindowOpenDisposition::NEW_WINDOW: { + pending_popups_.emplace_back(); + PendingPopup& popup = pending_popups_.back(); + popup.creation_info.set_initial_url(last_popup_url_.spec()); + popup.creation_info.set_initiated_by_user(user_gesture); + popup.web_contents = std::move(new_contents); + last_popup_url_ = {}; + + MaybeSendPopup(); + return; + } + + // These kinds of windows don't produce Frames. + case WindowOpenDisposition::CURRENT_TAB: + case WindowOpenDisposition::SINGLETON_TAB: + case WindowOpenDisposition::SAVE_TO_DISK: + case WindowOpenDisposition::OFF_THE_RECORD: + case WindowOpenDisposition::IGNORE_ACTION: + case WindowOpenDisposition::SWITCH_TO_TAB: + case WindowOpenDisposition::UNKNOWN: + NOTIMPLEMENTED() << "Dropped new web contents (disposition: " + << static_cast<int>(disposition) << ")"; + return; + } +} + +void FrameImpl::WebContentsCreated(content::WebContents* source_contents, + int opener_render_process_id, + int opener_render_frame_id, + const std::string& frame_name, + const GURL& target_url, + content::WebContents* new_contents) { + last_popup_url_ = target_url; +} + +void FrameImpl::MaybeSendPopup() { + if (!popup_listener_) + return; + + if (popup_ack_outstanding_ || pending_popups_.empty()) + return; + + PendingPopup& popup = pending_popups_.front(); + popup_listener_->OnPopupFrameCreated( + context_->CreateFrameForPopupWebContents(std::move(popup.web_contents)), + std::move(popup.creation_info), [this] { + popup_ack_outstanding_ = false; + MaybeSendPopup(); + }); + pending_popups_.pop_front(); + popup_ack_outstanding_ = true; +} + +void FrameImpl::OnPopupListenerDisconnected(zx_status_t status) { + ZX_LOG_IF(WARNING, status != ZX_ERR_PEER_CLOSED, status) + << "Popup listener disconnected."; + pending_popups_.clear(); +} + void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) { // If a View to this Frame is already active then disconnect it. TearDownView(); @@ -372,7 +483,7 @@ // Create a read-only VMO from |script|. fuchsia::mem::Buffer script_buffer = - cr_fuchsia::MemBufferFromString16(script_utf16); + cr_fuchsia::MemBufferFromString16(script_utf16, "cr-before-load-js"); // Wrap the VMO into a read-only shared-memory container that Mojo can work // with. @@ -485,6 +596,13 @@ discarding_event_filter_.set_discard_events(!enable_input); } +void FrameImpl::SetPopupFrameCreationListener( + fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener) { + popup_listener_ = listener.Bind(); + popup_listener_.set_error_handler( + fit::bind_member(this, &FrameImpl::OnPopupListenerDisconnected)); +} + void FrameImpl::CloseContents(content::WebContents* source) { DCHECK_EQ(source, web_contents_.get()); context_->DestroyFrame(this); @@ -529,29 +647,6 @@ return true; } -bool FrameImpl::ShouldCreateWebContents( - content::WebContents* web_contents, - content::RenderFrameHost* opener, - content::SiteInstance* source_site_instance, - int32_t route_id, - int32_t main_frame_route_id, - int32_t main_frame_widget_route_id, - content::mojom::WindowContainerType window_container_type, - const GURL& opener_url, - const std::string& frame_name, - const GURL& target_url, - const std::string& partition_id, - content::SessionStorageNamespace* session_storage_namespace) { - DCHECK_EQ(web_contents, web_contents_.get()); - - // Prevent any child WebContents (popup windows, tabs, etc.) from spawning. - // TODO(crbug.com/888131): Implement support for popup windows. - NOTIMPLEMENTED() << "Ignored popup window request for URL: " - << target_url.spec(); - - return false; -} - void FrameImpl::ReadyToCommitNavigation( content::NavigationHandle* navigation_handle) { if (before_load_scripts_.empty())
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h index 74415513..dd85b2c1 100644 --- a/fuchsia/engine/browser/frame_impl.h +++ b/fuchsia/engine/browser/frame_impl.h
@@ -61,6 +61,14 @@ FRIEND_TEST_ALL_PREFIXES(FrameImplTest, ReloadFrame); FRIEND_TEST_ALL_PREFIXES(FrameImplTest, Stop); + struct PendingPopup { + PendingPopup(); + ~PendingPopup(); + + std::unique_ptr<content::WebContents> web_contents; + fuchsia::web::PopupFrameCreationInfo creation_info; + }; + class OriginScopedScript { public: OriginScopedScript(); @@ -92,6 +100,11 @@ ExecuteJavaScriptCallback callback, bool need_result); + // Sends the next entry in |pending_popups_| to |popup_listener_|. + void MaybeSendPopup(); + + void OnPopupListenerDisconnected(zx_status_t status); + // fuchsia::web::Frame implementation. void CreateView(fuchsia::ui::views::ViewToken view_token) override; void GetNavigationController( @@ -118,6 +131,9 @@ override; void SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel level) override; void SetEnableInput(bool enable_input) override; + void SetPopupFrameCreationListener( + fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener) + override; // content::WebContentsDelegate implementation. void CloseContents(content::WebContents* source) override; @@ -139,6 +155,18 @@ const GURL& target_url, const std::string& partition_id, content::SessionStorageNamespace* session_storage_namespace) override; + void WebContentsCreated(content::WebContents* source_contents, + int opener_render_process_id, + int opener_render_frame_id, + const std::string& frame_name, + const GURL& target_url, + content::WebContents* new_contents) override; + void AddNewContents(content::WebContents* source, + std::unique_ptr<content::WebContents> new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_rect, + bool user_gesture, + bool* was_blocked) override; // content::WebContentsObserver implementation. void ReadyToCommitNavigation( @@ -158,6 +186,12 @@ std::vector<uint64_t> before_load_scripts_order_; base::RepeatingCallback<void(base::StringPiece)> console_log_message_hook_; + // Used for receiving and dispatching popup created by this Frame. + fuchsia::web::PopupFrameCreationListenerPtr popup_listener_; + GURL last_popup_url_; + std::list<PendingPopup> pending_popups_; + bool popup_ack_outstanding_ = false; + fidl::Binding<fuchsia::web::Frame> binding_; DISALLOW_COPY_AND_ASSIGN(FrameImpl);
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc index d7a07105..50bd253 100644 --- a/fuchsia/engine/browser/frame_impl_browsertest.cc +++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -51,6 +51,9 @@ const char kPage2Path[] = "/title2.html"; const char kPage3Path[] = "/websql.html"; const char kDynamicTitlePath[] = "/dynamic_title.html"; +const char kPopupPath[] = "/popup_parent.html"; +const char kPopupRedirectPath[] = "/popup_child.html"; +const char kPopupMultiplePath[] = "/popup_multiple.html"; const char kPage1Title[] = "title 1"; const char kPage2Title[] = "title 2"; const char kPage3Title[] = "websql not available"; @@ -606,7 +609,7 @@ frame->AddBeforeLoadJavaScript( kBindingsId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -628,7 +631,7 @@ frame->AddBeforeLoadJavaScript( kBindingsId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -639,7 +642,7 @@ frame->AddBeforeLoadJavaScript( kBindingsId, {url.GetOrigin().spec()}, cr_fuchsia::MemBufferFromString( - "stashed_title = document.title + 'clobber';"), + "stashed_title = document.title + 'clobber';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -664,13 +667,13 @@ frame->AddBeforeLoadJavaScript( kBindingsId1, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); frame->AddBeforeLoadJavaScript( kBindingsId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title += ' there';"), + cr_fuchsia::MemBufferFromString("stashed_title += ' there';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -693,7 +696,7 @@ frame->AddBeforeLoadJavaScript( kBindingsId1, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'foo';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'foo';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -701,7 +704,7 @@ // Add a script which clobbers "foo". frame->AddBeforeLoadJavaScript( kBindingsId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'bar';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'bar';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -753,7 +756,7 @@ frame->ExecuteJavaScriptNoResult( {kUrl.GetOrigin().spec()}, cr_fuchsia::MemBufferFromString( - base::StringPrintf("my_variable = %s;", kJsonStringLiteral)), + base::StringPrintf("my_variable = %s;", kJsonStringLiteral), "test"), [](fuchsia::web::Frame_ExecuteJavaScriptNoResult_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -762,7 +765,7 @@ base::RunLoop loop; frame->ExecuteJavaScript( {kUrl.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("my_variable;"), + cr_fuchsia::MemBufferFromString("my_variable;", "test"), [&](fuchsia::web::Frame_ExecuteJavaScript_Result result) { ASSERT_TRUE(result.is_response()); std::string result_json = @@ -780,7 +783,7 @@ frame->AddBeforeLoadJavaScript( kOnLoadScriptId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -800,7 +803,7 @@ frame->AddBeforeLoadJavaScript( kOnLoadScriptId, {"http://example.com"}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -823,7 +826,7 @@ frame->AddBeforeLoadJavaScript( kOnLoadScriptId, {"*"}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -859,7 +862,7 @@ frame->AddBeforeLoadJavaScript( kOnLoadScriptId, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title = 'hello';"), + cr_fuchsia::MemBufferFromString("stashed_title = 'hello';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -873,7 +876,7 @@ frame->AddBeforeLoadJavaScript( kOnLoadScriptId2, {url.GetOrigin().spec()}, - cr_fuchsia::MemBufferFromString("stashed_title += ' there';"), + cr_fuchsia::MemBufferFromString("stashed_title += ' there';", "test"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { EXPECT_TRUE(result.is_response()); }); @@ -906,7 +909,8 @@ // 0xFE is an illegal UTF-8 byte; it should cause UTF-8 conversion to fail. frame->ExecuteJavaScriptNoResult( - {url.GetOrigin().spec()}, cr_fuchsia::MemBufferFromString("true;\xfe"), + {url.GetOrigin().spec()}, + cr_fuchsia::MemBufferFromString("true;\xfe", "test"), [&run_loop](fuchsia::web::Frame_ExecuteJavaScriptNoResult_Result result) { EXPECT_TRUE(result.is_err()); EXPECT_EQ(result.err(), fuchsia::web::FrameError::BUFFER_NOT_UTF8); @@ -1078,7 +1082,7 @@ "postmessage"); fuchsia::web::WebMessage message; - message.set_data(cr_fuchsia::MemBufferFromString(kPage1Path)); + message.set_data(cr_fuchsia::MemBufferFromString(kPage1Path, "test")); cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result> post_result; frame->PostMessage( @@ -1116,7 +1120,7 @@ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector; outgoing_vector.push_back(std::move(outgoing)); msg.set_outgoing_transfer(std::move(outgoing_vector)); - msg.set_data(cr_fuchsia::MemBufferFromString("hi")); + msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result> post_result; frame->PostMessage( @@ -1134,7 +1138,7 @@ } { - msg.set_data(cr_fuchsia::MemBufferFromString("ping")); + msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result> post_result; message_port->PostMessage( @@ -1177,7 +1181,7 @@ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector; outgoing_vector.push_back(std::move(outgoing)); msg.set_outgoing_transfer(std::move(outgoing_vector)); - msg.set_data(cr_fuchsia::MemBufferFromString("hi")); + msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result> post_result; frame->PostMessage( @@ -1234,7 +1238,7 @@ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector; outgoing_vector.push_back(std::move(outgoing)); msg.set_outgoing_transfer(std::move(outgoing_vector)); - msg.set_data(cr_fuchsia::MemBufferFromString("hi")); + msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result> post_result; frame->PostMessage( @@ -1262,7 +1266,7 @@ base::RunLoop run_loop; cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result> post_result(run_loop.QuitClosure()); - msg.set_data(cr_fuchsia::MemBufferFromString("ping")); + msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test")); incoming_message_port->PostMessage( std::move(msg), cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback())); @@ -1280,7 +1284,7 @@ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector; outgoing_vector.push_back(std::move(outgoing)); msg.set_outgoing_transfer(std::move(outgoing_vector)); - msg.set_data(cr_fuchsia::MemBufferFromString("hi")); + msg.set_data(cr_fuchsia::MemBufferFromString("hi", "test")); // Quit the runloop only after we've received a WebMessage AND a PostMessage // result. @@ -1339,7 +1343,7 @@ std::vector<fuchsia::web::OutgoingTransferable> unused_outgoing_vector; unused_outgoing_vector.push_back(std::move(unused_outgoing)); msg.set_outgoing_transfer(std::move(unused_outgoing_vector)); - msg.set_data(cr_fuchsia::MemBufferFromString("bad origin, bad!")); + msg.set_data(cr_fuchsia::MemBufferFromString("bad origin, bad!", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result> unused_post_result; @@ -1363,7 +1367,7 @@ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector; outgoing_vector.push_back(std::move(outgoing)); msg.set_outgoing_transfer(std::move(outgoing_vector)); - msg.set_data(cr_fuchsia::MemBufferFromString("good origin")); + msg.set_data(cr_fuchsia::MemBufferFromString("good origin", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::Frame_PostMessage_Result> post_result; @@ -1615,3 +1619,100 @@ EXPECT_THAT(iter->second.headers, testing::Contains(testing::Key("X-2ExtraHeaders"))); } + +class TestPopupListener : public fuchsia::web::PopupFrameCreationListener { + public: + TestPopupListener() = default; + ~TestPopupListener() override = default; + + void GetAndAckNextPopup(fuchsia::web::FramePtr* frame, + fuchsia::web::PopupFrameCreationInfo* creation_info) { + if (!frame_) { + base::RunLoop run_loop; + received_popup_callback_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + *frame = frame_.Bind(); + *creation_info = std::move(creation_info_); + + popup_ack_callback_(); + popup_ack_callback_ = {}; + } + + private: + void OnPopupFrameCreated(fidl::InterfaceHandle<fuchsia::web::Frame> frame, + fuchsia::web::PopupFrameCreationInfo creation_info, + OnPopupFrameCreatedCallback callback) override { + creation_info_ = std::move(creation_info); + frame_ = std::move(frame); + + popup_ack_callback_ = std::move(callback); + + if (received_popup_callback_) + std::move(received_popup_callback_).Run(); + } + + fidl::InterfaceHandle<fuchsia::web::Frame> frame_; + fuchsia::web::PopupFrameCreationInfo creation_info_; + base::OnceClosure received_popup_callback_; + OnPopupFrameCreatedCallback popup_ack_callback_; +}; + +IN_PROC_BROWSER_TEST_F(FrameImplTest, PopupWindow) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL popup_url(embedded_test_server()->GetURL(kPopupPath)); + GURL popup_child_url(embedded_test_server()->GetURL(kPopupRedirectPath)); + GURL title1_url(embedded_test_server()->GetURL(kPage1Path)); + fuchsia::web::FramePtr frame = CreateFrame(); + + TestPopupListener popup_listener; + fidl::Binding<fuchsia::web::PopupFrameCreationListener> + popup_listener_binding(&popup_listener); + frame->SetPopupFrameCreationListener(popup_listener_binding.NewBinding()); + + fuchsia::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); + EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {}, + popup_url.spec())); + + // Verify the popup's initial URL, "popup_child.html". + fuchsia::web::FramePtr popup_frame; + fuchsia::web::PopupFrameCreationInfo popup_info; + popup_listener.GetAndAckNextPopup(&popup_frame, &popup_info); + EXPECT_EQ(popup_info.initial_url(), popup_child_url); + + // Verify that the popup eventually redirects to "title1.html". + cr_fuchsia::TestNavigationListener popup_nav_listener; + fidl::Binding<fuchsia::web::NavigationEventListener> + popup_nav_listener_binding(&popup_nav_listener); + popup_frame->SetNavigationEventListener( + popup_nav_listener_binding.NewBinding()); + popup_nav_listener.RunUntilUrlAndTitleEquals(title1_url, kPage1Title); +} + +IN_PROC_BROWSER_TEST_F(FrameImplTest, MultiplePopups) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL popup_url(embedded_test_server()->GetURL(kPopupMultiplePath)); + GURL title1_url(embedded_test_server()->GetURL(kPage1Path)); + GURL title2_url(embedded_test_server()->GetURL(kPage2Path)); + fuchsia::web::FramePtr frame = CreateFrame(); + + TestPopupListener popup_listener; + fidl::Binding<fuchsia::web::PopupFrameCreationListener> + popup_listener_binding(&popup_listener); + frame->SetPopupFrameCreationListener(popup_listener_binding.NewBinding()); + + fuchsia::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); + EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {}, + popup_url.spec())); + + fuchsia::web::FramePtr popup_frame; + fuchsia::web::PopupFrameCreationInfo popup_info; + popup_listener.GetAndAckNextPopup(&popup_frame, &popup_info); + EXPECT_EQ(popup_info.initial_url(), title1_url); + + popup_listener.GetAndAckNextPopup(&popup_frame, &popup_info); + EXPECT_EQ(popup_info.initial_url(), title2_url); +}
diff --git a/fuchsia/engine/test/data/popup_child.html b/fuchsia/engine/test/data/popup_child.html new file mode 100644 index 0000000..eb4cbe5 --- /dev/null +++ b/fuchsia/engine/test/data/popup_child.html
@@ -0,0 +1,8 @@ +<html> + <head><title>Popup child</title></head> + <body> + <script> + window.location.href = 'title1.html'; + </script> + </body> +</html>
diff --git a/fuchsia/engine/test/data/popup_multiple.html b/fuchsia/engine/test/data/popup_multiple.html new file mode 100644 index 0000000..1ca5f20 --- /dev/null +++ b/fuchsia/engine/test/data/popup_multiple.html
@@ -0,0 +1,9 @@ +<html> + <head><title>Let's Spawn Popups Like It's 2005</title></head> + <body> + <script> + window.open('title1.html'); + window.open('title2.html'); + </script> + </body> +</html>
diff --git a/fuchsia/engine/test/data/popup_parent.html b/fuchsia/engine/test/data/popup_parent.html new file mode 100644 index 0000000..0464808e --- /dev/null +++ b/fuchsia/engine/test/data/popup_parent.html
@@ -0,0 +1,8 @@ +<html> + <head><title>Popup parent</title></head> + <body> + <script> + window.open('popup_child.html'); + </script> + </body> +</html>
diff --git a/fuchsia/http/BUILD.gn b/fuchsia/http/BUILD.gn index 624ff0ad..e156efe 100644 --- a/fuchsia/http/BUILD.gn +++ b/fuchsia/http/BUILD.gn
@@ -20,6 +20,7 @@ ] public_deps = [ "//base:base", + "//fuchsia/base", "//net:net", "//third_party/fuchsia-sdk/sdk:net_oldhttp", "//third_party/fuchsia-sdk/sdk:sys",
diff --git a/fuchsia/http/url_loader_impl.cc b/fuchsia/http/url_loader_impl.cc index 681ad48..fdcdf92 100644 --- a/fuchsia/http/url_loader_impl.cc +++ b/fuchsia/http/url_loader_impl.cc
@@ -7,6 +7,7 @@ #include "base/fuchsia/fuchsia_logging.h" #include "base/message_loop/message_loop_current.h" #include "base/task/post_task.h" +#include "fuchsia/base/mem_buffer_util.h" #include "net/base/chunked_upload_data_stream.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" @@ -30,20 +31,9 @@ // The response buffer size is exactly the offset. size_t total_size = buffer->offset(); - ::fuchsia::mem::Buffer mem_buffer; - mem_buffer.size = total_size; - zx_status_t result = zx::vmo::create(total_size, 0, &mem_buffer.vmo); - if (result != ZX_OK) { - ZX_DLOG(WARNING, result) << "zx_vmo_create"; - return nullptr; - } - - result = mem_buffer.vmo.write(buffer->StartOfBuffer(), 0, total_size); - if (result != ZX_OK) { - ZX_DLOG(WARNING, result) << "zx_vmo_write"; - return nullptr; - } - body->set_buffer(std::move(mem_buffer)); + body->set_buffer(cr_fuchsia::MemBufferFromString( + base::StringPiece(buffer->StartOfBuffer(), total_size), + "cr-http-url-body")); return body; }
diff --git a/fuchsia/runners/cast/api_bindings_client_browsertest.cc b/fuchsia/runners/cast/api_bindings_client_browsertest.cc index 947886f1..3cbb795 100644 --- a/fuchsia/runners/cast/api_bindings_client_browsertest.cc +++ b/fuchsia/runners/cast/api_bindings_client_browsertest.cc
@@ -77,7 +77,8 @@ std::vector<chromium::cast::ApiBinding> binding_list; chromium::cast::ApiBinding echo_binding; echo_binding.set_before_load_script(cr_fuchsia::MemBufferFromString( - "window.echo = cast.__platform__.PortConnector.bind('echoService');")); + "window.echo = cast.__platform__.PortConnector.bind('echoService');", + "test")); binding_list.emplace_back(std::move(echo_binding)); api_service_.set_bindings(std::move(binding_list)); StartClient(); @@ -92,7 +93,7 @@ api_service_.RunUntilMessagePortReceived("echoService").Bind(); fuchsia::web::WebMessage message; - message.set_data(cr_fuchsia::MemBufferFromString("ping")); + message.set_data(cr_fuchsia::MemBufferFromString("ping", "ping-msg")); port->PostMessage(std::move(message), [](fuchsia::web::MessagePort_PostMessage_Result result) { EXPECT_TRUE(result.is_response());
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc index f0b8250..e2d5cc6 100644 --- a/fuchsia/runners/cast/cast_runner_integration_test.cc +++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -346,7 +346,8 @@ std::vector<chromium::cast::ApiBinding> binding_list; chromium::cast::ApiBinding echo_binding; echo_binding.set_before_load_script(cr_fuchsia::MemBufferFromString( - "window.echo = cast.__platform__.PortConnector.bind('echoService');")); + "window.echo = cast.__platform__.PortConnector.bind('echoService');", + "test")); binding_list.emplace_back(std::move(echo_binding)); api_bindings_.set_bindings(std::move(binding_list)); @@ -359,7 +360,7 @@ api_bindings_.RunUntilMessagePortReceived("echoService").Bind(); fuchsia::web::WebMessage message; - message.set_data(cr_fuchsia::MemBufferFromString("ping")); + message.set_data(cr_fuchsia::MemBufferFromString("ping", "ping-msg")); port->PostMessage(std::move(message), [](fuchsia::web::MessagePort_PostMessage_Result result) { EXPECT_TRUE(result.is_response());
diff --git a/fuchsia/runners/cast/named_message_port_connector.cc b/fuchsia/runners/cast/named_message_port_connector.cc index 7bdf4ad..a9c53063 100644 --- a/fuchsia/runners/cast/named_message_port_connector.cc +++ b/fuchsia/runners/cast/named_message_port_connector.cc
@@ -43,7 +43,8 @@ frame_->AddBeforeLoadJavaScript( static_cast<uint64_t>( CastPlatformBindingsId::NAMED_MESSAGE_PORT_CONNECTOR), - std::move(origins), cr_fuchsia::CloneBuffer(bindings_script_), + std::move(origins), + cr_fuchsia::CloneBuffer(bindings_script_, "cast-bindings-js"), [](fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result) { CHECK(result.is_response()) << "Couldn't inject bindings."; }); @@ -81,7 +82,8 @@ control_port_.Unbind(); fuchsia::web::WebMessage message; - message.set_data(cr_fuchsia::MemBufferFromString(kControlPortConnectMessage)); + message.set_data(cr_fuchsia::MemBufferFromString(kControlPortConnectMessage, + "cast-connect-message")); std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector(1); outgoing_vector[0].set_message_port(control_port_.NewRequest()); message.set_outgoing_transfer(std::move(outgoing_vector));
diff --git a/fuchsia/runners/cast/named_message_port_connector_browsertest.cc b/fuchsia/runners/cast/named_message_port_connector_browsertest.cc index 30e702d..01c9e76 100644 --- a/fuchsia/runners/cast/named_message_port_connector_browsertest.cc +++ b/fuchsia/runners/cast/named_message_port_connector_browsertest.cc
@@ -97,7 +97,7 @@ fuchsia::web::MessagePortPtr message_port = message_port_receiver->Bind(); fuchsia::web::WebMessage msg; - msg.set_data(cr_fuchsia::MemBufferFromString("ping")); + msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result> post_result; message_port->PostMessage( @@ -175,7 +175,7 @@ for (fuchsia::web::MessagePortPtr* port : {&port_1, &port_2}) { fuchsia::web::WebMessage msg; - msg.set_data(cr_fuchsia::MemBufferFromString("ping")); + msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test")); cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result> post_result; (*port)->PostMessage(std::move(msg), cr_fuchsia::CallbackToFitFunction(
diff --git a/fuchsia/runners/cast/not_implemented_api_bindings_browsertest.cc b/fuchsia/runners/cast/not_implemented_api_bindings_browsertest.cc index 6d019e0..d0867c5 100644 --- a/fuchsia/runners/cast/not_implemented_api_bindings_browsertest.cc +++ b/fuchsia/runners/cast/not_implemented_api_bindings_browsertest.cc
@@ -178,7 +178,8 @@ {"*"}, cr_fuchsia::MemBufferFromString( base::StringPrintf("try { cast.__platform__.%s(); } catch {}", - expectation.function_name.c_str())), + expectation.function_name.c_str()), + "test"), [](fuchsia::web::Frame_ExecuteJavaScriptNoResult_Result result) { ASSERT_TRUE(result.is_response()); }); @@ -194,7 +195,7 @@ frame_->ExecuteJavaScriptNoResult( {"*"}, cr_fuchsia::MemBufferFromString( - "cast.__platform__.sendAssistantRequest(1,2,'foo');"), + "cast.__platform__.sendAssistantRequest(1,2,'foo');", "test"), [](fuchsia::web::Frame_ExecuteJavaScriptNoResult_Result result) { ASSERT_TRUE(result.is_response()); });
diff --git a/fuchsia/runners/cast/touch_input_bindings.cc b/fuchsia/runners/cast/touch_input_bindings.cc index ea27f6d..3138586 100644 --- a/fuchsia/runners/cast/touch_input_bindings.cc +++ b/fuchsia/runners/cast/touch_input_bindings.cc
@@ -140,7 +140,8 @@ std::string response_json; CHECK(base::JSONWriter::Write(response, &response_json)); fuchsia::web::WebMessage response_message = {}; - response_message.set_data(cr_fuchsia::MemBufferFromString(response_json)); + response_message.set_data(cr_fuchsia::MemBufferFromString( + response_json, "cast-touch-message-response")); port_->PostMessage(std::move(response_message), [](fuchsia::web::MessagePort_PostMessage_Result result) { LOG_IF(ERROR, result.is_err())
diff --git a/gpu/command_buffer/OWNERS b/gpu/command_buffer/OWNERS index 8a60f49..fba89df3 100644 --- a/gpu/command_buffer/OWNERS +++ b/gpu/command_buffer/OWNERS
@@ -1,6 +1,7 @@ bajones@chromium.org -zmo@chromium.org +geofflang@chromium.org vmiura@chromium.org +zmo@chromium.org # GPU memory buffer tests. per-file *gpu_memory_buffer*=reveman@chromium.org
diff --git a/gpu/tools/check_gpu_bots.py b/gpu/tools/check_gpu_bots.py deleted file mode 100755 index bd7c938..0000000 --- a/gpu/tools/check_gpu_bots.py +++ /dev/null
@@ -1,648 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import argparse -import datetime -import getpass -import json -import os -import smtplib -import sys -import time -import urllib -import urllib2 - -class Emailer: - DEFAULT_EMAIL_PASSWORD_FILE = '.email_password' - GMAIL_SMTP_SERVER = 'smtp.gmail.com:587' - SUBJECT = 'Chrome GPU Bots Notification' - - def __init__(self, email_from, email_to, email_password_file): - self.email_from = email_from - self.email_to = email_to - self.email_password = Emailer._getEmailPassword(email_password_file) - - @staticmethod - def format_email_body(time_str, offline_str, failed_str, noteworthy_str): - return '%s%s%s%s' % (time_str, offline_str, failed_str, noteworthy_str) - - def send_email(self, body): - message = 'From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s' % (self.email_from, - ','.join(self.email_to), Emailer.SUBJECT, body) - - try: - server = smtplib.SMTP(Emailer.GMAIL_SMTP_SERVER) - server.starttls() - server.login(self.email_from, self.email_password) - server.sendmail(self.email_from, self.email_to, message) - server.quit() - except Exception as e: - print 'Error sending email: %s' % str(e) - - def testEmailLogin(self): - server = smtplib.SMTP(Emailer.GMAIL_SMTP_SERVER) - server.starttls() - server.login(self.email_from, self.email_password) - server.quit() - - @staticmethod - def _getEmailPassword(email_password_file): - password = '' - - password_file = (email_password_file if email_password_file is not None - else Emailer.DEFAULT_EMAIL_PASSWORD_FILE) - - if os.path.isfile(password_file): - with open(password_file, 'r') as f: - password = f.read().strip() - else: - password = getpass.getpass( - 'Please enter email password for source email account: ') - - return password - -class GpuBot: - def __init__(self, waterfall_name, bot_name, bot_data): - self.waterfall_name = waterfall_name - self.bot_name = bot_name - self.bot_data = bot_data - self._end_time = None - self._hours_since_last_run = None - self.failure_string = None - self.bot_url = None - self.build_url = None - - def getEndTime(self): - return self._end_time - - def setEndTime(self, end_time): - self._end_time = end_time - self._hours_since_last_run = \ - roughTimeDiffInHours(end_time, time.localtime()) - - def getHoursSinceLastRun(self): - return self._hours_since_last_run - - def toDict(self): - dict = {'waterfall_name': self.waterfall_name, 'bot_name': self.bot_name} - - if self._end_time is not None: - dict['end_time'] = serialTime(self._end_time) - dict['hours_since_last_run'] = self._hours_since_last_run - - if self.failure_string is not None: - dict['failure_string'] = self.failure_string - - if self.bot_url is not None: - dict['bot_url'] = self.bot_url - - if self.build_url is not None: - dict['build_url'] = self.build_url - - return dict - - @staticmethod - def fromDict(dict): - gpu_bot = GpuBot(dict['waterfall_name'], dict['bot_name'], None) - - if 'end_time' in dict: - gpu_bot._end_time = unserializeTime(dict['end_time']) - - if 'hours_since_last_run' in dict: - gpu_bot._hours_since_last_run = dict['hours_since_last_run'] - - if 'failure_string' in dict: - gpu_bot.failure_string = dict['failure_string'] - - if 'bot_url' in dict: - gpu_bot.bot_url = dict['bot_url'] - - if 'build_url' in dict: - gpu_bot.build_url = dict['build_url'] - - return gpu_bot - -def errorNoMostRecentBuild(waterfall_name, bot_name): - print 'No most recent build available: %s::%s' % (waterfall_name, bot_name) - -class Waterfall: - BASE_URL = 'http://build.chromium.org/p/' - BASE_BUILD_URL = BASE_URL + '%s/builders/%s' - SPECIFIC_BUILD_URL = BASE_URL + '%s/builders/%s/builds/%s' - BASE_JSON_BUILDERS_URL = BASE_URL + '%s/json/builders' - BASE_JSON_BUILDS_URL = BASE_URL + '%s/json/builders/%s/builds' - REGULAR_WATERFALLS = ['chromium.gpu', 'chromium.gpu.fyi'] - WEBKIT_GPU_BOTS = ['GPU Win Builder', - 'GPU Win Builder (dbg)', - 'GPU Win7 (NVIDIA)', - 'GPU Win7 (dbg) (NVIDIA)', - 'GPU Mac Builder', - 'GPU Mac Builder (dbg)', - 'GPU Mac10.7', - 'GPU Mac10.7 (dbg)', - 'GPU Linux Builder', - 'GPU Linux Builder (dbg)', - 'GPU Linux (NVIDIA)', - 'GPU Linux (dbg) (NVIDIA)'] - FILTERED_WATERFALLS = [('chromium.webkit', WEBKIT_GPU_BOTS)] - - @staticmethod - def getJsonFromUrl(url): - conn = urllib2.urlopen(url) - result = conn.read() - conn.close() - return json.loads(result) - - @staticmethod - def getBuildersJsonForWaterfall(waterfall): - querystring = '?filter' - return (Waterfall.getJsonFromUrl((Waterfall.BASE_JSON_BUILDERS_URL + '%s') - % (waterfall, querystring))) - - @staticmethod - def getLastNBuildsForBuilder(n, waterfall, builder): - if n <= 0: - return {} - - querystring = '?' - - for i in range(n): - querystring += 'select=-%d&' % (i + 1) - - querystring += 'filter' - - return Waterfall.getJsonFromUrl((Waterfall.BASE_JSON_BUILDS_URL + '%s') % - (waterfall, urllib.quote(builder), querystring)) - - @staticmethod - def getFilteredBuildersJsonForWaterfall(waterfall, filter): - querystring = '?' - - for bot_name in filter: - querystring += 'select=%s&' % urllib.quote(bot_name) - - querystring += 'filter' - - return Waterfall.getJsonFromUrl((Waterfall.BASE_JSON_BUILDERS_URL + '%s') - % (waterfall, querystring)) - - @staticmethod - def getAllGpuBots(): - allbots = {k: Waterfall.getBuildersJsonForWaterfall(k) - for k in Waterfall.REGULAR_WATERFALLS} - - filteredbots = {k[0]: - Waterfall.getFilteredBuildersJsonForWaterfall(k[0], k[1]) - for k in Waterfall.FILTERED_WATERFALLS} - - allbots.update(filteredbots) - - return allbots - - @staticmethod - def getOfflineBots(bots): - offline_bots = [] - - for waterfall_name in bots: - waterfall = bots[waterfall_name] - - for bot_name in waterfall: - bot = waterfall[bot_name] - - if bot['state'] != 'offline': - continue - - gpu_bot = GpuBot(waterfall_name, bot_name, bot) - gpu_bot.bot_url = Waterfall.BASE_BUILD_URL % (waterfall_name, - urllib.quote(bot_name)) - - most_recent_build = Waterfall.getMostRecentlyCompletedBuildForBot( - gpu_bot) - - if (most_recent_build and 'times' in most_recent_build and - most_recent_build['times']): - gpu_bot.setEndTime(time.localtime(most_recent_build['times'][1])) - else: - errorNoMostRecentBuild(waterfall_name, bot_name) - - offline_bots.append(gpu_bot) - - return offline_bots - - @staticmethod - def getMostRecentlyCompletedBuildForBot(bot): - if bot.bot_data is not None and 'most_recent_build' in bot.bot_data: - return bot.bot_data['most_recent_build'] - - # Unfortunately, the JSON API doesn't provide a "most recent completed - # build" call. We just have to get some number of the most recent (including - # current, in-progress builds) and give up if that's not enough. - NUM_BUILDS = 10 - builds = Waterfall.getLastNBuildsForBuilder(NUM_BUILDS, bot.waterfall_name, - bot.bot_name) - - for i in range(NUM_BUILDS): - current_build_name = '-%d' % (i + 1) - current_build = builds[current_build_name] - - if 'results' in current_build and current_build['results'] is not None: - if bot.bot_data is not None: - bot.bot_data['most_recent_build'] = current_build - - return current_build - - return None - - @staticmethod - def getFailedBots(bots): - failed_bots = [] - - for waterfall_name in bots: - waterfall = bots[waterfall_name] - - for bot_name in waterfall: - bot = waterfall[bot_name] - gpu_bot = GpuBot(waterfall_name, bot_name, bot) - gpu_bot.bot_url = Waterfall.BASE_BUILD_URL % (waterfall_name, - urllib.quote(bot_name)) - - most_recent_build = Waterfall.getMostRecentlyCompletedBuildForBot( - gpu_bot) - - if (most_recent_build and 'text' in most_recent_build and - 'failed' in most_recent_build['text']): - gpu_bot.failure_string = ' '.join(most_recent_build['text']) - gpu_bot.build_url = Waterfall.SPECIFIC_BUILD_URL % (waterfall_name, - urllib.quote(bot_name), most_recent_build['number']) - failed_bots.append(gpu_bot) - elif not most_recent_build: - errorNoMostRecentBuild(waterfall_name, bot_name) - - return failed_bots - -def formatTime(t): - return time.strftime("%a, %d %b %Y %H:%M:%S", t) - -def roughTimeDiffInHours(t1, t2): - datetimes = [] - - for t in [t1, t2]: - datetimes.append(datetime.datetime(t.tm_year, t.tm_mon, t.tm_mday, - t.tm_hour, t.tm_min, t.tm_sec)) - - datetime_diff = datetimes[0] - datetimes[1] - - hours = float(datetime_diff.total_seconds()) / 3600.0 - - return abs(hours) - -def getBotStr(bot): - s = ' %s::%s\n' % (bot.waterfall_name, bot.bot_name) - - if bot.failure_string is not None: - s += ' failure: %s\n' % bot.failure_string - - if bot.getEndTime() is not None: - s += (' last build end time: %s (roughly %f hours ago)\n' % - (formatTime(bot.getEndTime()), bot.getHoursSinceLastRun())) - - if bot.bot_url is not None: - s += ' bot url: %s\n' % bot.bot_url - - if bot.build_url is not None: - s += ' build url: %s\n' % bot.build_url - - s += '\n' - return s - -def getBotsStr(bots): - s = '' - - for bot in bots: - s += getBotStr(bot) - - s += '\n' - return s - -def getOfflineBotsStr(offline_bots): - return 'Offline bots:\n%s' % getBotsStr(offline_bots) - -def getFailedBotsStr(failed_bots): - return 'Failed bots:\n%s' % getBotsStr(failed_bots) - -def getBotDicts(bots): - dicts = [] - - for bot in bots: - dicts.append(bot.toDict()) - - return dicts - -def unserializeTime(t): - return time.struct_time((t['year'], t['mon'], t['day'], t['hour'], t['min'], - t['sec'], 0, 0, 0)) - -def serialTime(t): - return {'year': t.tm_year, 'mon': t.tm_mon, 'day': t.tm_mday, - 'hour': t.tm_hour, 'min': t.tm_min, 'sec': t.tm_sec} - -def getSummary(offline_bots, failed_bots): - offline_bot_dict = getBotDicts(offline_bots) - failed_bot_dict = getBotDicts(failed_bots) - return {'offline': offline_bot_dict, 'failed': failed_bot_dict} - -def findBot(name, lst): - for bot in lst: - if bot.bot_name == name: - return bot - - return None - -def getNoteworthyEvents(offline_bots, failed_bots, previous_results): - CRITICAL_NUM_HOURS = 1.0 - - previous_offline = (previous_results['offline'] if 'offline' - in previous_results else []) - - previous_failures = (previous_results['failed'] if 'failed' - in previous_results else []) - - noteworthy_offline = [] - for bot in offline_bots: - if bot.getHoursSinceLastRun() >= CRITICAL_NUM_HOURS: - previous_bot = findBot(bot.bot_name, previous_offline) - - if (previous_bot is None or - previous_bot.getHoursSinceLastRun() < CRITICAL_NUM_HOURS): - noteworthy_offline.append(bot) - - noteworthy_new_failures = [] - for bot in failed_bots: - previous_bot = findBot(bot.bot_name, previous_failures) - - if previous_bot is None: - noteworthy_new_failures.append(bot) - - noteworthy_new_offline_recoveries = [] - for bot in previous_offline: - if bot.getHoursSinceLastRun() < CRITICAL_NUM_HOURS: - continue - - current_bot = findBot(bot.bot_name, offline_bots) - if current_bot is None: - noteworthy_new_offline_recoveries.append(bot) - - noteworthy_new_failure_recoveries = [] - for bot in previous_failures: - current_bot = findBot(bot.bot_name, failed_bots) - - if current_bot is None: - noteworthy_new_failure_recoveries.append(bot) - - return {'offline': noteworthy_offline, 'failed': noteworthy_new_failures, - 'recovered_failures': noteworthy_new_failure_recoveries, - 'recovered_offline': noteworthy_new_offline_recoveries} - -def getNoteworthyStr(noteworthy_events): - s = '' - - if noteworthy_events['offline']: - s += 'IMPORTANT bots newly offline for over an hour:\n' - - for bot in noteworthy_events['offline']: - s += getBotStr(bot) - - s += '\n' - - if noteworthy_events['failed']: - s += 'IMPORTANT new failing bots:\n' - - for bot in noteworthy_events['failed']: - s += getBotStr(bot) - - s += '\n' - - if noteworthy_events['recovered_offline']: - s += 'IMPORTANT newly recovered previously offline bots:\n' - - for bot in noteworthy_events['recovered_offline']: - s += getBotStr(bot) - - s += '\n' - - if noteworthy_events['recovered_failures']: - s += 'IMPORTANT newly recovered failing bots:\n' - - for bot in noteworthy_events['recovered_failures']: - s += getBotStr(bot) - - s += '\n' - - return s - -def dictsToBots(bots): - offline_bots = [] - for bot in bots['offline']: - offline_bots.append(GpuBot.fromDict(bot)) - - failed_bots = [] - for bot in bots['failed']: - failed_bots.append(GpuBot.fromDict(bot)) - - return {'offline': offline_bots, 'failed': failed_bots} - -class GpuBotPoller: - DEFAULT_PREVIOUS_RESULTS_FILE = '.check_gpu_bots_previous_results' - - def __init__(self, emailer, send_email_for_recovered_offline_bots, - send_email_for_recovered_failing_bots, send_email_on_error, - previous_results_file): - self.emailer = emailer - - self.send_email_for_recovered_offline_bots = \ - send_email_for_recovered_offline_bots - - self.send_email_for_recovered_failing_bots = \ - send_email_for_recovered_failing_bots - - self.send_email_on_error = send_email_on_error - self.previous_results_file = previous_results_file - - def shouldEmail(self, noteworthy_events): - if noteworthy_events['offline'] or noteworthy_events['failed']: - return True - - if (self.send_email_for_recovered_offline_bots and - noteworthy_events['recovered_offline']): - return True - - if (self.send_email_for_recovered_failing_bots and - noteworthy_events['recovered_failures']): - return True - - return False - - def writeResults(self, summary): - results_file = (self.previous_results_file - if self.previous_results_file is not None - else GpuBotPoller.DEFAULT_PREVIOUS_RESULTS_FILE) - - with open(results_file, 'w') as f: - f.write(json.dumps(summary)) - - def getPreviousResults(self): - previous_results_file = (self.previous_results_file - if self.previous_results_file is not None - else GpuBotPoller.DEFAULT_PREVIOUS_RESULTS_FILE) - - previous_results = {} - if os.path.isfile(previous_results_file): - with open(previous_results_file, 'r') as f: - previous_results = dictsToBots(json.loads(f.read())) - - return previous_results - - def checkBots(self): - time_str = 'Current time: %s\n\n' % (formatTime(time.localtime())) - print time_str - - try: - bots = Waterfall.getAllGpuBots() - - offline_bots = Waterfall.getOfflineBots(bots) - offline_str = getOfflineBotsStr(offline_bots) - print offline_str - - failed_bots = Waterfall.getFailedBots(bots) - failed_str = getFailedBotsStr(failed_bots) - print failed_str - - previous_results = self.getPreviousResults() - noteworthy_events = getNoteworthyEvents(offline_bots, failed_bots, - previous_results) - - noteworthy_str = getNoteworthyStr(noteworthy_events) - print noteworthy_str - - summary = getSummary(offline_bots, failed_bots) - self.writeResults(summary) - - if (self.emailer is not None and self.shouldEmail(noteworthy_events)): - self.emailer.send_email(Emailer.format_email_body(time_str, offline_str, - failed_str, noteworthy_str)) - except Exception as e: - error_str = 'Error: %s' % str(e) - print error_str - - if self.send_email_on_error: - self.emailer.send_email(error_str) - -def parseArgs(sys_args): - parser = argparse.ArgumentParser(prog=sys_args[0], - description='Query the Chromium GPU Bots Waterfall, output ' + - 'potential problems, and optionally repeat automatically and/or ' + - 'email notifications of results.') - - parser.add_argument('--repeat-delay', type=int, dest='repeat_delay', - required=False, - help='How often to automatically re-run the script, in minutes.') - - parser.add_argument('--email-from', type=str, dest='email_from', - required=False, - help='Email address to send from. Requires also specifying ' + - '\'--email-to\'.') - - parser.add_argument('--email-to', type=str, dest='email_to', required=False, - nargs='+', - help='Email address(es) to send to. Requires also specifying ' + - '\'--email-from\'') - - parser.add_argument('--send-email-for-recovered-offline-bots', - dest='send_email_for_recovered_offline_bots', action='store_true', - default=False, - help='Send an email out when a bot which has been offline for more ' + - 'than 1 hour goes back online.') - - parser.add_argument('--send-email-for-recovered-failing-bots', - dest='send_email_for_recovered_failing_bots', - action='store_true', default=False, - help='Send an email when a failing bot recovers.') - - parser.add_argument('--send-email-on-error', - dest='send_email_on_error', - action='store_true', default=False, - help='Send an email when the script has an error. For example, if ' + - 'the server is unreachable.') - - parser.add_argument('--email-password-file', - dest='email_password_file', - required=False, - help=(('File containing the plaintext password of the source email ' + - 'account. By default, \'%s\' will be tried. If it does not exist, ' + - 'you will be prompted. If you opt to store your password on disk ' + - 'in plaintext, use of a dummy account is strongly recommended.') - % Emailer.DEFAULT_EMAIL_PASSWORD_FILE)) - - parser.add_argument('--previous-results-file', - dest='previous_results_file', - required=False, - help=(('File to store the results of the previous invocation of ' + - 'this script. By default, \'%s\' will be used.') - % GpuBotPoller.DEFAULT_PREVIOUS_RESULTS_FILE)) - - args = parser.parse_args(sys_args[1:]) - - if args.email_from is not None and args.email_to is None: - parser.error('--email-from requires --email-to.') - elif args.email_to is not None and args.email_from is None: - parser.error('--email-to requires --email-from.') - elif args.email_from is None and args.send_email_for_recovered_offline_bots: - parser.error('--send-email-for-recovered-offline-bots requires ' + - '--email-to and --email-from.') - elif (args.email_from is None and args.send_email_for_recovered_failing_bots): - parser.error('--send-email-for-recovered-failing-bots ' + - 'requires --email-to and --email-from.') - elif (args.email_from is None and args.send_email_on_error): - parser.error('--send-email-on-error ' + - 'requires --email-to and --email-from.') - elif (args.email_password_file and - not os.path.isfile(args.email_password_file)): - parser.error('File does not exist: %s' % args.email_password_file) - - return args - -def main(sys_args): - args = parseArgs(sys_args) - - emailer = None - if args.email_from is not None and args.email_to is not None: - emailer = Emailer(args.email_from, args.email_to, args.email_password_file) - - try: - emailer.testEmailLogin() - except Exception as e: - print 'Error logging into email account: %s' % str(e) - return 1 - - poller = GpuBotPoller(emailer, - args.send_email_for_recovered_offline_bots, - args.send_email_for_recovered_failing_bots, - args.send_email_on_error, - args.previous_results_file) - - while True: - poller.checkBots() - - if args.repeat_delay is None: - break - - print 'Will run again in %d minutes...\n' % args.repeat_delay - time.sleep(args.repeat_delay * 60) - - return 0 - -if __name__ == '__main__': - sys.exit(main(sys.argv))
diff --git a/infra/config/commit-queue.cfg b/infra/config/commit-queue.cfg index 1058e7c..0598ddfc 100644 --- a/infra/config/commit-queue.cfg +++ b/infra/config/commit-queue.cfg
@@ -204,8 +204,8 @@ location_regexp: ".+/[+]/gpu/.+" location_regexp: ".+/[+]/testing/buildbot/chromium.dawn.json" location_regexp: ".+/[+]/third_party/blink/renderer/modules/webgpu/.+" - location_regexp: ".+/[+]/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu" - location_regexp: ".+/[+]/third_party/blink/web_tests/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" } builders { @@ -213,8 +213,8 @@ location_regexp: ".+/[+]/gpu/.+" location_regexp: ".+/[+]/testing/buildbot/chromium.dawn.json" location_regexp: ".+/[+]/third_party/blink/renderer/modules/webgpu/.+" - location_regexp: ".+/[+]/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu" - location_regexp: ".+/[+]/third_party/blink/web_tests/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" } builders { @@ -222,8 +222,8 @@ location_regexp: ".+/[+]/gpu/.+" location_regexp: ".+/[+]/testing/buildbot/chromium.dawn.json" location_regexp: ".+/[+]/third_party/blink/renderer/modules/webgpu/.+" - location_regexp: ".+/[+]/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu" - location_regexp: ".+/[+]/third_party/blink/web_tests/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" } builders { @@ -231,8 +231,8 @@ location_regexp: ".+/[+]/gpu/.+" location_regexp: ".+/[+]/testing/buildbot/chromium.dawn.json" location_regexp: ".+/[+]/third_party/blink/renderer/modules/webgpu/.+" - location_regexp: ".+/[+]/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu" - location_regexp: ".+/[+]/third_party/blink/web_tests/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" } builders { @@ -244,20 +244,6 @@ location_regexp: ".+/[+]/chromecast/.+" } builders { - name: "chromium/try/gpu-fyi-try-android-p-pixel-2-skv-32" - # Some locations disabled due to limited capacity. - #location_regexp: ".+/[+]/cc/.+" - location_regexp: ".+/[+]/components/viz/.+" - location_regexp: ".+/[+]/content/test/gpu/gpu_tests/.+py" - location_regexp: ".+/[+]/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt" - location_regexp: ".+/[+]/gpu/vulkan/.+" - #location_regexp: ".+/[+]/media/gpu/.+" - location_regexp: ".+/[+]/services/viz/.+" - #location_regexp: ".+/[+]/third_party/blink/renderer/platform/graphics/gpu/.+" - #location_regexp: ".+/[+]/third_party/skia/src/gpu/.+" - #location_regexp: ".+/[+]/third_party/skia/include/gpu/.+" - } - builders { name: "chromium/try/ios-simulator-cronet" location_regexp: ".+/[+]/components/cronet/.+" location_regexp: ".+/[+]/components/grpc_support/.+" @@ -290,7 +276,7 @@ location_regexp: ".+/[+]/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/.+" } builders { - name: "chromium/try/linux_layout_tests_layout_ng" + name: "chromium/try/linux_layout_tests_layout_ng_disabled" location_regexp: ".+/[+]/third_party/blink/renderer/core/editing/.+" location_regexp: ".+/[+]/third_party/blink/renderer/core/layout/.+" location_regexp: ".+/[+]/third_party/blink/renderer/core/paint/.+"
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index 74cef9d..0f853821 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -4359,7 +4359,7 @@ } builders { mixins: "linux-try" - name: "linux_layout_tests_layout_ng" + name: "linux_layout_tests_layout_ng_disabled" mixins: "builderless" } builders {
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg index e8bf7df..0d0ffaa 100644 --- a/infra/config/luci-milo.cfg +++ b/infra/config/luci-milo.cfg
@@ -2722,8 +2722,8 @@ short_name: "p2" } builders { - name: "buildbucket/luci.chromium.ci/Android FYI eDQP Release (Nexus 5X)" - category: "week2a|android|edqp" + name: "buildbucket/luci.chromium.ci/Android FYI dEQP Release (Nexus 5X)" + category: "week2a|android|deqp" short_name: "n5x" } builders { @@ -2883,9 +2883,9 @@ short_name: "ozone" } builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Linux eDQP Builder" + name: "buildbucket/luci.chromium.ci/GPU FYI Linux dEQP Builder" category: "week2d|linux|gpu|fyi" - short_name: "edqp" + short_name: "deqp" } builders { name: "buildbucket/luci.chromium.ci/Linux FYI GPU TSAN Release" @@ -2945,9 +2945,9 @@ short_name: "dbg" } builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Mac eDQP Builder" + name: "buildbucket/luci.chromium.ci/GPU FYI Mac dEQP Builder" category: "week2d|mac|gpu|fyi" - short_name: "edqp" + short_name: "deqp" } builders { name: "buildbucket/luci.chromium.ci/Mac FYI GPU ASAN Release" @@ -4365,7 +4365,7 @@ name: "buildbucket/luci.chromium.try/linux_layout_tests_composite_after_paint" } builders { - name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng" + name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng_disabled" } builders { name: "buildbucket/luci.chromium.try/linux_mojo" @@ -5108,7 +5108,7 @@ name: "buildbucket/luci.chromium.try/linux_layout_tests_composite_after_paint" } builders { - name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng" + name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng_disabled" } builders { name: "buildbucket/luci.chromium.try/linux_mojo"
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index fcccc0b..be8e477 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -237,22 +237,22 @@ <message name="IDS_IOS_PRODUCT_NAME" desc="The Chrome application name"> Chromium </message> - <message name="IDS_IOS_QR_SCANNER_CAMERA_IN_USE_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR scanner but the camera is in use by another application. [Length: 140em] [iOS only]"> + <message name="IDS_IOS_SCANNER_CAMERA_IN_USE_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR or credit card scanner but the camera is in use by another application. [Length: 140em] [iOS only]"> Chromium can't use your camera because it's in use by another application </message> - <message name="IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL" desc="Body of modal dialog shown when the user tries to open the QR scanner but the application lacks permission to use the camera. The text instructs the user how to change the permissions setting. [Length: 140em] [iOS only]"> + <message name="IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL" desc="Body of modal dialog shown when the user tries to open the QR or credit card scanner but the application lacks permission to use the camera. The text instructs the user how to change the permissions setting. [Length: 140em] [iOS only]"> Open Settings > Privacy > Camera > Chromium and turn on the camera. </message> - <message name="IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE" desc="Title of modal dialog shown when the user tries to open the QR scanner but the application lacks permission to use the camera. The body of this dialog instructs the user how to change the permissions setting. [Length: 50em] [iOS only]"> - Start using Chromium QR scanner + <message name="IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE" desc="Title of modal dialog shown when the user tries to open the QR or Credit Card scanner but the application lacks permission to use the camera. The body of this dialog instructs the user how to change the permissions setting. [Length: 50em] [iOS only]"> + Start using Chromium scanner </message> - <message name="IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS" desc="Title of modal dialog shown when the user tries to open the QR scanner but the application lacks permission to use the camera. [Length: 40em] [iOS only]"> - Turn on Chromium QR scanner + <message name="IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS" desc="Title of modal dialog shown when the user tries to open the QR or credit card scanner but the application lacks permission to use the camera. [Length: 40em] [iOS only]"> + Turn on Chromium scanner </message> - <message name="IDS_IOS_QR_SCANNER_CAMERA_UNAVAILABLE_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR scanner but the camera is unavailable. [Length: 140em] [iOS only]"> + <message name="IDS_IOS_SCANNER_CAMERA_UNAVAILABLE_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR or credit card scanner but the camera is unavailable. [Length: 140em] [iOS only]"> Chromium can't use your camera right now </message> - <message name="IDS_IOS_QR_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR scanner in a Split View mode, when the camera is unavailable. [Length: 140em] [iOS only]"> + <message name="IDS_IOS_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR or credit card scanner in a Split View mode, when the camera is unavailable. [Length: 140em] [iOS only]"> Chromium can't use your camera in Split View mode </message> <message name="IDS_IOS_SAFE_MODE_NAMED_TWEAKS_FOUND" desc="The message indicating a 3rd party tweak has been found that is known to crash Chromium. After the ':', we will list the names of the libraries. [Length: 140em]">
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index c4b1664..8325e2b 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -246,8 +246,8 @@ <message name="IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE" desc="Title of modal dialog shown when the user tries to open the QR scanner but the application lacks permission to use the camera. The body of this dialog instructs the user how to change the permissions setting. [Length: 50em] [iOS only]"> Start using Google Chrome QR scanner </message> - <message name="IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS" desc="Title of modal dialog shown when the user tries to open the QR scanner but the application lacks permission to use the camera. [Length: 40em] [iOS only]"> - Turn on Google Chrome QR scanner + <message name="IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS" desc="Title of modal dialog shown when the user tries to open the QR or credit card scanner but the application lacks permission to use the camera. [Length: 40em] [iOS only]"> + Chrome Would Like to Access the Camera </message> <message name="IDS_IOS_QR_SCANNER_CAMERA_UNAVAILABLE_ALERT_DETAIL" desc="Body of a modal dialog shown when the user tries to open the QR scanner but the camera is unavailable. [Length: 140em] [iOS only]"> Google Chrome can't use your camera right now
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 7f8fe91f..220df29 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1250,13 +1250,13 @@ <message name="IDS_IOS_QR_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_TITLE" desc="Title of a modal dialog shown when the user tries to open the QR scanner in a Split View mode. [Length: 40em] [iOS only]" meaning="Title of a Split View error dialog in QR Scanner."> Split View </message> - <message name="IDS_IOS_SCANNER_TORCH_BUTTON_ACCESSIBILITY_LABEL" desc="Accessibility label for the button to turn torch on and off in the scanner. The current state of the button is communicated using the accessibility value. [Length: unlimited] [iOS only]"> + <message name="IDS_IOS_SCANNER_TORCH_BUTTON_ACCESSIBILITY_LABEL" desc="Accessibility label for the button to turn torch on and off in the Scanner. The current state of the button is communicated using the accessibility value. [Length: unlimited] [iOS only]" meaning="The button to turn on and off the torch. [20em] [Read by Text-to-Speech]"> Torch </message> - <message name="IDS_IOS_SCANNER_TORCH_OFF_ACCESSIBILITY_VALUE" desc="Accessiblity value of the button to turn torch on in the scanner. The button communicates that the torch is current off. [Length: unlimited] [iOS only]"> + <message name="IDS_IOS_SCANNER_TORCH_OFF_ACCESSIBILITY_VALUE" desc="Accessiblity value of the button to turn torch on in the Scanner. The button communicates that the torch is current off. [Length: unlimited] [iOS only]" meaning="The user will put off the torch [20em] [Read by Text-to-Speech]"> Off </message> - <message name="IDS_IOS_SCANNER_TORCH_ON_ACCESSIBILITY_VALUE" desc="Accessibility value of the button to turn torch off in the scanner. The button communicates that the torch is currently on. [Length: unlimited] [iOS only]"> + <message name="IDS_IOS_SCANNER_TORCH_ON_ACCESSIBILITY_VALUE" desc="Accessibility value of the button to turn torch off in the Scanner. The button communicates that the torch is currently on. [Length: unlimited] [iOS only]" meaning="The user will put on the torch [20em] [Read by Text-to-Speech]"> On </message> <message name="IDS_IOS_QR_SCANNER_VIEWPORT_CAPTION" desc="Message displayed below the QR scanner viewport instructing the user to position the scanned QR or bar code inside the viewport. [Length: unlimited] [iOS only]"> @@ -1277,6 +1277,27 @@ <message name="IDS_IOS_READING_LIST_CANCEL_BUTTON" desc="Label of the button to stop editing the reading list entries (delete, mark as read/unread) [Length: 25em]" meaning="Stop editing. [Length: 25em]"> Cancel </message> + <message name="IDS_IOS_SCANNER_ALERT_CANCEL" desc="Title for a button to cancel a Scanner error dialog. The dialog will be dismissed and no action will be taken. [Length: 20em] [iOS only]" meaning="A button to cancel a Scanner error dialog."> + Cancel + </message> + <message name="IDS_IOS_SCANNER_CAMERA_IN_USE_ALERT_TITLE" desc="Title of a modal dialog shown when the user tries to open the scanner but the camera is in use by another application. [Length: 40em] [iOS only]"> + Camera is in use + </message> + <message name="IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL_GO_TO_SETTINGS" desc="Body of modal dialog shown when the user tries to open the scanner but the application lacks permission to use the camera. This body tells the users they'll be redirected to the Settings app. [Length: 140em] [iOS only]"> + To scan a QR code or credit card, enable the camera from settings. + </message> + <message name="IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_GO_TO_SETTINGS" desc="Title for a button to go to System settings app. [Length: 20em] [iOS only]"> + Settings + </message> + <message name="IDS_IOS_SCANNER_CAMERA_UNAVAILABLE_ALERT_TITLE" desc="Title of a modal dialog shown when the user tries to open the scanner but the camera is unavailable. [Length: 40em] [iOS only]"> + Camera is unavailable + </message> + <message name="IDS_IOS_SCANNER_SCANNED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the user scans a QR code, bar code, or Credit Card. [Length: unlimited] [iOS only]"> + Scanned + </message> + <message name="IDS_IOS_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_TITLE" desc="Title of a modal dialog shown when the user tries to open the scanner in a Split View mode. [Length: 40em] [iOS only]" meaning="Title of a Split View error dialog in Scanner."> + Split View + </message> <message name="IDS_IOS_TOOLS_MENU_CELL_NEW_FEATURE_BADGE" desc="Title and accessibility label of the badge displayed on a tools menu item when it represents a new feature [Length: 20em]" meaning="A badge with this title is displayed informing the user that this feature that is new to them."> New </message>
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn index f1722e0..434a768 100644 --- a/ios/chrome/browser/ui/autofill/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -117,12 +117,14 @@ "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/image_util", "//ios/chrome/browser/ui/infobars:infobars_ui", + "//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/ui/util", "//ios/chrome/common", + "//ios/chrome/common/colors", "//ios/chrome/common/ui_util", "//ios/third_party/material_components_ios", "//ios/third_party/material_roboto_font_loader_ios", - "//ui/base:base", + "//ui/base", "//url:url", ] libs = [ "UIKit.framework" ]
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_controller.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_controller.mm index fe165d4..eb9cd7c 100644 --- a/ios/chrome/browser/ui/autofill/save_card_infobar_controller.mm +++ b/ios/chrome/browser/ui/autofill/save_card_infobar_controller.mm
@@ -82,10 +82,13 @@ // Icon. gfx::Image icon = self.infoBarDelegate->GetIcon(); DCHECK(!icon.IsEmpty()); - if (self.infoBarDelegate->IsGooglePayBrandingEnabled()) + if (self.infoBarDelegate->IsGooglePayBrandingEnabled()) { [self.infoBarView setGooglePayIcon:icon.ToUIImage()]; - else - [self.infoBarView setIcon:icon.ToUIImage()]; + } else { + UIImage* iconImage = [icon.ToUIImage() + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + [self.infoBarView setIcon:iconImage]; + } // Message, if any. base::string16 messageText = self.infoBarDelegate->GetMessageText();
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm index a155704b0d..3374d96 100644 --- a/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm +++ b/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm
@@ -10,13 +10,16 @@ #import "ios/chrome/browser/ui/autofill/save_card_infobar_view_delegate.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/infobars/infobar_constants.h" +#import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" #import "ios/chrome/browser/ui/util/label_link_controller.h" #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/colors/semantic_color_names.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util.h" +#import "ui/gfx/ios/uikit_util.h" #include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -38,9 +41,6 @@ // to the close button icon's intrinsic padding equals kPadding. const CGFloat kCloseButtonPadding = 12; -// Color in RGB to be used as tint color on the icon. -const CGFloat kIconTintColor = 0x1A73E8; - // Padding used on the bottom edge of the title. const CGFloat kTitleBottomPadding = 24; @@ -53,9 +53,6 @@ // Padding used on the top edge of the action buttons' container. const CGFloat kButtonsTopPadding = 32; -// Color in RGB used as background of the action buttons. -const int kButtonTitleColorBlue = 0x4285f4; - // Corner radius for action buttons. const CGFloat kButtonCornerRadius = 8.0; @@ -173,9 +170,22 @@ // Creates and adds subviews. - (void)setupSubviews { [self setAccessibilityViewIsModal:YES]; - self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); + self.backgroundColor = [UIColor colorNamed:kBackgroundColor]; id<LayoutGuideProvider> safeAreaLayoutGuide = self.safeAreaLayoutGuide; + // Add thin separator to separate infobar from the web content. + UIView* separator = [[UIView alloc] initWithFrame:CGRectZero]; + separator.translatesAutoresizingMaskIntoConstraints = NO; + separator.backgroundColor = [UIColor colorNamed:kToolbarShadowColor]; + [self addSubview:separator]; + CGFloat separatorHeight = ui::AlignValueToUpperPixel(kToolbarSeparatorHeight); + [NSLayoutConstraint activateConstraints:@[ + [separator.heightAnchor constraintEqualToConstant:separatorHeight], + [self.leadingAnchor constraintEqualToAnchor:separator.leadingAnchor], + [self.trailingAnchor constraintEqualToAnchor:separator.trailingAnchor], + [self.topAnchor constraintEqualToAnchor:separator.bottomAnchor], + ]]; + // Add the icon. The icon is fixed to the top leading corner of the infobar. // |iconContainerView| is used here because the AutoLayout constraints for // UIImageView would get ignored otherwise. @@ -191,7 +201,7 @@ iconImageView.translatesAutoresizingMaskIntoConstraints = NO; iconImageView.accessibilityIdentifier = kIconImageViewAccessibilityIdentifier; - iconImageView.tintColor = UIColorFromRGB(kIconTintColor); + iconImageView.tintColor = [UIColor colorNamed:kBlueColor]; // Prevent the icon from shrinking horizontally. This is needed when the // title is long and needs to wrap. [iconImageView @@ -266,8 +276,7 @@ action:@selector(didTapClose) forControlEvents:UIControlEventTouchUpInside]; [closeButton setAccessibilityLabel:l10n_util::GetNSString(IDS_CLOSE)]; - closeButton.tintColor = [UIColor blackColor]; - closeButton.alpha = 0.20; + closeButton.tintColor = [UIColor colorNamed:kToolbarButtonColor]; // Prevent the button from shrinking horizontally. This is needed when the // title is long and needs to wrap. [closeButton @@ -337,8 +346,8 @@ if (self.cancelButtonTitle.length > 0UL) { UIButton* cancelButton = [self actionButtonWithTitle:self.cancelButtonTitle - palette:nil - titleColor:UIColorFromRGB(kButtonTitleColorBlue) + backgroundColor:nil + titleColor:[UIColor colorNamed:kBlueColor] target:self action:@selector(didTapCancel)]; @@ -348,8 +357,8 @@ if (self.confirmButtonTitle.length > 0UL) { UIButton* confirmButton = [self actionButtonWithTitle:self.confirmButtonTitle - palette:[MDCPalette cr_bluePalette] - titleColor:[UIColor whiteColor] + backgroundColor:[UIColor colorNamed:kBlueColor] + titleColor:[UIColor colorNamed:kSolidButtonTextColor] target:self action:@selector(didTapConfirm)]; @@ -404,9 +413,8 @@ label.accessibilityIdentifier = kTitleLabelAccessibilityIdentifier; label.translatesAutoresizingMaskIntoConstraints = NO; label.clipsToBounds = YES; - label.textColor = [[MDCPalette greyPalette] tint900]; + label.textColor = [UIColor colorNamed:kTextPrimaryColor]; label.numberOfLines = 0; - label.backgroundColor = [UIColor clearColor]; NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; @@ -475,9 +483,8 @@ if (self.description.length > 0UL) { UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; label.accessibilityIdentifier = kDescriptionLabelAccessibilityIdentifier; - label.textColor = [[MDCPalette greyPalette] tint700]; + label.textColor = [UIColor colorNamed:kTextSecondaryColor]; label.numberOfLines = 0; - label.backgroundColor = [UIColor clearColor]; NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; @@ -519,16 +526,14 @@ cardLabel.accessibilityIdentifier = kCardLabelAccessibilityIdentifier; cardLabel.text = self.cardLabel; cardLabel.font = [MDCTypography body1Font]; - cardLabel.textColor = [[MDCPalette greyPalette] tint900]; - cardLabel.backgroundColor = [UIColor clearColor]; + cardLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; [cardDetailsContainerView addArrangedSubview:cardLabel]; UILabel* cardSublabel = [[UILabel alloc] initWithFrame:CGRectZero]; cardSublabel.accessibilityIdentifier = kCardSublabelAccessibilityIdentifier; cardSublabel.text = self.cardSublabel; cardSublabel.font = [MDCTypography body1Font]; - cardSublabel.textColor = [[MDCPalette greyPalette] tint700]; - cardSublabel.backgroundColor = [UIColor clearColor]; + cardSublabel.textColor = [UIColor colorNamed:kTextSecondaryColor]; [cardDetailsContainerView addArrangedSubview:cardSublabel]; // Dummy view that expands so that the card details are aligned to the leading @@ -547,7 +552,6 @@ label.accessibilityIdentifier = kLegalMessageLabelAccessibilityIdentifier; label.textColor = [[MDCPalette greyPalette] tint700]; label.numberOfLines = 0; - label.backgroundColor = [UIColor clearColor]; NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; @@ -592,14 +596,14 @@ action { LabelLinkController* labelLinkController = [[LabelLinkController alloc] initWithLabel:label action:action]; - [labelLinkController setLinkColor:[[MDCPalette cr_bluePalette] tint500]]; + [labelLinkController setLinkColor:[UIColor colorNamed:kBlueColor]]; return labelLinkController; } // Creates and returns an infobar action button initialized with the given // title, colors, and action. - (UIButton*)actionButtonWithTitle:(NSString*)title - palette:(MDCPalette*)palette + backgroundColor:(UIColor*)backgroundColor titleColor:(UIColor*)titleColor target:(id)target action:(SEL)action { @@ -610,17 +614,17 @@ [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; - [button setUnderlyingColorHint:[UIColor blackColor]]; + [button setUnderlyingColorHint:[UIColor colorNamed:kBackgroundColor]]; button.uppercaseTitle = NO; button.layer.cornerRadius = kButtonCornerRadius; [button setTitleFont:[UIFont preferredFontForTextStyle:UIFontTextStyleHeadline] forState:UIControlStateNormal]; - if (palette) { + if (backgroundColor) { button.hasOpaqueBackground = YES; - button.inkColor = [[palette tint300] colorWithAlphaComponent:0.5f]; - [button setBackgroundColor:[palette tint500] forState:UIControlStateNormal]; + button.inkColor = [UIColor colorNamed:kMDCInkColor]; + [button setBackgroundColor:backgroundColor forState:UIControlStateNormal]; } if (titleColor) {
diff --git a/ios/chrome/browser/ui/qr_scanner/BUILD.gn b/ios/chrome/browser/ui/qr_scanner/BUILD.gn index 7b838b59..3124623 100644 --- a/ios/chrome/browser/ui/qr_scanner/BUILD.gn +++ b/ios/chrome/browser/ui/qr_scanner/BUILD.gn
@@ -5,13 +5,6 @@ source_set("qr_scanner") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "camera_controller.h", - "camera_controller.mm", - "qr_scanner_alerts.h", - "qr_scanner_alerts.mm", - "qr_scanner_presenting.h", - "qr_scanner_transitioning_delegate.h", - "qr_scanner_transitioning_delegate.mm", "qr_scanner_view.h", "qr_scanner_view.mm", "qr_scanner_view_controller.h", @@ -47,6 +40,7 @@ "//base", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/browser/ui/scanner", "//ios/chrome/browser/ui/toolbar/public", ] } @@ -70,6 +64,7 @@ "//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/location_bar", "//ios/chrome/browser/ui/omnibox", + "//ios/chrome/browser/ui/scanner", "//ios/chrome/browser/ui/toolbar", "//ios/chrome/browser/ui/toolbar/public:feature_flags", "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.mm index 42b54074c..c5ef7b1 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.mm +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.mm
@@ -7,15 +7,15 @@ #include "base/logging.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" -#import "ios/chrome/browser/ui/qr_scanner/qr_scanner_presenting.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h" +#import "ios/chrome/browser/ui/scanner/scanner_presenting.h" #import "ios/chrome/browser/ui/toolbar/public/omnibox_focuser.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -@interface QRScannerLegacyCoordinator ()<QRScannerPresenting> +@interface QRScannerLegacyCoordinator () <ScannerPresenting> @property(nonatomic, readwrite, strong) QRScannerViewController* viewController; @@ -71,8 +71,8 @@ #pragma mark - QRScannerPresenting -- (void)dismissQRScannerViewController:(UIViewController*)controller - completion:(void (^)(void))completion { +- (void)dismissScannerViewController:(UIViewController*)controller + completion:(void (^)(void))completion { DCHECK_EQ(self.viewController, self.baseViewController.presentedViewController); [self.baseViewController dismissViewControllerAnimated:YES
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_presenting.h b/ios/chrome/browser/ui/qr_scanner/qr_scanner_presenting.h deleted file mode 100644 index c426ac6b..0000000 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_presenting.h +++ /dev/null
@@ -1,19 +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_UI_QR_SCANNER_QR_SCANNER_PRESENTING_H_ -#define IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_PRESENTING_H_ - -// QRScannerPresenting contains methods that control how the QR scanner UI is -// dismissed on screen. -@protocol QRScannerPresenting - -// Asks the implementer to dismiss the given |controller| and call the given -// |completion| afterwards. -- (void)dismissQRScannerViewController:(UIViewController*)controller - completion:(void (^)(void))completion; - -@end - -#endif // IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_PRESENTING_H_
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.h b/ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.h deleted file mode 100644 index bb2562e..0000000 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2016 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_UI_QR_SCANNER_QR_SCANNER_TRANSITIONING_DELEGATE_H_ -#define IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_TRANSITIONING_DELEGATE_H_ - -#import <UIKit/UIKit.h> - -@interface QRScannerTransitioningDelegate - : NSObject<UIViewControllerTransitioningDelegate> - -@end - -#endif // IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_TRANSITIONING_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h index 031b9d57..6aa1b74 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h
@@ -1,40 +1,32 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// 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 IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_VIEW_CONTROLLER_H_ -#import <UIKit/UIKit.h> - -#include "ios/chrome/browser/ui/qr_scanner/camera_controller.h" -#include "ios/chrome/browser/ui/qr_scanner/qr_scanner_view.h" +#import "ios/chrome/browser/ui/scanner/scanner_view_controller.h" @protocol LoadQueryCommands; -@protocol QRScannerPresenting; -// View controller for the QR scanner. -@interface QRScannerViewController - : UIViewController <CameraControllerDelegate, ScannerViewDelegate> +// View controller for the QR Scanner. +@interface QRScannerViewController : ScannerViewController - (instancetype)initWithPresentationProvider: - (id<QRScannerPresenting>)presentationProvider + (id<ScannerPresenting>)presentationProvider queryLoader:(id<LoadQueryCommands>)queryLoader NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPresentationProvider: + (id<ScannerPresenting>)presentationProvider + cameraController:(CameraController*)cameraController + NS_UNAVAILABLE; + - (instancetype)initWithNibName:(NSString*)name bundle:(NSBundle*)bundle NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE; -// Returns a view controller to be presented based on the camera state. Returns -// |self| if the camera is available or an appropriate UIAlertController if -// there was an error loading the camera. -- (UIViewController*)getViewControllerToPresent; - -// Builds a scanner view overlay. Can be overridden by a subclass. -- (QRScannerView*)scannerView; - @end #endif // IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.mm index 8fa6bfaa..6df9e1c9 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.mm +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.mm
@@ -1,19 +1,18 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// 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. #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h" -#import <AVFoundation/AVFoundation.h> - #include "base/logging.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "ios/chrome/browser/ui/commands/load_query_commands.h" -#include "ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.h" -#include "ios/chrome/browser/ui/qr_scanner/qr_scanner_presenting.h" -#include "ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.h" #include "ios/chrome/browser/ui/qr_scanner/qr_scanner_view.h" +#include "ios/chrome/browser/ui/scanner/scanner_alerts.h" +#include "ios/chrome/browser/ui/scanner/scanner_presenting.h" +#include "ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.h" +#include "ios/chrome/browser/ui/scanner/scanner_view.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -23,363 +22,60 @@ using base::UserMetricsAction; -namespace { - -// The reason why the QRScannerViewController was dismissed. Used for collecting -// metrics. -enum DismissalReason { - CLOSE_BUTTON, - ERROR_DIALOG, - SCANNED_CODE, - // Not reported. Should be kept last of enum. - IMPOSSIBLY_UNLIKELY_AUTHORIZATION_CHANGE -}; - -} // namespace - @interface QRScannerViewController () { - // The CameraController managing the camera connection. - CameraController* _cameraController; - // The view displaying the QR scanner. - QRScannerView* _qrScannerView; // The scanned result. NSString* _result; // Whether the scanned result should be immediately loaded. BOOL _loadResultImmediately; // The transitioning delegate used for presenting and dismissing the QR // scanner. - QRScannerTransitioningDelegate* _transitioningDelegate; + ScannerTransitioningDelegate* _transitioningDelegate; } -@property(nonatomic, readwrite, weak) id<QRScannerPresenting> - presentationProvider; @property(nonatomic, readwrite, weak) id<LoadQueryCommands> queryLoader; -// Dismisses the QRScannerViewController and runs |completion| on completion. -// Logs metrics according to the |reason| for dismissal. -- (void)dismissForReason:(DismissalReason)reason - withCompletion:(void (^)(void))completion; -// Starts receiving notifications about the UIApplication going to background. -- (void)startReceivingNotifications; -// Stops receiving all notificatins. -- (void)stopReceivingNotifications; -// Requests the torch mode to be set to |mode| by the |_cameraController| and -// the icon of the torch button to be changed by the |_qrScannerView|. -- (void)setTorchMode:(AVCaptureTorchMode)mode; - -// Stops recording when the application resigns active. -- (void)handleUIApplicationWillResignActiveNotification; -// Dismisses the QR scanner and passes the scanned result to the delegate when -// the accessibility announcement for scanned QR code finishes. -- (void)handleUIAccessibilityAnnouncementDidFinishNotification: - (NSNotification*)notification; - @end @implementation QRScannerViewController -@synthesize queryLoader = _queryLoader; -@synthesize presentationProvider = _presentationProvider; - -#pragma mark - Lifecycle +#pragma mark Lifecycle - (instancetype) -initWithPresentationProvider:(id<QRScannerPresenting>)presentationProvider - queryLoader:(id<LoadQueryCommands>)queryLoader { - self = [super initWithNibName:nil bundle:nil]; + initWithPresentationProvider:(id<ScannerPresenting>)presentationProvider + queryLoader:(id<LoadQueryCommands>)queryLoader { + self = [super + initWithPresentationProvider:presentationProvider + cameraController:[CameraController + cameraControllerWithDelegate:self]]; if (self) { _queryLoader = queryLoader; - _presentationProvider = presentationProvider; - _cameraController = [CameraController cameraControllerWithDelegate:self]; } return self; } -- (instancetype)initWithNibName:(NSString*)name bundle:(NSBundle*)bundle { - NOTREACHED(); - return nil; -} +#pragma mark - ScannerViewController -- (instancetype)initWithCoder:(NSCoder*)coder { - NOTREACHED(); - return nil; -} - -#pragma mark - UIAccessibilityAction - -- (BOOL)accessibilityPerformEscape { - [self dismissForReason:CLOSE_BUTTON withCompletion:nil]; - return YES; -} - -#pragma mark - UIViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - DCHECK(_cameraController); - - _qrScannerView = [self scannerView]; - - [self.view addSubview:_qrScannerView]; - - // Constraints for |_qrScannerView|. - [_qrScannerView setTranslatesAutoresizingMaskIntoConstraints:NO]; - [NSLayoutConstraint activateConstraints:@[ - [[_qrScannerView leadingAnchor] - constraintEqualToAnchor:[self.view leadingAnchor]], - [[_qrScannerView trailingAnchor] - constraintEqualToAnchor:[self.view trailingAnchor]], - [[_qrScannerView topAnchor] constraintEqualToAnchor:[self.view topAnchor]], - [[_qrScannerView bottomAnchor] - constraintEqualToAnchor:[self.view bottomAnchor]], - ]]; - - AVCaptureVideoPreviewLayer* previewLayer = [_qrScannerView getPreviewLayer]; - switch ([_cameraController getAuthorizationStatus]) { - case AVAuthorizationStatusNotDetermined: - [_cameraController - requestAuthorizationAndLoadCaptureSession:previewLayer]; - break; - case AVAuthorizationStatusAuthorized: - [_cameraController loadCaptureSession:previewLayer]; - break; - case AVAuthorizationStatusRestricted: - case AVAuthorizationStatusDenied: - // If this happens, then the user is really unlucky: - // The authorization status changed in between the moment this VC was - // instantiated and presented, and the moment viewDidLoad was called. - [self dismissForReason:IMPOSSIBLY_UNLIKELY_AUTHORIZATION_CHANGE - withCompletion:nil]; - break; - } -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [self startReceivingNotifications]; - [_cameraController startRecording]; - - // Reset torch. - [self setTorchMode:AVCaptureTorchModeOff]; -} - -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator: - (id<UIViewControllerTransitionCoordinator>)coordinator { - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; - CGFloat epsilon = 0.0001; - // Note: targetTransform is always either identity or a 90, -90, or 180 degree - // rotation. - CGAffineTransform targetTransform = coordinator.targetTransform; - CGFloat angle = atan2f(targetTransform.b, targetTransform.a); - if (fabs(angle) > epsilon) { - // Rotate the preview in the opposite direction of the interface rotation - // and add a small value to the angle to force the rotation to occur in the - // correct direction when rotating by 180 degrees. - void (^animationBlock)(id<UIViewControllerTransitionCoordinatorContext>) = - ^void(id<UIViewControllerTransitionCoordinatorContext> context) { - [_qrScannerView rotatePreviewByAngle:(epsilon - angle)]; - }; - // Note: The completion block is called even if the animation is - // interrupted, for example by pressing the home button, with the same - // target transform as the animation block. - void (^completionBlock)(id<UIViewControllerTransitionCoordinatorContext>) = - ^void(id<UIViewControllerTransitionCoordinatorContext> context) { - [_qrScannerView finishPreviewRotation]; - }; - [coordinator animateAlongsideTransition:animationBlock - completion:completionBlock]; - } else if (!CGSizeEqualToSize(self.view.frame.size, size)) { - // Reset the size of the preview if the bounds of the view controller - // changed. This can happen if entering or leaving Split View mode on iPad. - [_qrScannerView resetPreviewFrame:size]; - [_cameraController resetVideoOrientation:[_qrScannerView getPreviewLayer]]; - } -} - -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; - [_cameraController stopRecording]; - [self stopReceivingNotifications]; - - // Reset torch. - [self setTorchMode:AVCaptureTorchModeOff]; -} - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -#pragma mark - Public methods - -- (UIViewController*)getViewControllerToPresent { - DCHECK(_cameraController); - switch ([_cameraController getAuthorizationStatus]) { - case AVAuthorizationStatusNotDetermined: - case AVAuthorizationStatusAuthorized: - _transitioningDelegate = [[QRScannerTransitioningDelegate alloc] init]; - [self setTransitioningDelegate:_transitioningDelegate]; - return self; - case AVAuthorizationStatusRestricted: - case AVAuthorizationStatusDenied: - return qr_scanner::DialogForCameraState( - qr_scanner::CAMERA_PERMISSION_DENIED, nil); - } -} - -- (QRScannerView*)scannerView { +- (ScannerView*)buildScannerView { return [[QRScannerView alloc] initWithFrame:self.view.frame delegate:self]; } -#pragma mark - Private methods - -- (void)dismissForReason:(DismissalReason)reason +- (void)dismissForReason:(scannerViewController::DismissalReason)reason withCompletion:(void (^)(void))completion { switch (reason) { - case CLOSE_BUTTON: + case scannerViewController::CLOSE_BUTTON: base::RecordAction(UserMetricsAction("MobileQRScannerClose")); break; - case ERROR_DIALOG: + case scannerViewController::ERROR_DIALOG: base::RecordAction(UserMetricsAction("MobileQRScannerError")); break; - case SCANNED_CODE: + case scannerViewController::SCANNED_CODE: base::RecordAction(UserMetricsAction("MobileQRScannerScannedCode")); break; - case IMPOSSIBLY_UNLIKELY_AUTHORIZATION_CHANGE: + case scannerViewController::IMPOSSIBLY_UNLIKELY_AUTHORIZATION_CHANGE: break; } - [self.presentationProvider dismissQRScannerViewController:self - completion:completion]; -} - -- (void)startReceivingNotifications { - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(handleUIApplicationWillResignActiveNotification) - name:UIApplicationWillResignActiveNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector( - handleUIAccessibilityAnnouncementDidFinishNotification:) - name:UIAccessibilityAnnouncementDidFinishNotification - object:nil]; -} - -- (void)stopReceivingNotifications { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)setTorchMode:(AVCaptureTorchMode)mode { - [_cameraController setTorchMode:mode]; -} - -#pragma mark - Notification handlers - -- (void)handleUIApplicationWillResignActiveNotification { - [self setTorchMode:AVCaptureTorchModeOff]; -} - -- (void)handleUIAccessibilityAnnouncementDidFinishNotification: - (NSNotification*)notification { - NSString* announcement = [[notification userInfo] - valueForKey:UIAccessibilityAnnouncementKeyStringValue]; - if ([announcement - isEqualToString: - l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CODE_SCANNED_ACCESSIBILITY_ANNOUNCEMENT)]) { - DCHECK(_result); - [self dismissForReason:SCANNED_CODE - withCompletion:^{ - [self.queryLoader loadQuery:_result - immediately:_loadResultImmediately]; - }]; - } -} - -#pragma mark - CameraControllerDelegate - -- (void)captureSessionIsConnected { - [_cameraController setViewport:[_qrScannerView viewportRectOfInterest]]; -} - -- (void)cameraStateChanged:(qr_scanner::CameraState)state { - switch (state) { - case qr_scanner::CAMERA_AVAILABLE: - // Dismiss any presented alerts. - if ([self presentedViewController]) { - [self dismissViewControllerAnimated:YES completion:nil]; - } - break; - case qr_scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION: - case qr_scanner::MULTIPLE_FOREGROUND_APPS: - case qr_scanner::CAMERA_PERMISSION_DENIED: - case qr_scanner::CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: - case qr_scanner::CAMERA_UNAVAILABLE: { - // Dismiss any presented alerts. - if ([self presentedViewController]) { - [self dismissViewControllerAnimated:YES completion:nil]; - } - [self presentViewController:qr_scanner::DialogForCameraState( - state, - ^(UIAlertAction*) { - [self dismissForReason:ERROR_DIALOG - withCompletion:nil]; - }) - animated:YES - completion:nil]; - break; - } - case qr_scanner::CAMERA_NOT_LOADED: - NOTREACHED(); - break; - } -} - -- (void)torchStateChanged:(BOOL)torchIsOn { - [_qrScannerView setTorchButtonTo:torchIsOn]; -} - -- (void)torchAvailabilityChanged:(BOOL)torchIsAvailable { - [_qrScannerView enableTorchButton:torchIsAvailable]; -} - -- (void)receiveQRScannerResult:(NSString*)result loadImmediately:(BOOL)load { - if (UIAccessibilityIsVoiceOverRunning()) { - // Post a notification announcing that a code was scanned. QR scanner will - // be dismissed when the UIAccessibilityAnnouncementDidFinishNotification is - // received. - _result = [result copy]; - _loadResultImmediately = load; - UIAccessibilityPostNotification( - UIAccessibilityAnnouncementNotification, - l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CODE_SCANNED_ACCESSIBILITY_ANNOUNCEMENT)); - } else { - [_qrScannerView animateScanningResultWithCompletion:^void(void) { - [self dismissForReason:SCANNED_CODE - withCompletion:^{ - [self.queryLoader loadQuery:result immediately:load]; - }]; - }]; - } -} - -#pragma mark - ScannerViewDelegate - -- (void)dismissScannerView:(id)sender { - [self dismissForReason:CLOSE_BUTTON withCompletion:nil]; -} - -- (void)toggleTorch:(id)sender { - if ([_cameraController isTorchActive]) { - [self setTorchMode:AVCaptureTorchModeOff]; - } else { - base::RecordAction(UserMetricsAction("MobileQRScannerTorchOn")); - [self setTorchMode:AVCaptureTorchModeOn]; - } + [super dismissForReason:reason withCompletion:completion]; } @end
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm index 7ee4088..bb41cc1 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -16,9 +16,9 @@ #import "ios/chrome/browser/ui/location_bar/location_bar_coordinator.h" #import "ios/chrome/browser/ui/location_bar/location_bar_url_loader.h" #include "ios/chrome/browser/ui/omnibox/location_bar_delegate.h" -#include "ios/chrome/browser/ui/qr_scanner/camera_controller.h" #include "ios/chrome/browser/ui/qr_scanner/qr_scanner_view.h" #include "ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller.h" +#include "ios/chrome/browser/ui/scanner/camera_controller.h" #import "ios/chrome/browser/ui/toolbar/public/features.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" @@ -42,7 +42,7 @@ #endif using namespace chrome_test_util; -using namespace qr_scanner; +using namespace scanner; namespace { @@ -380,7 +380,7 @@ IDS_IOS_QR_SCANNER_CAMERA_IN_USE_ALERT_TITLE); case CAMERA_PERMISSION_DENIED: return l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS); + IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS); case CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: case CAMERA_UNAVAILABLE: return l10n_util::GetNSString(
diff --git a/ios/chrome/browser/ui/scanner/BUILD.gn b/ios/chrome/browser/ui/scanner/BUILD.gn index 1607d52d..cd9cb14 100644 --- a/ios/chrome/browser/ui/scanner/BUILD.gn +++ b/ios/chrome/browser/ui/scanner/BUILD.gn
@@ -5,10 +5,19 @@ source_set("scanner") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "camera_controller.h", + "camera_controller.mm", "preview_overlay_view.h", "preview_overlay_view.mm", + "scanner_alerts.h", + "scanner_alerts.mm", + "scanner_presenting.h", + "scanner_transitioning_delegate.h", + "scanner_transitioning_delegate.mm", "scanner_view.h", "scanner_view.mm", + "scanner_view_controller.h", + "scanner_view_controller.mm", "video_preview_view.h", "video_preview_view.mm", ]
diff --git a/ios/chrome/browser/ui/qr_scanner/camera_controller.h b/ios/chrome/browser/ui/scanner/camera_controller.h similarity index 93% rename from ios/chrome/browser/ui/qr_scanner/camera_controller.h rename to ios/chrome/browser/ui/scanner/camera_controller.h index 45c4bcc..689753a 100644 --- a/ios/chrome/browser/ui/qr_scanner/camera_controller.h +++ b/ios/chrome/browser/ui/scanner/camera_controller.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_QR_SCANNER_CAMERA_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_QR_SCANNER_CAMERA_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SCANNER_CAMERA_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SCANNER_CAMERA_CONTROLLER_H_ #import <AVFoundation/AVFoundation.h> #import <UIKit/UIKit.h> #include "base/ios/block_types.h" -namespace qr_scanner { +namespace scanner { // Values to distinguish between different camera states to display the correct // view controller or system alert. @@ -38,7 +38,7 @@ CAMERA_NOT_LOADED, }; -} // namespace qr_scanner +} // namespace scanner @protocol CameraControllerDelegate @@ -46,7 +46,7 @@ // preview. - (void)captureSessionIsConnected; // Called on the main queue when the camera state changes. -- (void)cameraStateChanged:(qr_scanner::CameraState)state; +- (void)cameraStateChanged:(scanner::CameraState)state; // Called on the main queue when the torch state changes. - (void)torchStateChanged:(BOOL)torchIsOn; // Called on the main queue when the torch availability changes. @@ -109,4 +109,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_QR_SCANNER_CAMERA_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SCANNER_CAMERA_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/qr_scanner/camera_controller.mm b/ios/chrome/browser/ui/scanner/camera_controller.mm similarity index 90% rename from ios/chrome/browser/ui/qr_scanner/camera_controller.mm rename to ios/chrome/browser/ui/scanner/camera_controller.mm index 2157e8b5..c82ded2 100644 --- a/ios/chrome/browser/ui/qr_scanner/camera_controller.mm +++ b/ios/chrome/browser/ui/scanner/camera_controller.mm
@@ -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 "ios/chrome/browser/ui/qr_scanner/camera_controller.h" +#import "ios/chrome/browser/ui/scanner/camera_controller.h" #include "base/logging.h" #include "base/mac/foundation_util.h" @@ -13,7 +13,7 @@ #error "This file requires ARC support." #endif -@interface CameraController ()<AVCaptureMetadataOutputObjectsDelegate> { +@interface CameraController () <AVCaptureMetadataOutputObjectsDelegate> { // The queue for dispatching calls to |_captureSession|. dispatch_queue_t _sessionQueue; } @@ -23,7 +23,7 @@ @property(nonatomic, readwrite, weak) id<CameraControllerDelegate> delegate; // The current state of the camera. The state is set to CAMERA_NOT_LOADED before // the camera is first loaded, and afterwards it is never CAMERA_NOT_LOADED. -@property(nonatomic, readwrite, assign) qr_scanner::CameraState cameraState; +@property(nonatomic, readwrite, assign) scanner::CameraState cameraState; // Redeclaration of |torchActive| to make the setter private. @property(nonatomic, readwrite, assign, getter=isTorchActive) BOOL torchActive; // The current availability of the torch. @@ -59,7 +59,7 @@ @implementation CameraController -#pragma mark lifecycle +#pragma mark - Lifecycle + (instancetype)cameraControllerWithDelegate: (id<CameraControllerDelegate>)delegate { @@ -72,7 +72,7 @@ self = [super init]; if (self) { DCHECK(delegate); - _cameraState = qr_scanner::CAMERA_NOT_LOADED; + _cameraState = scanner::CAMERA_NOT_LOADED; _delegate = delegate; std::string queueName = base::StringPrintf("%s.chrome.ios.QRScannerCaptureSessionQueue", @@ -90,7 +90,7 @@ [self stopReceivingNotifications]; } -#pragma mark public methods +#pragma mark - Public methods - (AVAuthorizationStatus)getAuthorizationStatus { return [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; @@ -105,8 +105,7 @@ requestAccessForMediaType:AVMediaTypeVideo completionHandler:^void(BOOL granted) { if (!granted) { - [weakSelf - setCameraState:qr_scanner::CAMERA_PERMISSION_DENIED]; + [weakSelf setCameraState:scanner::CAMERA_PERMISSION_DENIED]; } else { [weakSelf loadCaptureSession:previewLayer]; } @@ -186,15 +185,15 @@ }); } -#pragma mark private methods +#pragma mark - Private methods - (BOOL)isCameraAvailable { - return [self cameraState] == qr_scanner::CAMERA_AVAILABLE; + return [self cameraState] == scanner::CAMERA_AVAILABLE; } - (void)loadCaptureSession:(AVCaptureVideoPreviewLayer*)previewLayer { DCHECK(previewLayer); - DCHECK([self cameraState] == qr_scanner::CAMERA_NOT_LOADED); + DCHECK([self cameraState] == scanner::CAMERA_NOT_LOADED); DCHECK([self getAuthorizationStatus] == AVAuthorizationStatusAuthorized); __weak CameraController* weakSelf = self; dispatch_async(_sessionQueue, ^{ @@ -213,7 +212,7 @@ position:AVCaptureDevicePositionBack]; videoCaptureDevices = [discoverySession devices]; if ([videoCaptureDevices count] == 0) { - [self setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [self setCameraState:scanner::CAMERA_UNAVAILABLE]; return; } @@ -225,7 +224,7 @@ // Allow only the back camera. if (cameraIndex == NSNotFound) { - [self setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [self setCameraState:scanner::CAMERA_UNAVAILABLE]; return; } AVCaptureDevice* camera = videoCaptureDevices[cameraIndex]; @@ -235,13 +234,13 @@ AVCaptureDeviceInput* videoInput = [AVCaptureDeviceInput deviceInputWithDevice:camera error:&error]; if (error || !videoInput) { - [self setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [self setCameraState:scanner::CAMERA_UNAVAILABLE]; return; } AVCaptureSession* session = [[AVCaptureSession alloc] init]; if (![session canAddInput:videoInput]) { - [self setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [self setCameraState:scanner::CAMERA_UNAVAILABLE]; return; } [session addInput:videoInput]; @@ -252,7 +251,7 @@ [metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; if (![session canAddOutput:metadataOutput]) { - [self setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [self setCameraState:scanner::CAMERA_UNAVAILABLE]; return; } [session addOutput:metadataOutput]; @@ -260,14 +259,14 @@ // Require QR code recognition to be available. if (![availableCodeTypes containsObject:AVMetadataObjectTypeQRCode]) { - [self setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [self setCameraState:scanner::CAMERA_UNAVAILABLE]; return; } [metadataOutput setMetadataObjectTypes:availableCodeTypes]; _metadataOutput = metadataOutput; _captureSession = session; - [self setCameraState:qr_scanner::CAMERA_AVAILABLE]; + [self setCameraState:scanner::CAMERA_AVAILABLE]; // Setup torchAvailable. [self setTorchAvailable:[camera hasTorch] && [camera isTorchModeSupported:AVCaptureTorchModeOn] && @@ -365,12 +364,12 @@ } } -#pragma mark notification handlers +#pragma mark - Notification Handlers - (void)handleAVCaptureSessionRuntimeError:(NSNotification*)notification { __weak CameraController* weakSelf = self; dispatch_async(_sessionQueue, ^{ - [weakSelf setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [weakSelf setCameraState:scanner::CAMERA_UNAVAILABLE]; }); } @@ -386,15 +385,14 @@ // is backgrounded and foregrounded. break; case AVCaptureSessionInterruptionReasonVideoDeviceInUseByAnotherClient: - [weakSelf - setCameraState:qr_scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION]; + [weakSelf setCameraState:scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION]; break; case AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps: - [weakSelf setCameraState:qr_scanner::MULTIPLE_FOREGROUND_APPS]; + [weakSelf setCameraState:scanner::MULTIPLE_FOREGROUND_APPS]; break; case AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableDueToSystemPressure: - [weakSelf setCameraState:qr_scanner:: - CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE]; + [weakSelf + setCameraState:scanner::CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE]; break; case AVCaptureSessionInterruptionReasonAudioDeviceInUseByAnotherClient: NOTREACHED(); @@ -408,7 +406,7 @@ dispatch_async(_sessionQueue, ^{ CameraController* strongSelf = weakSelf; if (strongSelf && [strongSelf.captureSession isRunning]) { - [strongSelf setCameraState:qr_scanner::CAMERA_AVAILABLE]; + [strongSelf setCameraState:scanner::CAMERA_AVAILABLE]; } }); } @@ -416,7 +414,7 @@ - (void)handleAVCaptureDeviceWasDisconnected:(NSNotification*)notification { __weak CameraController* weakSelf = self; dispatch_async(_sessionQueue, ^{ - [weakSelf setCameraState:qr_scanner::CAMERA_UNAVAILABLE]; + [weakSelf setCameraState:scanner::CAMERA_UNAVAILABLE]; }); } @@ -433,9 +431,9 @@ } } -#pragma mark property implementation +#pragma mark - Property Implementation -- (void)setCameraState:(qr_scanner::CameraState)state { +- (void)setCameraState:(scanner::CameraState)state { if (state == _cameraState) { return; } @@ -468,7 +466,7 @@ }); } -#pragma mark AVCaptureMetadataOutputObjectsDelegate +#pragma mark - AVCaptureMetadataOutputObjectsDelegate - (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputMetadataObjects:(NSArray*)metadataObjects
diff --git a/ios/chrome/browser/ui/scanner/preview_overlay_view.mm b/ios/chrome/browser/ui/scanner/preview_overlay_view.mm index bfad635..3f3b1b43 100644 --- a/ios/chrome/browser/ui/scanner/preview_overlay_view.mm +++ b/ios/chrome/browser/ui/scanner/preview_overlay_view.mm
@@ -105,7 +105,7 @@ [_viewportBorder setMask:[self viewportBorderMaskWithFrameSize:frameSize]]; } -#pragma mark Private +#pragma mark - Private // Creates a square mask for the overlay to keep the viewport transparent. - (CAShapeLayer*)viewportMaskWithFrameSize:(CGSize)frameSize {
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.h b/ios/chrome/browser/ui/scanner/scanner_alerts.h similarity index 66% rename from ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.h rename to ios/chrome/browser/ui/scanner/scanner_alerts.h index 0b9585d..31f48e27 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.h +++ b/ios/chrome/browser/ui/scanner/scanner_alerts.h
@@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_ALERTS_H_ -#define IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_ALERTS_H_ +#ifndef IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_ALERTS_H_ +#define IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_ALERTS_H_ -#include "ios/chrome/browser/ui/qr_scanner/camera_controller.h" +#include "ios/chrome/browser/ui/scanner/camera_controller.h" -@class UIAlertAction; -@class UIAlertController; +#import <UIKit/UIKit.h> -namespace qr_scanner { +namespace scanner { // Block type that takes a UIAlertAction. Blocks of this type will be called // when the Cancel button of a UIAlertView is pressed. @@ -22,6 +21,6 @@ UIAlertController* DialogForCameraState(CameraState state, CancelAlertAction cancelBlock); -} // namespace qr_scanner +} // namespace scanner -#endif // IOS_CHROME_BROWSER_UI_QR_SCANNER_QR_SCANNER_ALERTS_H_ +#endif // IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_ALERTS_H_
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.mm b/ios/chrome/browser/ui/scanner/scanner_alerts.mm similarity index 69% rename from ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.mm rename to ios/chrome/browser/ui/scanner/scanner_alerts.mm index 71d085c..3e9d0616 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.mm +++ b/ios/chrome/browser/ui/scanner/scanner_alerts.mm
@@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/qr_scanner/qr_scanner_alerts.h" - -#import <UIKit/UIKit.h> +#import "ios/chrome/browser/ui/scanner/scanner_alerts.h" #include "base/logging.h" #include "components/version_info/version_info.h" @@ -20,9 +18,9 @@ namespace { // Returns a "Cancel" UIAlertAction for the given |block|. -UIAlertAction* CancelAction(qr_scanner::CancelAlertAction block) { +UIAlertAction* CancelAction(scanner::CancelAlertAction block) { NSString* cancelButtonTitle = - l10n_util::GetNSString(IDS_IOS_QR_SCANNER_ALERT_CANCEL); + l10n_util::GetNSString(IDS_IOS_SCANNER_ALERT_CANCEL); return [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:block]; @@ -34,7 +32,7 @@ UIAlertController* AlertWithCancelButton( NSString* title, NSString* body, - qr_scanner::CancelAlertAction cancelBlock) { + scanner::CancelAlertAction cancelBlock) { UIAlertController* dialog = [UIAlertController alertControllerWithTitle:title message:body @@ -54,25 +52,25 @@ // Returns a UIAlertController to be displayed when the camera state is // CAMERA_PERMISSION_DENIED. UIAlertController* CameraPermissionDeniedDialog( - qr_scanner::CancelAlertAction cancelBlock) { + scanner::CancelAlertAction cancelBlock) { NSURL* settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if (![[UIApplication sharedApplication] canOpenURL:settingsURL]) { // Display a dialog instructing the user how to change the settings. - NSString* dialogTitle = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE); - NSString* dialogBody = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL); + NSString* dialogTitle = + l10n_util::GetNSString(IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE); + NSString* dialogBody = + l10n_util::GetNSString(IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL); return AlertWithCancelButton(dialogTitle, dialogBody, cancelBlock); } // Display a dialog with a link to the Settings app. NSString* dialogTitle = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS); + IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS); NSString* dialogBody = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL_GO_TO_SETTINGS); + IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_DETAIL_GO_TO_SETTINGS); NSString* settingsButton = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_PERMISSIONS_HELP_GO_TO_SETTINGS); + IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_GO_TO_SETTINGS); UIAlertController* dialog = AlertWithCancelButton(dialogTitle, dialogBody, cancelBlock); @@ -94,44 +92,44 @@ } // namespace -namespace qr_scanner { +namespace scanner { UIAlertController* DialogForCameraState( CameraState state, - qr_scanner::CancelAlertAction cancelBlock) { + scanner::CancelAlertAction cancelBlock) { NSString* dialogTitle = nil; NSString* dialogBody = nil; switch (state) { - case qr_scanner::CAMERA_AVAILABLE: - case qr_scanner::CAMERA_NOT_LOADED: + case scanner::CAMERA_AVAILABLE: + case scanner::CAMERA_NOT_LOADED: NOTREACHED(); return nil; - case qr_scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION: + case scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION: dialogTitle = - l10n_util::GetNSString(IDS_IOS_QR_SCANNER_CAMERA_IN_USE_ALERT_TITLE); + l10n_util::GetNSString(IDS_IOS_SCANNER_CAMERA_IN_USE_ALERT_TITLE); dialogBody = - l10n_util::GetNSString(IDS_IOS_QR_SCANNER_CAMERA_IN_USE_ALERT_DETAIL); + l10n_util::GetNSString(IDS_IOS_SCANNER_CAMERA_IN_USE_ALERT_DETAIL); return AlertWithCancelButton(dialogTitle, dialogBody, cancelBlock); - case qr_scanner::MULTIPLE_FOREGROUND_APPS: + case scanner::MULTIPLE_FOREGROUND_APPS: dialogTitle = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_TITLE); + IDS_IOS_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_TITLE); dialogBody = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_DETAIL); + IDS_IOS_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_DETAIL); return AlertWithCancelButton(dialogTitle, dialogBody, cancelBlock); - case qr_scanner::CAMERA_PERMISSION_DENIED: + case scanner::CAMERA_PERMISSION_DENIED: return CameraPermissionDeniedDialog(cancelBlock); - case qr_scanner::CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: - case qr_scanner::CAMERA_UNAVAILABLE: + case scanner::CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: + case scanner::CAMERA_UNAVAILABLE: dialogTitle = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_UNAVAILABLE_ALERT_TITLE); + IDS_IOS_SCANNER_CAMERA_UNAVAILABLE_ALERT_TITLE); dialogBody = l10n_util::GetNSString( - IDS_IOS_QR_SCANNER_CAMERA_UNAVAILABLE_ALERT_DETAIL); + IDS_IOS_SCANNER_CAMERA_UNAVAILABLE_ALERT_DETAIL); return AlertWithCancelButton(dialogTitle, dialogBody, cancelBlock); } } -} // namespace qr_scanner +} // namespace scanner
diff --git a/ios/chrome/browser/ui/scanner/scanner_presenting.h b/ios/chrome/browser/ui/scanner/scanner_presenting.h new file mode 100644 index 0000000..c3851da --- /dev/null +++ b/ios/chrome/browser/ui/scanner/scanner_presenting.h
@@ -0,0 +1,19 @@ +// 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 IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_PRESENTING_H_ +#define IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_PRESENTING_H_ + +// ScannerPresenting contains methods that control how a scanner UI is +// dismissed on screen. +@protocol ScannerPresenting + +// Asks the implementer to dismiss the given |controller| and call the given +// |completion| afterwards. +- (void)dismissScannerViewController:(UIViewController*)controller + completion:(void (^)(void))completion; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_PRESENTING_H_
diff --git a/ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.h b/ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.h new file mode 100644 index 0000000..76c4551 --- /dev/null +++ b/ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.h
@@ -0,0 +1,15 @@ +// 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 IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_TRANSITIONING_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_TRANSITIONING_DELEGATE_H_ + +#import <UIKit/UIKit.h> + +@interface ScannerTransitioningDelegate + : NSObject <UIViewControllerTransitioningDelegate> + +@end + +#endif // IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_TRANSITIONING_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.mm b/ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.mm similarity index 69% rename from ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.mm rename to ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.mm index 03e0e988..c348352c 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.mm +++ b/ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.mm
@@ -1,8 +1,8 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// 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. -#import "ios/chrome/browser/ui/qr_scanner/qr_scanner_transitioning_delegate.h" +#import "ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.h" #include "base/ios/block_types.h" @@ -15,28 +15,28 @@ // The default animation duration. const NSTimeInterval kDefaultDuration = 0.25; -enum QRScannerTransition { PRESENT, DISMISS }; +enum ScannerTransition { PRESENT, DISMISS }; } // namespace -// Animates the QR Scanner transition. If initialized with the |PRESENT| -// transition, positions the QR Scanner view below its presenting view +// Animates the Scanner transition. If initialized with the |PRESENT| +// transition, positions the Scanner view below its presenting view // controller's view in the container view and animates the presenting view to // slide up. If initialized with the |DISMISS| transition, positions the -// presenting view controller's view above the QR Scanner view in the container +// presenting view controller's view above the Scanner view in the container // view and animates the presenting view to slide down. -@interface QRScannerTransitionAnimator - : NSObject<UIViewControllerAnimatedTransitioning> { - QRScannerTransition _transition; +@interface ScannerTransitionAnimator + : NSObject <UIViewControllerAnimatedTransitioning> { + ScannerTransition _transition; } -- (instancetype)initWithTransition:(QRScannerTransition)transition; +- (instancetype)initWithTransition:(ScannerTransition)transition; @end -@implementation QRScannerTransitionAnimator +@implementation ScannerTransitionAnimator -- (instancetype)initWithTransition:(QRScannerTransition)transition { +- (instancetype)initWithTransition:(ScannerTransition)transition { self = [super init]; if (self) { _transition = transition; @@ -108,18 +108,18 @@ @end -@implementation QRScannerTransitioningDelegate +@implementation ScannerTransitioningDelegate - (id<UIViewControllerAnimatedTransitioning>) -animationControllerForPresentedController:(UIViewController*)presented - presentingController:(UIViewController*)presenting - sourceController:(UIViewController*)source { - return [[QRScannerTransitionAnimator alloc] initWithTransition:PRESENT]; + animationControllerForPresentedController:(UIViewController*)presented + presentingController:(UIViewController*)presenting + sourceController:(UIViewController*)source { + return [[ScannerTransitionAnimator alloc] initWithTransition:PRESENT]; } - (id<UIViewControllerAnimatedTransitioning>) -animationControllerForDismissedController:(UIViewController*)dismissed { - return [[QRScannerTransitionAnimator alloc] initWithTransition:DISMISS]; + animationControllerForDismissedController:(UIViewController*)dismissed { + return [[ScannerTransitionAnimator alloc] initWithTransition:DISMISS]; } @end
diff --git a/ios/chrome/browser/ui/scanner/scanner_view.mm b/ios/chrome/browser/ui/scanner/scanner_view.mm index 7bfdb33..4533e81 100644 --- a/ios/chrome/browser/ui/scanner/scanner_view.mm +++ b/ios/chrome/browser/ui/scanner/scanner_view.mm
@@ -174,7 +174,7 @@ } - (NSString*)caption { - return nil; + return @""; } #pragma mark - private methods
diff --git a/ios/chrome/browser/ui/scanner/scanner_view_controller.h b/ios/chrome/browser/ui/scanner/scanner_view_controller.h new file mode 100644 index 0000000..133f6d2 --- /dev/null +++ b/ios/chrome/browser/ui/scanner/scanner_view_controller.h
@@ -0,0 +1,69 @@ +// 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 IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#include "ios/chrome/browser/ui/scanner/camera_controller.h" +#include "ios/chrome/browser/ui/scanner/scanner_view.h" + +namespace scannerViewController { +// The reason why the ScannerViewController was dismissed. Used for collecting +// metrics. +enum DismissalReason { + CLOSE_BUTTON, + ERROR_DIALOG, + SCANNED_CODE, + // Not reported. Should be kept last of enum. + IMPOSSIBLY_UNLIKELY_AUTHORIZATION_CHANGE +}; +} // namespace scannerViewController + +@protocol ScannerPresenting; + +// View controller for a generic scanner. This is an abstract class that creates +// the view and camera controller, required for a QR code or Credit Card +// Scanner. +@interface ScannerViewController + : UIViewController <CameraControllerDelegate, ScannerViewDelegate> + +// Stores the camera controller for the scanner. +@property(nonatomic, readwrite, strong) CameraController* cameraController; + +// Stores the presentation provider. +@property(nonatomic, readwrite, weak) id<ScannerPresenting> + presentationProvider; + +- (instancetype)initWithPresentationProvider: + (id<ScannerPresenting>)presentationProvider + cameraController:(CameraController*)cameraController + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithNibName:(NSString*)name + bundle:(NSBundle*)bundle NS_UNAVAILABLE; + +- (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE; + +// Returns a view controller to be presented based on the camera state. Returns +// |self| if the camera is available or an appropriate UIAlertController if +// there was an error loading the camera. +- (UIViewController*)getViewControllerToPresent; + +// Builds the scanner view. Must be overridden in the subclass. +- (ScannerView*)buildScannerView; + +// Dismiss scanner. Subclass can override to update metrics. +// implementation. +- (void)dismissForReason:(scannerViewController::DismissalReason)reason + withCompletion:(void (^)(void))completion; + +- (void)stopReceivingNotifications; + +- (void)setTorchMode:(AVCaptureTorchMode)mode; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SCANNER_SCANNER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/scanner/scanner_view_controller.mm b/ios/chrome/browser/ui/scanner/scanner_view_controller.mm new file mode 100644 index 0000000..f2c4973 --- /dev/null +++ b/ios/chrome/browser/ui/scanner/scanner_view_controller.mm
@@ -0,0 +1,337 @@ +// 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. + +#import "ios/chrome/browser/ui/scanner/scanner_view_controller.h" + +#import <AVFoundation/AVFoundation.h> + +#include "base/logging.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "ios/chrome/browser/ui/commands/load_query_commands.h" +#include "ios/chrome/browser/ui/scanner/scanner_alerts.h" +#include "ios/chrome/browser/ui/scanner/scanner_presenting.h" +#include "ios/chrome/browser/ui/scanner/scanner_transitioning_delegate.h" +#include "ios/chrome/browser/ui/scanner/scanner_view.h" +#include "ios/chrome/grit/ios_strings.h" +#include "ui/base/l10n/l10n_util.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using base::UserMetricsAction; + +@interface ScannerViewController () { + // The scanned result. + NSString* _result; + // Whether the scanned result should be immediately loaded. + BOOL _loadResultImmediately; + // The transitioning delegate used for presenting and dismissing the scanner. + ScannerTransitioningDelegate* _transitioningDelegate; +} + +@property(nonatomic, readwrite, weak) id<LoadQueryCommands> queryLoader; + +// Stores the view for the scanner. Can be subclassed as a QR code or Credit +// Card scanner view. +@property(nonatomic, readwrite) ScannerView* scannerView; + +@end + +@implementation ScannerViewController + +#pragma mark - lifecycle + +- (instancetype) + initWithPresentationProvider:(id<ScannerPresenting>)presentationProvider + cameraController:(CameraController*)cameraController { + self = [super initWithNibName:nil bundle:nil]; + if (self) { + _presentationProvider = presentationProvider; + _cameraController = cameraController; + } + return self; +} + +#pragma mark - UIAccessibilityAction + +- (BOOL)accessibilityPerformEscape { + [self dismissForReason:scannerViewController::CLOSE_BUTTON + withCompletion:nil]; + return YES; +} + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + DCHECK(_cameraController); + + [self.view addSubview:self.scannerView]; + + // Constraints for |self.scannerView|. + [self.scannerView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [NSLayoutConstraint activateConstraints:@[ + [[self.scannerView leadingAnchor] + constraintEqualToAnchor:[self.view leadingAnchor]], + [[self.scannerView trailingAnchor] + constraintEqualToAnchor:[self.view trailingAnchor]], + [[self.scannerView topAnchor] + constraintEqualToAnchor:[self.view topAnchor]], + [[self.scannerView bottomAnchor] + constraintEqualToAnchor:[self.view bottomAnchor]], + ]]; + + AVCaptureVideoPreviewLayer* previewLayer = [self.scannerView getPreviewLayer]; + switch ([_cameraController getAuthorizationStatus]) { + case AVAuthorizationStatusNotDetermined: + [_cameraController + requestAuthorizationAndLoadCaptureSession:previewLayer]; + break; + case AVAuthorizationStatusAuthorized: + [_cameraController loadCaptureSession:previewLayer]; + break; + case AVAuthorizationStatusRestricted: + case AVAuthorizationStatusDenied: + // If this happens, then the user is really unlucky: + // The authorization status changed in between the moment this VC was + // instantiated and presented, and the moment viewDidLoad was called. + [self dismissForReason:scannerViewController:: + IMPOSSIBLY_UNLIKELY_AUTHORIZATION_CHANGE + withCompletion:nil]; + break; + } +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self startReceivingNotifications]; + [_cameraController startRecording]; + + // Reset torch. + [self setTorchMode:AVCaptureTorchModeOff]; +} + +- (void)viewWillTransitionToSize:(CGSize)size + withTransitionCoordinator: + (id<UIViewControllerTransitionCoordinator>)coordinator { + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + CGFloat epsilon = 0.0001; + // Note: targetTransform is always either identity or a 90, -90, or 180 degree + // rotation. + CGAffineTransform targetTransform = coordinator.targetTransform; + CGFloat angle = atan2f(targetTransform.b, targetTransform.a); + if (fabs(angle) > epsilon) { + // Rotate the preview in the opposite direction of the interface rotation + // and add a small value to the angle to force the rotation to occur in the + // correct direction when rotating by 180 degrees. + void (^animationBlock)(id<UIViewControllerTransitionCoordinatorContext>) = + ^void(id<UIViewControllerTransitionCoordinatorContext> context) { + [self.scannerView rotatePreviewByAngle:(epsilon - angle)]; + }; + // Note: The completion block is called even if the animation is + // interrupted, for example by pressing the home button, with the same + // target transform as the animation block. + void (^completionBlock)(id<UIViewControllerTransitionCoordinatorContext>) = + ^void(id<UIViewControllerTransitionCoordinatorContext> context) { + [self.scannerView finishPreviewRotation]; + }; + [coordinator animateAlongsideTransition:animationBlock + completion:completionBlock]; + } else if (!CGSizeEqualToSize(self.view.frame.size, size)) { + // Reset the size of the preview if the bounds of the view controller + // changed. This can happen if entering or leaving Split View mode on iPad. + [self.scannerView resetPreviewFrame:size]; + [_cameraController + resetVideoOrientation:[self.scannerView getPreviewLayer]]; + } +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + [_cameraController stopRecording]; + [self stopReceivingNotifications]; + + // Reset torch. + [self setTorchMode:AVCaptureTorchModeOff]; +} + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +#pragma mark - public methods + +- (UIViewController*)getViewControllerToPresent { + DCHECK(_cameraController); + switch ([_cameraController getAuthorizationStatus]) { + case AVAuthorizationStatusNotDetermined: + case AVAuthorizationStatusAuthorized: + _transitioningDelegate = [[ScannerTransitioningDelegate alloc] init]; + [self setTransitioningDelegate:_transitioningDelegate]; + return self; + case AVAuthorizationStatusRestricted: + case AVAuthorizationStatusDenied: + return scanner::DialogForCameraState(scanner::CAMERA_PERMISSION_DENIED, + nil); + } +} + +- (void)dismissForReason:(scannerViewController::DismissalReason)reason + withCompletion:(void (^)(void))completion { + [self.presentationProvider dismissScannerViewController:self + completion:completion]; +} + +- (ScannerView*)buildScannerView { + NOTIMPLEMENTED(); + return nil; +} + +#pragma mark - private methods + +// Starts receiving notifications about the UIApplication going to background. +- (void)startReceivingNotifications { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleUIApplicationWillResignActiveNotification) + name:UIApplicationWillResignActiveNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector + (handleUIAccessibilityAnnouncementDidFinishNotification:) + name:UIAccessibilityAnnouncementDidFinishNotification + object:nil]; +} + +// Stops receiving all notifications. +- (void)stopReceivingNotifications { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +// Requests the torch mode to be set to |mode| by the |_cameraController| +// and the icon of the torch button to be changed by the |self.scannerView|. +- (void)setTorchMode:(AVCaptureTorchMode)mode { + [_cameraController setTorchMode:mode]; +} + +- (ScannerView*)scannerView { + if (!_scannerView) { + _scannerView = [self buildScannerView]; + } + return _scannerView; +} + +#pragma mark - notification handlers + +- (void)handleUIApplicationWillResignActiveNotification { + [self setTorchMode:AVCaptureTorchModeOff]; +} + +- (void)handleUIAccessibilityAnnouncementDidFinishNotification: + (NSNotification*)notification { + NSString* announcement = [[notification userInfo] + valueForKey:UIAccessibilityAnnouncementKeyStringValue]; + if ([announcement + isEqualToString: + l10n_util::GetNSString( + IDS_IOS_SCANNER_SCANNED_ACCESSIBILITY_ANNOUNCEMENT)]) { + DCHECK(_result); + [self dismissForReason:scannerViewController::SCANNED_CODE + withCompletion:^{ + [self.queryLoader loadQuery:_result + immediately:_loadResultImmediately]; + }]; + } +} + +#pragma mark - CameraControllerDelegate + +- (void)captureSessionIsConnected { + [_cameraController setViewport:[self.scannerView viewportRectOfInterest]]; +} + +- (void)cameraStateChanged:(scanner::CameraState)state { + switch (state) { + case scanner::CAMERA_AVAILABLE: + // Dismiss any presented alerts. + if ([self presentedViewController]) { + [self dismissViewControllerAnimated:YES completion:nil]; + } + break; + case scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION: + case scanner::MULTIPLE_FOREGROUND_APPS: + case scanner::CAMERA_PERMISSION_DENIED: + case scanner::CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: + case scanner::CAMERA_UNAVAILABLE: { + // Dismiss any presented alerts. + if ([self presentedViewController]) { + [self dismissViewControllerAnimated:YES completion:nil]; + } + [self presentViewController: + scanner::DialogForCameraState( + state, + ^(UIAlertAction*) { + [self dismissForReason:scannerViewController::ERROR_DIALOG + withCompletion:nil]; + }) + animated:YES + completion:nil]; + break; + } + case scanner::CAMERA_NOT_LOADED: + NOTREACHED(); + break; + } +} + +- (void)torchStateChanged:(BOOL)torchIsOn { + [self.scannerView setTorchButtonTo:torchIsOn]; +} + +- (void)torchAvailabilityChanged:(BOOL)torchIsAvailable { + [self.scannerView enableTorchButton:torchIsAvailable]; +} + +- (void)receiveQRScannerResult:(NSString*)result loadImmediately:(BOOL)load { + if (UIAccessibilityIsVoiceOverRunning()) { + // Post a notification announcing that a code was scanned. QR scanner will + // be dismissed when the UIAccessibilityAnnouncementDidFinishNotification is + // received. + _result = [result copy]; + _loadResultImmediately = load; + UIAccessibilityPostNotification( + UIAccessibilityAnnouncementNotification, + l10n_util::GetNSString( + IDS_IOS_SCANNER_SCANNED_ACCESSIBILITY_ANNOUNCEMENT)); + } else { + [self.scannerView animateScanningResultWithCompletion:^void(void) { + [self dismissForReason:scannerViewController::SCANNED_CODE + withCompletion:^{ + [self.queryLoader loadQuery:result immediately:load]; + }]; + }]; + } +} + +#pragma mark - ScannerViewDelegate + +- (void)dismissScannerView:(id)sender { + [self dismissForReason:scannerViewController::CLOSE_BUTTON + withCompletion:nil]; +} + +- (void)toggleTorch:(id)sender { + if ([_cameraController isTorchActive]) { + [self setTorchMode:AVCaptureTorchModeOff]; + } else { + base::RecordAction(UserMetricsAction("MobileQRScannerTorchOn")); + [self setTorchMode:AVCaptureTorchModeOn]; + } +} + +@end
diff --git a/ios/web/navigation/crw_web_view_navigation_observer.mm b/ios/web/navigation/crw_web_view_navigation_observer.mm index 9d0b67f..81e35541 100644 --- a/ios/web/navigation/crw_web_view_navigation_observer.mm +++ b/ios/web/navigation/crw_web_view_navigation_observer.mm
@@ -144,19 +144,23 @@ // not fire 'pageshow', 'onload', 'popstate' or any of the // WKNavigationDelegate callbacks for back/forward navigation from an about: // scheme placeholder URL to another entry or if either of the redirect fails - // to load (e.g. in airplane mode). Loading state KVO is the only observable - // event in this scenario, so force a reload to trigger redirect from - // restore_session.html to the restored URL. + // to load (e.g. in airplane mode, <iOS13). Loading state KVO is the only + // observable event in this scenario, so force a reload to trigger redirect + // from restore_session.html to the restored URL. bool previousURLHasAboutScheme = self.documentURL.SchemeIs(url::kAboutScheme) || IsPlaceholderUrl(self.documentURL) || web::GetWebClient()->IsAppSpecificURL(self.documentURL); - bool is_back_forward_navigation = + bool needs_back_forward_navigation_reload = existingContext && (existingContext->GetPageTransition() & ui::PAGE_TRANSITION_FORWARD_BACK); + // The back-forward workaround isn't need on iOS13. + if (@available(iOS 13, *)) { + needs_back_forward_navigation_reload = false; + } if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && IsRestoreSessionUrl(webViewURL)) { - if (previousURLHasAboutScheme || is_back_forward_navigation) { + if (previousURLHasAboutScheme || needs_back_forward_navigation_reload) { [self.webView reload]; self.navigationHandler.navigationState = web::WKNavigationState::REQUESTED;
diff --git a/ios/web/public/test/test_web_thread.h b/ios/web/public/test/test_web_thread.h index a6beff3..a9c3728 100644 --- a/ios/web/public/test/test_web_thread.h +++ b/ios/web/public/test/test_web_thread.h
@@ -20,7 +20,7 @@ class WebSubThread; class WebThreadImpl; -// DEPRECATED: use TestWebThreadBundle instead. +// DEPRECATED: use WebTaskEnvironment instead. // A WebThread for unit tests; this lets unit tests outside of web create // WebThread instances. class TestWebThread {
diff --git a/ios/web/public/test/test_web_thread_bundle.h b/ios/web/public/test/test_web_thread_bundle.h index 5b95bf9..4231e66 100644 --- a/ios/web/public/test/test_web_thread_bundle.h +++ b/ios/web/public/test/test_web_thread_bundle.h
@@ -7,27 +7,31 @@ #include "base/test/scoped_task_environment.h" -// TestWebThreadBundle is a convenience class for creating a set of -// TestWebThreads and a thread pool in unit tests. For most tests, it is -// sufficient to just instantiate the TestWebThreadBundle as a member variable. -// It is a good idea to put the TestWebThreadBundle as the first member variable -// in test classes, so it is destroyed last, and the test threads always exist -// from the perspective of other classes. +// TODO(crbug.com/992483): Rename this header to web_task_environment.h and +// migrate all users. +// +// WebTaskEnvironment is the iOS equivalent of content::BrowserTaskEnvironment. +// +// It's is a convenience class for creating a set of TestWebThreads and a thread +// pool in unit tests. For most tests, it is sufficient to just instantiate the +// WebTaskEnvironment as a member variable. It is a good idea to put the +// WebTaskEnvironment as the first member variable in test classes, so it is +// destroyed last, and the test threads always exist from the perspective of +// other classes. // // By default, all of the created TestWebThreads will be backed by a single // shared MessageLoop. If a test truly needs separate threads, it can do so by // passing the appropriate combination of option values during the -// TestWebThreadBundle construction. +// WebTaskEnvironment construction. // // To synchronously run tasks posted to TestWebThreads that use the shared // MessageLoop, call RunLoop::Run/RunUntilIdle() on the thread where the -// TestWebThreadBundle lives. The destructor of TestWebThreadBundle runs -// remaining TestWebThreads tasks and remaining BLOCK_SHUTDOWN thread pool -// tasks. +// WebTaskEnvironment lives. The destructor of WebTaskEnvironment runs remaining +// TestWebThreads tasks and remaining BLOCK_SHUTDOWN thread pool tasks. // -// Some tests using the IO thread expect a MessageLoopForIO. Passing -// IO_MAINLOOP will use a MessageLoopForIO for the main MessageLoop. -// Most of the time, this avoids needing to use a REAL_IO_THREAD. +// Some tests using the IO thread expect a MessageLoopForIO. Passing IO_MAINLOOP +// will use a MessageLoopForIO for the main MessageLoop. Most of the time, this +// avoids needing to use a REAL_IO_THREAD. #include <memory> @@ -41,7 +45,7 @@ class TestWebThread; -class TestWebThreadBundle : public base::test::TaskEnvironment { +class WebTaskEnvironment : public base::test::TaskEnvironment { public: // Used to specify the type of MessageLoop that backs the UI thread, and // which of the named WebThreads should be backed by a real @@ -52,9 +56,9 @@ REAL_IO_THREAD = 1 << 1, }; - explicit TestWebThreadBundle(int options = Options::DEFAULT); + explicit WebTaskEnvironment(int options = Options::DEFAULT); - ~TestWebThreadBundle() override; + ~WebTaskEnvironment() override; private: void Init(int options); @@ -62,7 +66,13 @@ std::unique_ptr<TestWebThread> ui_thread_; std::unique_ptr<TestWebThread> io_thread_; - DISALLOW_COPY_AND_ASSIGN(TestWebThreadBundle); + DISALLOW_COPY_AND_ASSIGN(WebTaskEnvironment); +}; + +// TODO(crbug.com/992483): Mass migrate users and remove this. +class TestWebThreadBundle : public WebTaskEnvironment { + public: + using WebTaskEnvironment::WebTaskEnvironment; }; } // namespace web
diff --git a/ios/web/test/test_web_thread_bundle.cc b/ios/web/test/test_web_thread_bundle.cc index b938b9a..c27ee6c 100644 --- a/ios/web/test/test_web_thread_bundle.cc +++ b/ios/web/test/test_web_thread_bundle.cc
@@ -12,13 +12,13 @@ namespace web { -TestWebThreadBundle::TestWebThreadBundle(int options) +WebTaskEnvironment::WebTaskEnvironment(int options) : base::test::TaskEnvironment(options == IO_MAINLOOP ? MainThreadType::IO : MainThreadType::UI) { Init(options); } -TestWebThreadBundle::~TestWebThreadBundle() { +WebTaskEnvironment::~WebTaskEnvironment() { // To ensure a clean teardown, each thread's message loop must be flushed // just before the thread is destroyed. But stopping a fake thread does not // automatically flush the message loop, so do it manually. @@ -40,13 +40,13 @@ WebThreadImpl::ResetTaskExecutorForTesting(); } -void TestWebThreadBundle::Init(int options) { +void WebTaskEnvironment::Init(int options) { WebThreadImpl::CreateTaskExecutor(); ui_thread_ = std::make_unique<TestWebThread>(WebThread::UI, GetMainThreadTaskRunner()); - if (options & TestWebThreadBundle::REAL_IO_THREAD) { + if (options & WebTaskEnvironment::REAL_IO_THREAD) { io_thread_ = std::make_unique<TestWebThread>(WebThread::IO); io_thread_->StartIOThread(); } else {
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc index efe45dd3..e0c53bc 100644 --- a/media/filters/fuchsia/fuchsia_video_decoder.cc +++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -61,11 +61,16 @@ zx::vmo CreateVmo(size_t size) { zx::vmo vmo; zx_status_t status = zx::vmo::create(size, 0, &vmo); + if (status != ZX_OK) { ZX_DLOG(ERROR, status) << "zx_vmo_create"; return zx::vmo(); } + static const char kVmoName[] = "cr-codec-output"; + status = vmo.set_property(ZX_PROP_NAME, kVmoName, strlen(kVmoName)); + ZX_DCHECK(status == ZX_OK, status); + return vmo; }
diff --git a/media/fuchsia/cdm/fuchsia_cdm.cc b/media/fuchsia/cdm/fuchsia_cdm.cc index a63face..cbe083a 100644 --- a/media/fuchsia/cdm/fuchsia_cdm.cc +++ b/media/fuchsia/cdm/fuchsia_cdm.cc
@@ -41,7 +41,9 @@ const std::vector<uint8_t>& response) { fuchsia::media::drm::LicenseServerMessage message; message.message = cr_fuchsia::MemBufferFromString( - std::string(response.begin(), response.end())); + base::StringPiece(reinterpret_cast<const char*>(response.data()), + response.size()), + "cr-drm-license-server-message"); return message; }
diff --git a/media/fuchsia/cdm/service/fuchsia_cdm_manager.cc b/media/fuchsia/cdm/service/fuchsia_cdm_manager.cc index 4142aa2..a47aa03 100644 --- a/media/fuchsia/cdm/service/fuchsia_cdm_manager.cc +++ b/media/fuchsia/cdm/service/fuchsia_cdm_manager.cc
@@ -171,7 +171,9 @@ } fuchsia::media::drm::ProvisioningResponse provision_response; - provision_response.message = cr_fuchsia::MemBufferFromString(response); + provision_response.message = + cr_fuchsia::MemBufferFromString(response, "cr-drm-provision-response"); + provisioner_->ProcessProvisioningResponse( std::move(provision_response), fit::bind_member(this, &OriginProvisioner::OnProvisioningResponseResult));
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index cc86de2..8b090e5ff 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -1375,7 +1375,6 @@ { "name": "thepaymentscompany.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "xps2pdf.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ansdell.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "brunosouza.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bugzil.la", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ethitter.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "firemail.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -3909,7 +3908,6 @@ { "name": "ulrik.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "utopians.dk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "vanetv.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "varunagw.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "vistb.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "vyber-odhadce.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "webyazilimankara.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -4951,7 +4949,6 @@ { "name": "jayharris.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jcraft.us", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jennythebaker.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "jobss.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jonaskjodt.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jonathan-apps.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jonathancarter.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -7641,7 +7638,6 @@ { "name": "goldmark.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "graciousmay.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "greatnet.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "grunex.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "grytics.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gtlfsonlinepay.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gunwatch.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -8191,7 +8187,6 @@ { "name": "aberdeenjudo.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "abilitylist.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "abthorpe.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "accelerole.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "acheritage.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "acisonline.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "acritelli.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -9335,7 +9330,6 @@ { "name": "leesilvey.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "legarage.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "leilonorte.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "leitner.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "leiyun.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "lengzzz.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "lenovogaming.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -9576,7 +9570,6 @@ { "name": "networkingphoenix.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "netzwerkwerk.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "neuronasdigitales.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "never-afk.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "newedivideo.it", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "newlooknow.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "newstone-tech.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -10578,7 +10571,6 @@ { "name": "amerimex.cc", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "alpencam.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "aluroof.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "affordableazdivorce.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "alpencams.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "amihub.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "antons.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -11925,7 +11917,6 @@ { "name": "hpbn.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "hsts-preload-test.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ime.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "imitza.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "immunicity.date", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "immunicity.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "immunicity.press", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -12164,7 +12155,6 @@ { "name": "rentbrowser.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "reuter-shop.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "reuter.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "ricardobalk.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "richardb.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rickweijers.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "right2.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -12198,7 +12188,6 @@ { "name": "sefru.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "seoinc.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "seon.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "septillion.cn", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "server-bg.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "server-daten.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "settleapp.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -13087,7 +13076,6 @@ { "name": "jing.su", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jlhmedia.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jncde.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "jncie.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jncip.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "joehenry.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "johannes-sprink.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -13518,7 +13506,6 @@ { "name": "qwikdash.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ra4wvpn.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "radioilusion.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "railgun.com.cn", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "raissarobles.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ralfs-zusizone.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ranzbak.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -14341,7 +14328,6 @@ { "name": "directinsure.in", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "danielmostertman.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "devcu.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "cybertu.be", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "danielmostertman.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "domenic.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "designville.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -15420,7 +15406,6 @@ { "name": "stammtisch.domains", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "storyland.ie", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "stevensheffey.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "spacecafe.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sobieray.dyndns.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "snip.host", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sperohub.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -15854,7 +15839,6 @@ { "name": "andrea-wirthensohn.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "7x24servis.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bobobox.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "advanced.info", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "amsterdamian.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "burgers.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "bradler.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -17859,7 +17843,6 @@ { "name": "g-rickroll-o.pw", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "graphsearchengine.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "geschmacksache.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "grepmaste.rs", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gradients.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gramati.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gracetini.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -18440,7 +18423,6 @@ { "name": "naughty.audio", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "kinmunity.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "newday.host", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "mlvbphotography.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ncands.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "n8ch.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "mosfet.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -19412,7 +19394,6 @@ { "name": "analteengirls.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "allcloud.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "allshousedesigns.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "3bakayottu.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "analpantyhose.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "aliacraft.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "aicial.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -19785,7 +19766,6 @@ { "name": "clovissantos.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "codelitmus.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "craigwfox.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "craftyguy.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "cnbs.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "coreum.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "confuddledpenguin.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -20033,7 +20013,6 @@ { "name": "educators.co.nz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "erudicia.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "erethon.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "englishstudio.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "embellir-aroma.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "erudicia.it", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "erudicia.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -20569,7 +20548,6 @@ { "name": "kueche-co.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "l18.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "knowdebt.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "kaisakura.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "knigadel.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "koha.be", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "jichi.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -24065,7 +24043,6 @@ { "name": "freeasyshop.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "freedev.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "freegutters.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "freela.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "freifahrt.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "freifunk-in-solingen.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "freifunk-lindlar.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -25713,7 +25690,6 @@ { "name": "security201.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "securitykey.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "seefirm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "seekers.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sehnenweh.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "seiler-bad.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "seiryokuzai-ch.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -28568,7 +28544,6 @@ { "name": "myspicer.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nodeselect.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nirvanashop.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "nipe-systems.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "nihon-no-sake.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ngtoys.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "normalady.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -29735,7 +29710,6 @@ { "name": "wsup.social", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "writing-expert.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "writecustomessay.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "wpturnedup.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "victoreriksson.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "writingcities.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "wpdirecto.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -30054,7 +30028,6 @@ { "name": "amoozesh98.ir", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "arox.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "azlo.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "arxell.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "astral.gq", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "acendealuz.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "amorimendes.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -30401,7 +30374,6 @@ { "name": "drogoz.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "dosomeworks.biz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "droidgyan.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "dorfbrunnen.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "discoveryottawa.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "dukec.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "eashwar.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -31635,7 +31607,6 @@ { "name": "svc-sitec.com.mx", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "stuttgart-gablenberg.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "streamer.tips", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "suareforma.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "studentforums.biz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "summa-prefis.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "straka.name", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -32306,7 +32277,6 @@ { "name": "emporiodosperfumes.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "equinecoaching.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "equipeferramentas.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "equityflows.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "esite.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "esprit-cloture.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "faciledireto.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -32730,7 +32700,6 @@ { "name": "fzx750.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gaines-sodiamex.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gamoice.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "geekclubbooks.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "geertdegraaf.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "gehreslaw.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "genia-life.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -32883,7 +32852,6 @@ { "name": "mosaic-design.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "moube.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "mrpropop.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "mubiflex.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "multimail.work", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "multivpn.com.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "my-host.ovh", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -34117,7 +34085,6 @@ { "name": "learnplayground.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "ledzom.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "leideninternationalreview.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "leinfelder.in", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "lennyfaces.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "leon.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "lexpartsofac.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -36421,7 +36388,6 @@ { "name": "laindonleisure.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lakehavasucitynews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lakesherwoodelectrical.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lanonfire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lasseleegaard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lasseleegaard.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lasseleegaard.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -37749,7 +37715,6 @@ { "name": "vollans.id.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vosgym.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vreeman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "vrsgames.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wacky.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "waf.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wallpaperup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -41055,7 +41020,6 @@ { "name": "leadinfo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "led-tl-wereld.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ledscontato.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lesjardinsdemathieu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lesterchan.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "linkthis.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "linuxos.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -42427,7 +42391,6 @@ { "name": "buyritefairview.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cadre.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "caibi.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "callanbryant.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "canadian-nurse.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cannahealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "carbontv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -42607,7 +42570,6 @@ { "name": "greenhats.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "groentebesteld.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "guides-et-admin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "guildbase.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "hakaru.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "hamburgerbesteld.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "happydietplan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -44384,7 +44346,6 @@ { "name": "sho-tanaka.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "show-stream.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "signal.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "simplithai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sirencallofficial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sisseastumine.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sistemos.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -46444,7 +46405,6 @@ { "name": "sircon.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sisgopro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sistov.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "skrivande.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smit.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smithchow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smmcab.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -46778,7 +46738,6 @@ { "name": "emby.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "er-mgmt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "etch.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "eugeneyan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eve.ac", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eveswell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "extensionschallenge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -47925,7 +47884,6 @@ { "name": "niklasanderson.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ninesix.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "niqex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "nocmd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "nonametheme.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "notepad.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "nowitzki.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -48683,7 +48641,6 @@ { "name": "ldjb.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "learningman.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lebendige-heilkunst.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "legissa.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "leter.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "letskick.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "liberdademg.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -49079,7 +49036,6 @@ { "name": "xn--cfa.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xn--fp8h58f.ws", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xn--y-5ga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "xo7.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xposedornot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yawen.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yell.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -50684,7 +50640,6 @@ { "name": "52hentai.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "55797.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "656088.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "66136.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "666omg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "755k3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "7570.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -50908,7 +50863,6 @@ { "name": "cjean.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cloudlessdreams.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "clsfoundationrepairandwaterproofing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "clubcorsavenezuela.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cobcode.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "codejots.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "codexpo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -51395,7 +51349,6 @@ { "name": "mobisium.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "modulex-gmbh.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moeyoo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "moeyun.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mojizuri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moneoci.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moneybird.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -51850,7 +51803,6 @@ { "name": "vandorenscholars.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vandyhacks.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vangoghcoaching.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "varalwamp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "vendermicasarapido.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "verifiedjoseph.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "verifiny.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -52276,7 +52228,6 @@ { "name": "mcon.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mds-paris.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "meditel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "medmarkt24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "medvedikorenka.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "merchant-automotive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "merlinsoap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -53480,7 +53431,6 @@ { "name": "martin-loewer.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "matdogs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mathematris.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "mathfinder.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "matome-surume.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mcfipvt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mediabackoffice.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -56146,14 +56096,12 @@ { "name": "darwinsearch.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "datajobs.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "davidfetveit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ddoser.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "decay24.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "demiranda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "desktopd.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "detecmon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "detuprovincia.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "dev-gutools.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "deviser.wang", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "devstroke.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "devtty.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "dicksakowicz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -56336,7 +56284,6 @@ { "name": "gmacedo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "golang.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "goodth.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "goover.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "goproinspectiongroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gpureport.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "grantplatform.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -56488,7 +56435,6 @@ { "name": "lisanzauomo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "livingkingsinc.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lonestarlandandcommercial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "looker.wang", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "loricozengeller.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "loungepapillon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "luca-steeb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -56663,7 +56609,6 @@ { "name": "qianmo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "radioactivenetwork.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "raku.bzh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "reads.wang", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "realestate-in-uruguay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "realestatecentralcoast.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "realestatemarketingblog.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -59170,7 +59115,6 @@ { "name": "biblethoughts.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bigshopper.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bigshopper.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "biomin.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bishopscourt-hawarden.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "biznesonline.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bizzdesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -66036,7 +65980,6 @@ { "name": "hamiltonweather.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "haruhi.org.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "headlinesclub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "helm-pokale.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "henryocallaghan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "hentaipornography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "herbolarigranvida.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -66871,7 +66814,6 @@ { "name": "basketforex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bazari.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "berkat-luqs.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "bestartshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bf5.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bfh.science", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bibliotecadeseguranca.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -66907,7 +66849,6 @@ { "name": "controlambientalbogota.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "counterenlol.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "crazypowered.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "createcpanama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ctoin.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "czwartybrat.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "dale-west.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -67424,7 +67365,6 @@ { "name": "aramloebmd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "art-et-tonneaux.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "artigianociao.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "assetbacked.capital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "associatedwomenshealthcare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "asu.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "atf.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -68262,7 +68202,6 @@ { "name": "christianadventurecamps.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "chwilrank.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "clearpay.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "clearwaterbidets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "co-founder-stuttgart.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "competencyassessment.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "conftree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -68473,7 +68412,6 @@ { "name": "location-appartement-dakar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "long116.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "luminary.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lushan.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lust.works", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "luxurydistribution.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "m5197.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -69706,7 +69644,6 @@ { "name": "yr8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zingpetfood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "01918.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "05am8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "06918.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "08918.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "09btt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -70039,7 +69976,6 @@ { "name": "btt2121.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt256.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt381g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "btt529g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt686.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt8.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt88.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -70049,7 +69985,6 @@ { "name": "btt9090.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt9898.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btta13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "btta27.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bttna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bttt222.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bttt333.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -70749,7 +70684,6 @@ { "name": "dunyahalleri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "e-mandataires.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "e-michiganinsurance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ebooknetworking.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "echo-in.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eddy-vh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "edvinaspaliskis.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -72204,7 +72138,6 @@ { "name": "konfekcjonowanie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "koreanrandom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks3636.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5808.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kusadasiforum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "labworks.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lelux.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -73157,7 +73090,6 @@ { "name": "btopc.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt285.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt6262a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "btt8383a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "btt9292a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "buysoft.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "byfeldt.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -73666,7 +73598,6 @@ { "name": "7214.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "8083d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "8130d88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "8196d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "8207d88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "8806d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "8815d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -76779,7 +76710,6 @@ { "name": "ks0668.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks257.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks318.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks549.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks600.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks641.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -76837,7 +76767,6 @@ { "name": "locksmithservice-humble.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "locksmithssanmarcostx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "locksmithstaffordtx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "locomen.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "london-mafia.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lorimullins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lorisfnotary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -77406,7 +77335,6 @@ { "name": "salvadorinfantil.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sambuchanan.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "samiratv.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "samvui.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sandwichcouncil.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sanfranciscopersonalinjuryattorney.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sangen.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -78612,40 +78540,6 @@ { "name": "africanhosting.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "agaveandpine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "agks02.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks05.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks20.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks21.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks26.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks30.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks31.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks32.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks36.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks38.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks39.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks46.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks49.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks52.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks53.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks56.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks57.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks59.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks60.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks61.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks69.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks71.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks72.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks75.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks79.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks80.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks82.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks83.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks85.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks86.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks87.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks90.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks92.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks93.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks97.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "agrodronechile.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "agweili.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "agzlapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79273,38 +79167,12 @@ { "name": "ks06.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks17.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks19.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2251.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2298.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2375.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2652.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks35.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks3533.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks410.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5525.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5531.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5532.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks56.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5822.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6872.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6875.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8112.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8113.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8128.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8129.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8135.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8152.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8176.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8177.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks82.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks82.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8211.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8218.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8233.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8266.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8278.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8281.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks85.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks87.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks96.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks97.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kudinilam.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -80734,11 +80602,6 @@ { "name": "activespacetech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adamtatusko.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ag8819-livechat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks23.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks27.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks45.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks47.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks78.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ai-cuisine.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "akash.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "aktive-arbeitslose.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -80953,27 +80816,12 @@ { "name": "kocka.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kp0808.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kpaycoin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5529.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6800.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6806.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6813.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6821.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6822.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6838.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6839.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6851.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6852.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6853.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6861.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6862.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6870.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6871.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6873.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8115.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks8127.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8222.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8886.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks9122.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kuadey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "l36594.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lakeandriverrestoration.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81265,13 +81113,6 @@ { "name": "active247.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adontenchambers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "afilio.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks29.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks35.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks50.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks63.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks67.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "agks70.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "airtable.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "alles-nur-ge.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "alonas.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81292,7 +81133,6 @@ { "name": "b81818.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "baufi24.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bb168.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "bb221.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bea.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "beatz-anime.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "beticalia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81374,7 +81214,6 @@ { "name": "einquiz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eisenhowerlibrary.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "elasticshift.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "electricallpro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "emergency-federal-register.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "empoweren.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "enerte.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81482,13 +81321,7 @@ { "name": "kodomo.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "koflegend.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "krillz.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2235.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2383.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks2955.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks3536.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks36.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5528.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks5958.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6807.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6812.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6815.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81501,16 +81334,8 @@ { "name": "ks6829.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6830.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks6831.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6836.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6837.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6850.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6857.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6863.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks6867.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks70.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks8126.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8225.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ks8265.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks8892.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks8895.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ks8915.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81639,7 +81464,6 @@ { "name": "securewebcomputing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sellmyphone.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "seyrederiz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "sgc.am", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sh68.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "shelfplanner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "shiftsecurityleft.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81690,7 +81514,6 @@ { "name": "time.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tokitover.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tommyemo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "tommyemo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "topappandroid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "topcanadianescorts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tourx.co.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -82176,6 +81999,434 @@ { "name": "z8950.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zombmage.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zoohaus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "04d88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "051ks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "111plus.design", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "168fff.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "281ks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "3dlab.team", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "3pestki.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "620207.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "623kb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "633kb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "655ks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "698kb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "8888yule8888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "889w889.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "889w889.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "88home9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "88wewin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "9kb.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aaapo.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "afashion.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aigner-club.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aigner-club.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aignerimage.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "akmade.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "albstaedter-kids-cup.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alibaba-test.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "anonymoushackers.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "antyfake.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arslonga.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aucospa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aumentada.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "av-systems.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "b889b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "backupassist.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bahrevaran.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "banananet.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "baokhangfood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bayltd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "beardsome.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "becleverwithyourcash.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "belebey.city", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "belplombier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "benu.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bepayd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bestedeal.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "betterselfbetterworld.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bicromoestudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bionovanaturalpools.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "biznesinfo.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bjl688.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blackmagickwitch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bogurl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bojiu99.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bonsi.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "borderless360.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bridgetroll.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "brightpool-markets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "broodingblogger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bviphotovideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "carlosmfalves.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "catalogobiblioteca.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cdigitale.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "censys.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chathund.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "checkrent.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "clinicaarques.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cocbaoan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "comparesolarquote.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "conciencia.fit", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "connect-more.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "conradboraboranuiresort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "countdowntrader.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cp015.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "creativeideasagency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cryptex.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cryptoninjas.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ctf-albstadt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d88a.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d88b.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d88e.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "d88g.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "daunatotala.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dbettenleur.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "de-kramers.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "deckersheaven.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dermaldistinction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "descargar-apk.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "desentupidorademais.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "desheng28.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "diananeves.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ds138.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dtinel.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dylnuge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ebertlang.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elainesearer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "electricfencemidrand.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eliasong.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elisabethcasanova.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elitepainmanagement.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elsanoguera.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "emirefek.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "equisecu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ervinthagod.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "escortbruxelles.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "escortgigolo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "espherapromocional.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "esteriliza-me.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "excerp.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "exxpozed-image.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "exxpozed.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "exxpozed.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "exxpozed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "exxpozed.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "exxpozed.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fctwo.download", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fdremodelingatlanta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fekir.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ferlc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "finestrina.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fins.money", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fivestartrader.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "foodphotographyblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "forsi.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frauen-etappenrennen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "g818city.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gaci88play.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "game818play.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "game88play.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "game88yule.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gdpr.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gelaendermanufaktur.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gentledance.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gentledance.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "getalitools.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "giaphaco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "globalesm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "go-datasecurity.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "go889w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "golsportsoccer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "griswoldplumbingct.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "grizz.gdn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "groupem6.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gruhn.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gstand.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hadleyluker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hammercast.fm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "happybrush.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "heartbound.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hemainteriors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hg661.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hgc369.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hibanaworld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hifumi.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horairetrain.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horairetrain.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horairetrain.lu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "horairetrain.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hosoi-tax.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hospeda1.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hotelpalmas.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hqon.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iberion.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "idealog.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "idesoft.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "idesoft.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "idesoft.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "idkidknow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "igmt-guinea.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "imlhx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "immovit.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "imperioth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inegol.mobi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infomundord.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inodari.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ipsum.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "irioka.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "itzer.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ivocotec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jadesong.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jasonwei.nctu.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jb138.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jbc88.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jf886.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jinbijin.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jkland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jl-dx.com.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jof.guru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jplennard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jshub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "juezz.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "justeducationonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "karoke.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kartoffel-tobi.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kazmamall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kb98.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kcfmradio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kerner.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kettinggeleider.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kickingpixels.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kinaesthetics-forschung.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kobudo49.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6809.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6810.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6819.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6823.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6828.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6832.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks6833.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ks9211.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kuditel.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ladiesofvietnam.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leeannescreations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lequocthai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "liberta-me.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lideradigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lighthouseglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lilianejuchli.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "linuxhub.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "locksmithfourways24-7.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "loli.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lonelypawn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "loverngifts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lz898.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lzh.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "m6pub.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "machinerysafety101.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "magicnethosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "magicvps.md", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marketing-apps.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marvnet.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "maryluzturismo.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matchupmagic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "maxmusical.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mdaemon.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "melda.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "merdacz.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minload.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minton.systems", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mllz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mnszone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "modell-lq.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "momentumdesign.website", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mothership.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mu105.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mudaomundo.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "musicsense.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myfiladelfia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mythen-fonds.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mythenfonds.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "n-gram.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nationalaustriabank.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "netfirmtextile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nethorizon.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "networksolutionsconsultant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newstargeted.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "noga4you.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nomzamo.spdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nsine.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "octopoos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "octopoos.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "official-sensitive.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "official-sensitive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "official-sensitive.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "official-sensitive.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ontogenese.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "openwrt-dist.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "operr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "operrtel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "operrwork.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "orangelandgaming.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ouest-annonces.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "parasca7.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pari.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pastimeproject.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paulcloud.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pcxserver.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pelosanimais.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "percloud.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pharmasana.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "phoenixnow.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "phukienchanh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pier23.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pirateproxy.vet", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "plus-aliance.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "praladofuturo.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "praveenravichandran.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "progaudio.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "promodance.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proxybay.lat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pube.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "puntacanatransporte.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "putasdelporno.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "qlinksgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "quuck.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "quuck.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "r8369.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "r8700.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "racevinyl.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "radlina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raketa.travel", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raportdnia.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ratajczak.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ratujava.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raveboy.dyndns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raydius.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reeves-family.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "renedekoeijer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rheijmans.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ribella.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "richieheijmans.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ruf888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "runningandoutdoors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "russstudios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ryanjarvis.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ryanjarvis.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "s-pro.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "safetysign.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "salnet.wf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "scriptslug.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "seamus.party", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "seblod.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "serkanceyhan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sham-group.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shoppingvrimini.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sksongs.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "skuizy.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sm-kyoushitsu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smakoszwegrzynka.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smartacademy.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smartresumeservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "smcj.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "snj.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sofiawestergren.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "softly.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sonderfloral.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "songyang.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spectrum-markets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spikefishdesigns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "srfloki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "srkb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stainhaufen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "studiovictorialimited.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stuffie.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "summusglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "suniru.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sunnistan.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sunpig.fit", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "suroot.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sweetcalculus.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "swiftbonds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "swindontennisclub.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "syncplay.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "szww99.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tasadar.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "taubin.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tehden.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "teriyakiweasel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "terselubung.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thebarrypatch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "theedisoncapital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "theilluminatisociety.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "therudeworkout.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thierrymazue.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tiochambita.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toddlerleaf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tokky.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toprelatos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "topstore.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "transfersw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "travelingbagsmke.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trelki.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trumtrimun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tugesha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uestc.icu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "upvoted.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "videogamer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vigilantesporcolombia.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "voicr.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "volatilethunk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vpsrussia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "w889vip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wagonyard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wallmarketing.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wanghuiblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "watchhentai.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wattcontrol.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "we168168.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "we88fun.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "westmidlandslettings.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wew888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wewillfixyouripad.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wewillfixyourpc.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wewin889.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "whitemountainnaturalcreations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "winall8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wiredmedia.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wirkungs-forschung.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wirkungs-forschung.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wirkungs-forschung.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wirkungs-forschung.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wirkungs-forschung.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wjg.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wordops.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "woxter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wsv-pfeffingen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ww8989.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wwin818.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wwvip88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wy188.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xavita.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xcharge.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xeniox.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xiaojiyoupin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--nidar-tib.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--prfontaine-c7a.name", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xuehao.net.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yaseminuzumcu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yesh.lk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yesildiyetisyen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yuleyule88game.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zestadionu.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zimtoel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zmiguel.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "znidar.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zollernalbtour.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zupzup.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zz606.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, // END OF 1-YEAR BULK HSTS ENTRIES // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/sandbox/win/src/signed_interception.cc b/sandbox/win/src/signed_interception.cc index 5341e5f..d9b1bc8 100644 --- a/sandbox/win/src/signed_interception.cc +++ b/sandbox/win/src/signed_interception.cc
@@ -26,48 +26,46 @@ ULONG section_page_protection, ULONG allocation_attributes, HANDLE file_handle) { - NTSTATUS status = orig_CreateSection( - section_handle, desired_access, object_attributes, maximum_size, - section_page_protection, allocation_attributes, file_handle); - - // Only intercept calls that match a particular signature. - if (status != STATUS_INVALID_IMAGE_HASH) - return status; - // The section only needs to have SECTION_MAP_EXECUTE, but the permissions - // vary depending on the OS. Windows 1903 and higher requests (SECTION_QUERY | - // SECTION_MAP_READ | SECTION_MAP_EXECUTE) while previous OS versions also - // request SECTION_MAP_WRITE. Just check for EXECUTE. - if (!(desired_access & SECTION_MAP_EXECUTE)) - return status; - if (object_attributes) - return status; - if (maximum_size) - return status; - if (section_page_protection != PAGE_EXECUTE) - return status; - if (allocation_attributes != SEC_IMAGE) - return status; - do { - if (!ValidParameter(section_handle, sizeof(HANDLE), WRITE)) + // The section only needs to have SECTION_MAP_EXECUTE, but the permissions + // vary depending on the OS. Windows 1903 and higher requests (SECTION_QUERY + // | SECTION_MAP_READ | SECTION_MAP_EXECUTE) while previous OS versions also + // request SECTION_MAP_WRITE. Just check for EXECUTE. + if (!(desired_access & SECTION_MAP_EXECUTE)) + break; + if (object_attributes) + break; + if (maximum_size) + break; + if (section_page_protection != PAGE_EXECUTE) + break; + if (allocation_attributes != SEC_IMAGE) break; + // IPC must be fully started. void* memory = GetGlobalIPCMemory(); if (!memory) break; + std::unique_ptr<wchar_t, NtAllocDeleter> path; + if (!NtGetPathFromHandle(file_handle, &path)) break; + const wchar_t* const_name = path.get(); CountedParameterSet<NameBased> params; params[NameBased::NAME] = ParamPickerMake(const_name); + // Check if this will be sent to the broker. if (!QueryBroker(IPC_NTCREATESECTION_TAG, params.GetBase())) break; + if (!ValidParameter(section_handle, sizeof(HANDLE), WRITE)) + break; + CrossCallReturn answer = {0}; - answer.nt_status = status; + answer.nt_status = STATUS_INVALID_IMAGE_HASH; SharedMemIPCClient ipc(memory); ResultCode code = CrossCall(ipc, IPC_NTCREATESECTION_TAG, file_handle, &answer); @@ -75,19 +73,21 @@ if (code != SBOX_ALL_OK) break; - status = answer.nt_status; - if (!NT_SUCCESS(answer.nt_status)) break; __try { *section_handle = answer.handle; + return answer.nt_status; } __except (EXCEPTION_EXECUTE_HANDLER) { break; } } while (false); - return status; + // Fall back to the original API in all failure cases. + return orig_CreateSection(section_handle, desired_access, object_attributes, + maximum_size, section_page_protection, + allocation_attributes, file_handle); } } // namespace sandbox
diff --git a/services/data_decoder/OWNERS b/services/data_decoder/OWNERS index cd1f44c..915d04e 100644 --- a/services/data_decoder/OWNERS +++ b/services/data_decoder/OWNERS
@@ -1,2 +1,4 @@ palmer@chromium.org rsesek@chromium.org +# COMPONENT: Internals>Mojo>Bindings +# TEAM: chrome-security@google.com
diff --git a/services/device/serial/serial_device_enumerator_linux.cc b/services/device/serial/serial_device_enumerator_linux.cc index f1e59d3..7243bdc 100644 --- a/services/device/serial/serial_device_enumerator_linux.cc +++ b/services/device/serial/serial_device_enumerator_linux.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/threading/scoped_blocking_call.h" namespace device { @@ -74,26 +75,58 @@ if (!subsystem || strcmp(subsystem, kSerialSubsystem) != 0) return; + const char* syspath_str = udev_device_get_syspath(device.get()); + if (!syspath_str) + return; + std::string syspath(syspath_str); + + // Platform serial ports. + if (base::StartsWith(syspath, "/sys/devices/platform/", + base::CompareCase::SENSITIVE)) { + CreatePort(std::move(device), syspath); + return; + } + + // USB serial ports and others that have a proper bus identifier. + const char* bus = udev_device_get_property_value(device.get(), kHostBusKey); + if (bus) { + CreatePort(std::move(device), syspath); + return; + } + + // Bluetooth ports are virtual TTYs but have an identifiable major number. + const char* major = udev_device_get_property_value(device.get(), kMajorKey); + if (major && base::StringPiece(major) == kRfcommMajor) { + CreatePort(std::move(device), syspath); + return; + } +} + +void SerialDeviceEnumeratorLinux::OnDeviceChanged(ScopedUdevDevicePtr device) {} + +void SerialDeviceEnumeratorLinux::OnDeviceRemoved(ScopedUdevDevicePtr device) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, + base::BlockingType::MAY_BLOCK); + const char* syspath = udev_device_get_syspath(device.get()); if (!syspath) return; + auto it = paths_.find(syspath); + if (it == paths_.end()) + return; + + ports_.erase(it->second); + paths_.erase(it); +} + +void SerialDeviceEnumeratorLinux::CreatePort(ScopedUdevDevicePtr device, + const std::string& syspath) { const char* path = udev_device_get_property_value(device.get(), kHostPathKey); if (!path) return; - // TODO(rockot): There may be a better way to filter serial devices here, - // but it's not clear what that would be. Udev will list lots of virtual - // devices with no real endpoint to back them anywhere. The presence of - // a bus identifier (e.g., "pci" or "usb") seems to be a good heuristic - // for detecting actual devices. - const char* bus = udev_device_get_property_value(device.get(), kHostBusKey); - if (!bus) { - const char* major = udev_device_get_property_value(device.get(), kMajorKey); - if (!major || strcmp(major, kRfcommMajor) != 0) - return; - } - auto token = base::UnguessableToken::Create(); auto info = mojom::SerialPortInfo::New(); info->path = base::FilePath(path); @@ -122,23 +155,4 @@ paths_.insert(std::make_pair(syspath, token)); } -void SerialDeviceEnumeratorLinux::OnDeviceChanged(ScopedUdevDevicePtr device) {} - -void SerialDeviceEnumeratorLinux::OnDeviceRemoved(ScopedUdevDevicePtr device) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::MAY_BLOCK); - - const char* syspath = udev_device_get_syspath(device.get()); - if (!syspath) - return; - - auto it = paths_.find(syspath); - if (it == paths_.end()) - return; - - ports_.erase(it->second); - paths_.erase(it); -} - } // namespace device
diff --git a/services/device/serial/serial_device_enumerator_linux.h b/services/device/serial/serial_device_enumerator_linux.h index d91f2ed..a171afdc2 100644 --- a/services/device/serial/serial_device_enumerator_linux.h +++ b/services/device/serial/serial_device_enumerator_linux.h
@@ -36,6 +36,8 @@ void OnDeviceRemoved(ScopedUdevDevicePtr device) override; private: + void CreatePort(ScopedUdevDevicePtr device, const std::string& syspath); + std::unique_ptr<UdevWatcher> watcher_; std::map<base::UnguessableToken, mojom::SerialPortInfoPtr> ports_; std::map<std::string, base::UnguessableToken> paths_;
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 9923e19a..41e3a49 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -1536,8 +1536,7 @@ void NetworkContext::PreconnectSockets( uint32_t num_streams, const GURL& original_url, - int32_t load_flags, - bool privacy_mode_enabled, + bool allow_credentials, const net::NetworkIsolationKey& network_isolation_key) { GURL url = GetHSTSRedirect(original_url); @@ -1557,9 +1556,15 @@ request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, user_agent); - request_info.load_flags = load_flags; - request_info.privacy_mode = privacy_mode_enabled ? net::PRIVACY_MODE_ENABLED - : net::PRIVACY_MODE_DISABLED; + if (allow_credentials) { + request_info.load_flags = net::LOAD_NORMAL; + request_info.privacy_mode = net::PRIVACY_MODE_DISABLED; + } else { + request_info.load_flags = net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES | + net::LOAD_DO_NOT_SEND_AUTH_DATA; + request_info.privacy_mode = net::PRIVACY_MODE_ENABLED; + } request_info.network_isolation_key = network_isolation_key; net::HttpTransactionFactory* factory =
diff --git a/services/network/network_context.h b/services/network/network_context.h index ee8b7ec4..12806873 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -316,8 +316,7 @@ void PreconnectSockets( uint32_t num_streams, const GURL& url, - int32_t load_flags, - bool privacy_mode_enabled, + bool allow_credentials, const net::NetworkIsolationKey& network_isolation_key) override; void CreateP2PSocketManager( mojom::P2PTrustedSocketManagerClientPtr client,
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index e303ec7..1e3c260 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -3482,9 +3482,9 @@ test_server.SetConnectionListener(&connection_listener); ASSERT_TRUE(test_server.Start()); - network_context->PreconnectSockets( - 1, test_server.base_url(), net::LOAD_NORMAL, - true /* privacy_mode_enabled */, net::NetworkIsolationKey()); + network_context->PreconnectSockets(1, test_server.base_url(), + /*allow_credentials=*/true, + net::NetworkIsolationKey()); connection_listener.WaitForAcceptedConnections(1u); } @@ -3498,8 +3498,8 @@ ASSERT_TRUE(test_server.Start()); const GURL server_http_url = GetHttpUrlFromHttps(test_server.base_url()); - network_context->PreconnectSockets(1, server_http_url, net::LOAD_NORMAL, - true /* privacy_mode_enabled */, + network_context->PreconnectSockets(1, server_http_url, + /*allow_credentials=*/false, net::NetworkIsolationKey()); connection_listener.WaitForAcceptedConnections(1u); @@ -3512,8 +3512,8 @@ base::Time::Now() + base::TimeDelta::FromSeconds(1000); network_context->url_request_context()->transport_security_state()->AddHSTS( server_http_url.host(), expiry, false); - network_context->PreconnectSockets(1, server_http_url, net::LOAD_NORMAL, - true /* privacy_mode_enabled */, + network_context->PreconnectSockets(1, server_http_url, + /*allow_credentials=*/false, net::NetworkIsolationKey()); connection_listener.WaitForAcceptedConnections(1u); @@ -3533,9 +3533,9 @@ test_server.SetConnectionListener(&connection_listener); ASSERT_TRUE(test_server.Start()); - network_context->PreconnectSockets( - 0, test_server.base_url(), net::LOAD_NORMAL, - true /* privacy_mode_enabled */, net::NetworkIsolationKey()); + network_context->PreconnectSockets(0, test_server.base_url(), + /*allow_credentials=*/true, + net::NetworkIsolationKey()); base::RunLoop().RunUntilIdle(); int num_sockets = @@ -3555,9 +3555,9 @@ test_server.SetConnectionListener(&connection_listener); ASSERT_TRUE(test_server.Start()); - network_context->PreconnectSockets( - 2, test_server.base_url(), net::LOAD_NORMAL, - true /* privacy_mode_enabled */, net::NetworkIsolationKey()); + network_context->PreconnectSockets(2, test_server.base_url(), + /*allow_credentials=*/true, + net::NetworkIsolationKey()); connection_listener.WaitForAcceptedConnections(2u); int num_sockets = @@ -3574,9 +3574,9 @@ test_server.SetConnectionListener(&connection_listener); ASSERT_TRUE(test_server.Start()); - network_context->PreconnectSockets( - 4, test_server.base_url(), net::LOAD_NORMAL, - true /* privacy_mode_enabled */, net::NetworkIsolationKey()); + network_context->PreconnectSockets(4, test_server.base_url(), + /*allow_credentials=*/true, + net::NetworkIsolationKey()); connection_listener.WaitForAcceptedConnections(4u); @@ -3598,9 +3598,9 @@ GetSocketPoolInfo(network_context.get(), "max_sockets_per_group"); EXPECT_GT(76, max_num_sockets); - network_context->PreconnectSockets( - 76, test_server.base_url(), net::LOAD_NORMAL, - true /* privacy_mode_enabled */, net::NetworkIsolationKey()); + network_context->PreconnectSockets(76, test_server.base_url(), + /*allow_credentials=*/true, + net::NetworkIsolationKey()); // Wait until |max_num_sockets| have been connected. connection_listener.WaitForAcceptedConnections(max_num_sockets); @@ -3635,11 +3635,9 @@ const net::NetworkIsolationKey kKey1(kOriginFoo, kOriginFoo); const net::NetworkIsolationKey kKey2(kOriginBar, kOriginBar); network_context->PreconnectSockets(1, test_server.base_url(), - net::LOAD_NORMAL, - true /* privacy_mode_enabled */, kKey1); + /*allow_credentials=*/false, kKey1); network_context->PreconnectSockets(2, test_server.base_url(), - net::LOAD_NORMAL, - true /* privacy_mode_enabled */, kKey2); + /*allow_credentials=*/false, kKey2); connection_listener.WaitForAcceptedConnections(3u); net::ClientSocketPool::GroupId group_id1(
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index d2241b8c..549fe42 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -646,7 +646,7 @@ static base::debug::CrashKeyString* time_key = base::debug::AllocateCrashKeyString("time_since_dump_request_ms", base::debug::CrashKeySize::Size32); - base::debug::ScopedCrashKeyString( + base::debug::ScopedCrashKeyString scoped_time( time_key, base::NumberToString( (base::Time::Now() - dump_request_time).InMilliseconds())); base::debug::DumpWithoutCrashing();
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index afa8aaf..59c05e85 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -903,18 +903,14 @@ // Tries to preconnect to |url|. |num_streams| may be used to request more // than one connection be established in parallel. - // |load_flags| is passed into the HttpRequestInfo used to make the request. - // See |load_flags.h| for possible values. - // |privacy_mode_enabled| is also passed into the HttpRequestInfo class: if - // it is true, then the request must be sent over a connection that cannot be - // tracked by the server. + // |allow_credentials| is true if the connection is to be pooled with + // credentialed requests and false otherwise. // |network_isolation_key| specifies the NetworkIsolationKey to associate // with the preconnected sockets. The sockets will only be used for requests // associated with the same key. PreconnectSockets(uint32 num_streams, url.mojom.Url url, - int32 load_flags, - bool privacy_mode_enabled, + bool allow_credentials, NetworkIsolationKey network_isolation_key); // Creates a P2PSocketManager instance, used for WebRTC.
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index 99aef1f..c2c3f63 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h
@@ -196,8 +196,7 @@ void PreconnectSockets( uint32_t num_streams, const GURL& url, - int32_t load_flags, - bool privacy_mode_enabled, + bool allow_credentials, const net::NetworkIsolationKey& network_isolation_key) override {} void CreateP2PSocketManager( mojom::P2PTrustedSocketManagerClientPtr client,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 36d87d7d..2d59808 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -25,7 +25,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "version:1.6" + "revision": "version:1.7" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 555ca87..557e3a5f 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -74,7 +74,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "version:1.6" + "revision": "version:1.7" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -221,7 +221,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "version:1.6" + "revision": "version:1.7" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -366,7 +366,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "version:1.6" + "revision": "version:1.7" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -511,7 +511,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "version:1.6" + "revision": "version:1.7" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -26234,7 +26234,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "version:1.6" + "revision": "version:1.7" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.dawn.json b/testing/buildbot/chromium.dawn.json index 61e83bf..239b319 100644 --- a/testing/buildbot/chromium.dawn.json +++ b/testing/buildbot/chromium.dawn.json
@@ -123,8 +123,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "external/wpt/webgpu/", "--no-xvfb" ], @@ -269,8 +269,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "external/wpt/webgpu/", "--no-xvfb" ], @@ -563,8 +563,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "external/wpt/webgpu/" ], "isolate_name": "blink_web_tests_exparchive", @@ -703,8 +703,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "external/wpt/webgpu/" ], "isolate_name": "blink_web_tests_exparchive", @@ -990,8 +990,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "-t", "Release_x64", "external/wpt/webgpu/" @@ -1136,8 +1136,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "-t", "Release_x64", "external/wpt/webgpu/" @@ -1426,8 +1426,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "external/wpt/webgpu/" ], "isolate_name": "blink_web_tests_exparchive", @@ -1570,8 +1570,8 @@ "--additional-driver-flag", "--disable-gpu-sandbox", "--driver-logging", - "--skipped", - "ignore", + "--ignore-default-expectations", + "--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations", "external/wpt/webgpu/" ], "isolate_name": "blink_web_tests_exparchive",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 051dc97..c75d79a 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -1019,7 +1019,7 @@ } ] }, - "WebKit Linux layout_ng Dummy Builder": { + "WebKit Linux layout_ng_disabled Builder": { "gtest_tests": [ { "args": [
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 035cdcf..c071ad7f 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -1026,7 +1026,7 @@ 'win10-blink-rel-dummy', 'Dummy WebKit Mac10.13', 'WebKit Linux composite_after_paint Dummy Builder', - 'WebKit Linux layout_ng Dummy Builder', + 'WebKit Linux layout_ng_disabled Builder', # chromium, due to https://crbug.com/878915 'win-dbg', 'win32-dbg',
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 98a7ecf..22712e1 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1859,7 +1859,7 @@ '--additional-driver-flag=--enable-blink-features=CompositeAfterPaint', ], }, - 'WebKit Linux layout_ng Dummy Builder': { + 'WebKit Linux layout_ng_disabled Builder': { 'args': [ '--additional-driver-flag=--disable-blink-features=LayoutNG', ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index c55c3155..a95ec7d 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3975,9 +3975,12 @@ '--additional-driver-flag', '--enable-unsafe-webgpu', '--additional-driver-flag', '--disable-gpu-sandbox', '--driver-logging', - # These tests are skipped by default. Since we run with - # --enable-unsafe-webgpu, ignore the Skip expectation. - '--skipped', 'ignore', + '--ignore-default-expectations', + '--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations', + # TODO(crbug.com/984815): Use --isolated-script-test-filter to select + # webgpu tests, instead of just the file path, so retries (which just + # append the specific test path to the end of this command line) work + # correctly instead of also running the whole rest of the test suite. 'external/wpt/webgpu/', ], 'linux_args': [ '--no-xvfb' ], @@ -3998,10 +4001,13 @@ '--additional-driver-flag', '--enable-unsafe-webgpu', '--additional-driver-flag', '--disable-gpu-sandbox', '--driver-logging', - # These tests are skipped by default. Since we run with - # --enable-unsafe-webgpu, ignore the Skip expectation. - '--skipped', 'ignore', + '--ignore-default-expectations', + '--additional-expectations=../../third_party/blink/web_tests/WebGPUExpectations', '-t', 'Release_x64', + # TODO(crbug.com/984815): Use --isolated-script-test-filter to select + # webgpu tests, instead of just the file path, so retries (which just + # append the specific test path to the end of this command line) work + # correctly instead of also running the whole rest of the test suite. 'external/wpt/webgpu/', ], 'merge': { @@ -4736,7 +4742,7 @@ { "cipd_package": 'chromium/android_webview/tools/cts_archive', 'location': 'android_webview/tools/cts_archive', - 'revision': 'version:1.6', + 'revision': 'version:1.7', } ] },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index d811f819..8c27157 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1440,7 +1440,7 @@ 'isolated_scripts': 'chromium_webkit_isolated_scripts', }, }, - 'WebKit Linux layout_ng Dummy Builder': { + 'WebKit Linux layout_ng_disabled Builder': { 'mixins': [ 'linux-xenial', ],
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 303f16f..ed9e3dd 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1833,6 +1833,21 @@ ] } ], + "DeferAllScript": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "DeferAllScriptPreviews_Enabled_20190814", + "enable_features": [ + "DeferAllScript" + ] + } + ] + } + ], "DialMediaRouteProvider": [ { "platforms": [ @@ -2531,6 +2546,25 @@ ] } ], + "GpuWatchdogV2": [ + { + "platforms": [ + "android", + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "GpuWatchdogV2" + ] + } + ] + } + ], "GridLayoutForNtpShortcuts": [ { "platforms": [ @@ -3866,7 +3900,7 @@ ], "experiments": [ { - "name": "AndroidExperiments", + "name": "Enabled", "enable_features": [ "OmniboxGroupSuggestionsBySearchVsUrl" ]
diff --git a/third_party/.gitignore b/third_party/.gitignore index e1b200c7..4a0d413a 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -44,6 +44,7 @@ /boringssl/src /bouncycastle/lib/ /breakpad/breakpad +/byte_buddy/android_sdk_build_tools_25_0_2 /byte_buddy/lib/ /cacheinvalidation/cacheinvalidation_unittests_run.xml /cardboard-java/src
diff --git a/third_party/android_sdk/OWNERS b/third_party/android_sdk/OWNERS index f2b992a..0faedf1d 100644 --- a/third_party/android_sdk/OWNERS +++ b/third_party/android_sdk/OWNERS
@@ -7,3 +7,5 @@ wangxianzhu@chromium.org wnwen@chromium.org yfriedman@chromium.org +# COMPONENT: Infra>Client>Chrome +# TEAM: chromium-reviews@chromium.org
diff --git a/third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom b/third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom index 9ea7916..938e73fb 100644 --- a/third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom +++ b/third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom
@@ -6,10 +6,31 @@ import "mojo/public/mojom/base/file_error.mojom"; -// This struct represents errors as they are reported by various methods in the -// Native File System API. For now this is just a base FileError, but not all -// errors can be easily represented by that, and some errors could use a more -// descriptive string, so in the future this struct will likely change. +// Always returned as a member of a NativeFileSystemError, which is declared below. +enum NativeFileSystemStatus { + kOk, + // The website doesn't/didn't have permission to do what it tried to do. + kPermissionDenied, + // The object being operated on was in an invalid state for the operation. + kInvalidState, + // An invalid argument was passed to a method. + kInvalidArgument, + // The operation failed for some unspecified reason. + kOperationFailed, + // The operation was aborted by the user. + kOperationAborted, + // The operation failed with a mojom_base.mojom.FileError describing the + // underlying cause. + kFileError, +}; + +// Errors reported by Native File System API methods. struct NativeFileSystemError { - mojo_base.mojom.FileError error_code; -}; \ No newline at end of file + NativeFileSystemStatus status; + // Only meaningful when |status| is kFileError. + // Conceptually, this should be an optional member, but mojo does not + // currently support optionals. + mojo_base.mojom.FileError file_error; + // Optional extra information describing the error. + string message; +};
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py b/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py index 12ba24d..caefbe3 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/__init__.py
@@ -14,13 +14,13 @@ this_dir = os.path.dirname(__file__) root_dir = os.path.join(this_dir, *(['..'] * expected_path.count('/'))) sys.path = [ + # //third_party/blink/renderer/build/scripts/blinkbuild + os.path.join(root_dir, 'third_party', 'blink', 'renderer', 'build', + 'scripts'), # //third_party/ply os.path.join(root_dir, 'third_party'), # //tools/idl_parser os.path.join(root_dir, 'tools'), - # //third_party/blink/renderer/build/scripts/blinkbuild - os.path.join(root_dir, 'third_party', 'blink', 'renderer', 'build', - 'scripts'), ] + sys.path
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/reference.py b/third_party/blink/renderer/bindings/scripts/web_idl/reference.py index 895d002b..9870ecca 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/reference.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/reference.py
@@ -35,17 +35,29 @@ self._target_attrs_with_priority = target_attrs_with_priority def __getattr__(self, attribute): - target_object = object.__getattribute__(self, '_target_object') - target_attrs = object.__getattribute__(self, '_target_attrs') + try: + target_object = object.__getattribute__(self, '_target_object') + target_attrs = object.__getattribute__(self, '_target_attrs') + except AttributeError: + # When unpickling, __init__ does not get called. _target_object is + # not defined yet during unpickling. Then, just fallback to the + # default access. + return object.__getattribute__(self, attribute) assert target_object is not None if target_attrs is None or attribute in target_attrs: return getattr(target_object, attribute) raise AttributeError def __getattribute__(self, attribute): - target_object = object.__getattribute__(self, '_target_object') - target_attrs = object.__getattribute__(self, - '_target_attrs_with_priority') + try: + target_object = object.__getattribute__(self, '_target_object') + target_attrs = object.__getattribute__( + self, '_target_attrs_with_priority') + except AttributeError: + # When unpickling, __init__ does not get called. _target_object is + # not defined yet during unpickling. Then, just fallback to the + # default access. + return object.__getattribute__(self, attribute) # It's okay to access own attributes, such as 'identifier', even when # the target object is not yet resolved. if target_object is None:
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h index 78ab3c3..70a3ae1 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.h +++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -76,6 +76,10 @@ virtual bool IsBinaryOperation() const { return false; } virtual bool IsVariadicOperation() const { return false; } + bool IsMathFunction() const { + return !IsNumericLiteral() && !IsBinaryOperation(); + } + virtual bool IsZero() const = 0; // Resolves the expression into one value *without doing any type conversion*.
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.cc b/third_party/blink/renderer/core/css/css_math_function_value.cc index d2d9674..8a267e556 100644 --- a/third_party/blink/renderer/core/css/css_math_function_value.cc +++ b/third_party/blink/renderer/core/css/css_math_function_value.cc
@@ -97,7 +97,13 @@ } String CSSMathFunctionValue::CustomCSSText() const { - return BuildCSSText(expression_->CustomCSSText()); + const String& expression_text = expression_->CustomCSSText(); + if (expression_->IsMathFunction()) { + // If |expression_| is already a math function (e.g., min/max), we don't + // need to wrap it in |calc()|. + return expression_text; + } + return BuildCSSText(expression_text); } bool CSSMathFunctionValue::Equals(const CSSMathFunctionValue& other) const {
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 c473019..d44159e1 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
@@ -982,11 +982,8 @@ return 0; } const auto& primitive_value = To<CSSPrimitiveValue>(value); - double result = - primitive_value.ComputeLength<double>(state.CssToLengthConversionData()); - return clampTo<float>(RoundForImpreciseConversion<float>(result), - defaultMinimumForClamp<float>(), - defaultMaximumForClamp<float>()); + return primitive_value.ComputeLength<float>( + state.CssToLengthConversionData()); } GapLength StyleBuilderConverter::ConvertGapLength(StyleResolverState& state,
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc index 5deeff34..3b314e2b 100644 --- a/third_party/blink/renderer/core/css/rule_feature_set.cc +++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -1018,6 +1018,7 @@ pseudo_invalidation_sets_.clear(); universal_sibling_invalidation_set_ = nullptr; nth_invalidation_set_ = nullptr; + type_rule_invalidation_set_ = nullptr; viewport_dependent_media_query_results_.clear(); device_dependent_media_query_results_.clear(); }
diff --git a/third_party/blink/renderer/core/events/portal_activate_event.cc b/third_party/blink/renderer/core/events/portal_activate_event.cc index 7243a1a..1b34ff4c 100644 --- a/third_party/blink/renderer/core/events/portal_activate_event.cc +++ b/third_party/blink/renderer/core/events/portal_activate_event.cc
@@ -107,6 +107,7 @@ void PortalActivateEvent::Trace(blink::Visitor* visitor) { Event::Trace(visitor); visitor->Trace(document_); + visitor->Trace(adopted_portal_); visitor->Trace(data_); visitor->Trace(ports_); visitor->Trace(data_from_init_); @@ -127,14 +128,27 @@ return nullptr; } - HTMLPortalElement* portal = MakeGarbageCollected<HTMLPortalElement>( + DCHECK(!adopted_portal_); + adopted_portal_ = MakeGarbageCollected<HTMLPortalElement>( *document_, predecessor_portal_token_, std::move(predecessor_portal_), std::move(predecessor_portal_client_receiver_)); std::move(on_portal_activated_callback_).Run(true); - return portal; + return adopted_portal_; } -void PortalActivateEvent::DetachPortalIfNotAdopted() { +void PortalActivateEvent::ExpireAdoptionLifetime() { + // End the special privilege associated with any adopted portals. + // This may destroy the guest contents. + if (adopted_portal_) { + adopted_portal_->ExpireAdoptionLifetime(); + + // We no longer need to hold the adopted portal, so stop drop the GC + // reference. + adopted_portal_ = nullptr; + } + + // End the special privilege associated with the predecessor contents if it + // was not adopted. This may destroy the guest contents. if (predecessor_portal_) { std::move(on_portal_activated_callback_).Run(false); predecessor_portal_.reset();
diff --git a/third_party/blink/renderer/core/events/portal_activate_event.h b/third_party/blink/renderer/core/events/portal_activate_event.h index 5c7f209f..7e7b67b 100644 --- a/third_party/blink/renderer/core/events/portal_activate_event.h +++ b/third_party/blink/renderer/core/events/portal_activate_event.h
@@ -72,10 +72,14 @@ ScriptValue data(ScriptState*); HTMLPortalElement* adoptPredecessor(ExceptionState& exception_state); - void DetachPortalIfNotAdopted(); + // Invoked when this event should no longer keep its guest contents alive + // due to the portalactivate event. + void ExpireAdoptionLifetime(); private: Member<Document> document_; + Member<HTMLPortalElement> adopted_portal_; + base::UnguessableToken predecessor_portal_token_; mojo::AssociatedRemote<mojom::blink::Portal> predecessor_portal_; mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
diff --git a/third_party/blink/renderer/core/frame/link_highlights.h b/third_party/blink/renderer/core/frame/link_highlights.h index 967bed18..e613f1e 100644 --- a/third_party/blink/renderer/core/frame/link_highlights.h +++ b/third_party/blink/renderer/core/frame/link_highlights.h
@@ -68,6 +68,7 @@ FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, multipleHighlights); FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, HighlightLayerEffectNode); FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, MultiColumn); + FRIEND_TEST_ALL_PREFIXES(LinkHighlightSquashingImplTest, SquashingLayer); void RemoveAllHighlights();
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 903494b..85481bb0 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2585,11 +2585,15 @@ GetFrame()->DomWindow()->DispatchEvent(*event); if (debugger) debugger->ExternalAsyncTaskFinished(blink_data.sender_stack_trace_id); - event->DetachPortalIfNotAdopted(); + event->ExpireAdoptionLifetime(); // After dispatching the portalactivate event, we check to see if we need to // cleanup the portal hosting the predecessor. If the portal was created, // but wasn't inserted or activated, we destroy it. + // + // TODO(jbroman): This should probably be done as part of + // ExpireAdoptionLifetime, now that the event knows about the adopted + // HTMLPortalElement explicitly. HTMLPortalElement* portal_element = DocumentPortals::From(*(GetFrame()->GetDocument())) .GetPortal(portal_token);
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index a74ab225..93801116 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -120,10 +120,6 @@ return IsLink() || HTMLElement::SupportsFocus(); } -bool HTMLAnchorElement::MatchesEnabledPseudoClass() const { - return IsLink(); -} - bool HTMLAnchorElement::ShouldHaveFocusAppearance() const { return (GetDocument().LastFocusType() != kWebFocusTypeMouse) || HTMLElement::SupportsFocus();
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.h b/third_party/blink/renderer/core/html/html_anchor_element.h index fd135ee..402055f 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.h +++ b/third_party/blink/renderer/core/html/html_anchor_element.h
@@ -104,7 +104,6 @@ protected: void ParseAttribute(const AttributeModificationParams&) override; bool SupportsFocus() const override; - bool MatchesEnabledPseudoClass() const override; private: void AttributeChanged(const AttributeModificationParams&) override;
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc index babc141..5711b249 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -55,6 +55,12 @@ remote_portal_(std::move(remote_portal)), portal_client_receiver_(this, std::move(portal_client_receiver)) { if (remote_portal_) { + was_just_adopted_ = true; + + DCHECK(CanHaveGuestContents()) + << "<portal> element was created with an existing contents but is not " + "permitted to have one"; + // If the portal element hosts a predecessor from activation, it can be // activated before being inserted into the DOM, and we need to keep track // of it from creation. @@ -78,6 +84,29 @@ portal_client_receiver_.reset(); } +void HTMLPortalElement::ExpireAdoptionLifetime() { + was_just_adopted_ = false; +} + +// https://wicg.github.io/portals/#htmlportalelement-may-have-a-guest-browsing-context +HTMLPortalElement::GuestContentsEligibility +HTMLPortalElement::GetGuestContentsEligibility() const { + // Non-HTML documents aren't eligible at all. + if (!GetDocument().IsHTMLDocument()) + return GuestContentsEligibility::kIneligible; + + LocalFrame* frame = GetDocument().GetFrame(); + const bool is_connected = frame && isConnected(); + if (!is_connected && !was_just_adopted_) + return GuestContentsEligibility::kIneligible; + + const bool is_top_level = frame && frame->IsMainFrame(); + if (!is_top_level) + return GuestContentsEligibility::kNotTopLevel; + + return GuestContentsEligibility::kEligible; +} + void HTMLPortalElement::Navigate() { KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr); if (!remote_portal_ || url.IsEmpty()) @@ -304,18 +333,20 @@ ContainerNode& node) { auto result = HTMLFrameOwnerElement::InsertedInto(node); - if (!node.IsInDocumentTree() || !GetDocument().IsHTMLDocument() || - !GetDocument().GetFrame()) - return result; + switch (GetGuestContentsEligibility()) { + case GuestContentsEligibility::kIneligible: + return result; - // We don't support embedding portals in nested browsing contexts. - if (!GetDocument().GetFrame()->IsMainFrame()) { - GetDocument().AddConsoleMessage(ConsoleMessage::Create( - mojom::ConsoleMessageSource::kRendering, - mojom::ConsoleMessageLevel::kWarning, - "Cannot use <portal> in a nested browsing context.")); - return result; - } + case GuestContentsEligibility::kNotTopLevel: + GetDocument().AddConsoleMessage(ConsoleMessage::Create( + mojom::ConsoleMessageSource::kRendering, + mojom::ConsoleMessageLevel::kWarning, + "Cannot use <portal> in a nested browsing context.")); + return result; + + case GuestContentsEligibility::kEligible: + break; + }; if (remote_portal_) { // The interface is already bound if the HTMLPortalElement is adopting the
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h index 32fb107..4fa8300 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.h +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -79,7 +79,26 @@ // terminate the portal interface. void ConsumePortal(); + // Invoked when this element should no longer keep its guest contents alive + // due to recent adoption. + void ExpireAdoptionLifetime(); + private: + enum class GuestContentsEligibility { + // Can have a guest contents. + kEligible, + + // Would be eligible except that it is not top-level. + kNotTopLevel, + + // Ineligible for additional reasons. + kIneligible, + }; + GuestContentsEligibility GetGuestContentsEligibility() const; + bool CanHaveGuestContents() const { + return GetGuestContentsEligibility() == GuestContentsEligibility::kEligible; + } + // Navigates the portal to |url_|. void Navigate(); @@ -115,6 +134,9 @@ mojo::AssociatedRemote<mojom::blink::Portal> remote_portal_; mojo::AssociatedReceiver<mojom::blink::PortalClient> portal_client_receiver_; + + // Temporarily set to keep this element alive after adoption. + bool was_just_adopted_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc index f577d13..5f3ae41 100644 --- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc +++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -242,14 +242,13 @@ FloatQuad transformed_quad = paint_invalidation_container.AbsoluteToLocalQuad( absolute_quad, kTraverseDocumentBoundaries); - PhysicalOffset offset_to_backing; - PaintLayer::MapPointInPaintInvalidationContainerToBacking( - paint_invalidation_container, offset_to_backing); + PaintLayer::MapQuadInPaintInvalidationContainerToBacking( + paint_invalidation_container, transformed_quad); // Adjust for offset from LayoutObject. - offset_to_backing -= - PhysicalOffset(current_graphics_layer_->OffsetFromLayoutObject()); + PhysicalOffset offset_to_backing = + PhysicalOffset(-current_graphics_layer_->OffsetFromLayoutObject()); transformed_quad.Move(FloatSize(offset_to_backing));
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc index d13204e3..e2059928 100644 --- a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc +++ b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -425,4 +425,103 @@ EXPECT_EQ(layer_count_before_highlight, ContentLayerCount()); } +class LinkHighlightSquashingImplTest : public testing::Test, + public PaintTestConfigurations { + protected: + GestureEventWithHitTestResults GetTargetedEvent( + WebGestureEvent& touch_event) { + WebGestureEvent scaled_event = TransformWebGestureEvent( + web_view_helper_.GetWebView()->MainFrameImpl()->GetFrameView(), + touch_event); + return web_view_helper_.GetWebView() + ->GetPage() + ->DeprecatedLocalMainFrame() + ->GetEventHandler() + .TargetGestureEvent(scaled_event, true); + } + + void SetUp() override { + WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase( + WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(), + WebString::FromUTF8("test_touch_link_highlight_squashing.html")); + web_view_helper_.InitializeAndLoad(url.GetString().Utf8()); + } + + void TearDown() override { + Platform::Current() + ->GetURLLoaderMockFactory() + ->UnregisterAllURLsAndClearMemoryCache(); + + // Ensure we fully clean up while scoped settings are enabled. Without this, + // garbage collection would occur after Scoped[setting]ForTest is out of + // scope, so the settings would not apply in some destructors. + web_view_helper_.Reset(); + ThreadState::Current()->CollectAllGarbageForTesting(); + } + + size_t ContentLayerCount() { + // paint_artifact_compositor()->EnableExtraDataForTesting() should be called + // before using this function. + DCHECK(paint_artifact_compositor()->GetExtraDataForTesting()); + return paint_artifact_compositor() + ->GetExtraDataForTesting() + ->content_layers.size(); + } + + PaintArtifactCompositor* paint_artifact_compositor() { + auto* local_frame_view = web_view_helper_.LocalMainFrame()->GetFrameView(); + return local_frame_view->GetPaintArtifactCompositor(); + } + + void UpdateAllLifecyclePhases() { + web_view_helper_.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases( + WebWidget::LifecycleUpdateReason::kTest); + } + + frame_test_helpers::WebViewHelper web_view_helper_; +}; + +INSTANTIATE_PAINT_TEST_SUITE_P(LinkHighlightSquashingImplTest); + +TEST_P(LinkHighlightSquashingImplTest, SquashingLayer) { + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + return; + + bool was_running_web_test = WebTestSupport::IsRunningWebTest(); + WebTestSupport::SetIsRunningWebTest(false); + int page_width = 640; + int page_height = 480; + WebViewImpl* web_view_impl = web_view_helper_.GetWebView(); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); + + paint_artifact_compositor()->EnableExtraDataForTesting(); + UpdateAllLifecyclePhases(); + size_t layer_count_before_highlight = ContentLayerCount(); + WebGestureEvent touch_event(WebInputEvent::kGestureShowPress, + WebInputEvent::kNoModifiers, + WebInputEvent::GetStaticTimeStampForTests(), + WebGestureDevice::kTouchscreen); + touch_event.SetPositionInWidget(WebFloatPoint(100, 100)); + + GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event); + Node* touch_node = web_view_impl->BestTapNode(targeted_event); + ASSERT_TRUE(touch_node); + + web_view_impl->EnableTapHighlightAtPoint(targeted_event); + // The highlight should create one additional layer. + EXPECT_EQ(layer_count_before_highlight + 1, ContentLayerCount()); + + auto& highlights = web_view_impl->GetPage()->GetLinkHighlights(); + auto* highlight = highlights.link_highlights_.at(0).get(); + ASSERT_TRUE(highlight); + + // Check that the link highlight cc layer has a cc effect property tree node. + EXPECT_EQ(1u, highlight->FragmentCountForTesting()); + auto* layer = highlight->LayerForTesting(0); + + EXPECT_EQ(gfx::Size(256, 256), layer->bounds()); + + WebTestSupport::SetIsRunningWebTest(was_running_web_test); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index aa17abe..b17fdf7 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -600,6 +600,31 @@ point -= PhysicalOffset(squashing_layer->GetOffsetFromTransformNode()); } +void PaintLayer::MapQuadInPaintInvalidationContainerToBacking( + const LayoutBoxModelObject& paint_invalidation_container, + FloatQuad& quad) { + PaintLayer* paint_invalidation_layer = paint_invalidation_container.Layer(); + if (!paint_invalidation_layer->GroupedMapping()) + return; + + GraphicsLayer* squashing_layer = + paint_invalidation_layer->GroupedMapping()->SquashingLayer(); + + PropertyTreeState source_state = + paint_invalidation_container.FirstFragment().LocalBorderBoxProperties(); + PropertyTreeState dest_state = squashing_layer->GetPropertyTreeState(); + + // Move the rect into the source_state transform space, map to dest_state + // transform space, then move into squashing layer state. + quad.Move( + FloatSize(paint_invalidation_container.FirstFragment().PaintOffset())); + GeometryMapper::SourceToDestinationProjection(source_state.Transform(), + dest_state.Transform()) + .MapQuad(quad); + quad.Move( + -ToFloatSize(FloatPoint(squashing_layer->GetOffsetFromTransformNode()))); +} + void PaintLayer::DirtyVisibleContentStatus() { MarkAncestorChainForFlagsUpdate(); // Non-self-painting layers paint into their ancestor layer, and count as part
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 8ed44402..cf858801 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -587,6 +587,9 @@ static void MapPointInPaintInvalidationContainerToBacking( const LayoutBoxModelObject& paint_invalidation_container, PhysicalOffset&); + static void MapQuadInPaintInvalidationContainerToBacking( + const LayoutBoxModelObject& paint_invalidation_container, + FloatQuad&); bool PaintsWithTransparency(GlobalPaintFlags global_paint_flags) const { return IsTransparent() && !PaintsIntoOwnBacking(global_paint_flags);
diff --git a/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html b/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html new file mode 100644 index 0000000..a2f5d90 --- /dev/null +++ b/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> + +<style> + .abs { + position: absolute; + top: 5; + left: 5; + width: 512px; + height: 512px; + } + + #target { + display: block; + transform: scale(0.5); + transform-origin: left top; + background-color: green; + } +</style> +<div class=abs style="will-change: transform; pointer-events: none;"></div> +<a class=abs id=target href="javascript:void(0)"></a>
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 866b559..47046d0 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -613,6 +613,14 @@ return true; } + // Ignore continuations, since those are essentially duplicate copies + // of inline nodes with blocks inside. + if (layout_object_->IsElementContinuation()) { + if (ignored_reasons) + ignored_reasons->push_back(IgnoredReason(kAXUninteresting)); + return true; + } + // Check first if any of the common reasons cause this element to be ignored. AXObjectInclusion default_inclusion = DefaultObjectInclusion(ignored_reasons); if (default_inclusion == kIncludeObject) @@ -633,14 +641,6 @@ return true; } - // Ignore continuations, since those are essentially duplicate copies - // of inline nodes with blocks inside. - if (layout_object_->IsElementContinuation()) { - if (ignored_reasons) - ignored_reasons->push_back(IgnoredReason(kAXUninteresting)); - return true; - } - // A LayoutEmbeddedContent is an iframe element or embedded object element or // something like that. We don't want to ignore those. if (layout_object_->IsLayoutEmbeddedContent()) @@ -2055,8 +2055,12 @@ if (IsDetached()) return; + // Avoid calling AXNodeObject logic for continuations. + bool is_continuation = layout_object_->IsElementContinuation(); + if (auto* element = DynamicTo<Element>(GetNode())) { - if (!IsA<HTMLMapElement>( + if (!is_continuation && + !IsA<HTMLMapElement>( *element) && // Handled in AddImageMapChildren (img) !IsHTMLRubyElement(*element) && // Special layout handling !IsHTMLTableElement(*element) && // thead/tfoot move around @@ -2076,10 +2080,8 @@ ComputeAriaOwnsChildren(owned_children); for (AXObject* obj = RawFirstChild(); obj; obj = obj->RawNextSibling()) { - if (!AXObjectCache().IsAriaOwned(obj)) { - obj->SetParent(this); + if (!AXObjectCache().IsAriaOwned(obj)) AddChild(obj); - } } AddHiddenChildren(); @@ -2091,8 +2093,11 @@ AddAccessibleNodeChildren(); for (const auto& child : children_) { - if (!child->CachedParentObject()) + if (!is_continuation && !child->CachedParentObject()) { + // Never set continuations as a parent object. The first layout object + // in the chain must be used instead. child->SetParent(this); + } } for (const auto& owned_child : owned_children)
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc index 9085fff..59dbf92 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -268,7 +268,7 @@ WebFeature::kFileAccessedDatabase); } - if (!AllowIndexedDB(ExecutionContext::From(script_state))) { + if (!CachedAllowIndexedDB(script_state)) { request->HandleResponse(MakeGarbageCollected<DOMException>( DOMExceptionCode::kUnknownError, kPermissionDeniedErrorMessage)); return request; @@ -330,7 +330,7 @@ script_state, database_callbacks, std::move(transaction_backend), transaction_id, version, std::move(metrics)); - if (!AllowIndexedDB(ExecutionContext::From(script_state))) { + if (!CachedAllowIndexedDB(script_state)) { request->HandleResponse(MakeGarbageCollected<DOMException>( DOMExceptionCode::kUnknownError, kPermissionDeniedErrorMessage)); return request; @@ -397,7 +397,7 @@ script_state, nullptr, /*IDBTransactionAssociatedPtr=*/nullptr, 0, IDBDatabaseMetadata::kDefaultVersion, std::move(metrics)); - if (!AllowIndexedDB(ExecutionContext::From(script_state))) { + if (!CachedAllowIndexedDB(script_state)) { request->HandleResponse(MakeGarbageCollected<DOMException>( DOMExceptionCode::kUnknownError, kPermissionDeniedErrorMessage)); return request; @@ -444,7 +444,8 @@ return static_cast<int16_t>(first->Compare(second.get())); } -bool IDBFactory::AllowIndexedDB(ExecutionContext* execution_context) { +bool IDBFactory::AllowIndexedDB(ScriptState* script_state) { + ExecutionContext* execution_context = ExecutionContext::From(script_state); DCHECK(execution_context->IsContextThread()); SECURITY_DCHECK(execution_context->IsDocument() || execution_context->IsWorkerGlobalScope()); @@ -453,6 +454,7 @@ if (!frame) return false; if (auto* settings_client = frame->GetContentSettingsClient()) { + // This triggers a sync IPC. return settings_client->AllowIndexedDB( WebSecurityOrigin(execution_context->GetSecurityOrigin())); } @@ -463,8 +465,17 @@ To<WorkerGlobalScope>(execution_context)->ContentSettingsClient(); if (!content_settings_client) return true; + // This triggers a sync IPC. return content_settings_client->AllowIndexedDB( WebSecurityOrigin(execution_context->GetSecurityOrigin())); } +bool IDBFactory::CachedAllowIndexedDB(ScriptState* script_state) { + if (!cached_allowed_.has_value()) { + // Cache the AllowIndexedDB() call because it triggers a sync IPC. + cached_allowed_.emplace(AllowIndexedDB(script_state)); + } + return cached_allowed_.value(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.h b/third_party/blink/renderer/modules/indexeddb/idb_factory.h index 26268cc..f9036267 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_factory.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.h
@@ -84,9 +84,11 @@ ExceptionState&, bool); - bool AllowIndexedDB(ExecutionContext* execution_context); + bool AllowIndexedDB(ScriptState* script_state); + bool CachedAllowIndexedDB(ScriptState* script_state); std::unique_ptr<WebIDBFactory> web_idb_factory_; + base::Optional<bool> cached_allowed_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_controller.cc b/third_party/blink/renderer/modules/mediastream/user_media_controller.cc index 10de2d4..0df4e46 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_controller.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_controller.cc
@@ -29,27 +29,33 @@ const char UserMediaController::kSupplementName[] = "UserMediaController"; -UserMediaController::UserMediaController( - LocalFrame& frame, - std::unique_ptr<UserMediaClient> client) +UserMediaController::UserMediaController(LocalFrame& frame) : Supplement<LocalFrame>(frame), - ContextLifecycleObserver(frame.GetDocument()), - client_(std::move(client)) {} + ContextLifecycleObserver(frame.GetDocument()) {} void UserMediaController::Trace(blink::Visitor* visitor) { Supplement<LocalFrame>::Trace(visitor); ContextLifecycleObserver::Trace(visitor); } +UserMediaClient* UserMediaController::Client() { + if (!client_) { + client_ = std::make_unique<UserMediaClient>( + GetFrame(), GetFrame()->GetTaskRunner(TaskType::kInternalMedia)); + } + + return client_.get(); +} + void UserMediaController::ContextDestroyed(ExecutionContext*) { + if (!client_) + return; client_->ContextDestroyed(); } -void ProvideUserMediaTo(LocalFrame& frame, - std::unique_ptr<UserMediaClient> client) { +void ProvideUserMediaTo(LocalFrame& frame) { UserMediaController::ProvideTo( - frame, - MakeGarbageCollected<UserMediaController>(frame, std::move(client))); + frame, MakeGarbageCollected<UserMediaController>(frame)); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_controller.h b/third_party/blink/renderer/modules/mediastream/user_media_controller.h index 1a24cc57..095f5c9 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_controller.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_controller.h
@@ -46,10 +46,10 @@ public: static const char kSupplementName[]; - UserMediaController(LocalFrame&, std::unique_ptr<UserMediaClient>); + UserMediaController(LocalFrame&); void Trace(blink::Visitor*) override; - UserMediaClient* Client() const { return client_.get(); } + UserMediaClient* Client(); void RequestUserMedia(UserMediaRequest*); void CancelUserMediaRequest(UserMediaRequest*); @@ -70,30 +70,29 @@ }; inline void UserMediaController::RequestUserMedia(UserMediaRequest* request) { - client_->RequestUserMedia(request); + Client()->RequestUserMedia(request); has_requested_user_media_ = true; } inline void UserMediaController::CancelUserMediaRequest( UserMediaRequest* request) { - client_->CancelUserMediaRequest(WebUserMediaRequest(request)); + Client()->CancelUserMediaRequest(WebUserMediaRequest(request)); } inline void UserMediaController::ApplyConstraints( ApplyConstraintsRequest* request) { - client_->ApplyConstraints(WebApplyConstraintsRequest(request)); + Client()->ApplyConstraints(WebApplyConstraintsRequest(request)); } inline void UserMediaController::StopTrack(MediaStreamComponent* track) { - client_->StopTrack(WebMediaStreamTrack(track)); + Client()->StopTrack(WebMediaStreamTrack(track)); } inline bool UserMediaController::HasRequestedUserMedia() { return has_requested_user_media_; } -MODULES_EXPORT void ProvideUserMediaTo(LocalFrame&, - std::unique_ptr<UserMediaClient>); +MODULES_EXPORT void ProvideUserMediaTo(LocalFrame&); } // namespace blink
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index ae1a3572..6e599c2 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -181,9 +181,7 @@ DCHECK(client); ProvidePushMessagingClientTo( frame, MakeGarbageCollected<PushMessagingClient>(frame)); - ProvideUserMediaTo( - frame, std::make_unique<UserMediaClient>( - &frame, frame.GetTaskRunner(TaskType::kInternalMedia))); + ProvideUserMediaTo(frame); ProvideLocalFileSystemTo(frame, std::make_unique<LocalFileSystemClient>()); ScreenOrientationControllerImpl::ProvideTo(frame);
diff --git a/third_party/blink/renderer/modules/native_file_system/BUILD.gn b/third_party/blink/renderer/modules/native_file_system/BUILD.gn index 3fa676a9..40f5865 100644 --- a/third_party/blink/renderer/modules/native_file_system/BUILD.gn +++ b/third_party/blink/renderer/modules/native_file_system/BUILD.gn
@@ -10,6 +10,8 @@ "native_file_system_directory_handle.h", "native_file_system_directory_iterator.cc", "native_file_system_directory_iterator.h", + "native_file_system_error.cc", + "native_file_system_error.h", "native_file_system_file_handle.cc", "native_file_system_file_handle.h", "native_file_system_handle.cc",
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc index aaa45db..4e6d5dc 100644 --- a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
@@ -14,6 +14,7 @@ #include "third_party/blink/renderer/modules/native_file_system/file_system_get_file_options.h" #include "third_party/blink/renderer/modules/native_file_system/file_system_remove_options.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h" +#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -49,19 +50,15 @@ ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->error_code == base::File::FILE_OK) { - resolver->Resolve( - MakeGarbageCollected<NativeFileSystemFileHandle>( - name, - RevocableInterfacePtr< - mojom::blink::NativeFileSystemFileHandle>( - handle.PassInterface(), - context->GetInterfaceInvalidator(), - context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); - } else { - resolver->Reject( - file_error::CreateDOMException(result->error_code)); + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, *result); + return; } + resolver->Resolve(MakeGarbageCollected<NativeFileSystemFileHandle>( + name, + RevocableInterfacePtr<mojom::blink::NativeFileSystemFileHandle>( + handle.PassInterface(), context->GetInterfaceInvalidator(), + context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); }, WrapPersistent(resolver), name)); @@ -84,19 +81,18 @@ ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->error_code == base::File::FILE_OK) { - resolver->Resolve( - MakeGarbageCollected<NativeFileSystemDirectoryHandle>( - name, - RevocableInterfacePtr< - mojom::blink::NativeFileSystemDirectoryHandle>( - handle.PassInterface(), - context->GetInterfaceInvalidator(), - context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); - } else { - resolver->Reject( - file_error::CreateDOMException(result->error_code)); + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, *result); + return; } + resolver->Resolve( + MakeGarbageCollected<NativeFileSystemDirectoryHandle>( + name, + RevocableInterfacePtr< + mojom::blink::NativeFileSystemDirectoryHandle>( + handle.PassInterface(), + context->GetInterfaceInvalidator(), + context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); }, WrapPersistent(resolver), name)); @@ -140,12 +136,7 @@ name, options->recursive(), WTF::Bind( [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result) { - if (result->error_code == base::File::FILE_OK) { - resolver->Resolve(); - } else { - resolver->Reject( - file_error::CreateDOMException(result->error_code)); - } + native_file_system_error::ResolveOrReject(resolver, *result); }, WrapPersistent(resolver))); @@ -180,18 +171,16 @@ ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->error_code == base::File::FILE_OK) { - resolver->Resolve( - MakeGarbageCollected<NativeFileSystemDirectoryHandle>( - kSandboxRootDirectoryName, - RevocableInterfacePtr< - mojom::blink::NativeFileSystemDirectoryHandle>( - handle.PassInterface(), - context->GetInterfaceInvalidator(), - context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); - } else { - resolver->Reject(file_error::CreateDOMException(result->error_code)); + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, *result); + return; } + resolver->Resolve(MakeGarbageCollected<NativeFileSystemDirectoryHandle>( + kSandboxRootDirectoryName, + RevocableInterfacePtr< + mojom::blink::NativeFileSystemDirectoryHandle>( + handle.PassInterface(), context->GetInterfaceInvalidator(), + context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); }, WrapPersistent(resolver), std::move(manager)));
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.cc index f0016994..b934f8d 100644 --- a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.cc +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator_entry.h" +#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -25,9 +26,11 @@ ScriptPromise NativeFileSystemDirectoryIterator::next( ScriptState* script_state) { - if (error_ != base::File::FILE_OK) { - return ScriptPromise::RejectWithDOMException( - script_state, file_error::CreateDOMException(error_)); + if (error_) { + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + auto result = resolver->Promise(); + native_file_system_error::Reject(resolver, *error_); + return result; } if (!entries_.IsEmpty()) { @@ -62,10 +65,10 @@ Vector<mojom::blink::NativeFileSystemEntryPtr> entries) { if (!GetExecutionContext()) return; - if (result->error_code != base::File::FILE_OK) { - error_ = result->error_code; + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + error_ = std::move(result); if (pending_next_) { - pending_next_->Reject(file_error::CreateDOMException(error_)); + native_file_system_error::Reject(pending_next_, *error_); pending_next_ = nullptr; } return;
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h index 65dcc19..93d5f13d 100644 --- a/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h
@@ -39,7 +39,7 @@ void OnGotEntries(mojom::blink::NativeFileSystemErrorPtr result, Vector<mojom::blink::NativeFileSystemEntryPtr> entries); - base::File::Error error_ = base::File::FILE_OK; + mojom::blink::NativeFileSystemErrorPtr error_; bool waiting_for_more_entries_ = true; HeapDeque<Member<NativeFileSystemHandle>> entries_; Member<ScriptPromiseResolver> pending_next_;
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc new file mode 100644 index 0000000..dcbbcc1 --- /dev/null +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc
@@ -0,0 +1,64 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" + +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" +#include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/core/fileapi/file_error.h" +#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h" +#include "third_party/blink/renderer/platform/heap/heap.h" + +namespace blink { +namespace native_file_system_error { + +void Reject(ScriptPromiseResolver* resolver, + const mojom::blink::NativeFileSystemError& error) { + DCHECK_NE(error.status, mojom::blink::NativeFileSystemStatus::kOk); + ResolveOrReject(resolver, error); +} + +void ResolveOrReject(ScriptPromiseResolver* resolver, + const mojom::blink::NativeFileSystemError& error) { + // Early exit if the resolver's context has been destroyed already. + if (!resolver->GetScriptState()->ContextIsValid()) + return; + auto* const isolate = resolver->GetScriptState()->GetIsolate(); + ScriptState::Scope scope(resolver->GetScriptState()); + + // Convert empty message to a null string, to make sure we get the default + // error message if no custom error message is provided. + const String message = error.message.IsEmpty() ? String() : error.message; + + switch (error.status) { + case mojom::blink::NativeFileSystemStatus::kOk: + resolver->Resolve(); + break; + case mojom::blink::NativeFileSystemStatus::kPermissionDenied: + resolver->Reject(V8ThrowDOMException::CreateOrEmpty( + isolate, DOMExceptionCode::kNotAllowedError, message)); + break; + case mojom::blink::NativeFileSystemStatus::kInvalidState: + resolver->Reject(V8ThrowDOMException::CreateOrEmpty( + isolate, DOMExceptionCode::kInvalidStateError, message)); + break; + case mojom::blink::NativeFileSystemStatus::kInvalidArgument: + resolver->Reject(V8ThrowException::CreateTypeError( + resolver->GetScriptState()->GetIsolate(), message)); + break; + case mojom::blink::NativeFileSystemStatus::kOperationFailed: + case mojom::blink::NativeFileSystemStatus::kOperationAborted: + resolver->Reject(V8ThrowDOMException::CreateOrEmpty( + isolate, DOMExceptionCode::kAbortError, message)); + break; + case mojom::blink::NativeFileSystemStatus::kFileError: + // TODO(mek): We might want to support custom messages for these cases. + resolver->Reject(file_error::CreateDOMException(error.file_error)); + break; + } +} + +} // namespace native_file_system_error +} // namespace blink
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h b/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h new file mode 100644 index 0000000..ea63282 --- /dev/null +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h
@@ -0,0 +1,28 @@ +// 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_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_ + +#include "base/files/file.h" +#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h" + +namespace blink { +class ScriptPromiseResolver; +namespace native_file_system_error { + +// Rejects |resolver| with an appropriate exception if |status| represents an +// error. Resolves |resolver| with undefined otherwise. +void ResolveOrReject(ScriptPromiseResolver* resolver, + const mojom::blink::NativeFileSystemError& status); + +// Rejects |resolver| with an appropriate exception if |status| represents an +// error. DCHECKs otherwise. +void Reject(ScriptPromiseResolver* resolver, + const mojom::blink::NativeFileSystemError& error); + +} // namespace native_file_system_error +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc index 2fbaf48f..bbf2221 100644 --- a/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/core/fileapi/file.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/modules/native_file_system/file_system_create_writer_options.h" +#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_writer.h" #include "third_party/blink/renderer/platform/file_metadata.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -41,17 +42,14 @@ ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->error_code == base::File::FILE_OK) { - resolver->Resolve(MakeGarbageCollected<NativeFileSystemWriter>( - RevocableInterfacePtr< - mojom::blink::NativeFileSystemFileWriter>( - writer.PassInterface(), - context->GetInterfaceInvalidator(), - context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); - } else { - resolver->Reject( - file_error::CreateDOMException(result->error_code)); + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, *result); + return; } + resolver->Resolve(MakeGarbageCollected<NativeFileSystemWriter>( + RevocableInterfacePtr<mojom::blink::NativeFileSystemFileWriter>( + writer.PassInterface(), context->GetInterfaceInvalidator(), + context->GetTaskRunner(TaskType::kMiscPlatformAPI)))); }, WrapPersistent(resolver))); @@ -66,11 +64,11 @@ [](ScriptPromiseResolver* resolver, const String& name, NativeFileSystemErrorPtr result, const scoped_refptr<BlobDataHandle>& blob) { - if (result->error_code == base::File::FILE_OK) { - resolver->Resolve(File::Create(name, InvalidFileTime(), blob)); - } else { - resolver->Reject(file_error::CreateDOMException(result->error_code)); + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, *result); + return; } + resolver->Resolve(File::Create(name, InvalidFileTime(), blob)); }, WrapPersistent(resolver), name()));
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc index 82fc280..2d69acc 100644 --- a/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc +++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc
@@ -17,6 +17,7 @@ #include "third_party/blink/renderer/core/fileapi/blob.h" #include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/core/streams/readable_stream.h" +#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h" #include "third_party/blink/renderer/platform/blob/blob_data.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -139,9 +140,8 @@ return; DCHECK(writer_->pending_operation_); did_complete_ = true; - if (result->error_code != base::File::FILE_OK) { - writer_->pending_operation_->Reject( - file_error::CreateDOMException(result->error_code)); + if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(writer_->pending_operation_, *result); } else { DCHECK(did_finish_writing_to_pipe_); writer_->pending_operation_->Resolve(); @@ -238,51 +238,21 @@ mojom::blink::NativeFileSystemErrorPtr result, uint64_t bytes_written) { DCHECK(pending_operation_); - if (result->error_code == base::File::FILE_OK) { - pending_operation_->Resolve(); - } else if (result->error_code == base::File::FILE_ERROR_INVALID_OPERATION) { - // TODO(https://crbug.com/971268): Better error messages that make sense in - // JS. - pending_operation_->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); - } else { - pending_operation_->Reject( - file_error::CreateDOMException(result->error_code)); - } + native_file_system_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; } void NativeFileSystemWriter::TruncateComplete( mojom::blink::NativeFileSystemErrorPtr result) { DCHECK(pending_operation_); - if (result->error_code == base::File::FILE_OK) { - pending_operation_->Resolve(); - } else if (result->error_code == base::File::FILE_ERROR_INVALID_OPERATION) { - // TODO(https://crbug.com/971268): Better error messages that make sense in - // JS. - pending_operation_->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); - } else { - pending_operation_->Reject( - file_error::CreateDOMException(result->error_code)); - } + native_file_system_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; } void NativeFileSystemWriter::CloseComplete( mojom::blink::NativeFileSystemErrorPtr result) { DCHECK(pending_operation_); - if (result->error_code == base::File::FILE_OK) { - pending_operation_->Resolve(); - } else if (result->error_code == base::File::FILE_ERROR_INVALID_OPERATION) { - // TODO(https://crbug.com/971268): Better error messages that make sense in - // JS. - pending_operation_->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); - } else { - pending_operation_->Reject( - file_error::CreateDOMException(result->error_code)); - } + native_file_system_error::ResolveOrReject(pending_operation_, *result); file_ = nullptr; pending_operation_ = nullptr; // We close the mojo pipe because we intend this writer to be discarded after
diff --git a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc b/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc index 615b933..93837df 100644 --- a/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc +++ b/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/modules/native_file_system/choose_file_system_entries_options.h" #include "third_party/blink/renderer/modules/native_file_system/choose_file_system_entries_options_accepts.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h" +#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h" #include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -121,9 +122,10 @@ ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (file_operation_result->error_code != base::File::FILE_OK) { - resolver->Reject(file_error::CreateDOMException( - file_operation_result->error_code)); + if (file_operation_result->status != + mojom::blink::NativeFileSystemStatus::kOk) { + native_file_system_error::Reject(resolver, + *file_operation_result); return; } if (options->multiple()) {
diff --git a/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc b/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc index 87c87c7..06d6d59 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc +++ b/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
@@ -19,7 +19,6 @@ SensorProviderProxy* provider, Page* page) : SensorProxy(sensor_type, provider, page), - client_binding_(this), polling_timer_( provider->GetSupplementable()->GetTaskRunner(TaskType::kSensor), this, @@ -28,7 +27,7 @@ SensorProxyImpl::~SensorProxyImpl() {} void SensorProxyImpl::Dispose() { - client_binding_.Close(); + client_receiver_.reset(); } void SensorProxyImpl::Trace(blink::Visitor* visitor) { @@ -55,14 +54,15 @@ base::OnceCallback<void(bool)> callback) { DCHECK(IsInitialized()); AddActiveFrequency(configuration->frequency); - sensor_->AddConfiguration(std::move(configuration), std::move(callback)); + sensor_remote_->AddConfiguration(std::move(configuration), + std::move(callback)); } void SensorProxyImpl::RemoveConfiguration( SensorConfigurationPtr configuration) { DCHECK(IsInitialized()); RemoveActiveFrequency(configuration->frequency); - sensor_->RemoveConfiguration(std::move(configuration)); + sensor_remote_->RemoveConfiguration(std::move(configuration)); } double SensorProxyImpl::GetDefaultFrequency() const { @@ -79,7 +79,7 @@ if (suspended_) return; - sensor_->Suspend(); + sensor_remote_->Suspend(); suspended_ = true; UpdatePollingStatus(); } @@ -88,7 +88,7 @@ if (!suspended_) return; - sensor_->Resume(); + sensor_remote_->Resume(); suspended_ = false; UpdatePollingStatus(); } @@ -136,11 +136,11 @@ // The m_sensor.reset() will release all callbacks and its bound parameters, // therefore, handleSensorError accepts messages by value. - sensor_.reset(); + sensor_remote_.reset(); shared_buffer_reader_.reset(); default_frequency_ = 0.0; frequency_limits_ = {0.0, 0.0}; - client_binding_.Close(); + client_receiver_.reset(); SensorProxy::ReportError(code, message); } @@ -174,8 +174,8 @@ default_frequency_ = params->default_configuration->frequency; DCHECK_GT(default_frequency_, 0.0); - sensor_.Bind(std::move(params->sensor)); - client_binding_.Bind(std::move(params->client_request)); + sensor_remote_.Bind(std::move(params->sensor)); + client_receiver_.Bind(std::move(params->client_request)); shared_buffer_reader_ = device::SensorReadingSharedBufferReader::Create( std::move(params->memory), params->buffer_offset); @@ -197,7 +197,7 @@ auto error_callback = WTF::Bind(&SensorProxyImpl::HandleSensorError, WrapWeakPersistent(this), SensorCreationResult::ERROR_NOT_AVAILABLE); - sensor_.set_connection_error_handler(std::move(error_callback)); + sensor_remote_.set_disconnect_handler(std::move(error_callback)); state_ = kInitialized;
diff --git a/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h b/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h index 3fd5519..ea7973c 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h +++ b/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h
@@ -7,7 +7,8 @@ #include "third_party/blink/renderer/modules/sensor/sensor_proxy.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -77,8 +78,8 @@ device::mojom::blink::ReportingMode mode_ = device::mojom::blink::ReportingMode::CONTINUOUS; - device::mojom::blink::SensorPtr sensor_; - mojo::Binding<device::mojom::blink::SensorClient> client_binding_; + mojo::Remote<device::mojom::blink::Sensor> sensor_remote_; + mojo::Receiver<device::mojom::blink::SensorClient> client_receiver_{this}; std::unique_ptr<device::SensorReadingSharedBufferReader> shared_buffer_reader_;
diff --git a/third_party/blink/renderer/modules/webgpu/README.md b/third_party/blink/renderer/modules/webgpu/README.md index fc38f89..4f8bd738 100644 --- a/third_party/blink/renderer/modules/webgpu/README.md +++ b/third_party/blink/renderer/modules/webgpu/README.md
@@ -4,4 +4,4 @@ It will provide modern features such as “GPU compute” as well as lower overhead access to GPU hardware and better, more predictable performance. WebGPU is being developed by the [“GPU for the Web”](https://www.w3.org/community/gpu/) W3C community group. -This Blink module implements the WebGPU API's [sketch WebIDL](https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl) that will evolve as WebGPU gets closer to an MVP. +This Blink module implements the WebGPU API's [spec](https://gpuweb.github.io/gpuweb/) that will evolve as WebGPU gets closer to an MVP.
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.idl b/third_party/blink/renderer/modules/webgpu/gpu.idl index efc456a..2e5f6eb 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl index 1d9a51a..4edcf417 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group.idl index ac28e0a..7affa268 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_binding.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_binding.idl index 6f9a12b0..3dbc7d39 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_binding.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_binding.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ typedef (GPUSampler or GPUTextureView or GPUBufferBinding) GPUBindingResource;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl index 06e94cd..ab56efc 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBindGroupDescriptor { required GPUBindGroupLayout layout;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.idl index bdf52f2f..00c5707 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl index 83c6548a..206cc8f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBindGroupLayoutBinding { required unsigned long binding;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl index b6bab79..74663eab 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBindGroupLayoutDescriptor { required sequence<GPUBindGroupLayoutBinding> bindings;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_blend_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_blend_descriptor.idl index 1a34476..fd955ac 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_blend_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_blend_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBlendDescriptor { GPUBlendFactor srcFactor = "one";
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl b/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl index 9431e7a..23e8050 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl b/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl index 0554535..e3ee3c6 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBufferBinding { required GPUBuffer buffer;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl b/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl index a8172375..0ba2fb0 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBufferCopyView { required GPUBuffer buffer;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl index e04e960..f36194db 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUBufferDescriptor { required unsigned long long size;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl b/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl index a7de395..981d67fa 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ typedef unsigned long GPUBufferUsageFlags; [
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl index 71b4faf..5e4ac97 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_color.idl b/third_party/blink/renderer/modules/webgpu/gpu_color.idl index aedb6299..3055ed71 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_color.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_color.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUColor { required float r;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl index eeb87a9..165f7594 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUColorStateDescriptor { required GPUTextureFormat format;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl b/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl index 12c0a58..a28647f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ typedef unsigned long GPUColorWriteFlags; [
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_buffer.idl b/third_party/blink/renderer/modules/webgpu/gpu_command_buffer.idl index 4e7db38..6c6af47 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_buffer.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_buffer.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl index 83a719f..1a76aca1 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl index 2a0d33d8..0cef584 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUCommandEncoderDescriptor { };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl index 82e2e93..75149c6 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.idl b/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.idl index d219d87a..9fb2b5c 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl index a05ee1f..aefb71c1 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase { required GPUPipelineStageDescriptor computeStage;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl index 0817b7e..03f2efe 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUDepthStencilStateDescriptor { required GPUTextureFormat format;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.idl b/third_party/blink/renderer/modules/webgpu/gpu_device.idl index 50ead88..cc32b405 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl index 405e1583..a5983c8 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUDeviceDescriptor { GPUExtensions extensions;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_extensions.idl b/third_party/blink/renderer/modules/webgpu/gpu_extensions.idl index 600c20aa..660c740 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_extensions.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_extensions.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUExtensions { };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl b/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl index 4aea702..19b45af4 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUExtent3D { required unsigned long width;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_fence.idl b/third_party/blink/renderer/modules/webgpu/gpu_fence.idl index bd4a24f..df7c035 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_fence.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_fence.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl index 1bd3681b..4a94de1 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUFenceDescriptor { unsigned long long initialValue = 0;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_limits.idl b/third_party/blink/renderer/modules/webgpu/gpu_limits.idl index 1f0c909..47d27c6 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_limits.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_limits.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPULimits { unsigned long maxBindGroups = 4;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl b/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl index a26844a..d1359ba 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUOrigin3D { required unsigned long x;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_out_of_memory_error.idl b/third_party/blink/renderer/modules/webgpu/gpu_out_of_memory_error.idl index 5cae5cf..83002f7 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_out_of_memory_error.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_out_of_memory_error.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ Constructor(),
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl index e9ff6c46..417592f8 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUPipelineDescriptorBase { DOMString label;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.idl b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.idl index 6a8fb678..3fbf4922 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl index affec68..e6fbc7b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUPipelineLayoutDescriptor { required sequence<GPUBindGroupLayout> bindGroupLayouts;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl index 5a98562..dc75910 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUPipelineStageDescriptor { required GPUShaderModule module;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.idl b/third_party/blink/renderer/modules/webgpu/gpu_queue.idl index 85ad859..cafda686 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_queue.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_rasterization_state_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_rasterization_state_descriptor.idl index d246337..5abb135e 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_rasterization_state_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_rasterization_state_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPURasterizationStateDescriptor { GPUFrontFace frontFace = "ccw";
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_color_attachment_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_color_attachment_descriptor.idl index c78ef98..8fff3a0 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_color_attachment_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_color_attachment_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPURenderPassColorAttachmentDescriptor { required GPUTextureView attachment;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl index 155dc46..63c9b326 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPURenderPassDepthStencilAttachmentDescriptor { required GPUTextureView attachment;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl index 9483f11..cb0bcdb 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPURenderPassDescriptor { required sequence<GPURenderPassColorAttachmentDescriptor> colorAttachments;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl index 7ee5b463..b3db800 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.idl index e71cba6e..a4a1c7f1 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl index e53432f..1fbd75e 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase { required GPUPipelineStageDescriptor vertexStage;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl b/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl index 978760d..6a10358 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ enum GPUPowerPreference { "low-power",
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_sampler.idl b/third_party/blink/renderer/modules/webgpu/gpu_sampler.idl index 5d38f06b..96599ce 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_sampler.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_sampler.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl index 0858a6939..4eb8b2b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUSamplerDescriptor { GPUAddressMode addressModeU = "clamp-to-edge";
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_shader_module.idl b/third_party/blink/renderer/modules/webgpu/gpu_shader_module.idl index 1d29edd6..dd63cdf2 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_shader_module.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_shader_module.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl index 9fadccd..640d875 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUShaderModuleDescriptor { DOMString label;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl b/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl index ac66406..54f8588 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ typedef unsigned long GPUShaderStageFlags; [
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_stencil_state_face_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_stencil_state_face_descriptor.idl index d442ac1..bcdca5f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_stencil_state_face_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_stencil_state_face_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUStencilStateFaceDescriptor { GPUCompareFunction compare = "always";
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.idl b/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.idl index b3baf97..f89aead 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl index 365a07ef..073b8e0 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUSwapChainDescriptor { required GPUDevice device;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture.idl index 45c4259..0049a47 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl index fcde17b..c0630b9 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUTextureCopyView { required GPUTexture texture;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl index 769ba0a..3f9836ea 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUTextureDescriptor { required GPUExtent3D size;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl index ba982e2d..8a5c208 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ typedef unsigned long GPUTextureUsageFlags; [
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_view.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_view.idl index 1b6e30b..db31277 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture_view.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_view.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl index a0db1193..dda055b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUTextureViewDescriptor { required GPUTextureFormat format;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl b/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl index 5c66f357..515407b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ Constructor(DOMString type, GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict),
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event_init.idl b/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event_init.idl index 793f42b..2e3f602 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event_init.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event_init.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUUncapturedErrorEventInit : EventInit { required GPUError error;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_validation_error.idl b/third_party/blink/renderer/modules/webgpu/gpu_validation_error.idl index fe3527f..0b93ed1b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_validation_error.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_validation_error.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ Constructor(DOMString message),
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl index f6729dc9..297b7f9e 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ typedef unsigned long GPUShaderAttributeIndex;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl index 18eea45..b6ab191 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUVertexBufferDescriptor { required unsigned long long stride;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_vertex_input_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_vertex_input_descriptor.idl index 0f9591f..dc30a7c 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_vertex_input_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_vertex_input_descriptor.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ dictionary GPUVertexInputDescriptor { GPUIndexFormat indexFormat = "uint32";
diff --git a/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl b/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl index 5d5fa8b..1ee4f3f 100644 --- a/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl +++ b/third_party/blink/renderer/modules/webgpu/navigator_gpu.idl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl +// https://gpuweb.github.io/gpuweb/ [ Exposed=Window,
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share.cc b/third_party/blink/renderer/modules/webshare/navigator_share.cc index 565d0a0..6e07bec 100644 --- a/third_party/blink/renderer/modules/webshare/navigator_share.cc +++ b/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -186,7 +186,7 @@ return ScriptPromise::RejectWithDOMException(script_state, error); } - if (!service_) { + if (!service_remote_) { LocalFrame* frame = doc->GetFrame(); if (!frame) { auto* error = MakeGarbageCollected<DOMException>( @@ -197,11 +197,12 @@ } // See https://bit.ly/2S0zRAS for task types. - frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest( - &service_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI))); - service_.set_connection_error_handler(WTF::Bind( + frame->GetInterfaceProvider().GetInterface( + service_remote_.BindNewPipeAndPassReceiver( + frame->GetTaskRunner(TaskType::kMiscPlatformAPI))); + service_remote_.set_disconnect_handler(WTF::Bind( &NavigatorShare::OnConnectionError, WrapWeakPersistent(this))); - DCHECK(service_); + DCHECK(service_remote_); } bool has_files = HasFiles(*share_data); @@ -229,7 +230,7 @@ } } - service_->Share( + service_remote_->Share( share_data->hasTitle() ? share_data->title() : g_empty_string, share_data->hasText() ? share_data->text() : g_empty_string, full_url, std::move(files), @@ -249,7 +250,7 @@ client->OnConnectionError(); } clients_.clear(); - service_.reset(); + service_remote_.reset(); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share.h b/third_party/blink/renderer/modules/webshare/navigator_share.h index a68c104..af3c18e 100644 --- a/third_party/blink/renderer/modules/webshare/navigator_share.h +++ b/third_party/blink/renderer/modules/webshare/navigator_share.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSHARE_NAVIGATOR_SHARE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSHARE_NAVIGATOR_SHARE_H_ +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/webshare/webshare.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" @@ -50,7 +51,7 @@ void OnConnectionError(); - blink::mojom::blink::ShareServicePtr service_; + mojo::Remote<blink::mojom::blink::ShareService> service_remote_; HeapHashSet<Member<ShareClientImpl>> clients_; };
diff --git a/third_party/blink/renderer/modules/webshare/navigator_share_test.cc b/third_party/blink/renderer/modules/webshare/navigator_share_test.cc index 7da87c1..5244fe9 100644 --- a/third_party/blink/renderer/modules/webshare/navigator_share_test.cc +++ b/third_party/blink/renderer/modules/webshare/navigator_share_test.cc
@@ -29,11 +29,11 @@ // A mock ShareService used to intercept calls to the mojo methods. class MockShareService : public ShareService { public: - MockShareService() : binding_(this), error_(mojom::ShareError::OK) {} + MockShareService() : error_(mojom::ShareError::OK) {} ~MockShareService() override = default; void Bind(mojo::ScopedMessagePipeHandle handle) { - binding_.Bind(mojom::blink::ShareServiceRequest(std::move(handle))); + receiver_.Bind(mojom::blink::ShareServiceRequest(std::move(handle))); } void set_error(mojom::ShareError value) { error_ = value; } @@ -63,7 +63,7 @@ std::move(callback).Run(error_); } - mojo::Binding<ShareService> binding_; + mojo::Receiver<ShareService> receiver_{this}; WTF::String title_; WTF::String text_; KURL url_;
diff --git a/third_party/blink/renderer/platform/audio/hrtf_elevation.cc b/third_party/blink/renderer/platform/audio/hrtf_elevation.cc index ca1afacb..d2948f4a 100644 --- a/third_party/blink/renderer/platform/audio/hrtf_elevation.cc +++ b/third_party/blink/renderer/platform/audio/hrtf_elevation.cc
@@ -125,12 +125,6 @@ if (!is_elevation_good) return false; - // Construct the resource name from the subject name, azimuth, and elevation, - // for example: - // "IRC_Composite_C_R0195_T015_P000" - // Note: the passed in subjectName is not a string passed in via JavaScript or - // the web. It's passed in as an internal ASCII identifier and is an - // implementation detail. int positive_elevation = elevation < 0 ? elevation + 360 : elevation; scoped_refptr<AudioBus> bus(
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 ac2bf41..0dc5ca3 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h
@@ -68,6 +68,13 @@ rect = Matrix().MapRect(rect); } + void MapQuad(FloatQuad& quad) const { + if (LIKELY(IsIdentityOr2DTranslation())) + quad.Move(Translation2D()); + else + quad = Matrix().MapQuad(quad); + } + void MapFloatClipRect(FloatClipRect& rect) const { if (LIKELY(IsIdentityOr2DTranslation())) rect.MoveBy(FloatPoint(Translation2D()));
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index bfbc31cc..62510d8 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -326,6 +326,7 @@ 'layout_invalidation_reason::.+', 'media_constraints_impl::.+', 'media_element_parser_helpers::.+', + 'native_file_system_error::.+', 'network_utils::.+', 'origin_trials::.+', 'paint_filter_builder::.+',
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu b/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu deleted file mode 100644 index 2aea60b..0000000 --- a/third_party/blink/web_tests/FlagExpectations/enable-unsafe-webgpu +++ /dev/null
@@ -1,3 +0,0 @@ -# WebGPU tests are only run on GPU bots, so they are skipped by default and run -# separately from other Web Tests. -Bug(none) external/wpt/webgpu/ [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index de421ad..e867443a 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -4612,6 +4612,7 @@ crbug.com/626703 external/wpt/html/cross-origin-embedder-policy/require-corp.https.html [ Failure ] crbug.com/626703 external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html [ Failure ] crbug.com/626703 [ Linux Mac10.10 ] virtual/cross-origin-embedder-policy/external/wpt/html/cross-origin-embedder-policy/require-corp.https.html [ Pass Failure ] +crbug.com/626703 [ Linux Mac10.10 ] virtual/cross-origin-embedder-policy/external/wpt/html/cross-origin-embedder-policy/none.https.html [ Pass Failure ] # Failure due to on-going off-thread paint worklet project. crbug.com/957457 virtual/threaded/external/wpt/css/css-paint-api/invalid-image-pending-script.https.html [ Crash ]
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations new file mode 100644 index 0000000..71d0a02 --- /dev/null +++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -0,0 +1,2 @@ +# WebGPU tests are only run on GPU bots, so they are skipped by default and run +# separately from other Web Tests, with this expectations file.
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index 26c8af2a..5491f293 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -140241,6 +140241,12 @@ "css/css-logical/parsing/inset-block-inline-valid-expected.txt": [ [] ], + "css/css-logical/parsing/margin-block-inline-computed-expected.txt": [ + [] + ], + "css/css-logical/parsing/padding-block-inline-computed-expected.txt": [ + [] + ], "css/css-logical/reference/logical-values-float-clear-reftest-ref.html": [ [] ], @@ -149391,6 +149397,15 @@ "css/filter-effects/OWNERS": [ [] ], + "css/filter-effects/animation/filter-interpolation-001-expected.txt": [ + [] + ], + "css/filter-effects/animation/filter-interpolation-002-expected.txt": [ + [] + ], + "css/filter-effects/animation/filter-interpolation-003-expected.txt": [ + [] + ], "css/filter-effects/backdrop-filter-basic-background-color-ref.html": [ [] ], @@ -159528,7 +159543,7 @@ "html/infrastructure/urls/resolving-urls/query-encoding/windows-1251-expected.txt": [ [] ], - "html/interaction/focus/document-level-focus-apis/test.html": [ + "html/interaction/focus/document-level-focus-apis/support/test.html": [ [] ], "html/interaction/focus/processing-model/support/preventScroll-helper.html": [ @@ -161913,9 +161928,6 @@ "html/semantics/selectors/pseudo-classes/dir01-expected.txt": [ [] ], - "html/semantics/selectors/pseudo-classes/enabled-expected.txt": [ - [] - ], "html/semantics/selectors/pseudo-classes/focus-iframe.html": [ [] ], @@ -201887,6 +201899,30 @@ {} ] ], + "css/css-backgrounds/animations/background-color-interpolation.html": [ + [ + "css/css-backgrounds/animations/background-color-interpolation.html", + {} + ] + ], + "css/css-backgrounds/animations/background-position-interpolation.html": [ + [ + "css/css-backgrounds/animations/background-position-interpolation.html", + {} + ] + ], + "css/css-backgrounds/animations/background-position-origin-interpolation.html": [ + [ + "css/css-backgrounds/animations/background-position-origin-interpolation.html", + {} + ] + ], + "css/css-backgrounds/animations/background-size-interpolation.html": [ + [ + "css/css-backgrounds/animations/background-size-interpolation.html", + {} + ] + ], "css/css-backgrounds/background-331.html": [ [ "css/css-backgrounds/background-331.html", @@ -203737,6 +203773,36 @@ {} ] ], + "css/css-fonts/animations/font-size-adjust-interpolation.html": [ + [ + "css/css-fonts/animations/font-size-adjust-interpolation.html", + {} + ] + ], + "css/css-fonts/animations/font-size-interpolation-001.html": [ + [ + "css/css-fonts/animations/font-size-interpolation-001.html", + {} + ] + ], + "css/css-fonts/animations/font-size-interpolation-002.html": [ + [ + "css/css-fonts/animations/font-size-interpolation-002.html", + {} + ] + ], + "css/css-fonts/animations/font-size-interpolation-003.html": [ + [ + "css/css-fonts/animations/font-size-interpolation-003.html", + {} + ] + ], + "css/css-fonts/animations/font-variation-settings-interpolation.html": [ + [ + "css/css-fonts/animations/font-variation-settings-interpolation.html", + {} + ] + ], "css/css-fonts/calc-in-font-variation-settings.html": [ [ "css/css-fonts/calc-in-font-variation-settings.html", @@ -206897,6 +206963,12 @@ {} ] ], + "css/css-logical/parsing/margin-block-inline-computed.html": [ + [ + "css/css-logical/parsing/margin-block-inline-computed.html", + {} + ] + ], "css/css-logical/parsing/margin-block-inline-invalid.html": [ [ "css/css-logical/parsing/margin-block-inline-invalid.html", @@ -206981,6 +207053,12 @@ {} ] ], + "css/css-logical/parsing/padding-block-inline-computed.html": [ + [ + "css/css-logical/parsing/padding-block-inline-computed.html", + {} + ] + ], "css/css-logical/parsing/padding-block-inline-invalid.html": [ [ "css/css-logical/parsing/padding-block-inline-invalid.html", @@ -215525,6 +215603,24 @@ {} ] ], + "css/css-values/minmax-angle-serialize.html": [ + [ + "css/css-values/minmax-angle-serialize.html", + {} + ] + ], + "css/css-values/minmax-time-computed.html": [ + [ + "css/css-values/minmax-time-computed.html", + {} + ] + ], + "css/css-values/minmax-time-invalid.html": [ + [ + "css/css-values/minmax-time-invalid.html", + {} + ] + ], "css/css-values/rgba-011.html": [ [ "css/css-values/rgba-011.html", @@ -346874,6 +346970,22 @@ "9b2e5be0a19c48f73b57fe0ad8bbeea81238a1d1", "support" ], + "css/css-backgrounds/animations/background-color-interpolation.html": [ + "bb727d8e4ef3328547a746c31340b6ca2b885f5c", + "testharness" + ], + "css/css-backgrounds/animations/background-position-interpolation.html": [ + "35100fb33622c03f6454ebc051569ccba67564e9", + "testharness" + ], + "css/css-backgrounds/animations/background-position-origin-interpolation.html": [ + "c6b84ca2aef0a8222b4b4c5713d1998beff799db", + "testharness" + ], + "css/css-backgrounds/animations/background-size-interpolation.html": [ + "f6a480c7bd2ccc4a6c46fa2eade5e7231fab4938", + "testharness" + ], "css/css-backgrounds/background-331.html": [ "121623453a61599fcc494a9582c31a79f78cfeb1", "testharness" @@ -357390,6 +357502,26 @@ "d47cbce32bb31ff1ea4df81f122c673d7f942677", "reftest" ], + "css/css-fonts/animations/font-size-adjust-interpolation.html": [ + "fd89da3b969c2ad2f8fb522c600bddc740d8146b", + "testharness" + ], + "css/css-fonts/animations/font-size-interpolation-001.html": [ + "0f60018c2e1ce453fe87b3854ffb25c4eb26f924", + "testharness" + ], + "css/css-fonts/animations/font-size-interpolation-002.html": [ + "d6f2f19ab1e585b802dc9b2214558bf6ae643022", + "testharness" + ], + "css/css-fonts/animations/font-size-interpolation-003.html": [ + "d84ff7e5dfe3f4c86ed4b9bf30914ed3d11b156c", + "testharness" + ], + "css/css-fonts/animations/font-variation-settings-interpolation.html": [ + "e11079cfc012ce8937b504662e1f0f6f92351fe2", + "testharness" + ], "css/css-fonts/calc-in-font-variation-settings.html": [ "1a7c59abd5ddebfc6cd1f972ee6a186bdb7b97df", "testharness" @@ -369930,6 +370062,14 @@ "2d8f937f075b0d0fbde677e15266f47af5fec3f8", "testharness" ], + "css/css-logical/parsing/margin-block-inline-computed-expected.txt": [ + "6e68778e87b6ef31a0291695ce8a31a216e006df", + "support" + ], + "css/css-logical/parsing/margin-block-inline-computed.html": [ + "6ef52bda3b87363942461ddd52ad935abeccc31c", + "testharness" + ], "css/css-logical/parsing/margin-block-inline-invalid.html": [ "a1e0cbf3885b6518266eba0ef23d40f53a0c5c20", "testharness" @@ -369986,6 +370126,14 @@ "fa4ba0d1bb2607d954d3a2ea3272282872704799", "testharness" ], + "css/css-logical/parsing/padding-block-inline-computed-expected.txt": [ + "ac6269fece26b196ec36be7a051863eefbe5f651", + "support" + ], + "css/css-logical/parsing/padding-block-inline-computed.html": [ + "230f18525a0ca4ef9a525081447461c444458bf8", + "testharness" + ], "css/css-logical/parsing/padding-block-inline-invalid.html": [ "56c2adb07827ef54b42b6a797e0f700eeec56165", "testharness" @@ -398274,6 +398422,18 @@ "29dc15dfd965c940910ca5c63d6201643277f907", "testharness" ], + "css/css-values/minmax-angle-serialize.html": [ + "3f424589ba6f9806fefc444320301da5a12303ac", + "testharness" + ], + "css/css-values/minmax-time-computed.html": [ + "36bcf601eb808311732562a6c1c6a7c801f33e9d", + "testharness" + ], + "css/css-values/minmax-time-invalid.html": [ + "bebe674cd79565a364253f3290dd60b7073e2af1", + "testharness" + ], "css/css-values/q-unit-case-insensitivity-001.html": [ "b4a08aa117952c6f92e2aec6f57843b46a460104", "reftest" @@ -407034,16 +407194,28 @@ "12389ae3f6441e4d744959ccece6741984c88455", "testharness" ], + "css/filter-effects/animation/filter-interpolation-001-expected.txt": [ + "3823e2f6def50e17bfdaf5d1dfe4947e3af6a1cf", + "support" + ], "css/filter-effects/animation/filter-interpolation-001.html": [ - "b4a4b3f4bbad00fb76ee731dd9ed2ac7c2be41bc", + "62fcbf0a5de51b6483d3d70b9f411831e2e3afb8", "testharness" ], + "css/filter-effects/animation/filter-interpolation-002-expected.txt": [ + "19f208ef9a9c8e123f30d12e7a1a4908f1965df1", + "support" + ], "css/filter-effects/animation/filter-interpolation-002.html": [ - "1b66c2751d417438bee5c8349cf1359dd2042f4a", + "6ef25a7dafec17a3f2a4440f82da03658da91986", "testharness" ], + "css/filter-effects/animation/filter-interpolation-003-expected.txt": [ + "92ca741aed79936f1da77c30255c19bd0cbea2e0", + "support" + ], "css/filter-effects/animation/filter-interpolation-003.html": [ - "5ca1229e297fc65c3a9f4127913d8cc8813de66e", + "1d512487de9693b2f8143a46e465cf672709b80b", "testharness" ], "css/filter-effects/animation/filter-interpolation-004.html": [ @@ -417279,7 +417451,7 @@ "testharness" ], "dom/nodes/Element-matches-expected.txt": [ - "87f0c28dd5155153ec0206f00e84244735c94777", + "e0c0cfcaa9562e707f9394b559c2cb17ba658883", "support" ], "dom/nodes/Element-matches-init.js": [ @@ -417343,7 +417515,7 @@ "testharness" ], "dom/nodes/Element-webkitMatchesSelector-expected.txt": [ - "a3f6e0afdbc6f2e618cbe19b75087a032a03cc78", + "25a6eceec17d203887c9733d9531538098bc54b0", "support" ], "dom/nodes/Element-webkitMatchesSelector.html": [ @@ -417515,11 +417687,11 @@ "support" ], "dom/nodes/ParentNode-querySelector-All-expected.txt": [ - "1b256e3727898f1aefde235fecd408df33b598f5", + "898e01c1458a5f51916d8f82df9c30be34b3f550", "support" ], "dom/nodes/ParentNode-querySelector-All-xht-expected.txt": [ - "af043dc5d5d1d2ed0330a387d38f4317ac648362", + "472d761b55f6e068827a11a1b6f24a2c95429309", "support" ], "dom/nodes/ParentNode-querySelector-All-xht.xht": [ @@ -417751,7 +417923,7 @@ "testharness" ], "dom/nodes/selectors.js": [ - "553e62f2587dc904f92eb1899a29e0c8a9e16f10", + "c1680cedd708d3228603598d157883e6e8a77222", "support" ], "dom/ranges/Range-attributes.html": [ @@ -434203,10 +434375,10 @@ "testharness" ], "html/interaction/focus/document-level-focus-apis/document-level-apis.html": [ - "2d8c49c7f6127fdca7e29800dde3c3096be44aca", + "4a8a9a291a9fab7bfa67df1887c53bd5e34aadec", "testharness" ], - "html/interaction/focus/document-level-focus-apis/test.html": [ + "html/interaction/focus/document-level-focus-apis/support/test.html": [ "90d63e51e931b147b23e8e1941324f8fb4237c94", "support" ], @@ -443234,10 +443406,6 @@ "8808675eb69b17c7763b407ea7ce4458e9e08fda", "testharness" ], - "html/semantics/selectors/pseudo-classes/enabled-expected.txt": [ - "c92dbef0482a132c1a47f09e3923475de9581095", - "support" - ], "html/semantics/selectors/pseudo-classes/enabled.html": [ "0ad0e1b402a2646d41f736271c65d413455a67e2", "testharness" @@ -472431,7 +472599,7 @@ "support" ], "resources/chromium/nfc-mock.js": [ - "83bd6b8a0dea2d2434728b9ed52027e6b79b798a", + "9722f8ee57009254b9186bce2b195f02356a4f1b", "support" ], "resources/chromium/sensor.mojom.js": [ @@ -486083,7 +486251,7 @@ "support" ], "tools/wptrunner/wptrunner/executors/base.py": [ - "588e0b2fad6afbe17ed4ba9ea5b8f25cc9b7e055", + "b1e86ff1fd07ee040ed7c905a2462053b9e30a62", "support" ], "tools/wptrunner/wptrunner/executors/executorchrome.py": [ @@ -486231,7 +486399,7 @@ "support" ], "tools/wptrunner/wptrunner/testdriver-extra.js": [ - "e23073dece1f35db632d48ad6036a90a9cc12b46", + "9f97fac9a0cbc99ae8631ac2a1179da8bb9123a8", "support" ], "tools/wptrunner/wptrunner/testdriver-vendor.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/margin-block-inline-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/margin-block-inline-computed-expected.txt new file mode 100644 index 0000000..6e68778 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/margin-block-inline-computed-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS Property margin-block-start value '10px' computes to '10px' +FAIL Property margin-block-end value '10%' computes to '20px' assert_equals: expected "20px" but got "0px" +PASS Property margin-inline-start value '30px' computes to '30px' +PASS Property margin-inline-end value '1em' computes to '40px' +FAIL Property margin-block-start value 'calc(10% + 40px)' computes to '60px' assert_equals: expected "60px" but got "0px" +PASS Property margin-block-end value 'calc(10px + 0.5em)' computes to '30px' +PASS Property margin-inline-start value 'calc(10px + 0.5em)' computes to '30px' +FAIL Property margin-inline-end value 'calc(10% + 40px)' computes to '60px' assert_equals: expected "60px" but got "40px" +PASS Property margin-block value '10px' computes to '10px' +PASS Property margin-block value '10px 20px' computes to '10px 20px' +PASS Property margin-inline value '30px' computes to '30px' +PASS Property margin-inline value '30px 40px' computes to '30px 40px' +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/margin-block-inline-computed.html b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/margin-block-inline-computed.html new file mode 100644 index 0000000..6ef52bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/margin-block-inline-computed.html
@@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Logical Properties and Values: getComputedStyle().marginBlockStart etc.</title> +<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-margin-block"> +<link rel="help" href="https://drafts.csswg.org/cssom/#resolved-values"> +<meta name="assert" content="margin-block, margin-inline resolved values have absolute length."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<style> + #container { + will-change: transform; /* containing block for #target */ + width: 200px; + } + #parent { + width: 0px; + } + #target { + position: absolute; + font-size: 40px; + } +</style> +</head> +<body> +<div id="container"> + <div id="parent"> + <div id="target"></div> + </div> +</div> +<script> +test_computed_value("margin-block-start", "10px"); +test_computed_value("margin-block-end", "10%", "20px"); +test_computed_value("margin-inline-start", "30px"); +test_computed_value("margin-inline-end", "1em", "40px"); + +test_computed_value('margin-block-start', 'calc(10% + 40px)', '60px'); +test_computed_value('margin-block-end', 'calc(10px + 0.5em)', '30px'); +test_computed_value('margin-inline-start', 'calc(10px + 0.5em)', '30px'); +test_computed_value('margin-inline-end', 'calc(10% + 40px)', '60px'); + +test_computed_value("margin-block", "10px"); +test_computed_value("margin-block", "10px 20px"); +test_computed_value("margin-inline", "30px"); +test_computed_value("margin-inline", "30px 40px"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/padding-block-inline-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/padding-block-inline-computed-expected.txt new file mode 100644 index 0000000..ac6269f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/padding-block-inline-computed-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +PASS Property padding-block-start value '10px' computes to '10px' +FAIL Property padding-block-end value '10%' computes to '20px' assert_equals: expected "20px" but got "0px" +PASS Property padding-inline-start value '30px' computes to '30px' +PASS Property padding-inline-end value '1em' computes to '40px' +FAIL Property padding-block-start value 'calc(10% + 40px)' computes to '60px' assert_equals: expected "60px" but got "40px" +PASS Property padding-block-end value 'calc(10% - 40px)' computes to '0px' +PASS Property padding-inline-start value 'calc(10% - 40px)' computes to '0px' +FAIL Property padding-inline-end value 'calc(10% + 40px)' computes to '60px' assert_equals: expected "60px" but got "40px" +PASS Property padding-block-start value 'calc(10px - 0.5em)' computes to '0px' +PASS Property padding-block-end value 'calc(10px + 0.5em)' computes to '30px' +PASS Property padding-inline-start value 'calc(10px + 0.5em)' computes to '30px' +PASS Property padding-inline-end value 'calc(10px - 0.5em)' computes to '0px' +PASS Property padding-block value '10px' computes to '10px' +PASS Property padding-block value '10px 20px' computes to '10px 20px' +PASS Property padding-inline value '30px' computes to '30px' +PASS Property padding-inline value '30px 40px' computes to '30px 40px' +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/padding-block-inline-computed.html b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/padding-block-inline-computed.html new file mode 100644 index 0000000..230f185 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-logical/parsing/padding-block-inline-computed.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Logical Properties and Values: getComputedStyle().paddingBlockStart etc.</title> +<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-padding-block"> +<link rel="help" href="https://drafts.csswg.org/cssom/#resolved-values"> +<meta name="assert" content="padding-block, padding-inline resolved values have absolute length."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<style> + #container { + will-change: transform; /* containing block for #target */ + width: 200px; + } + #parent { + width: 0px; + } + #target { + position: absolute; + font-size: 40px; + } +</style> +</head> +<body> +<div id="container"> + <div id="parent"> + <div id="target"></div> + </div> +</div> +<script> +test_computed_value("padding-block-start", "10px"); +test_computed_value("padding-block-end", "10%", "20px"); +test_computed_value("padding-inline-start", "30px"); +test_computed_value("padding-inline-end", "1em", "40px"); + +test_computed_value('padding-block-start', 'calc(10% + 40px)', '60px'); +test_computed_value('padding-block-end', 'calc(10% - 40px)', '0px'); +test_computed_value('padding-inline-start', 'calc(10% - 40px)', '0px'); +test_computed_value('padding-inline-end', 'calc(10% + 40px)', '60px'); + +test_computed_value('padding-block-start', 'calc(10px - 0.5em)', '0px'); +test_computed_value('padding-block-end', 'calc(10px + 0.5em)', '30px'); +test_computed_value('padding-inline-start', 'calc(10px + 0.5em)', '30px'); +test_computed_value('padding-inline-end', 'calc(10px - 0.5em)', '0px'); + +test_computed_value("padding-block", "10px"); +test_computed_value("padding-block", "10px 20px"); +test_computed_value("padding-inline", "30px"); +test_computed_value("padding-inline", "30px 40px"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/minmax-angle-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/minmax-angle-serialize.html new file mode 100644 index 0000000..3f42458 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/minmax-angle-serialize.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#angles"> +<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking"> +<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../support/parsing-testcommon.js"></script> +<script> +function test_valid_angle(value, expected) { + test_valid_value('transform', `rotate(${value})`, `rotate(${expected})`); +} + +test_valid_angle('min(1deg)', 'min(1deg)'); +test_valid_angle('min(1rad)', 'min(1rad)'); +test_valid_angle('min(1turn)', 'min(1turn)'); +test_valid_angle('min(1grad)', 'min(1grad)'); +test_valid_angle('max(1deg)', 'max(1deg)'); +test_valid_angle('max(1rad)', 'max(1rad)'); +test_valid_angle('max(1turn)', 'max(1turn)'); +test_valid_angle('max(1grad)', 'max(1grad)'); + +// TODO(crbug.com/978682): Complete this test suite + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Element-matches-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/Element-matches-expected.txt index 87f0c28..e0c0cfc 100644 --- a/third_party/blink/web_tests/external/wpt/dom/nodes/Element-matches-expected.txt +++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Element-matches-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 661 tests; 659 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 669 tests; 667 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 PASS Document should not support matches PASS Detached Element supports matches @@ -172,7 +172,9 @@ PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) PASS In-document Element.matches: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled -PASS In-document Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.matches: :enabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :enabled +PASS In-document Element.matches: :disabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.matches: :disabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :disabled PASS In-document Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked PASS In-document Element.matches: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) PASS In-document Element.matches: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) @@ -333,7 +335,9 @@ PASS Detached Element.matches: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) PASS Detached Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) PASS Detached Element.matches: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled -PASS Detached Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Detached Element.matches: :enabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :enabled +PASS Detached Element.matches: :disabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Detached Element.matches: :disabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :disabled PASS Detached Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked PASS Detached Element.matches: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) PASS Detached Element.matches: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) @@ -493,7 +497,9 @@ PASS Fragment Element.matches: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) PASS Fragment Element.matches: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) PASS Fragment Element.matches: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled -PASS Fragment Element.matches: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Fragment Element.matches: :enabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :enabled +PASS Fragment Element.matches: :disabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Fragment Element.matches: :disabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :disabled PASS Fragment Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked PASS Fragment Element.matches: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) PASS Fragment Element.matches: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) @@ -657,7 +663,9 @@ PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with exact value (1) (with no refNodes): #pseudo-lang-div2:lang(fr) PASS In-document Element.matches: :lang pseudo-class selector, matching specified language with partial value (1) (with no refNodes): #pseudo-lang-div3:lang(en) PASS In-document Element.matches: :enabled pseudo-class selector, matching all enabled form controls (1) (with no refNodes): #pseudo-ui :enabled -PASS In-document Element.matches: :enabled pseudo-class selector, matching all disabled form controls (1) (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.matches: :enabled pseudo-class selector, not matching link elements (1) (with no refNodes): #pseudo-link :enabled +PASS In-document Element.matches: :disabled pseudo-class selector, matching all disabled form controls (1) (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.matches: :disabled pseudo-class selector, not matching link elements (1) (with no refNodes): #pseudo-link :disabled PASS In-document Element.matches: :checked pseudo-class selector, matching checked radio buttons and checkboxes (1) (with no refNodes): #pseudo-ui :checked PASS In-document Element.matches: :not pseudo-class selector, matching (1) (with no refNodes): #not>:not(div) PASS In-document Element.matches: :not pseudo-class selector, matching (1) (with no refNodes): #not * :not(:first-child)
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/Element-webkitMatchesSelector-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/Element-webkitMatchesSelector-expected.txt index a3f6e0a..25a6ece 100644 --- a/third_party/blink/web_tests/external/wpt/dom/nodes/Element-webkitMatchesSelector-expected.txt +++ b/third_party/blink/web_tests/external/wpt/dom/nodes/Element-webkitMatchesSelector-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 661 tests; 659 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 669 tests; 667 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 PASS Document should not support webkitMatchesSelector PASS Detached Element supports webkitMatchesSelector @@ -172,7 +172,9 @@ PASS In-document Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) PASS In-document Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) PASS In-document Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled -PASS In-document Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.webkitMatchesSelector: :enabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :enabled +PASS In-document Element.webkitMatchesSelector: :disabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.webkitMatchesSelector: :disabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :disabled PASS In-document Element.webkitMatchesSelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked PASS In-document Element.webkitMatchesSelector: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) PASS In-document Element.webkitMatchesSelector: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) @@ -333,7 +335,9 @@ PASS Detached Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) PASS Detached Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) PASS Detached Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled -PASS Detached Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Detached Element.webkitMatchesSelector: :enabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :enabled +PASS Detached Element.webkitMatchesSelector: :disabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Detached Element.webkitMatchesSelector: :disabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :disabled PASS Detached Element.webkitMatchesSelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked PASS Detached Element.webkitMatchesSelector: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) PASS Detached Element.webkitMatchesSelector: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) @@ -493,7 +497,9 @@ PASS Fragment Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with exact value (with no refNodes): #pseudo-lang-div2:lang(fr) PASS Fragment Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with partial value (with no refNodes): #pseudo-lang-div3:lang(en) PASS Fragment Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all enabled form controls (with no refNodes): #pseudo-ui :enabled -PASS Fragment Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Fragment Element.webkitMatchesSelector: :enabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :enabled +PASS Fragment Element.webkitMatchesSelector: :disabled pseudo-class selector, matching all disabled form controls (with no refNodes): #pseudo-ui :disabled +PASS Fragment Element.webkitMatchesSelector: :disabled pseudo-class selector, not matching link elements (with no refNodes): #pseudo-link :disabled PASS Fragment Element.webkitMatchesSelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes (with no refNodes): #pseudo-ui :checked PASS Fragment Element.webkitMatchesSelector: :not pseudo-class selector, matching (with no refNodes): #not>:not(div) PASS Fragment Element.webkitMatchesSelector: :not pseudo-class selector, matching (with no refNodes): #not * :not(:first-child) @@ -657,7 +663,9 @@ PASS In-document Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with exact value (1) (with no refNodes): #pseudo-lang-div2:lang(fr) PASS In-document Element.webkitMatchesSelector: :lang pseudo-class selector, matching specified language with partial value (1) (with no refNodes): #pseudo-lang-div3:lang(en) PASS In-document Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all enabled form controls (1) (with no refNodes): #pseudo-ui :enabled -PASS In-document Element.webkitMatchesSelector: :enabled pseudo-class selector, matching all disabled form controls (1) (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.webkitMatchesSelector: :enabled pseudo-class selector, not matching link elements (1) (with no refNodes): #pseudo-link :enabled +PASS In-document Element.webkitMatchesSelector: :disabled pseudo-class selector, matching all disabled form controls (1) (with no refNodes): #pseudo-ui :disabled +PASS In-document Element.webkitMatchesSelector: :disabled pseudo-class selector, not matching link elements (1) (with no refNodes): #pseudo-link :disabled PASS In-document Element.webkitMatchesSelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes (1) (with no refNodes): #pseudo-ui :checked PASS In-document Element.webkitMatchesSelector: :not pseudo-class selector, matching (1) (with no refNodes): #not>:not(div) PASS In-document Element.webkitMatchesSelector: :not pseudo-class selector, matching (1) (with no refNodes): #not * :not(:first-child)
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-expected.txt index 1b256e37..898e01c 100644 --- a/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-expected.txt +++ b/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 1959 tests; 1957 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 1975 tests; 1973 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Selectors-API Test Suite: HTML PASS Document supports querySelector PASS Document supports querySelectorAll @@ -609,8 +609,12 @@ PASS Document.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS Document.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS Document.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS Document.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS Document.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Document.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Document.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Document.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Document.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Document.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS Document.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS Document.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Document.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Document.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) @@ -1037,8 +1041,12 @@ PASS Detached Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS Detached Element.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS Detached Element.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Detached Element.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Detached Element.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Detached Element.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Detached Element.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Detached Element.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS Detached Element.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS Detached Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Detached Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Detached Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) @@ -1463,8 +1471,12 @@ PASS Fragment.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS Fragment.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS Fragment.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS Fragment.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS Fragment.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Fragment.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Fragment.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Fragment.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Fragment.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Fragment.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS Fragment.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS Fragment.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Fragment.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Fragment.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) @@ -1889,8 +1901,12 @@ PASS In-document Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS In-document Element.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS In-document Element.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS In-document Element.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS In-document Element.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS In-document Element.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS In-document Element.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS In-document Element.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS In-document Element.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS In-document Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS In-document Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS In-document Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div)
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-xht-expected.txt b/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-xht-expected.txt index af043dc..472d761 100644 --- a/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-xht-expected.txt +++ b/third_party/blink/web_tests/external/wpt/dom/nodes/ParentNode-querySelector-All-xht-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 1959 tests; 1957 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 1975 tests; 1973 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Selectors-API Test Suite: XHTML PASS Document supports querySelector PASS Document supports querySelectorAll @@ -609,8 +609,12 @@ PASS Document.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS Document.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS Document.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS Document.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS Document.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Document.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Document.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Document.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Document.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Document.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS Document.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS Document.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Document.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Document.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) @@ -1037,8 +1041,12 @@ PASS Detached Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS Detached Element.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS Detached Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS Detached Element.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Detached Element.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Detached Element.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Detached Element.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Detached Element.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Detached Element.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS Detached Element.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS Detached Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Detached Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Detached Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) @@ -1463,8 +1471,12 @@ PASS Fragment.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS Fragment.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS Fragment.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS Fragment.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS Fragment.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Fragment.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Fragment.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS Fragment.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Fragment.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS Fragment.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS Fragment.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS Fragment.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Fragment.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS Fragment.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div) @@ -1889,8 +1901,12 @@ PASS In-document Element.querySelector: :lang pseudo-class selector, not matching incorrect language: #pseudo-lang-div4:lang(es-AR) PASS In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled PASS In-document Element.querySelector: :enabled pseudo-class selector, matching all enabled form controls: #pseudo-ui :enabled -PASS In-document Element.querySelectorAll: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled -PASS In-document Element.querySelector: :enabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS In-document Element.querySelectorAll: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS In-document Element.querySelector: :enabled pseudo-class selector, not matching link elements: #pseudo-link :enabled +PASS In-document Element.querySelectorAll: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS In-document Element.querySelector: :disabled pseudo-class selector, matching all disabled form controls: #pseudo-ui :disabled +PASS In-document Element.querySelectorAll: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled +PASS In-document Element.querySelector: :disabled pseudo-class selector, not matching link elements: #pseudo-link :disabled PASS In-document Element.querySelectorAll: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS In-document Element.querySelector: :checked pseudo-class selector, matching checked radio buttons and checkboxes: #pseudo-ui :checked PASS In-document Element.querySelectorAll: :not pseudo-class selector, matching : #not>:not(div)
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/selectors.js b/third_party/blink/web_tests/external/wpt/dom/nodes/selectors.js index 553e62f..c1680ced 100644 --- a/third_party/blink/web_tests/external/wpt/dom/nodes/selectors.js +++ b/third_party/blink/web_tests/external/wpt/dom/nodes/selectors.js
@@ -237,10 +237,12 @@ // - :enabled (Level 3) {name: ":enabled pseudo-class selector, matching all enabled form controls", selector: "#pseudo-ui :enabled", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":enabled pseudo-class selector, not matching link elements", selector: "#pseudo-link :enabled", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, // - :disabled (Level 3) - {name: ":enabled pseudo-class selector, matching all disabled form controls", selector: "#pseudo-ui :disabled", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + {name: ":disabled pseudo-class selector, matching all disabled form controls", selector: "#pseudo-ui :disabled", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_QSA | TEST_MATCH}, + {name: ":disabled pseudo-class selector, not matching link elements", selector: "#pseudo-link :disabled", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, // - :checked (Level 3) {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes", selector: "#pseudo-ui :checked", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_QSA | TEST_MATCH}, @@ -619,10 +621,12 @@ // - :enabled (Level 3) {name: ":enabled pseudo-class selector, matching all enabled form controls (1)", selector: "#pseudo-ui :enabled", ctx: "", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":enabled pseudo-class selector, not matching link elements (1)", selector: "#pseudo-link :enabled", ctx: "", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, // - :disabled (Level 3) - {name: ":enabled pseudo-class selector, matching all disabled form controls (1)", selector: "#pseudo-ui :disabled", ctx: "", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + {name: ":disabled pseudo-class selector, matching all disabled form controls (1)", selector: "#pseudo-ui :disabled", ctx: "", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_FIND | TEST_MATCH}, + {name: ":disabled pseudo-class selector, not matching link elements (1)", selector: "#pseudo-link :disabled", ctx: "", expect: [] /*no matches*/, unexpected: ["pseudo-link-a1","pseudo-link-a2","pseudo-link-a3","pseudo-link-map1","pseudo-link-area1","pseudo-link-area2"], level: 3, testType: TEST_QSA | TEST_MATCH}, // - :checked (Level 3) {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes (1)", selector: "#pseudo-ui :checked", ctx: "", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_FIND | TEST_MATCH},
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/document-level-apis.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/document-level-apis.html index 2d8c49c..4a8a9a2 100644 --- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/document-level-apis.html +++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/document-level-apis.html
@@ -31,4 +31,4 @@ }, "The hasFocus() method must return false if the Document has no browsing context"); </script> -<iframe id="fr" src="test.html" onload="frame_load()"></iframe> +<iframe id="fr" src="support/test.html" onload="frame_load()"></iframe>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/test.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/support/test.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/test.html rename to third_party/blink/web_tests/external/wpt/html/interaction/focus/document-level-focus-apis/support/test.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/selectors/pseudo-classes/enabled-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/selectors/pseudo-classes/enabled-expected.txt deleted file mode 100644 index c92dbef..0000000 --- a/third_party/blink/web_tests/external/wpt/html/semantics/selectors/pseudo-classes/enabled-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL ':enabled' elements that are not disabled assert_array_equals: lengths differ, expected 8 got 10 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.https.window.js index a4eb287..fd2ff88 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemBaseHandle-remove.tentative.https.window.js
@@ -44,19 +44,19 @@ promise_test(async t => { const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); const dir = await createDirectory(t, 'dir', root); - await promise_rejects(t, 'NotFoundError', dir.removeEntry("")); + await promise_rejects(t, new TypeError(), dir.removeEntry("")); }, 'removeEntry() with empty name should fail'); promise_test(async t => { const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); const dir = await createDirectory(t, 'dir', root); - await promise_rejects(t, 'SecurityError', dir.removeEntry(kCurrentDirectory)); + await promise_rejects(t, new TypeError(), dir.removeEntry(kCurrentDirectory)); }, `removeEntry() with "${kCurrentDirectory}" name should fail`); promise_test(async t => { const root = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); const dir = await createDirectory(t, 'dir', root); - await promise_rejects(t, 'SecurityError', dir.removeEntry(kParentDirectory)); + await promise_rejects(t, new TypeError(), dir.removeEntry(kParentDirectory)); }, `removeEntry() with "${kParentDirectory}" name should fail`); promise_test(async t => { @@ -70,7 +70,7 @@ for (let i = 0; i < kPathSeparators.length; ++i) { const path_with_separator = `${dir_name}${kPathSeparators[i]}${file_name}`; - await promise_rejects(t, 'SecurityError', root.removeEntry(path_with_separator), + await promise_rejects(t, new TypeError(), root.removeEntry(path_with_separator), `removeEntry() must reject names containing "${kPathSeparators[i]}"`); } }, 'removeEntry() with a path separator should fail.');
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.https.window.js index 2064fc4..79154b0 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getDirectory.tentative.https.window.js
@@ -58,22 +58,22 @@ promise_test(async t => { const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); - await promise_rejects(t, 'NotFoundError', dir.getDirectory("", { create: true })); - await promise_rejects(t, 'NotFoundError', dir.getDirectory("", { create: false })); + await promise_rejects(t, new TypeError(), dir.getDirectory("", { create: true })); + await promise_rejects(t, new TypeError(), dir.getDirectory("", { create: false })); }, 'getDirectory() with empty name'); promise_test(async t => { const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); - await promise_rejects(t, 'SecurityError', dir.getDirectory(kCurrentDirectory)); - await promise_rejects(t, 'SecurityError', dir.getDirectory(kCurrentDirectory, { create: true })); + await promise_rejects(t, new TypeError(), dir.getDirectory(kCurrentDirectory)); + await promise_rejects(t, new TypeError(), dir.getDirectory(kCurrentDirectory, { create: true })); }, `getDirectory() with "${kCurrentDirectory}" name`); promise_test(async t => { const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); const subdir = await createDirectory(t, 'subdir-name', /*parent=*/dir); - await promise_rejects(t, 'SecurityError', subdir.getDirectory(kParentDirectory)); - await promise_rejects(t, 'SecurityError', subdir.getDirectory(kParentDirectory, { create: true })); + await promise_rejects(t, new TypeError(), subdir.getDirectory(kParentDirectory)); + await promise_rejects(t, new TypeError(), subdir.getDirectory(kParentDirectory, { create: true })); }, `getDirectory() with "${kParentDirectory}" name`); promise_test(async t => { @@ -87,7 +87,7 @@ for (let i = 0; i < kPathSeparators.length; ++i) { const path_with_separator = `${first_subdir_name}${kPathSeparators[i]}${second_subdir_name}`; - await promise_rejects(t, 'SecurityError', dir.getDirectory(path_with_separator), + await promise_rejects(t, new TypeError(), dir.getDirectory(path_with_separator), `getDirectory() must reject names containing "${kPathSeparators[i]}"`); } }, 'getDirectory(create=false) with a path separator when the directory exists'); @@ -100,7 +100,7 @@ for (let i = 0; i < kPathSeparators.length; ++i) { const path_with_separator = `${subdir_name}${kPathSeparators[i]}file_name`; - await promise_rejects(t, 'SecurityError', dir.getDirectory(path_with_separator, { create: true }), + await promise_rejects(t, new TypeError(), dir.getDirectory(path_with_separator, { create: true }), `getDirectory(true) must reject names containing "${kPathSeparators[i]}"`); } }, 'getDirectory(create=true) with a path separator');
diff --git a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.https.window.js index 473cad4..fa38abb 100644 --- a/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/native-file-system/FileSystemDirectoryHandle-getFile.tentative.https.window.js
@@ -63,22 +63,22 @@ promise_test(async t => { const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); - await promise_rejects(t, 'NotFoundError', dir.getFile("", { create: true })); - await promise_rejects(t, 'NotFoundError', dir.getFile("", { create: false })); + await promise_rejects(t, new TypeError(), dir.getFile("", { create: true })); + await promise_rejects(t, new TypeError(), dir.getFile("", { create: false })); }, 'getFile() with empty name'); promise_test(async t => { const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); - await promise_rejects(t, 'SecurityError', dir.getFile(kCurrentDirectory)); - await promise_rejects(t, 'SecurityError', dir.getFile(kCurrentDirectory, { create: true })); + await promise_rejects(t, new TypeError(), dir.getFile(kCurrentDirectory)); + await promise_rejects(t, new TypeError(), dir.getFile(kCurrentDirectory, { create: true })); }, `getFile() with "${kCurrentDirectory}" name`); promise_test(async t => { const dir = await FileSystemDirectoryHandle.getSystemDirectory({ type: 'sandbox' }); const subdir = await createDirectory(t, 'subdir-name', /*parent=*/dir); - await promise_rejects(t, 'SecurityError', subdir.getFile(kParentDirectory)); - await promise_rejects(t, 'SecurityError', subdir.getFile(kParentDirectory, { create: true })); + await promise_rejects(t, new TypeError(), subdir.getFile(kParentDirectory)); + await promise_rejects(t, new TypeError(), subdir.getFile(kParentDirectory, { create: true })); }, `getFile() with "${kParentDirectory}" name`); promise_test(async t => { @@ -92,7 +92,7 @@ for (let i = 0; i < kPathSeparators.length; ++i) { const path_with_separator = `${subdir_name}${kPathSeparators[i]}${file_name}`; - await promise_rejects(t, 'SecurityError', dir.getFile(path_with_separator), + await promise_rejects(t, new TypeError(), dir.getFile(path_with_separator), `getFile() must reject names containing "${kPathSeparators[i]}"`); } }, 'getFile(create=false) with a path separator when the file exists.'); @@ -105,7 +105,7 @@ for (let i = 0; i < kPathSeparators.length; ++i) { const path_with_separator = `${subdir_name}${kPathSeparators[i]}file_name`; - await promise_rejects(t, 'SecurityError', dir.getFile(path_with_separator, { create: true }), + await promise_rejects(t, new TypeError(), dir.getFile(path_with_separator, { create: true }), `getFile(true) must reject names containing "${kPathSeparators[i]}"`); } }, 'getFile(create=true) with a path separator');
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py index 588e0b2..b1e86ff 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -2,6 +2,7 @@ import hashlib from six.moves.http_client import HTTPConnection import io +import json import os import threading import traceback @@ -615,15 +616,16 @@ except KeyError: raise ValueError("Unknown action %s" % action) try: - action_handler(payload) + result = action_handler(payload) except Exception: self.logger.warning("Action %s failed" % action) self.logger.warning(traceback.format_exc()) self._send_message("complete", "error") raise else: - self.logger.debug("Action %s completed" % action) - self._send_message("complete", "success") + self.logger.debug("Action %s completed with result %s" % (action, result)) + return_message = {"result": result} + self._send_message("complete", "success", json.dumps(return_message)) return False, None
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testdriver-extra.js b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testdriver-extra.js index e23073d..9f97fac 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testdriver-extra.js +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/testdriver-extra.js
@@ -3,6 +3,7 @@ (function(){ let pending_resolve = null; let pending_reject = null; + let result = null; window.addEventListener("message", function(event) { const data = event.data; @@ -15,7 +16,8 @@ } if (data.status === "success") { - pending_resolve(); + result = JSON.parse(data.message).result + pending_resolve(result); } else { pending_reject(); }
diff --git a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html index 16956ca..65a65ca8 100644 --- a/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html +++ b/third_party/blink/web_tests/fast/css/forced-colors-mode/forced-colors-mode-12.html
@@ -4,7 +4,7 @@ Forced colors mode - animations. Tests that animation colors are overridden in forced colors mode. </title> - <style type="text/css"> + <style type="text/css" media="screen"> #forcedtextcolor { color: WindowText; forced-color-adjust: none; @@ -26,7 +26,7 @@ <p id="forcedtextcolor"></p> </body> -<script src="../../../animations/resources/animation-test-helpers.js"></script> +<script src="../../../animations/resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8"> var textcolor = getComputedStyle(forcedtextcolor).color; const expectedValues = [
diff --git a/third_party/blink/web_tests/fast/text/emoji-vertical-origin-visual-expected.png b/third_party/blink/web_tests/fast/text/emoji-vertical-origin-visual-expected.png deleted file mode 100644 index e69eac4..0000000 --- a/third_party/blink/web_tests/fast/text/emoji-vertical-origin-visual-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/emulation/emulation-user-agent-override.js b/third_party/blink/web_tests/http/tests/inspector-protocol/emulation/emulation-user-agent-override.js index d0d1780..f3137aa 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/emulation/emulation-user-agent-override.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/emulation/emulation-user-agent-override.js
@@ -11,11 +11,11 @@ testRunner.log('navigator.language == ' + await session.evaluate('navigator.language')); // Worker Accept Language - await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, flatten: true}); await session.evaluate(`var w = new Worker('${testRunner.url('resources/worker.js')}')`); let event = await dp.Target.onceAttachedToTarget(); - const worker = new WorkerProtocol(dp, event.params.sessionId); - await worker.dp.Emulation.setUserAgentOverride({userAgent: '', acceptLanguage: 'ko, en, zh-CN, zh-HK, en-US, en-GB'}); + const workerSession = session.createChild(event.params.sessionId); + await workerSession.protocol.Emulation.setUserAgentOverride({userAgent: '', acceptLanguage: 'ko, en, zh-CN, zh-HK, en-US, en-GB'}); testRunner.log('workerNavigator.language == ' + await session.evaluateAsync(` w.postMessage('ping!'); new Promise(resolve => w.onmessage = e => resolve(e.data.language))`));
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/resume-on-close.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/resume-on-close.js index b0a11caf..3f74278 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/resume-on-close.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/resume-on-close.js
@@ -11,20 +11,12 @@ var event = await dp.Target.onceTargetInfoChanged(event => event.params.targetInfo.url.endsWith('inspector-protocol-page.html')); var targetId = event.params.targetInfo.targetId; - var sessionId = (await dp.Target.attachToTarget({targetId: targetId})).result.sessionId; + var sessionId = (await dp.Target.attachToTarget({targetId: targetId, flatten: true})).result.sessionId; + const childSession = session.createChild(sessionId); testRunner.log('Attached to a second window'); - await dp.Target.sendMessageToTarget({ - sessionId: sessionId, - message: JSON.stringify({id: 1, method: 'Debugger.enable'}) - }); - dp.Target.sendMessageToTarget({ - sessionId: sessionId, - message: JSON.stringify({id: 2, method: 'Runtime.evaluate', params: {expression: 'debugger;'}}) - }); - await dp.Target.onceReceivedMessageFromTarget(event => { - var message = JSON.parse(event.params.message); - return message.method === 'Debugger.paused'; - }); + await childSession.protocol.Debugger.enable(); + childSession.evaluate('debugger;'); + await childSession.protocol.Debugger.oncePaused(); testRunner.log('Paused in a second window'); session.evaluate(`
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js index c91fe608..70b20f8 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js
@@ -1,5 +1,6 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank('Tests that one can evaluate in worker while main page is paused.'); + const {page, session, dp} = await testRunner.startBlank( + 'Tests that one can evaluate in worker while main page is paused.'); await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker.js')}'); @@ -8,32 +9,20 @@ `); testRunner.log('Started worker'); - var workerRequestId = 1; - function sendCommandToWorker(method, params) { - var message = {method, params, id: workerRequestId}; - dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); - return workerRequestId++; - } - dp.Debugger.enable(); dp.Runtime.evaluate({expression: 'debugger;' }); await dp.Debugger.oncePaused(); testRunner.log(`Paused on 'debugger;'`); - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: true}); - var messageObject = await dp.Target.onceAttachedToTarget(); - var workerId = messageObject.params.targetInfo.targetId; + const messageObject = await dp.Target.onceAttachedToTarget(); testRunner.log('Worker created'); testRunner.log('didConnectToWorker'); - var savedWorkerRequestId = sendCommandToWorker('Runtime.evaluate', {expression: '1+1'}); - dp.Target.onReceivedMessageFromTarget(messageObject => { - var message = JSON.parse(messageObject.params.message); - if (message.id === savedWorkerRequestId) { - var value = message.result.result.value; - testRunner.log('Successfully evaluated, result: ' + value); - testRunner.completeTest(); - } - }); + const childSession = session.createChild(messageObject.params.sessionId); + const result = await childSession.evaluateAsync('1+1'); + testRunner.log('Successfully evaluated, result: ' + result); + testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt index 8b5a2ad..43b8fd9 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop-expected.txt
@@ -5,5 +5,5 @@ Did enable debugger Did post message to worker Paused in worker -SUCCESS: evaluated, result: true +SUCCESS: messageId > 1
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js index 1047ca1..dd76cf3 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker-loop.js
@@ -1,6 +1,10 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank('Tests that worker can be interrupted with Debugger.pause.'); + var {page, session, dp} = await testRunner.startBlank( + 'Tests that worker can be interrupted with Debugger.pause.'); + await dp.Target.setAutoAttach({autoAttach: true, + waitForDebuggerOnStart: false, + flatten: true}); await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker-loop.js')}'); var resolve; @@ -12,48 +16,34 @@ `); testRunner.log('Started worker'); - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) { - var message = {method, params, id: workerRequestId}; - dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); - return workerRequestId++; - } - - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); - - var debuggerEnableRequestId = -1; - var evaluateRequestId = -1; - var pauseRequestId = -1; - - dp.Target.onReceivedMessageFromTarget(async messageObject => { - var message = JSON.parse(messageObject.params.message); - if (message.id === debuggerEnableRequestId) { - testRunner.log('Did enable debugger'); - // Start tight loop in the worker. - await dp.Runtime.evaluate({expression: 'worker.postMessage(1)' }); - testRunner.log('Did post message to worker'); - } - if (message.id === pauseRequestId) { - testRunner.log('Paused in worker'); - evaluateRequestId = sendCommandToWorker('Runtime.evaluate', { 'expression': 'message_id > 1'}); - } - if (message.id === evaluateRequestId) { - var value = message.result.result.value; - if (value === true) - testRunner.log('SUCCESS: evaluated, result: ' + value); - else - testRunner.log('FAIL: evaluated, result: ' + value); - testRunner.completeTest(); - } - }); - - workerId = (await dp.Target.onceAttachedToTarget()).params.targetInfo.targetId; + const sessionId = (await dp.Target.onceAttachedToTarget()).params.sessionId; testRunner.log('Worker created'); testRunner.log('didConnectToWorker'); - // Enable debugger so that V8 can interrupt and handle inspector commands while there is a script running in a tight loop. - debuggerEnableRequestId = sendCommandToWorker('Debugger.enable', {}); + + const childSession = session.createChild(sessionId); + + // Enable debugger so that V8 can interrupt and handle inspector + // commands while there is a script running in a tight loop. + + await childSession.protocol.Debugger.enable(); + testRunner.log('Did enable debugger'); + + // Start tight loop in the worker. + await session.evaluate('worker.postMessage(1);'); + testRunner.log('Did post message to worker'); await session.evaluateAsync('workerMessageReceivedPromise'); - pauseRequestId = sendCommandToWorker('Debugger.pause', {}); + + await childSession.protocol.Debugger.pause(); + await childSession.protocol.Debugger.oncePaused(); + testRunner.log('Paused in worker'); + + const messageId = await childSession.evaluate('message_id'); + if (messageId > 1) { + testRunner.log('SUCCESS: messageId > 1'); + } else { + testRunner.log('FAIL: evaluated, messageId: ' + message_id); + } + + testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js index 3839bdae..27b30b7 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-pause-dedicated-worker.js
@@ -1,5 +1,6 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank('Tests that worker can be paused.'); + const {page, session, dp} = await testRunner.startBlank( + 'Tests that worker can be paused.'); await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker.js')}'); @@ -8,17 +9,19 @@ `); testRunner.log('Started worker'); - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: true}); - let event = await dp.Target.onceAttachedToTarget(); - const worker = new WorkerProtocol(dp, event.params.sessionId); + const event = await dp.Target.onceAttachedToTarget(); + const childSession = session.createChild(event.params.sessionId); testRunner.log('Worker created'); testRunner.log('didConnectToWorker'); - await worker.dp.Debugger.enable({}); - worker.dp.Debugger.pause({}); - await worker.dp.Debugger.oncePaused(); + await childSession.protocol.Debugger.enable({}); + childSession.protocol.Debugger.pause({}); + await childSession.protocol.Debugger.oncePaused(); testRunner.log('SUCCESS: Worker paused'); - await worker.dp.Debugger.disable({}); + + await childSession.protocol.Debugger.disable({}); testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js index 8fd4e8d..a067d39 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-setTimeout-sourceUrl-dedicated-worker-loop.js
@@ -1,5 +1,9 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank('Tests sourceURL in setTimeout from worker.'); + const {page, session, dp} = await testRunner.startBlank( + 'Tests sourceURL in setTimeout from worker.'); + + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: true}); await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker-string-setTimeout.js')}'); @@ -8,40 +12,36 @@ `); testRunner.log('Started worker'); - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) { - var message = {method, params, id: workerRequestId}; - dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); - return workerRequestId++; - } + const messageObject = await dp.Target.onceAttachedToTarget(); + const childSession = session.createChild(messageObject.params.sessionId); - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); - - var messageObject = await dp.Target.onceAttachedToTarget(); - workerId = messageObject.params.targetInfo.targetId; testRunner.log('Worker created'); testRunner.log('didConnectToWorker'); - var debuggerEnableRequestId = sendCommandToWorker('Debugger.enable', {}); - var postMessageToWorker = false; - dp.Target.onReceivedMessageFromTarget(async messageObject => { - var message = JSON.parse(messageObject.params.message); - if (message.id === debuggerEnableRequestId) { - testRunner.log('Did enable debugger'); - // Start setTimeout. - await dp.Runtime.evaluate({expression: 'worker.postMessage(1)'}); - postMessageToWorker = true; - testRunner.log('Did post message to worker'); - } + await childSession.protocol.Debugger.enable(); + testRunner.log('Did enable debugger'); - if (postMessageToWorker && message.method === 'Debugger.scriptParsed') { - var sourceUrl = message.params.url; - if (!sourceUrl) - testRunner.log('SUCCESS: script created from string parameter of setTimeout has no url'); - else - testRunner.log('FAIL: script created from string parameter of setTimeout has url ' + sourceUrl); - testRunner.completeTest(); - } - }); + // posting a message to the worker triggers the onmessage function in + // dedicated-worker-string-setTimeout.js, which calls setTimeout("foo()", 0); + // - and as a side-effect of that, "foo()" is getting parsed as it has to be + // evaluated. + // Whereas parsing the worker script itself would result in a Debugger.scriptParsed + // message that reports a result url, parsing this string results in a message + // that has the url field set to the empty string. + // We use this fact below to verify that indeed, we did evaluate setTimeout + // in the worker. + + session.evaluate('worker.postMessage(1)'); + testRunner.log('Did post message to worker'); + + const sourceUrl = + (await childSession.protocol.Debugger.onceScriptParsed()).params.url; + if (sourceUrl === '') { + testRunner.log('SUCCESS: script created from string parameter of ' + + 'setTimeout has no url'); + } else { + testRunner.log('FAIL: script created from string parameter of ' + + 'setTimeout has url ' + sourceUrl); + } + testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt index 776e622..df27325 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker-expected.txt
@@ -1,7 +1,8 @@ -Tests that dedicated worker won't crash on attempt to step into.Bug 232392. +Tests that dedicated worker won't crash on attempt to step into. Bug 232392. Started worker Worker created SUCCESS: Worker paused Stepping into... -SUCCESS: Worker paused +Paused in onmessage +Paused in doWork
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js index 67db6c4..46a637b 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-step-into-dedicated-worker.js
@@ -1,15 +1,9 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank(`Tests that dedicated worker won't crash on attempt to step into.Bug 232392.`); + const {page, session, dp} = await testRunner.startBlank( + `Tests that dedicated worker won't crash on attempt to step into. Bug 232392.`); - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) { - var message = {method, params, id: workerRequestId}; - dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); - return workerRequestId++; - } - - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true}); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true, + flatten: true}); await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker-step-into.js')}'); window.worker.onmessage = function(event) { }; @@ -17,25 +11,32 @@ `); testRunner.log('Started worker'); - var messageObject = await dp.Target.onceAttachedToTarget(); - workerId = messageObject.params.targetInfo.targetId; + const sessionId = (await dp.Target.onceAttachedToTarget()).params.sessionId; testRunner.log('Worker created'); - sendCommandToWorker('Debugger.enable', {}); - sendCommandToWorker('Runtime.runIfWaitingForDebugger', {}); + const childSession = session.createChild(sessionId); - var pauseCount = 0; - dp.Target.onReceivedMessageFromTarget(async messageObject => { - var message = JSON.parse(messageObject.params.message); - if (message.method === 'Debugger.paused') { - testRunner.log('SUCCESS: Worker paused'); - if (++pauseCount === 1) { - testRunner.log('Stepping into...'); - sendCommandToWorker('Debugger.stepInto', {}); - } else { - sendCommandToWorker('Debugger.disable', {}); - testRunner.completeTest(); - } - } - }); + await childSession.protocol.Debugger.enable(); + await childSession.protocol.Runtime.runIfWaitingForDebugger(); + + // onmessage in dedicated-worker-step-into.js will run into the + // debugger statement, pausing itself. Below, we step into a couple of times + // while recording the transition into 'doWork' in the worker script. + await childSession.protocol.Debugger.oncePaused(); + testRunner.log('SUCCESS: Worker paused'); + + testRunner.log('Stepping into...'); + await childSession.protocol.Debugger.stepInto(); + + const onMessageCallFrame = + (await childSession.protocol.Debugger.oncePaused()).params.callFrames[0]; + testRunner.log('Paused in ' + onMessageCallFrame.functionName); + + await childSession.protocol.Debugger.stepInto(); + const doWorkCallFrame = + (await childSession.protocol.Debugger.oncePaused()).params.callFrames[0]; + testRunner.log('Paused in ' + doWorkCallFrame.functionName); + + await childSession.protocol.Debugger.disable(); + testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js index fd189a2..eda1be9 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-terminate-dedicated-worker-while-paused.js
@@ -1,25 +1,25 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank( + const {page, session, dp} = await testRunner.startBlank( `Test that inspected page won't crash if inspected worker is terminated while it is paused. Test passes if it doesn't crash. Bug 101065.`); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: true}); + await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker.js')}'); window.worker.onmessage = function(event) { }; window.worker.postMessage(1); `); testRunner.log('Started worker'); - - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); - - let event = await dp.Target.onceAttachedToTarget(); - const worker = new WorkerProtocol(dp, event.params.sessionId); + const sessionId = (await dp.Target.onceAttachedToTarget()).params.sessionId; + const childSession = session.createChild(sessionId); testRunner.log('Worker created'); testRunner.log('didConnectToWorker'); - await worker.dp.Debugger.enable({}); - worker.dp.Debugger.pause({}); - await worker.dp.Debugger.oncePaused(); + await childSession.protocol.Debugger.enable(); + childSession.protocol.Debugger.pause(); + await childSession.protocol.Debugger.oncePaused(); testRunner.log('Worker paused'); - await dp.Runtime.evaluate({expression: 'worker.terminate()' }); + await session.evaluate('worker.terminate()'); testRunner.log('SUCCESS: Did terminate paused worker'); testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js index 21764d4..aca1ee9e 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js
@@ -1,7 +1,8 @@ (async function(testRunner) { var {page, session, dp} = await testRunner.startBlank( 'Tests that tasks order is not changed when worker is resumed.'); - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true}); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true, + flatten: true}); await session.evaluate(` const workerScript = \` @@ -22,20 +23,20 @@ `); const event = await dp.Target.onceAttachedToTarget(); - const worker = new WorkerProtocol(dp, event.params.sessionId); + const childSession = session.createChild(event.params.sessionId); testRunner.log('Worker created'); - await worker.dp.Debugger.enable(); + await childSession.protocol.Debugger.enable(); - worker.dp.Runtime.runIfWaitingForDebugger(); - await worker.dp.Debugger.oncePaused(); + childSession.protocol.Runtime.runIfWaitingForDebugger(); + await childSession.protocol.Debugger.oncePaused(); await session.evaluate(`worker.postMessage(2)`); - worker.dp.Debugger.resume(); - await worker.dp.Debugger.oncePaused(); - const result = await worker.dp.Runtime.evaluate({expression: 'self.count'}); - testRunner.log(`count must be 1: ${result.result.value}`); + childSession.protocol.Debugger.resume(); + await childSession.protocol.Debugger.oncePaused(); + const value = await childSession.evaluate('self.count'); + testRunner.log(`count must be 1: ${value}`); - await worker.dp.Debugger.disable(); + await childSession.protocol.Debugger.disable(); testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt b/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt index 492170a..d28289e 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker-expected.txt
@@ -1,4 +1,4 @@ -Tests that setTimeout callback will not fire while script execution is paused.Bug 377926. +Tests that setTimeout callback will not fire while script execution is paused. Bug 377926. Started worker Worker created SUCCESS: Worker paused
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js b/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js index 2e14aea1..0f72fa9 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/suspend-setTimeout-on-pause-in-dedicated-worker.js
@@ -1,15 +1,8 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank('Tests that setTimeout callback will not fire while script execution is paused.Bug 377926.'); + const {page, session, dp} = await testRunner.startBlank('Tests that setTimeout callback will not fire while script execution is paused. Bug 377926.'); - var workerId; - var workerRequestId = 1; - function sendCommandToWorker(method, params) { - var message = {method, params, id: workerRequestId}; - dp.Target.sendMessageToTarget({targetId: workerId, message: JSON.stringify(message)}); - return workerRequestId++; - } - - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true}); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true, + flatten: true}); await session.evaluate(` window.worker = new Worker('${testRunner.url('resources/dedicated-worker-suspend-setTimeout.js')}'); window.worker.onmessage = function(event) { }; @@ -17,33 +10,20 @@ `); testRunner.log('Started worker'); - var messageObject = await dp.Target.onceAttachedToTarget(); - workerId = messageObject.params.targetInfo.targetId; + const event = await dp.Target.onceAttachedToTarget(); + const childSession = session.createChild(event.params.sessionId); testRunner.log('Worker created'); - sendCommandToWorker('Debugger.enable', {}); - sendCommandToWorker('Runtime.runIfWaitingForDebugger', {}); - - var pauseCount = 0; - var evalRequestId; - dp.Target.onReceivedMessageFromTarget(async messageObject => { - var message = JSON.parse(messageObject.params.message); - if (message.method === 'Debugger.paused') { - testRunner.log('SUCCESS: Worker paused'); - if (++pauseCount === 1) { - evalRequestId = sendCommandToWorker('Runtime.evaluate', {expression: 'global_value'}); - } else { - testRunner.log('FAIL: debugger paused second time'); - testRunner.completeTest(); - } - } else if (evalRequestId && message.id === evalRequestId) { - var value = message.result.result.value; - if (value === 1) - testRunner.log('SUCCESS: global_value is 1'); - else - testRunner.log('FAIL: setTimeout callback fired while script execution was paused'); - sendCommandToWorker('Debugger.disable', {}); - testRunner.completeTest(); - } - }); + await childSession.protocol.Debugger.enable(); + await childSession.protocol.Runtime.runIfWaitingForDebugger(); + await childSession.protocol.Debugger.oncePaused(); + testRunner.log('SUCCESS: Worker paused'); + const value = await childSession.evaluate('global_value'); + if (value === 1) { + // If the setTimeout in dedicated-worker-suspend-setTimeout.js + // had fired, global_value === 2014. + testRunner.log('SUCCESS: global_value is 1'); + } + await childSession.protocol.Debugger.disable(); + testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/inspector-protocol/target/target-send-message.js b/third_party/blink/web_tests/inspector-protocol/target/target-send-message.js index b0eb3e18..dab4c68 100644 --- a/third_party/blink/web_tests/inspector-protocol/target/target-send-message.js +++ b/third_party/blink/web_tests/inspector-protocol/target/target-send-message.js
@@ -7,7 +7,11 @@ window.worker.postMessage(1); `); - dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + // TODO(johannes): We plan to retire the non-flattened mode, in which + // case there's no need for this test. Or if we do want to keep it, it should + // use child sessions. See also crbug.com/991325. + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: false}); let {params:{sessionId}} = await dp.Target.onceAttachedToTarget(); let p = dp.Target.onceReceivedMessageFromTarget();
diff --git a/third_party/blink/web_tests/inspector-protocol/worker/exception-from-worker-contains-stack.js b/third_party/blink/web_tests/inspector-protocol/worker/exception-from-worker-contains-stack.js index c49b3f1c..076ee104 100644 --- a/third_party/blink/web_tests/inspector-protocol/worker/exception-from-worker-contains-stack.js +++ b/third_party/blink/web_tests/inspector-protocol/worker/exception-from-worker-contains-stack.js
@@ -1,7 +1,9 @@ (async function(testRunner) { - var {page, session, dp} = await testRunner.startBlank('Tests that console message from worker contains stack trace.'); + const {page, session, dp} = await testRunner.startBlank( + 'Tests that console message from worker contains stack trace.'); - await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}); + await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: true}); session.evaluate(` window.worker1 = new Worker('${testRunner.url('../resources/worker-with-throw.js')}'); @@ -11,9 +13,9 @@ } `); let event = await dp.Target.onceAttachedToTarget(); - const worker1 = new WorkerProtocol(dp, event.params.sessionId); + const childSession = session.createChild(event.params.sessionId); testRunner.log('Worker created'); - await worker1.dp.Runtime.enable({}); + await childSession.protocol.Runtime.enable(); session.evaluate('worker1.postMessage(239);'); await dp.Target.onceDetachedFromTarget(); testRunner.log('Worker destroyed'); @@ -22,13 +24,13 @@ window.worker2 = new Worker('${testRunner.url('../resources/worker-with-throw.js')}'); `); event = await dp.Target.onceAttachedToTarget(); - const worker2 = new WorkerProtocol(dp, event.params.sessionId); + const childSession2 = session.createChild(event.params.sessionId); testRunner.log('\nWorker created'); - await worker2.dp.Runtime.enable({}); + await childSession2.protocol.Runtime.enable(); session.evaluate('worker2.postMessage(42);'); - event = await worker2.dp.Runtime.onceExceptionThrown(); - const callFrames = event.exceptionDetails.stackTrace ? event.exceptionDetails.stackTrace.callFrames : []; + event = await childSession2.protocol.Runtime.onceExceptionThrown(); + const callFrames = event.params.exceptionDetails.stackTrace ? event.params.exceptionDetails.stackTrace.callFrames : []; testRunner.log(callFrames.length > 0 ? 'Message with stack trace received.' : '[FAIL] Message contains empty stack trace'); testRunner.completeTest();
diff --git a/third_party/blink/web_tests/inspector-protocol/worker/worker-autoattach-order.js b/third_party/blink/web_tests/inspector-protocol/worker/worker-autoattach-order.js index 812bf5a..25d58be 100644 --- a/third_party/blink/web_tests/inspector-protocol/worker/worker-autoattach-order.js +++ b/third_party/blink/web_tests/inspector-protocol/worker/worker-autoattach-order.js
@@ -1,6 +1,7 @@ (async function(testRunner) { - var {page, session, dp} = - await testRunner.startBlank('Target.setAutoAttach should report all workers before returning.'); + const {page, session, dp} = + await testRunner.startBlank( + 'Target.setAutoAttach should report all workers before returning.'); await session.evaluate(` const w1 = new Worker('${testRunner.url('../resources/worker-console-worker.js')}'); @@ -10,16 +11,22 @@ Promise.all([promise1, promise2]); `); - let resolved = false; - const autoAttach = dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false}).then(() => { - resolved = true; - }); + let autoAttachPromiseResolved = false; + + const autoAttachPromise = dp.Target.setAutoAttach({ + autoAttach: true, waitForDebuggerOnStart: false, flatten: true}).then( + () => { autoAttachPromiseResolved = true; }); testRunner.log((await dp.Target.onceAttachedToTarget()).params.targetInfo.type); testRunner.log((await dp.Target.onceAttachedToTarget()).params.targetInfo.type); - testRunner.log('Before await. Resolved: ' + resolved); - await autoAttach; - testRunner.log('After await. Resolved: ' + resolved); + // Up to here, the promise from Target.setAutoAttach is still not resolved, + // meaning that we've received the attachedToTarget events before + // setAutoAttach has returned. We log this fact, and then show that our + // mechanism for testing (the autoAttachPromiseResolved variable) is + // working by awaiting and logging again. + testRunner.log('Before await. Resolved: ' + autoAttachPromiseResolved); + await autoAttachPromise; + testRunner.log('After await. Resolved: ' + autoAttachPromiseResolved); testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/platform/linux/virtual/audio-service/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/linux/virtual/audio-service/media/track/track-cue-rendering-vertical-expected.png new file mode 100644 index 0000000..d6e4c55 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/audio-service/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5518-brdr-t-01-e-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5518-brdr-t-01-e-expected.png index 7adf21b..37c34472 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5518-brdr-t-01-e-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5518-brdr-t-01-e-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5519-brdr-r-00-a-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5519-brdr-r-00-a-expected.png index 12905ba..dbe6ce70 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5519-brdr-r-00-a-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5519-brdr-r-00-a-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5520-brdr-b-01-e-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5520-brdr-b-01-e-expected.png index d7d8ad4..4f8452dc 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5520-brdr-b-01-e-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5520-brdr-b-01-e-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-00-a-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-00-a-expected.png index a9c339c..5ad7d68 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-00-a-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-00-a-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-01-e-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-01-e-expected.png index 9d9a573..8b185e98 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-01-e-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-brdr-l-01-e-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-ibrdr-l-00-a-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-ibrdr-l-00-a-expected.png index 002a349..73ff1d2 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-ibrdr-l-00-a-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0805-c5521-ibrdr-l-00-a-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-02-c-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-02-c-expected.png index 06393dc..63a2661 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-02-c-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-02-c-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-03-c-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-03-c-expected.png index bef3e63..594c3f53 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-03-c-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-03-c-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-04-c-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-04-c-expected.png index 641143b..db95f6f 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-04-c-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c414-flt-04-c-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltblck-01-d-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltblck-01-d-expected.png index 9c9aec7c..13d1c3d 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltblck-01-d-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltblck-01-d-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltcont-00-d-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltcont-00-d-g-expected.png index 29ab702..9b36866 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltcont-00-d-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltcont-00-d-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png index c89baf5..eba83e9 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-02-c-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-02-c-g-expected.png index 6b8f806..a40f6b1 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-02-c-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-02-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-03-c-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-03-c-g-expected.png index 7e91584..35a26e0 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-03-c-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwidth-03-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwrap-00-b-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwrap-00-b-expected.png index 5080d34..1eb3dd8e 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwrap-00-b-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5525-fltwrap-00-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5526-flthw-00-c-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5526-flthw-00-c-g-expected.png index 9e0f9289..90828ba 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t0905-c5526-flthw-00-c-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t0905-c5526-flthw-00-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-01-b-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-01-b-expected.png index ec18e66..fe76f2d7 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-01-b-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-01-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-03-b-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-03-b-g-expected.png index e3e2f5e..960c2b6 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-03-b-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-03-b-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-ln-01-d-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-ln-01-d-g-expected.png index c7cbfba..a3825fb 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-ln-01-d-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t090501-c414-flt-ln-01-d-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-l-00-b-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-l-00-b-g-expected.png index f7e8b264..d32967f5 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-l-00-b-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-l-00-b-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-r-00-b-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-r-00-b-g-expected.png index cdf118d..95b56d7a 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-r-00-b-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t090501-c5525-flt-r-00-b-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t100304-c43-rpl-bbx-01-d-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t100304-c43-rpl-bbx-01-d-g-expected.png index 1d627bd..c5b12dc 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t100304-c43-rpl-bbx-01-d-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t100304-c43-rpl-bbx-01-d-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t1202-counter-04-b-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t1202-counter-04-b-expected.png index e414f17..a51f9ac 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t1202-counter-04-b-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t1202-counter-04-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t1202-counters-04-b-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t1202-counters-04-b-expected.png index 257838b..6074803 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t1202-counters-04-b-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t1202-counters-04-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css2.1/t1205-c566-list-stl-01-c-g-expected.png b/third_party/blink/web_tests/platform/win/css2.1/t1205-c566-list-stl-01-c-g-expected.png index e8cedc1..7c520e2 100644 --- a/third_party/blink/web_tests/platform/win/css2.1/t1205-c566-list-stl-01-c-g-expected.png +++ b/third_party/blink/web_tests/platform/win/css2.1/t1205-c566-list-stl-01-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css/line-height-determined-by-primary-font-expected.png b/third_party/blink/web_tests/platform/win/fast/css/line-height-determined-by-primary-font-expected.png index 2528854..298ea51 100644 --- a/third_party/blink/web_tests/platform/win/fast/css/line-height-determined-by-primary-font-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/css/line-height-determined-by-primary-font-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png index 17c29624..8d1ca66 100644 --- a/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/dynamic/text-combine-expected.png b/third_party/blink/web_tests/platform/win/fast/dynamic/text-combine-expected.png index 7879011..7b7dceb 100644 --- a/third_party/blink/web_tests/platform/win/fast/dynamic/text-combine-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/dynamic/text-combine-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/encoding/invalid-UTF-8-expected.png b/third_party/blink/web_tests/platform/win/fast/encoding/invalid-UTF-8-expected.png index fb71d70..94729585 100644 --- a/third_party/blink/web_tests/platform/win/fast/encoding/invalid-UTF-8-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/encoding/invalid-UTF-8-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/events/updateLayoutForHitTest-expected.png b/third_party/blink/web_tests/platform/win/fast/events/updateLayoutForHitTest-expected.png index 095428c..4885bcc 100644 --- a/third_party/blink/web_tests/platform/win/fast/events/updateLayoutForHitTest-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/events/updateLayoutForHitTest-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/month/month-appearance-l10n-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/month/month-appearance-l10n-expected.png index ac11d8b..ea80f85 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/month/month-appearance-l10n-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/month/month-appearance-l10n-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/placeholder-position-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/placeholder-position-expected.png index 878fc23e..559635f 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/placeholder-position-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/placeholder-position-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/text/text-font-height-mismatch-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/text/text-font-height-mismatch-expected.png index 3b4f724..9b36490f 100644 --- a/third_party/blink/web_tests/platform/win/fast/forms/text/text-font-height-mismatch-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/forms/text/text-font-height-mismatch-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/inline/justify-emphasis-inline-box-expected.png b/third_party/blink/web_tests/platform/win/fast/inline/justify-emphasis-inline-box-expected.png index 3d88ee10..edd0612 100644 --- a/third_party/blink/web_tests/platform/win/fast/inline/justify-emphasis-inline-box-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/inline/justify-emphasis-inline-box-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/inline/vertical-align-with-fallback-fonts-expected.png b/third_party/blink/web_tests/platform/win/fast/inline/vertical-align-with-fallback-fonts-expected.png index 61b72bd..7f95a096 100644 --- a/third_party/blink/web_tests/platform/win/fast/inline/vertical-align-with-fallback-fonts-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/inline/vertical-align-with-fallback-fonts-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png index a485f1b..db2eebd 100644 --- a/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png index 99d43864..9d19e17 100644 --- a/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/ruby/nested-ruby-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/atsui-multiple-renderers-expected.png b/third_party/blink/web_tests/platform/win/fast/text/atsui-multiple-renderers-expected.png index bc96de2f..d266d77 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/atsui-multiple-renderers-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/atsui-multiple-renderers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/decorations-with-text-combine-expected.png b/third_party/blink/web_tests/platform/win/fast/text/decorations-with-text-combine-expected.png index fb2066b..a2dd6b0 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/decorations-with-text-combine-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/decorations-with-text-combine-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/emoji-vertical-origin-visual-expected.png b/third_party/blink/web_tests/platform/win/fast/text/emoji-vertical-origin-visual-expected.png index d2af031..c28fb30 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/emoji-vertical-origin-visual-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/emoji-vertical-origin-visual-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/emoticons-expected.png b/third_party/blink/web_tests/platform/win/fast/text/emoticons-expected.png index a31d3f0..73c59d9 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/emoticons-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/emoticons-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/001-expected.png b/third_party/blink/web_tests/platform/win/fast/text/international/001-expected.png index 86e3dae..2e8b1ca 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/001-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/international/001-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/002-expected.png b/third_party/blink/web_tests/platform/win/fast/text/international/002-expected.png index bf41402..f9f7310 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/002-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/international/002-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/003-expected.png b/third_party/blink/web_tests/platform/win/fast/text/international/003-expected.png index 7c846805..9bc877b8 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/003-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/international/003-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/plane2-expected.png b/third_party/blink/web_tests/platform/win/fast/text/international/plane2-expected.png index abeaed3..918a38d0 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/plane2-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/international/plane2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/thai-baht-space-expected.png b/third_party/blink/web_tests/platform/win/fast/text/international/thai-baht-space-expected.png index 74b0a25..79e932d 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/thai-baht-space-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/vertical-text-metrics-test-expected.txt b/third_party/blink/web_tests/platform/win/fast/text/international/vertical-text-metrics-test-expected.txt index f3a6e9a..ccf7340 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/vertical-text-metrics-test-expected.txt +++ b/third_party/blink/web_tests/platform/win/fast/text/international/vertical-text-metrics-test-expected.txt
@@ -14,9 +14,9 @@ -width=219 -width=34 -width=34 -width=219 -width=34 -width=34 +width=172 +width=28 +width=28 +width=172 +width=28 +width=28
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/wrap-CJK-001-expected.png b/third_party/blink/web_tests/platform/win/fast/text/international/wrap-CJK-001-expected.png index 3b26c9d..818c2bd 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/international/wrap-CJK-001-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/international/wrap-CJK-001-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-complex-expected.png b/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-complex-expected.png index 9879ec0..5e14f45d 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-complex-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-complex-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-leading-expansion-expected.png b/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-leading-expansion-expected.png index 106f9ed..c96411b0 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-leading-expansion-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-leading-expansion-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-simple-expected.png b/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-simple-expected.png index 9879ec0..5e14f45d 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-simple-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/justify-ideograph-simple-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/selection/emphasis-expected.png b/third_party/blink/web_tests/platform/win/fast/text/selection/emphasis-expected.png index 286c44b..a4d0a058 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/selection/emphasis-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/selection/emphasis-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/selection/selection-multiple-runs-expected.png b/third_party/blink/web_tests/platform/win/fast/text/selection/selection-multiple-runs-expected.png index d5318f1..743e911835 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/selection/selection-multiple-runs-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/selection/selection-multiple-runs-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/text/vertical-surrogate-pair-expected.png b/third_party/blink/web_tests/platform/win/fast/text/vertical-surrogate-pair-expected.png index 21c2115a..935ebd6 100644 --- a/third_party/blink/web_tests/platform/win/fast/text/vertical-surrogate-pair-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/text/vertical-surrogate-pair-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/Kusa-Makura-background-canvas-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/Kusa-Makura-background-canvas-expected.png index 3077512..53b5d8e 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/Kusa-Makura-background-canvas-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/Kusa-Makura-background-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/fallback-orientation-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/fallback-orientation-expected.png index b936777..e7d02562 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/fallback-orientation-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/fallback-orientation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png index 58fc3471..2bc60f5 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-lr-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png index 0190774..bdc77987 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/japanese-ruby-vertical-rl-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/text-combine-various-fonts-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/text-combine-various-fonts-expected.png index 0da523b..44a00e8 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/text-combine-various-fonts-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/text-combine-various-fonts-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-align-table-baseline-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-align-table-baseline-expected.png index 981883e..f38e6e95 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-align-table-baseline-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-align-table-baseline-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-baseline-alignment-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-baseline-alignment-expected.png index a212822..f0512a7 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-baseline-alignment-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-baseline-alignment-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-font-fallback-expected.png b/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-font-fallback-expected.png index 253d49d..42af1a7 100644 --- a/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-font-fallback-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/writing-mode/vertical-font-fallback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/color-profile-svg-fill-text-expected.png b/third_party/blink/web_tests/platform/win/images/color-profile-svg-fill-text-expected.png index b25ef45..98730be 100644 --- a/third_party/blink/web_tests/platform/win/images/color-profile-svg-fill-text-expected.png +++ b/third_party/blink/web_tests/platform/win/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/lang-fallback-expected.txt b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/lang-fallback-expected.txt index 267de59..65abf06 100644 --- a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/lang-fallback-expected.txt +++ b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/lang-fallback-expected.txt
@@ -32,7 +32,7 @@ ⲁⲂ #copt: -"Segoe UI Symbol" : 2 +"Segoe UI Historic" : 2 𒀀𒀌 #akk: @@ -60,7 +60,7 @@ ႠႡ #ka: -"Sylfaen" : 2 +"Segoe UI" : 2 ΑΒ #el: @@ -72,23 +72,23 @@ 我 #zh-CN: -"SimSun" : 1 +"Microsoft YaHei UI" : 1 我 #zh-HK: -"微軟正黑體" : 1 +"Microsoft JhengHei UI" : 1 我 #zh-Hans: -"SimSun" : 1 +"Microsoft YaHei UI" : 1 我 #zh-Hant: -"微軟正黑體" : 1 +"Microsoft JhengHei UI" : 1 我 #ja: -"Yu Gothic" : 1 +"Yu Gothic UI" : 1 ᄀᄁ #ko: @@ -228,7 +228,7 @@ กข #th: -"Tahoma" : 2 +"Leelawadee UI" : 2 ༁༂ #bo:
diff --git a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt index 9d897ec..c4d5c85 100644 --- a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt +++ b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
@@ -1,11 +1,11 @@ 百家姓 趙錢孫李 周吳鄭王 馮陳褚衛 蔣沈韓楊 朱秦尤許 何呂施張 孔曹嚴華 金魏陶薑 戚謝鄒喻 柏水竇章 雲蘇潘葛 奚範彭郎 魯韋昌馬 苗鳳花方 俞任袁柳 酆鮑史唐 費廉岑薛 雷賀倪湯 滕殷羅畢 郝鄔安常 樂於時傅 皮卞齊康 伍餘元蔔 顧孟平黃 和穆蕭尹 姚邵堪汪 祁毛禹狄 米貝明臧 計伏成戴 談宋茅龐 熊紀舒屈 項祝董梁 杜阮藍閔 席季麻強 賈路婁危 江童顏郭 梅盛林刁 鍾徐邱駱 高夏蔡田 樊胡淩霍 虞萬支柯 昝管盧莫 經房裘繆 幹解應宗 丁宣賁鄧 鬱單杭洪 包諸左石 崔吉鈕龔 程嵇邢滑 裴陸榮翁 荀羊於惠 甄曲家封 芮羿儲靳 汲邴糜松 井段富巫 烏焦巴弓 牧隗山穀 車侯宓蓬 全郗班仰 秋仲伊宮 寧仇欒暴 甘鈄厲戎 祖武符劉 景詹束龍 葉幸司韶 郜黎薊薄 印宿白懷 蒲台從鄂 索鹹籍賴 卓藺屠蒙 池喬陰鬱 胥能蒼雙 聞莘黨翟 譚貢勞逄 姬申扶堵 冉宰酈雍 卻璩桑桂 濮牛壽通 邊扈燕冀 郟浦尚農 溫別莊晏 柴瞿閻充 慕連茹習 宦艾魚容 向古易慎 戈廖庚終 暨居衡步 都耿滿弘 匡國文寇 廣祿闕東 毆殳沃利 蔚越夔隆 師鞏厙聶 晁勾敖融 冷訾辛闞 那簡饒空 曾毋沙乜 養鞠須豐 巢關蒯相 查後荊紅 遊竺權逯 蓋益桓公 萬俟司馬 上官歐陽 夏侯諸葛 聞人東方 赫連皇甫 尉遲公羊 澹台公冶 宗政濮陽 淳於單於 太叔申屠 公孫仲孫 軒轅令狐 鐘離宇文 長孫慕容 鮮於閭丘 司徒司空 亓官司寇 仉督子車 顓孫端木 巫馬公西 漆雕樂正 壤駟公良 拓拔夾穀 宰父穀粱 晉楚閆法 汝鄢塗欽 段幹百里 東郭南門 呼延歸海 羊舌微生 嶽帥緱亢 況後有琴 梁丘左丘 東門西門 商牟佘佴 伯賞南宮 墨哈譙笪 年愛陽佟 #hundred_chinese_surnames: -"SimSun" : 563, +"Microsoft YaHei UI" : 563, "Times New Roman" : 140 いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさき ゆめみし ゑひもせす(ん)色は匂へど 散りぬるを 我が世誰ぞ 常ならむ 有為の奥山 今日越えて 浅き夢見じ 酔ひもせず(ん) #japanese_iroha: -"Yu Gothic" : 92, +"Yu Gothic UI" : 92, "Times New Roman" : 15 키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다. @@ -45,8 +45,7 @@ ⇦⇧⇨⇩←↑→↓⟀ #text_presentation_arrows_maths: -"MS PGothic" : 4, -"Cambria Math" : 4, -"Segoe UI Symbol" : 1 +"Segoe UI Symbol" : 5, +"Yu Gothic UI" : 4
diff --git a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png index 457955f..eb467fd 100644 --- a/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/win/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.png index 5a2ff6e..4e808a1 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.png +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/repaint-across-writing-mode-boundary-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.png index 3b4e9e5..3ae185c 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.png +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt index f07a9556..31ff1ed 100644 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt +++ b/third_party/blink/web_tests/platform/win/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt
@@ -19,72 +19,72 @@ "paintInvalidations": [ { "object": "NGPhysicalTextFragment '\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3059\u3002\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A\u3089\u30BF\u30A4'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8'", - "rect": [307, 123, 470, 404], + "rect": [361, 123, 416, 404], "reason": "geometry" } ]
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-align-08-b-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-align-08-b-expected.png index 09ab3b14..ef5d4295 100644 --- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-align-08-b-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-align-08-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png index 5e43d41..ee0f65867 100644 --- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-01-t-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-01-t-expected.png index d8d24af..d0d25c7 100644 --- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-01-t-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-01-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-03-b-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-03-b-expected.png index fca5cfa6..b528d57 100644 --- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-03-b-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-03-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-04-t-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-04-t-expected.png index 35dc3f6..3f668d0 100644 --- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-04-t-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/text-intro-04-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/batik/text/verticalText-expected.png b/third_party/blink/web_tests/platform/win/svg/batik/text/verticalText-expected.png index fa79ddb..c30ad3cc 100644 --- a/third_party/blink/web_tests/platform/win/svg/batik/text/verticalText-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/batik/text/verticalText-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/hixie/intrinsic/003-expected.png b/third_party/blink/web_tests/platform/win/svg/hixie/intrinsic/003-expected.png index 2710c72..d84c6c2f 100644 --- a/third_party/blink/web_tests/platform/win/svg/hixie/intrinsic/003-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/hixie/intrinsic/003-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/text/non-bmp-positioning-lists-expected.png b/third_party/blink/web_tests/platform/win/svg/text/non-bmp-positioning-lists-expected.png index 67f0eb23..3e5c1b7 100644 --- a/third_party/blink/web_tests/platform/win/svg/text/non-bmp-positioning-lists-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/text/non-bmp-positioning-lists-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/text/text-selection-fonts-01-t-expected.png b/third_party/blink/web_tests/platform/win/svg/text/text-selection-fonts-01-t-expected.png index ddf2d50..d4645cff 100644 --- a/third_party/blink/web_tests/platform/win/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png index 281b7d8..e8db9b0 100644 --- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png index fa90c8d..018c7924 100644 --- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png +++ b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest-expected.png b/third_party/blink/web_tests/platform/win/virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest-expected.png deleted file mode 100644 index 095428c..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png b/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png index 71d138d..ea3fa15 100644 --- a/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png +++ b/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5526-flthw-00-c-g-expected.png b/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5526-flthw-00-c-g-expected.png new file mode 100644 index 0000000..9e0f9289 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/css2.1/t0905-c5526-flthw-00-c-g-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/css2.1/t1202-counter-04-b-expected.png b/third_party/blink/web_tests/platform/win7/css2.1/t1202-counter-04-b-expected.png deleted file mode 100644 index a51f9ac..0000000 --- a/third_party/blink/web_tests/platform/win7/css2.1/t1202-counter-04-b-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/css2.1/t1202-counters-04-b-expected.png b/third_party/blink/web_tests/platform/win7/css2.1/t1202-counters-04-b-expected.png deleted file mode 100644 index 6074803..0000000 --- a/third_party/blink/web_tests/platform/win7/css2.1/t1202-counters-04-b-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/css/line-height-determined-by-primary-font-expected.png b/third_party/blink/web_tests/platform/win7/fast/css/line-height-determined-by-primary-font-expected.png deleted file mode 100644 index d6bfc745..0000000 --- a/third_party/blink/web_tests/platform/win7/fast/css/line-height-determined-by-primary-font-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png b/third_party/blink/web_tests/platform/win7/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png index 310e767..79a595b8 100644 --- a/third_party/blink/web_tests/platform/win7/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/dynamic/text-combine-expected.png b/third_party/blink/web_tests/platform/win7/fast/dynamic/text-combine-expected.png index ab21af1..7f89007 100644 --- a/third_party/blink/web_tests/platform/win7/fast/dynamic/text-combine-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/dynamic/text-combine-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/encoding/invalid-UTF-8-expected.png b/third_party/blink/web_tests/platform/win7/fast/encoding/invalid-UTF-8-expected.png new file mode 100644 index 0000000..fb71d70 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/fast/encoding/invalid-UTF-8-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/datetimelocal/datetimelocal-appearance-l10n-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/datetimelocal/datetimelocal-appearance-l10n-expected.png index c1ef6b4..f307685f 100644 --- a/third_party/blink/web_tests/platform/win7/fast/forms/datetimelocal/datetimelocal-appearance-l10n-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/forms/datetimelocal/datetimelocal-appearance-l10n-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/forms/month/month-appearance-l10n-expected.png b/third_party/blink/web_tests/platform/win7/fast/forms/month/month-appearance-l10n-expected.png index 9706a66..f639a13 100644 --- a/third_party/blink/web_tests/platform/win7/fast/forms/month/month-appearance-l10n-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/forms/month/month-appearance-l10n-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/inline/justify-emphasis-inline-box-expected.png b/third_party/blink/web_tests/platform/win7/fast/inline/justify-emphasis-inline-box-expected.png index 9ed65d9..a5dbf9e 100644 --- a/third_party/blink/web_tests/platform/win7/fast/inline/justify-emphasis-inline-box-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/inline/justify-emphasis-inline-box-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/inline/vertical-align-with-fallback-fonts-expected.png b/third_party/blink/web_tests/platform/win7/fast/inline/vertical-align-with-fallback-fonts-expected.png index 1462ad4..3e16510 100644 --- a/third_party/blink/web_tests/platform/win7/fast/inline/vertical-align-with-fallback-fonts-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/inline/vertical-align-with-fallback-fonts-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png index f9461a7..0d944bf 100644 --- a/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/ruby/base-shorter-than-text-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png b/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png index dd56802..61b30d3 100644 --- a/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/ruby/nested-ruby-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/atsui-multiple-renderers-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/atsui-multiple-renderers-expected.png index f70a69b9..aed8979 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/atsui-multiple-renderers-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/atsui-multiple-renderers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/capitalize-boundaries-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/capitalize-boundaries-expected.png index 8fb044b..8273332 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/capitalize-boundaries-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/capitalize-boundaries-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/decorations-with-text-combine-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/decorations-with-text-combine-expected.png index c6041e7..1350e61 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/decorations-with-text-combine-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/decorations-with-text-combine-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/emoji-vertical-origin-visual-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/emoji-vertical-origin-visual-expected.png index dd7c153..3fd0f4f 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/emoji-vertical-origin-visual-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/emoji-vertical-origin-visual-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/font-fallback-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/font-fallback-expected.png index 61ee5a9..4243bd63 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/font-fallback-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/font-fallback-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/international/002-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/international/002-expected.png index 9e3b8d8..7113141 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/international/002-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/international/002-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/international/003-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/international/003-expected.png index a9bbf5a..7f3a327 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/international/003-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/international/003-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/international/plane2-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/international/plane2-expected.png index 02ab940..0b25df7 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/international/plane2-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/international/plane2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/international/thai-baht-space-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/international/thai-baht-space-expected.png index 92fee0e..bf375a32 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/international/thai-baht-space-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/international/thai-baht-space-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/international/vertical-text-metrics-test-expected.txt b/third_party/blink/web_tests/platform/win7/fast/text/international/vertical-text-metrics-test-expected.txt index d253f60..ce67f2a7 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/international/vertical-text-metrics-test-expected.txt +++ b/third_party/blink/web_tests/platform/win7/fast/text/international/vertical-text-metrics-test-expected.txt
@@ -14,9 +14,9 @@ -width=219 -width=32 -width=32 -width=219 -width=32 -width=32 +width=172 +width=27 +width=27 +width=172 +width=27 +width=27
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/international/wrap-CJK-001-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/international/wrap-CJK-001-expected.png index a92eb47..8ae19224 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/international/wrap-CJK-001-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/international/wrap-CJK-001-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-complex-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-complex-expected.png index 7004df4..43a13e8 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-complex-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-complex-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-leading-expansion-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-leading-expansion-expected.png index efb7c004..e15ecf7 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-leading-expansion-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-leading-expansion-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-simple-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-simple-expected.png index 7004df4..43a13e8 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-simple-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/justify-ideograph-simple-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/selection/emphasis-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/selection/emphasis-expected.png index 7b321cbe..e014f71 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/selection/emphasis-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/selection/emphasis-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/selection/selection-multiple-runs-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/selection/selection-multiple-runs-expected.png index 02561a67..9d94e9a 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/selection/selection-multiple-runs-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/selection/selection-multiple-runs-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/unicode-fallback-font-expected.png index 18a84d6e..d899116 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/unicode-fallback-font-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/unicode-fallback-font-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/text/vertical-surrogate-pair-expected.png b/third_party/blink/web_tests/platform/win7/fast/text/vertical-surrogate-pair-expected.png index 9e09153b..6a01b24 100644 --- a/third_party/blink/web_tests/platform/win7/fast/text/vertical-surrogate-pair-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/text/vertical-surrogate-pair-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/Kusa-Makura-background-canvas-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/Kusa-Makura-background-canvas-expected.png index 6d686c5..1f00f434 100644 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/Kusa-Makura-background-canvas-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/Kusa-Makura-background-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/fallback-orientation-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/fallback-orientation-expected.png index a3b3cfb..ff28af0 100644 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/fallback-orientation-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/fallback-orientation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png index 765fae82..f9ede55 100644 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-lr-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png index ba74600..bb1b03f 100644 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/japanese-ruby-vertical-rl-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/text-combine-various-fonts-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/text-combine-various-fonts-expected.png index ee00aea..9314104 100644 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/text-combine-various-fonts-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/text-combine-various-fonts-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-align-table-baseline-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-align-table-baseline-expected.png index 4a9a0fde..c49f57e 100644 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-align-table-baseline-expected.png +++ b/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-align-table-baseline-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-baseline-alignment-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-baseline-alignment-expected.png deleted file mode 100644 index 05663ac..0000000 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-baseline-alignment-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-font-fallback-expected.png b/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-font-fallback-expected.png deleted file mode 100644 index 82a92b8cb..0000000 --- a/third_party/blink/web_tests/platform/win7/fast/writing-mode/vertical-font-fallback-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt index 498be4d5..58df3f2 100644 --- a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt +++ b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt
@@ -4,7 +4,7 @@ ՀՁ #hy-am: -"Tahoma" : 2 +"Sylfaen" : 2 সম #bn: @@ -28,7 +28,7 @@ ᎡᎢ #chr: -"Arial" : 2 +"Plantagenet Cherokee" : 2 ⲁⲂ #copt: @@ -48,7 +48,7 @@ 𐐀𐐁 #en: -"Arial" : 2 +"Segoe UI Symbol" : 2 अआ #hi: @@ -72,23 +72,23 @@ 我 #zh-CN: -"SimSun" : 1 +"Microsoft YaHei" : 1 我 #zh-HK: -"PMingLiU" : 1 +"Microsoft JhengHei" : 1 我 #zh-Hans: -"SimSun" : 1 +"Microsoft YaHei" : 1 我 #zh-Hant: -"PMingLiU" : 1 +"Microsoft JhengHei" : 1 我 #ja: -"Meiryo" : 1 +"Meiryo UI" : 1 ᄀᄁ #ko: @@ -172,7 +172,7 @@ 𐌁𐌂 #script_old_italic: -"Arial" : 2 +"Segoe UI Symbol" : 2 𐎡𐎢 #peo: @@ -228,7 +228,7 @@ กข #th: -"Tahoma" : 2 +"Leelawadee" : 2 ༁༂ #bo:
diff --git a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt index d9b888df..b0e7d4d 100644 --- a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt +++ b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
@@ -1,11 +1,11 @@ 百家姓 趙錢孫李 周吳鄭王 馮陳褚衛 蔣沈韓楊 朱秦尤許 何呂施張 孔曹嚴華 金魏陶薑 戚謝鄒喻 柏水竇章 雲蘇潘葛 奚範彭郎 魯韋昌馬 苗鳳花方 俞任袁柳 酆鮑史唐 費廉岑薛 雷賀倪湯 滕殷羅畢 郝鄔安常 樂於時傅 皮卞齊康 伍餘元蔔 顧孟平黃 和穆蕭尹 姚邵堪汪 祁毛禹狄 米貝明臧 計伏成戴 談宋茅龐 熊紀舒屈 項祝董梁 杜阮藍閔 席季麻強 賈路婁危 江童顏郭 梅盛林刁 鍾徐邱駱 高夏蔡田 樊胡淩霍 虞萬支柯 昝管盧莫 經房裘繆 幹解應宗 丁宣賁鄧 鬱單杭洪 包諸左石 崔吉鈕龔 程嵇邢滑 裴陸榮翁 荀羊於惠 甄曲家封 芮羿儲靳 汲邴糜松 井段富巫 烏焦巴弓 牧隗山穀 車侯宓蓬 全郗班仰 秋仲伊宮 寧仇欒暴 甘鈄厲戎 祖武符劉 景詹束龍 葉幸司韶 郜黎薊薄 印宿白懷 蒲台從鄂 索鹹籍賴 卓藺屠蒙 池喬陰鬱 胥能蒼雙 聞莘黨翟 譚貢勞逄 姬申扶堵 冉宰酈雍 卻璩桑桂 濮牛壽通 邊扈燕冀 郟浦尚農 溫別莊晏 柴瞿閻充 慕連茹習 宦艾魚容 向古易慎 戈廖庚終 暨居衡步 都耿滿弘 匡國文寇 廣祿闕東 毆殳沃利 蔚越夔隆 師鞏厙聶 晁勾敖融 冷訾辛闞 那簡饒空 曾毋沙乜 養鞠須豐 巢關蒯相 查後荊紅 遊竺權逯 蓋益桓公 萬俟司馬 上官歐陽 夏侯諸葛 聞人東方 赫連皇甫 尉遲公羊 澹台公冶 宗政濮陽 淳於單於 太叔申屠 公孫仲孫 軒轅令狐 鐘離宇文 長孫慕容 鮮於閭丘 司徒司空 亓官司寇 仉督子車 顓孫端木 巫馬公西 漆雕樂正 壤駟公良 拓拔夾穀 宰父穀粱 晉楚閆法 汝鄢塗欽 段幹百里 東郭南門 呼延歸海 羊舌微生 嶽帥緱亢 況後有琴 梁丘左丘 東門西門 商牟佘佴 伯賞南宮 墨哈譙笪 年愛陽佟 #hundred_chinese_surnames: -"SimSun" : 563, +"Microsoft YaHei" : 563, "Times New Roman" : 140 いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさき ゆめみし ゑひもせす(ん)色は匂へど 散りぬるを 我が世誰ぞ 常ならむ 有為の奥山 今日越えて 浅き夢見じ 酔ひもせず(ん) #japanese_iroha: -"Meiryo" : 92, +"Meiryo UI" : 92, "Times New Roman" : 15 키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다. @@ -46,8 +46,8 @@ ⇦⇧⇨⇩←↑→↓⟀ #text_presentation_arrows_maths: -"MS PGothic" : 4, -"Cambria Math" : 4, +"Meiryo UI" : 4, +"Segoe UI Symbol" : 4, "Arial" : 1
diff --git a/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png index 12d70d3..1b7536f 100644 --- a/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png +++ b/third_party/blink/web_tests/platform/win7/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/paint/invalidation/repaint-across-writing-mode-boundary-expected.png b/third_party/blink/web_tests/platform/win7/paint/invalidation/repaint-across-writing-mode-boundary-expected.png deleted file mode 100644 index 51b1ae8..0000000 --- a/third_party/blink/web_tests/platform/win7/paint/invalidation/repaint-across-writing-mode-boundary-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.png b/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.png index 89df879..a9b94742 100644 --- a/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.png +++ b/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt b/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt index 48ed1fe..5972384a 100644 --- a/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt +++ b/third_party/blink/web_tests/platform/win7/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt
@@ -19,72 +19,72 @@ "paintInvalidations": [ { "object": "NGPhysicalTextFragment '\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3059\u3002\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A\u3089\u30BF\u30A4'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" }, { "object": "NGPhysicalTextFragment '\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8'", - "rect": [334, 123, 443, 404], + "rect": [413, 123, 364, 404], "reason": "geometry" } ]
diff --git a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-align-08-b-expected.png b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-align-08-b-expected.png index d6c1c62..9411fe1 100644 --- a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-align-08-b-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-align-08-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png index 50a1ade..98bbcc80 100644 --- a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-01-t-expected.png b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-01-t-expected.png index a9f0112e..f059f4c 100644 --- a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-01-t-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-01-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-03-b-expected.png b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-03-b-expected.png index 4f3f400a..d57e59b 100644 --- a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-03-b-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-03-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-04-t-expected.png b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-04-t-expected.png index 3007977..c20ede9 100644 --- a/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-04-t-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/W3C-SVG-1.1/text-intro-04-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/batik/text/verticalText-expected.png b/third_party/blink/web_tests/platform/win7/svg/batik/text/verticalText-expected.png index 07cce28..08b4c01f 100644 --- a/third_party/blink/web_tests/platform/win7/svg/batik/text/verticalText-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/batik/text/verticalText-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/hixie/intrinsic/003-expected.png b/third_party/blink/web_tests/platform/win7/svg/hixie/intrinsic/003-expected.png new file mode 100644 index 0000000..2710c72 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/svg/hixie/intrinsic/003-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/text/non-bmp-positioning-lists-expected.png b/third_party/blink/web_tests/platform/win7/svg/text/non-bmp-positioning-lists-expected.png new file mode 100644 index 0000000..67f0eb23 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/svg/text/non-bmp-positioning-lists-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png b/third_party/blink/web_tests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png index 67dd2f10..e3d039f 100644 --- a/third_party/blink/web_tests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/blink/web_tests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/audio-service/media/track/track-cue-rendering-vertical-expected.png b/third_party/blink/web_tests/platform/win7/virtual/audio-service/media/track/track-cue-rendering-vertical-expected.png new file mode 100644 index 0000000..1b7536f --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/virtual/audio-service/media/track/track-cue-rendering-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest-expected.png b/third_party/blink/web_tests/platform/win7/virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest-expected.png deleted file mode 100644 index 095428c..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/mouseevent_fractional/fast/events/updateLayoutForHitTest-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/ced/OWNERS b/third_party/ced/OWNERS index 70ea1bf7..38383bf 100644 --- a/third_party/ced/OWNERS +++ b/third_party/ced/OWNERS
@@ -1,2 +1,3 @@ jinsukkim@chromium.org jshin@chromium.org +# COMPONENT: Blink>TextEncoding
diff --git a/third_party/gestures/OWNERS b/third_party/gestures/OWNERS index 08777b4..b4b89bb 100644 --- a/third_party/gestures/OWNERS +++ b/third_party/gestures/OWNERS
@@ -1,2 +1,3 @@ adlr@chromium.org djkurtz@chromium.org +# COMPONENT: Internals>Input
diff --git a/third_party/junit/OWNERS b/third_party/junit/OWNERS index 4c6d1adc..6bc1824 100644 --- a/third_party/junit/OWNERS +++ b/third_party/junit/OWNERS
@@ -1,3 +1,4 @@ jbudorick@chromium.org mikecase@chromium.org +# COMPONENT: Tests
diff --git a/third_party/libFuzzer/OWNERS b/third_party/libFuzzer/OWNERS index 139269c5..292df45 100644 --- a/third_party/libFuzzer/OWNERS +++ b/third_party/libFuzzer/OWNERS
@@ -3,3 +3,5 @@ metzman@chromium.org mmoroz@chromium.org ochang@chromium.org +# COMPONENT: Tools>Stability>libFuzzer +# TEAM: chrome-security-bugs--@chromium.org
diff --git a/third_party/libevdev/OWNERS b/third_party/libevdev/OWNERS index 08777b4..b4b89bb 100644 --- a/third_party/libevdev/OWNERS +++ b/third_party/libevdev/OWNERS
@@ -1,2 +1,3 @@ adlr@chromium.org djkurtz@chromium.org +# COMPONENT: Internals>Input
diff --git a/third_party/libjingle_xmpp/OWNERS b/third_party/libjingle_xmpp/OWNERS index 57740b5..a373168 100644 --- a/third_party/libjingle_xmpp/OWNERS +++ b/third_party/libjingle_xmpp/OWNERS
@@ -1,3 +1,4 @@ hta@chromium.org sergeyu@chromium.org tommi@chromium.org +# COMPONENT: Internals>WebRTC
diff --git a/third_party/libjingle_xmpp/task_runner/OWNERS b/third_party/libjingle_xmpp/task_runner/OWNERS new file mode 100644 index 0000000..585c4ae --- /dev/null +++ b/third_party/libjingle_xmpp/task_runner/OWNERS
@@ -0,0 +1 @@ +# COMPONENT: Internals>Headless
diff --git a/third_party/libjingle_xmpp/xmllite/OWNERS b/third_party/libjingle_xmpp/xmllite/OWNERS new file mode 100644 index 0000000..585c4ae --- /dev/null +++ b/third_party/libjingle_xmpp/xmllite/OWNERS
@@ -0,0 +1 @@ +# COMPONENT: Internals>Headless
diff --git a/third_party/libjingle_xmpp/xmpp/OWNERS b/third_party/libjingle_xmpp/xmpp/OWNERS new file mode 100644 index 0000000..888cd82 --- /dev/null +++ b/third_party/libjingle_xmpp/xmpp/OWNERS
@@ -0,0 +1 @@ +# COMPONENT: Blink>WebRTC
diff --git a/third_party/libprotobuf-mutator/OWNERS b/third_party/libprotobuf-mutator/OWNERS index d315db4d2..b718fa0 100644 --- a/third_party/libprotobuf-mutator/OWNERS +++ b/third_party/libprotobuf-mutator/OWNERS
@@ -2,3 +2,5 @@ metzman@chromium.org mmoroz@chromium.org vitalybuka@chromium.org +# COMPONENT: Tools>Stability>ClusterFuzz +# TEAM: chrome-security-bugs--@chromium.org
diff --git a/third_party/libusb/OWNERS b/third_party/libusb/OWNERS index 41d6ce4..6e983a4 100644 --- a/third_party/libusb/OWNERS +++ b/third_party/libusb/OWNERS
@@ -1,2 +1,4 @@ meacer@chromium.org reillyg@chromium.org +# COMPONENT: IO>USB +# TEAM: device-dev@chromium.org
diff --git a/third_party/lzma_sdk/OWNERS b/third_party/lzma_sdk/OWNERS index 76f3885..c5c5d1e 100644 --- a/third_party/lzma_sdk/OWNERS +++ b/third_party/lzma_sdk/OWNERS
@@ -1,2 +1,4 @@ grt@chromium.org waffles@chromium.org +# COMPONENT: Internals>Installer +# TEAM: chrome-updates-dev@chromium.org
diff --git a/third_party/protoc_javalite/OWNERS b/third_party/protoc_javalite/OWNERS index 7743545..6495920 100644 --- a/third_party/protoc_javalite/OWNERS +++ b/third_party/protoc_javalite/OWNERS
@@ -1,2 +1,3 @@ mheikal@chromium.org jkrcal@chromium.org +# COMPONENT: Internals
diff --git a/third_party/r8/README.chromium b/third_party/r8/README.chromium index 4055ea44..9f928d9d 100644 --- a/third_party/r8/README.chromium +++ b/third_party/r8/README.chromium
@@ -1,7 +1,7 @@ Name: R8 URL: https://r8.googlesource.com/r8 -Revision: 49dbca6424489d4320727bbd731175a310d7aa35 -Version: 1.6.19-dev +Revision: c8785efaf448967838de4b1b6a0afea7d4ea5b74 +Version: 1.6.22-dev License: BSD 3-Clause License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/r8/local_modifications.diff b/third_party/r8/local_modifications.diff index 2ba1e29..17c7a3c 100644 --- a/third_party/r8/local_modifications.diff +++ b/third_party/r8/local_modifications.diff
@@ -1,8 +1,8 @@ diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java -index 7e788e156..959d31348 100644 +index 2b170ba8f..684d496eb 100644 --- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java +++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java -@@ -168,8 +168,8 @@ public class InternalOptions { +@@ -175,8 +175,8 @@ public class InternalOptions { // Optimization-related flags. These should conform to -dontoptimize and disableAllOptimizations. public boolean enableDynamicTypeOptimization = true; @@ -13,7 +13,7 @@ public boolean enableArgumentRemoval = true; public boolean enableUnusedArgumentRemoval = true; public boolean enableUnusedInterfaceRemoval = true; -@@ -901,7 +901,7 @@ public class InternalOptions { +@@ -941,7 +941,7 @@ public class InternalOptions { public static final String CLASS_NAME = "com.android.tools.r8.GeneratedOutlineSupport"; public static final String METHOD_PREFIX = "outline";
diff --git a/tools/code_coverage/OWNERS b/tools/code_coverage/OWNERS index f36342a..9d226754 100644 --- a/tools/code_coverage/OWNERS +++ b/tools/code_coverage/OWNERS
@@ -1,3 +1,5 @@ liaoyuke@chromium.org mmoroz@chromium.org inferno@chromium.org +# COMPONENT: Tools>CodeCoverage +# TEAM: code-coverage@chromium.org
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index d61e861..0aa7063 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -777,7 +777,7 @@ 'linux_chromium_ubsan_rel_ng': 'ubsan_vptr_release_bot', 'linux_layout_tests_composite_after_paint': 'release_trybot', - 'linux_layout_tests_layout_ng': 'release_trybot', + 'linux_layout_tests_layout_ng_disabled': 'release_trybot', 'linux_mojo': 'release_trybot', 'linux_mojo_chromeos': 'chromeos_with_codecs_release_trybot', 'linux_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 65cb8bf4..72c7aa67 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -35913,6 +35913,8 @@ <int value="245896533" label="SearchSuggestionsOnLocalNtp:enabled"/> <int value="250855010" label="WebAssemblyBaseline:disabled"/> <int value="255375615" label="stop-non-timers-in-background:enabled"/> + <int value="258621334" + label="HappinessTrackingSurveysForDesktopDemo:disabled"/> <int value="259021228" label="OffMainThreadFetch:disabled"/> <int value="259633436" label="AutofillDropdownLayout:disabled"/> <int value="262382944" label="GuestViewCrossProcessFrames:disabled"/> @@ -37178,6 +37180,8 @@ <int value="2008878342" label="TouchToFillAndroid:disabled"/> <int value="2009097351" label="memlog-sampling-rate"/> <int value="2009362691" label="AllowStartingServiceManagerOnly:enabled"/> + <int value="2013593624" + label="HappinessTrackingSurveysForDesktopDemo:enabled"/> <int value="2014331873" label="NTPDownloadSuggestions:disabled"/> <int value="2014629801" label="view-passwords:disabled"/> <int value="2015335629" label="shelf-hover-previews"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index bd21124a..7a80b43 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -48783,7 +48783,7 @@ </summary> </histogram> -<histogram name="GPU.GrContextMemoryKb" units="KB" expires_after="2019-10-01"> +<histogram name="GPU.GrContextMemoryKb" units="KB" expires_after="2020-04-01"> <owner>enne@chromium.org</owner> <owner>khushalsagar@chromium.org</owner> <summary> @@ -136408,6 +136408,20 @@ </summary> </histogram> +<histogram name="Sync.BookmarksModelReadyToSyncTime" units="ms" + expires_after="M82"> + <owner>mamir@chromium.org</owner> + <owner>treib@chromium.org</owner> + <summary> + Time used to parse the Bookmarks persisted sync metadata after being read + from the Bookmarks JSON file. It includes the time spent in initializing + Bookmark Sync data structures as well as the time spent to check the + correctness of the data. It's reported on every startup for already syncing + users. It's not reported for non-syncing users or users going through the + first sync experience. + </summary> +</histogram> + <histogram name="Sync.BookmarksModelSyncStateAtNewDuplication" enum="SyncBookmarkModelSyncState" expires_after="M82"> <owner>mamir@chromium.org</owner> @@ -139569,8 +139583,8 @@ <histogram name="Tab.Screenshot.Action" enum="TabScreenshotAction" expires_after="2020-09-01"> - <owner>petewil@chromium.org</owner> - <owner>jianli@chromium.org</owner> + <owner>ramyan@chromium.org</owner> + <owner>cyflee@chromium.org</owner> <summary> Records actions taken after one or more screenshots of a page were taken. This will not be recorded if Chromium is killed before leaving the page. If @@ -139582,8 +139596,8 @@ <histogram name="Tab.Screenshot.ScreenshotsPerPage" units="screenshots" expires_after="2020-09-01"> - <owner>petewil@chromium.org</owner> - <owner>jianli@chromium.org</owner> + <owner>ramyan@chromium.org</owner> + <owner>cyflee@chromium.org</owner> <summary> Records the number of screenshots taken of a specific page. It is recorded when the user navigates away from this page or the tab is destroyed. This @@ -147904,6 +147918,20 @@ </summary> </histogram> +<histogram name="V8.WasmDeserializeModuleStreamingMicroSeconds" + units="microseconds" expires_after="2020-03-31"> + <owner>bbudge@chromium.org</owner> + <owner>clemensh@chromium.org</owner> + <owner>adamk@chromium.org</owner> + <summary> + Time to deserialize a WebAssembly module during streaming compilation (via + the 'WebAssembly.compileStreaming' API). Recorded on each streaming + WebAssembly deserialization from the code cache, but only if a + high-resolution clock is available. Note that compilation speed is often + limited by the network speed, which is also reflected in thie metric. + </summary> +</histogram> + <histogram name="V8.WasmExecutionTimeMicroSeconds" units="microseconds" expires_after="2019-03-12"> <obsolete>
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 55d1708..437d685 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -5892,7 +5892,7 @@ return UIA_PaneControlTypeId; case ax::mojom::Role::kArticle: - return UIA_DocumentControlTypeId; + return UIA_GroupControlTypeId; case ax::mojom::Role::kAudio: return UIA_GroupControlTypeId;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc index bd957f94..1245a4ed 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.cc +++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -603,6 +603,9 @@ case ax::mojom::Role::kDetails: return base::ASCIIToUTF16("details"); + case ax::mojom::Role::kFigure: + return base::ASCIIToUTF16("figure"); + case ax::mojom::Role::kMeter: return base::ASCIIToUTF16("meter");
diff --git a/ui/base/clipboard/clipboard_aura.cc b/ui/base/clipboard/clipboard_aura.cc index 055c489b..371a6ea 100644 --- a/ui/base/clipboard/clipboard_aura.cc +++ b/ui/base/clipboard/clipboard_aura.cc
@@ -32,14 +32,14 @@ const size_t kMaxClipboardSize = 1; // Clipboard data format used by AuraClipboard. -enum AuraClipboardFormat { - TEXT = 1 << 0, - HTML = 1 << 1, - RTF = 1 << 2, - BOOKMARK = 1 << 3, - BITMAP = 1 << 4, - CUSTOM = 1 << 5, - WEB = 1 << 6, +enum class AuraClipboardFormat { + kText = 1 << 0, + kHtml = 1 << 1, + kRtf = 1 << 2, + kBookmark = 1 << 3, + kBitmap = 1 << 4, + kCustom = 1 << 5, + kWeb = 1 << 6, }; // ClipboardData contains data copied to the Clipboard for a variety of formats. @@ -58,37 +58,37 @@ const std::string& text() const { return text_; } void set_text(const std::string& text) { text_ = text; - format_ |= TEXT; + format_ |= static_cast<int>(AuraClipboardFormat::kText); } const std::string& markup_data() const { return markup_data_; } void set_markup_data(const std::string& markup_data) { markup_data_ = markup_data; - format_ |= HTML; + format_ |= static_cast<int>(AuraClipboardFormat::kHtml); } const std::string& rtf_data() const { return rtf_data_; } void SetRTFData(const std::string& rtf_data) { rtf_data_ = rtf_data; - format_ |= RTF; + format_ |= static_cast<int>(AuraClipboardFormat::kRtf); } const std::string& url() const { return url_; } void set_url(const std::string& url) { url_ = url; - format_ |= HTML; + format_ |= static_cast<int>(AuraClipboardFormat::kHtml); } const std::string& bookmark_title() const { return bookmark_title_; } void set_bookmark_title(const std::string& bookmark_title) { bookmark_title_ = bookmark_title; - format_ |= BOOKMARK; + format_ |= static_cast<int>(AuraClipboardFormat::kBookmark); } const std::string& bookmark_url() const { return bookmark_url_; } void set_bookmark_url(const std::string& bookmark_url) { bookmark_url_ = bookmark_url; - format_ |= BOOKMARK; + format_ |= static_cast<int>(AuraClipboardFormat::kBookmark); } const SkBitmap& bitmap() const { return bitmap_; } @@ -97,7 +97,7 @@ NOTREACHED() << "Unable to convert bitmap for clipboard"; return; } - format_ |= BITMAP; + format_ |= static_cast<int>(AuraClipboardFormat::kBitmap); } const std::string& custom_data_format() const { return custom_data_format_; } @@ -111,13 +111,13 @@ } custom_data_data_ = data_data; custom_data_format_ = data_format; - format_ |= CUSTOM; + format_ |= static_cast<int>(AuraClipboardFormat::kCustom); } bool web_smart_paste() const { return web_smart_paste_; } void set_web_smart_paste(bool web_smart_paste) { web_smart_paste_ = web_smart_paste; - format_ |= WEB; + format_ |= static_cast<int>(AuraClipboardFormat::kWeb); } private: @@ -188,8 +188,9 @@ // or another format that can be converted to |format|. bool IsFormatAvailable(AuraClipboardFormat format) const { switch (format) { - case TEXT: - return HasFormat(TEXT) || HasFormat(BOOKMARK); + case AuraClipboardFormat::kText: + return HasFormat(AuraClipboardFormat::kText) || + HasFormat(AuraClipboardFormat::kBookmark); default: return HasFormat(format); } @@ -208,11 +209,11 @@ const ClipboardData* data = GetData(); if (!data) return; - if (HasFormat(TEXT)) + if (HasFormat(AuraClipboardFormat::kText)) *result = data->text(); - else if (HasFormat(HTML)) + else if (HasFormat(AuraClipboardFormat::kHtml)) *result = data->markup_data(); - else if (HasFormat(BOOKMARK)) + else if (HasFormat(AuraClipboardFormat::kBookmark)) *result = data->bookmark_url(); } @@ -227,7 +228,7 @@ *fragment_start = 0; *fragment_end = 0; - if (!HasFormat(HTML)) + if (!HasFormat(AuraClipboardFormat::kHtml)) return; const ClipboardData* data = GetData(); @@ -243,7 +244,7 @@ void ReadRTF(std::string* result) const { result->clear(); const ClipboardData* data = GetData(); - if (!HasFormat(RTF)) + if (!HasFormat(AuraClipboardFormat::kRtf)) return; *result = data->rtf_data(); @@ -252,7 +253,7 @@ // Reads image from the data at the top of clipboard stack. SkBitmap ReadImage() const { SkBitmap img; - if (!HasFormat(BITMAP)) + if (!HasFormat(AuraClipboardFormat::kBitmap)) return img; // A shallow copy should be fine here, but just to be safe... @@ -269,7 +270,7 @@ base::string16* result) const { result->clear(); const ClipboardData* data = GetData(); - if (!HasFormat(CUSTOM)) + if (!HasFormat(AuraClipboardFormat::kCustom)) return; ui::ReadCustomDataForType(data->custom_data_data().c_str(), @@ -283,7 +284,7 @@ title->clear(); if (url) url->clear(); - if (!HasFormat(BOOKMARK)) + if (!HasFormat(AuraClipboardFormat::kBookmark)) return; const ClipboardData* data = GetData(); @@ -296,7 +297,8 @@ void ReadData(const std::string& type, std::string* result) const { result->clear(); const ClipboardData* data = GetData(); - if (!HasFormat(CUSTOM) || type != data->custom_data_format()) + if (!HasFormat(AuraClipboardFormat::kCustom) || + type != data->custom_data_format()) return; *result = data->custom_data_data(); @@ -313,7 +315,7 @@ // True if the data on top of the clipboard stack has format |format|. bool HasFormat(AuraClipboardFormat format) const { const ClipboardData* data = GetData(); - return data ? data->format() & format : false; + return data ? data->format() & static_cast<int>(format) : false; } void AddToListEnsuringSize(std::unique_ptr<ClipboardData> data) { @@ -436,15 +438,15 @@ DCHECK(IsSupportedClipboardType(type)); if (ClipboardFormatType::GetPlainTextType().Equals(format) || ClipboardFormatType::GetUrlType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(TEXT); + return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kText); if (ClipboardFormatType::GetHtmlType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(HTML); + return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kHtml); if (ClipboardFormatType::GetRtfType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(RTF); + return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kRtf); if (ClipboardFormatType::GetBitmapType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(BITMAP); + return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kBitmap); if (ClipboardFormatType::GetWebKitSmartPasteType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(WEB); + return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kWeb); const ClipboardData* data = clipboard_internal_->GetData(); return data && data->custom_data_format() == format.ToString(); } @@ -478,7 +480,7 @@ if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), type)) types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); - if (clipboard_internal_->IsFormatAvailable(CUSTOM) && + if (clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kCustom) && clipboard_internal_->GetData()) { ui::ReadCustomDataTypes( clipboard_internal_->GetData()->custom_data_data().c_str(),
diff --git a/ui/base/ime/OWNERS b/ui/base/ime/OWNERS index 787255a1..42b1af0 100644 --- a/ui/base/ime/OWNERS +++ b/ui/base/ime/OWNERS
@@ -8,3 +8,4 @@ # For Windows. yukawa@chromium.org +# COMPONENT: UI>Input>Text>IME
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 9d8972c3..02579ea 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -1173,8 +1173,19 @@ void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) { if (device_scale_factor_ == device_scale_factor) return; - if (animator_) + + base::WeakPtr<Layer> weak_this = weak_ptr_factory_.GetWeakPtr(); + + // NOTE: Some animation observers destroy the layer when the animation ends. + if (animator_) { animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); + + // Do not proceed if the layer was destroyed due to an animation + // observer. + if (!weak_this) + return; + } + const float old_device_scale_factor = device_scale_factor_; device_scale_factor_ = device_scale_factor; RecomputeDrawsContentAndUVRect(); @@ -1189,8 +1200,14 @@ delegate_->OnDeviceScaleFactorChanged(old_device_scale_factor, device_scale_factor); } - for (auto* child : children_) + for (auto* child : children_) { child->OnDeviceScaleFactorChanged(device_scale_factor); + + // A child layer may have triggered a delegate or an observer to delete + // |this| layer. In which case return early to avoid crash. + if (!weak_this) + return; + } if (layer_mask_) layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor); }
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index dbeec073..b30fb185 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -2654,6 +2654,106 @@ EXPECT_TRUE(l1->cc_layer_for_testing()->masks_to_bounds()); } +// An animation observer that deletes the layer when the animation ends. +class TestAnimationObserver : public ImplicitAnimationObserver { + public: + TestAnimationObserver() = default; + + Layer* layer() const { return layer_.get(); } + + void SetLayer(std::unique_ptr<Layer> layer) { layer_ = std::move(layer); } + + // ui::ImplicitAnimationObserver overrides: + void OnImplicitAnimationsCompleted() override {} + + protected: + void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override { + layer_.reset(); + } + + private: + std::unique_ptr<Layer> layer_; + + DISALLOW_COPY_AND_ASSIGN(TestAnimationObserver); +}; + +// Triggerring a OnDeviceScaleFactorChanged while a layer is undergoing +// transform animation, may cause a crash. This is because the layer may be +// deleted by the animation observer leading to a seg fault. +TEST_P(LayerWithRealCompositorTest, DeletingLayerDuringScaleFactorChange) { + TestAnimationObserver animation_observer; + + std::unique_ptr<Layer> root = CreateLayer(LAYER_SOLID_COLOR); + animation_observer.SetLayer(CreateLayer(LAYER_SOLID_COLOR)); + + Layer* layer_to_delete = animation_observer.layer(); + + GetCompositor()->SetRootLayer(root.get()); + root->Add(layer_to_delete); + + EXPECT_EQ(gfx::Transform(), layer_to_delete->GetTargetTransform()); + + gfx::Transform transform; + transform.Scale(2, 1); + transform.Translate(10, 5); + + auto long_duration_animation = + std::make_unique<ui::ScopedAnimationDurationScaleMode>( + ui::ScopedAnimationDurationScaleMode::SLOW_DURATION); + { + ui::ScopedLayerAnimationSettings animation(layer_to_delete->GetAnimator()); + animation.AddObserver(&animation_observer); + animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); + layer_to_delete->SetTransform(transform); + } + + // This call should not crash. + root->OnDeviceScaleFactorChanged(2.f); + + animation_observer.SetLayer(CreateLayer(LAYER_SOLID_COLOR)); + layer_to_delete = animation_observer.layer(); + + std::unique_ptr<Layer> child = CreateLayer(LAYER_SOLID_COLOR); + + root->Add(layer_to_delete); + layer_to_delete->Add(child.get()); + + long_duration_animation = + std::make_unique<ui::ScopedAnimationDurationScaleMode>( + ui::ScopedAnimationDurationScaleMode::SLOW_DURATION); + { + ui::ScopedLayerAnimationSettings animation(layer_to_delete->GetAnimator()); + animation.AddObserver(&animation_observer); + animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); + layer_to_delete->SetTransform(transform); + } + + // This call should not crash. + root->OnDeviceScaleFactorChanged(1.5f); + + animation_observer.SetLayer(CreateLayer(LAYER_SOLID_COLOR)); + layer_to_delete = animation_observer.layer(); + + std::unique_ptr<Layer> child2 = CreateLayer(LAYER_SOLID_COLOR); + + root->Add(layer_to_delete); + layer_to_delete->Add(child.get()); + layer_to_delete->Add(child2.get()); + + long_duration_animation = + std::make_unique<ui::ScopedAnimationDurationScaleMode>( + ui::ScopedAnimationDurationScaleMode::SLOW_DURATION); + { + ui::ScopedLayerAnimationSettings animation(child->GetAnimator()); + animation.AddObserver(&animation_observer); + animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(1000)); + child->SetTransform(transform); + } + + // This call should not crash. + root->OnDeviceScaleFactorChanged(2.f); +} + // Tests that the animators in the layer tree is added to the // animator-collection when the root-layer is set to the compositor. TEST_F(LayerWithDelegateTest, RootLayerAnimatorsInCompositor) {
diff --git a/ui/display/fake/fake_display_snapshot.cc b/ui/display/fake/fake_display_snapshot.cc index ba2bed8..4a196cdc 100644 --- a/ui/display/fake/fake_display_snapshot.cc +++ b/ui/display/fake/fake_display_snapshot.cc
@@ -311,6 +311,7 @@ display_name, base::FilePath(), std::move(modes), + display::PanelOrientation::kNormal, std::vector<uint8_t>(), current_mode, native_mode,
diff --git a/ui/display/mojom/display_constants.mojom b/ui/display/mojom/display_constants.mojom index a10d8d3..224265d1 100644 --- a/ui/display/mojom/display_constants.mojom +++ b/ui/display/mojom/display_constants.mojom
@@ -21,4 +21,13 @@ HDCP_STATE_UNDESIRED, HDCP_STATE_DESIRED, HDCP_STATE_ENABLED, -}; \ No newline at end of file +}; + +// Corresponds to display::PanelOrientation. +enum PanelOrientation { + NORMAL = 0, + BOTTOM_UP = 1, + LEFT_UP = 2, + RIGHT_UP = 3 +}; +
diff --git a/ui/display/mojom/display_constants_mojom_traits.cc b/ui/display/mojom/display_constants_mojom_traits.cc index a34a657..c8a00b12 100644 --- a/ui/display/mojom/display_constants_mojom_traits.cc +++ b/ui/display/mojom/display_constants_mojom_traits.cc
@@ -108,4 +108,43 @@ return false; } +// static +display::mojom::PanelOrientation EnumTraits< + display::mojom::PanelOrientation, + display::PanelOrientation>::ToMojom(display::PanelOrientation rotation) { + switch (rotation) { + case display::PanelOrientation::kNormal: + return display::mojom::PanelOrientation::NORMAL; + case display::PanelOrientation::kBottomUp: + return display::mojom::PanelOrientation::BOTTOM_UP; + case display::PanelOrientation::kLeftUp: + return display::mojom::PanelOrientation::LEFT_UP; + case display::PanelOrientation::kRightUp: + return display::mojom::PanelOrientation::RIGHT_UP; + } + NOTREACHED(); + return display::mojom::PanelOrientation::NORMAL; +} + +// static +bool EnumTraits<display::mojom::PanelOrientation, display::PanelOrientation>:: + FromMojom(display::mojom::PanelOrientation rotation, + display::PanelOrientation* out) { + switch (rotation) { + case display::mojom::PanelOrientation::NORMAL: + *out = display::PanelOrientation::kNormal; + return true; + case display::mojom::PanelOrientation::BOTTOM_UP: + *out = display::PanelOrientation::kBottomUp; + return true; + case display::mojom::PanelOrientation::LEFT_UP: + *out = display::PanelOrientation::kLeftUp; + return true; + case display::mojom::PanelOrientation::RIGHT_UP: + *out = display::PanelOrientation::kRightUp; + return true; + } + return false; +} + } // namespace mojo
diff --git a/ui/display/mojom/display_constants_mojom_traits.h b/ui/display/mojom/display_constants_mojom_traits.h index 24ab48d..0fcf084 100644 --- a/ui/display/mojom/display_constants_mojom_traits.h +++ b/ui/display/mojom/display_constants_mojom_traits.h
@@ -26,6 +26,14 @@ display::HDCPState* out); }; +template <> +struct EnumTraits<display::mojom::PanelOrientation, display::PanelOrientation> { + static display::mojom::PanelOrientation ToMojom( + display::PanelOrientation type); + static bool FromMojom(display::mojom::PanelOrientation type, + display::PanelOrientation* out); +}; + } // namespace mojo #endif // UI_DISPLAY_MOJOM_DISPLAY_CONSTANTS_MOJOM_TRAITS_H_
diff --git a/ui/display/mojom/display_mojom_traits_unittest.cc b/ui/display/mojom/display_mojom_traits_unittest.cc index 7db6a6b..74276a1 100644 --- a/ui/display/mojom/display_mojom_traits_unittest.cc +++ b/ui/display/mojom/display_mojom_traits_unittest.cc
@@ -94,6 +94,7 @@ for (size_t i = 0; i < input.modes().size(); i++) CheckDisplayModesEqual(input.modes()[i].get(), output.modes()[i].get()); + EXPECT_EQ(input.panel_orientation(), output.panel_orientation()); EXPECT_EQ(input.edid(), output.edid()); CheckDisplayModesEqual(input.current_mode(), output.current_mode()); @@ -275,8 +276,9 @@ display_id, origin, physical_size, type, is_aspect_preserving_scaling, has_overscan, has_color_correction_matrix, color_correction_in_linear_space, display_color_space, display_name, - sys_path, std::move(modes), edid, current_mode, native_mode, product_code, - year_of_manufacture, maximum_cursor_size); + sys_path, std::move(modes), display::PanelOrientation::kNormal, edid, + current_mode, native_mode, product_code, year_of_manufacture, + maximum_cursor_size); std::unique_ptr<DisplaySnapshot> output; SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output); @@ -315,8 +317,9 @@ display_id, origin, physical_size, type, is_aspect_preserving_scaling, has_overscan, has_color_correction_matrix, color_correction_in_linear_space, display_color_space, display_name, - sys_path, std::move(modes), edid, current_mode, native_mode, product_code, - year_of_manufacture, maximum_cursor_size); + sys_path, std::move(modes), display::PanelOrientation::kNormal, edid, + current_mode, native_mode, product_code, year_of_manufacture, + maximum_cursor_size); std::unique_ptr<DisplaySnapshot> output; SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output); @@ -359,8 +362,9 @@ display_id, origin, physical_size, type, is_aspect_preserving_scaling, has_overscan, has_color_correction_matrix, color_correction_in_linear_space, display_color_space, display_name, - sys_path, std::move(modes), edid, current_mode, native_mode, product_code, - year_of_manufacture, maximum_cursor_size); + sys_path, std::move(modes), display::PanelOrientation::kLeftUp, edid, + current_mode, native_mode, product_code, year_of_manufacture, + maximum_cursor_size); std::unique_ptr<DisplaySnapshot> output; SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output); @@ -399,8 +403,9 @@ display_id, origin, physical_size, type, is_aspect_preserving_scaling, has_overscan, has_color_correction_matrix, color_correction_in_linear_space, display_color_space, display_name, - sys_path, std::move(modes), edid, current_mode, native_mode, product_code, - year_of_manufacture, maximum_cursor_size); + sys_path, std::move(modes), display::PanelOrientation::kRightUp, edid, + current_mode, native_mode, product_code, year_of_manufacture, + maximum_cursor_size); std::unique_ptr<DisplaySnapshot> output; SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
diff --git a/ui/display/mojom/display_snapshot.mojom b/ui/display/mojom/display_snapshot.mojom index abff2b0d..9d6fe1f 100644 --- a/ui/display/mojom/display_snapshot.mojom +++ b/ui/display/mojom/display_snapshot.mojom
@@ -24,6 +24,7 @@ string display_name; mojo_base.mojom.FilePath sys_path; array<display.mojom.DisplayMode> modes; + display.mojom.PanelOrientation panel_orientation; array<uint8> edid; uint64 current_mode_index; bool has_current_mode;
diff --git a/ui/display/mojom/display_snapshot_mojom_traits.cc b/ui/display/mojom/display_snapshot_mojom_traits.cc index 3440c55..84a67bf 100644 --- a/ui/display/mojom/display_snapshot_mojom_traits.cc +++ b/ui/display/mojom/display_snapshot_mojom_traits.cc
@@ -81,6 +81,10 @@ if (!data.ReadType(&type)) return false; + display::PanelOrientation panel_orientation; + if (!data.ReadPanelOrientation(&panel_orientation)) + return false; + gfx::ColorSpace color_space; if (!data.ReadColorSpace(&color_space)) return false; @@ -134,8 +138,9 @@ data.is_aspect_preserving_scaling(), data.has_overscan(), data.has_color_correction_matrix(), data.color_correction_in_linear_space(), color_space, display_name, - file_path, std::move(modes), std::move(edid), current_mode, native_mode, - data.product_code(), data.year_of_manufacture(), maximum_cursor_size); + file_path, std::move(modes), panel_orientation, std::move(edid), + current_mode, native_mode, data.product_code(), + data.year_of_manufacture(), maximum_cursor_size); return true; }
diff --git a/ui/display/mojom/display_snapshot_mojom_traits.h b/ui/display/mojom/display_snapshot_mojom_traits.h index ffa2c25a..0ea533ab 100644 --- a/ui/display/mojom/display_snapshot_mojom_traits.h +++ b/ui/display/mojom/display_snapshot_mojom_traits.h
@@ -39,6 +39,11 @@ return snapshot->type(); } + static display::PanelOrientation panel_orientation( + const std::unique_ptr<display::DisplaySnapshot>& snapshot) { + return snapshot->panel_orientation(); + } + static bool is_aspect_preserving_scaling( const std::unique_ptr<display::DisplaySnapshot>& snapshot) { return snapshot->is_aspect_preserving_scaling();
diff --git a/ui/display/types/display_constants.h b/ui/display/types/display_constants.h index 09752301..be029bd1 100644 --- a/ui/display/types/display_constants.h +++ b/ui/display/types/display_constants.h
@@ -63,6 +63,15 @@ HDCP_STATE_LAST = HDCP_STATE_ENABLED }; +// The orientation of the panel in respect to the natural device orientation. +enum PanelOrientation { + kNormal = 0, + kBottomUp = 1, + kLeftUp = 2, + kRightUp = 3, + kLast = kRightUp +}; + } // namespace display #endif // UI_DISPLAY_TYPES_DISPLAY_CONSTANTS_H_
diff --git a/ui/display/types/display_snapshot.cc b/ui/display/types/display_snapshot.cc index 2adf25c..c5474b5 100644 --- a/ui/display/types/display_snapshot.cc +++ b/ui/display/types/display_snapshot.cc
@@ -72,6 +72,7 @@ std::string display_name, const base::FilePath& sys_path, DisplayModeList modes, + PanelOrientation panel_orientation, const std::vector<uint8_t>& edid, const DisplayMode* current_mode, const DisplayMode* native_mode, @@ -90,6 +91,7 @@ display_name_(display_name), sys_path_(sys_path), modes_(std::move(modes)), + panel_orientation_(panel_orientation), edid_(edid), current_mode_(current_mode), native_mode_(native_mode), @@ -125,21 +127,23 @@ display_id_, origin_, physical_size_, type_, is_aspect_preserving_scaling_, has_overscan_, has_color_correction_matrix_, color_correction_in_linear_space_, - color_space_, display_name_, sys_path_, std::move(clone_modes), edid_, - cloned_current_mode, cloned_native_mode, product_code_, - year_of_manufacture_, maximum_cursor_size_); + color_space_, display_name_, sys_path_, std::move(clone_modes), + panel_orientation_, edid_, cloned_current_mode, cloned_native_mode, + product_code_, year_of_manufacture_, maximum_cursor_size_); } std::string DisplaySnapshot::ToString() const { return base::StringPrintf( "id=%" PRId64 " current_mode=%s native_mode=%s origin=%s" + " panel_orientation=%d" " physical_size=%s, type=%s name=\"%s\" (year:%d) " "modes=(%s)", display_id_, current_mode_ ? current_mode_->ToString().c_str() : "nullptr", native_mode_ ? native_mode_->ToString().c_str() : "nullptr", - origin_.ToString().c_str(), physical_size_.ToString().c_str(), + origin_.ToString().c_str(), panel_orientation_, + physical_size_.ToString().c_str(), DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(), year_of_manufacture_, ModeListString(modes_).c_str()); }
diff --git a/ui/display/types/display_snapshot.h b/ui/display/types/display_snapshot.h index d1dfd11..8cc47dd 100644 --- a/ui/display/types/display_snapshot.h +++ b/ui/display/types/display_snapshot.h
@@ -41,6 +41,7 @@ std::string display_name, const base::FilePath& sys_path, DisplayModeList modes, + PanelOrientation panel_orientation, const std::vector<uint8_t>& edid, const DisplayMode* current_mode, const DisplayMode* native_mode, @@ -69,6 +70,7 @@ const std::string& display_name() const { return display_name_; } const base::FilePath& sys_path() const { return sys_path_; } const DisplayModeList& modes() const { return modes_; } + PanelOrientation panel_orientation() const { return panel_orientation_; } const std::vector<uint8_t>& edid() const { return edid_; } const DisplayMode* current_mode() const { return current_mode_; } void set_current_mode(const DisplayMode* mode) { current_mode_ = mode; } @@ -120,6 +122,9 @@ DisplayModeList modes_; + // The orientation of the panel in respect to the natural device orientation. + PanelOrientation panel_orientation_; + // The display's EDID. It can be empty if nothing extracted such as in the // case of a virtual display. std::vector<uint8_t> edid_;
diff --git a/ui/ozone/common/gpu/ozone_gpu_message_params.h b/ui/ozone/common/gpu/ozone_gpu_message_params.h index 7d7182d..73abae76 100644 --- a/ui/ozone/common/gpu/ozone_gpu_message_params.h +++ b/ui/ozone/common/gpu/ozone_gpu_message_params.h
@@ -49,6 +49,8 @@ std::string display_name; base::FilePath sys_path; std::vector<DisplayMode_Params> modes; + display::PanelOrientation panel_orientation = + display::PanelOrientation::kNormal; std::vector<uint8_t> edid; bool has_current_mode = false; DisplayMode_Params current_mode;
diff --git a/ui/ozone/common/gpu/ozone_gpu_messages.h b/ui/ozone/common/gpu/ozone_gpu_messages.h index 77e5d70..0977214e 100644 --- a/ui/ozone/common/gpu/ozone_gpu_messages.h +++ b/ui/ozone/common/gpu/ozone_gpu_messages.h
@@ -35,6 +35,9 @@ IPC_ENUM_TRAITS_MAX_VALUE(display::HDCPState, display::HDCP_STATE_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(display::PanelOrientation, + display::PanelOrientation::kLast) + IPC_ENUM_TRAITS_MAX_VALUE(gfx::OverlayTransform, gfx::OVERLAY_TRANSFORM_LAST) IPC_ENUM_TRAITS_MAX_VALUE(ui::OverlayStatus, ui::OVERLAY_STATUS_LAST) @@ -59,6 +62,7 @@ IPC_STRUCT_TRAITS_MEMBER(display_name) IPC_STRUCT_TRAITS_MEMBER(sys_path) IPC_STRUCT_TRAITS_MEMBER(modes) + IPC_STRUCT_TRAITS_MEMBER(panel_orientation) IPC_STRUCT_TRAITS_MEMBER(edid) IPC_STRUCT_TRAITS_MEMBER(has_current_mode) IPC_STRUCT_TRAITS_MEMBER(current_mode)
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc index 936b2206..b8e5254 100644 --- a/ui/ozone/platform/drm/common/drm_util.cc +++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -189,6 +189,16 @@ "Full aspect"); } +display::PanelOrientation GetPanelOrientation(int fd, + drmModeConnector* connector) { + ScopedDrmPropertyPtr property; + int index = GetDrmProperty(fd, connector, "panel orientation", &property); + if (index < 0) + return display::PanelOrientation::kNormal; + DCHECK_LT(connector->prop_values[index], display::PanelOrientation::kLast); + return static_cast<display::PanelOrientation>(connector->prop_values[index]); +} + int ConnectorIndex(int device_index, int display_index) { DCHECK_LT(device_index, 16); DCHECK_LT(display_index, 16); @@ -427,6 +437,8 @@ const display::DisplayConnectionType type = GetDisplayType(info->connector()); const bool is_aspect_preserving_scaling = IsAspectPreserving(fd, info->connector()); + const display::PanelOrientation panel_orientation = + GetPanelOrientation(fd, info->connector()); const bool has_color_correction_matrix = HasColorCorrectionMatrix(fd, info->crtc()) || HasPerPlaneColorCorrectionMatrix(fd, info->crtc()); @@ -478,8 +490,8 @@ display_id, origin, physical_size, type, is_aspect_preserving_scaling, has_overscan, has_color_correction_matrix, color_correction_in_linear_space, display_color_space, display_name, - sys_path, std::move(modes), edid, current_mode, native_mode, product_code, - year_of_manufacture, maximum_cursor_size); + sys_path, std::move(modes), panel_orientation, edid, current_mode, + native_mode, product_code, year_of_manufacture, maximum_cursor_size); } // TODO(rjkroege): Remove in a subsequent CL once Mojo IPC is used everywhere. @@ -506,6 +518,7 @@ mode_params.push_back(GetDisplayModeParams(*m)); } p.modes = mode_params; + p.panel_orientation = d->panel_orientation(); p.edid = d->edid(); p.has_current_mode = d->current_mode(); @@ -543,9 +556,10 @@ params.is_aspect_preserving_scaling, params.has_overscan, params.has_color_correction_matrix, params.color_correction_in_linear_space, params.color_space, - params.display_name, params.sys_path, std::move(modes), params.edid, - current_mode, native_mode, params.product_code, - params.year_of_manufacture, params.maximum_cursor_size); + params.display_name, params.sys_path, std::move(modes), + params.panel_orientation, params.edid, current_mode, native_mode, + params.product_code, params.year_of_manufacture, + params.maximum_cursor_size); } int GetFourCCFormatForOpaqueFramebuffer(gfx::BufferFormat format) {
diff --git a/ui/ozone/platform/headless/headless_native_display_delegate.cc b/ui/ozone/platform/headless/headless_native_display_delegate.cc index adb1175..1432dd6 100644 --- a/ui/ozone/platform/headless/headless_native_display_delegate.cc +++ b/ui/ozone/platform/headless/headless_native_display_delegate.cc
@@ -41,7 +41,8 @@ next_display_id(), gfx::Point(0, 0), kDefaultWindowSize, display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE, false, false, false, false, gfx::ColorSpace(), "", base::FilePath(), - std::move(modes), std::vector<uint8_t>(), mode, mode, 0, 0, gfx::Size()); + std::move(modes), display::PanelOrientation::kNormal, + std::vector<uint8_t>(), mode, mode, 0, 0, gfx::Size()); for (display::NativeDisplayObserver& observer : observers_) observer.OnConfigurationChanged();
diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html index dfd16f5..8673bf3 100644 --- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html +++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html
@@ -68,11 +68,13 @@ .drawer-header { align-items: center; border-bottom: var(--cr-separator-line); + color: var(--cr-drawer-header-color, inherit); display: flex; font-size: 123.08%; /* go to 16px from 13px */ + font-weight: var(--cr-drawer-header-font-weight, inherit); min-height: 56px; outline: none; - padding-inline-start: 24px; + padding-inline-start: var(--cr-drawer-header-padding, 24px); } @media (prefers-color-scheme: dark) {
diff --git a/ui/webui/resources/cr_elements/cr_scrollable_behavior.js b/ui/webui/resources/cr_elements/cr_scrollable_behavior.js index 31d7934..02ef3534 100644 --- a/ui/webui/resources/cr_elements/cr_scrollable_behavior.js +++ b/ui/webui/resources/cr_elements/cr_scrollable_behavior.js
@@ -79,30 +79,46 @@ this.requestUpdateScroll(); - let nodeList = this.root.querySelectorAll('[scrollable] iron-list'); + const nodeList = this.root.querySelectorAll('[scrollable] iron-list'); if (!nodeList.length) { return; } + let nodesToResize = Array.from(nodeList).map(node => ({ + node: node, + lastScrollHeight: 0, + })); // Use setInterval to avoid initial render / sizing issues. - this.intervalId_ = window.setInterval(function() { - const unreadyNodes = []; - for (let i = 0; i < nodeList.length; i++) { - const node = nodeList[i]; - if (node.parentNode.scrollHeight == 0) { - unreadyNodes.push(node); - continue; + this.intervalId_ = window.setInterval(() => { + const checkAgain = []; + nodesToResize.forEach(({node, lastScrollHeight}) => { + const scrollHeight = node.parentNode.scrollHeight; + // A hidden scroll-container has a height of 0. When not hidden, it has + // a min-height of 1px and the iron-list needs a resize to show the + // initial items and update the |scrollHeight|. The initial item count + // is determined by the |scrollHeight|. A scrollHeight of 1px will + // result in the minimum default item count (currently 3). After the + // |scrollHeight| is updated to be greater than 1px, another resize is + // needed to correctly calculate the number of physical iron-list items + // to render. + if (scrollHeight != lastScrollHeight) { + const ironList = /** @type {!IronListElement} */ (node); + ironList.notifyResize(); } - const ironList = /** @type {!IronListElement} */ (node); - ironList.notifyResize(); - } - if (unreadyNodes.length == 0) { + if (scrollHeight <= 1) { + checkAgain.push({ + node: node, + lastScrollHeight: scrollHeight, + }); + } + }); + if (checkAgain.length == 0) { window.clearInterval(this.intervalId_); this.intervalId_ = null; } else { - nodeList = unreadyNodes; + nodesToResize = checkAgain; } - }.bind(this), 10); + }, 10); }, /**
diff --git a/url/gurl.cc b/url/gurl.cc index 91b0f24..d2374df 100644 --- a/url/gurl.cc +++ b/url/gurl.cc
@@ -10,20 +10,14 @@ #include <ostream> #include <utility> -#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/no_destructor.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/trace_event/memory_usage_estimator.h" #include "url/url_canon_stdstring.h" #include "url/url_util.h" -namespace { - -static base::LazyInstance<GURL>::Leaky empty_gurl = LAZY_INSTANCE_INITIALIZER; - -} // namespace - GURL::GURL() : is_valid_(false) { } @@ -449,7 +443,8 @@ } const GURL& GURL::EmptyGURL() { - return empty_gurl.Get(); + static base::NoDestructor<GURL> empty_gurl; + return *empty_gurl; } bool GURL::DomainIs(base::StringPiece canonical_domain) const {
diff --git a/url/url_idna_icu.cc b/url/url_idna_icu.cc index 601736e..41955085 100644 --- a/url/url_idna_icu.cc +++ b/url/url_idna_icu.cc
@@ -8,8 +8,8 @@ #include <stdlib.h> #include <string.h> -#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/no_destructor.h" #include "third_party/icu/source/common/unicode/uidna.h" #include "third_party/icu/source/common/unicode/utypes.h" #include "url/url_canon_icu.h" @@ -61,8 +61,10 @@ } // namespace -static base::LazyInstance<UIDNAWrapper>::Leaky g_uidna = - LAZY_INSTANCE_INITIALIZER; +UIDNA* GetUIDNA() { + static base::NoDestructor<UIDNAWrapper> uidna_wrapper; + return uidna_wrapper->value; +} // Converts the Unicode input representing a hostname to ASCII using IDN rules. // The output must be ASCII, but is represented as wide characters. @@ -81,7 +83,7 @@ bool IDNToASCII(const base::char16* src, int src_len, CanonOutputW* output) { DCHECK(output->length() == 0); // Output buffer is assumed empty. - UIDNA* uidna = g_uidna.Get().value; + UIDNA* uidna = GetUIDNA(); DCHECK(uidna != NULL); while (true) { UErrorCode err = U_ZERO_ERROR;